39#include "dng_area_task.h"
40#include "dng_color_space.h"
41#include "dng_errors.h"
42#include "dng_exceptions.h"
46#include "dng_memory.h"
47#include "dng_mosaic_info.h"
48#include "dng_negative.h"
49#include "dng_pixel_buffer.h"
51#include "dng_rational.h"
53#include "dng_render.h"
54#include "dng_sdk_limits.h"
55#include "dng_stream.h"
56#include "dng_tag_types.h"
61#include "src/piex_types.h"
72dng_point num_tiles_in_area(
const dng_point &areaSize,
73 const dng_point_real64 &tileSize) {
75 return dng_point(
static_cast<int32
>((areaSize.v + tileSize.v - 1) / tileSize.v),
76 static_cast<int32
>((areaSize.h + tileSize.h - 1) / tileSize.h));
79int num_tasks_required(
const dng_point& tilesInTask,
80 const dng_point& tilesInArea) {
81 return ((tilesInArea.v + tilesInTask.v - 1) / tilesInTask.v) *
82 ((tilesInArea.h + tilesInTask.h - 1) / tilesInTask.h);
87dng_point num_tiles_per_task(
const int maxTasks,
88 const dng_point &tilesInArea) {
89 dng_point tilesInTask = {1, 1};
90 while (num_tasks_required(tilesInTask, tilesInArea) > maxTasks) {
91 if (tilesInTask.h < tilesInArea.h) {
93 }
else if (tilesInTask.v < tilesInArea.v) {
96 ThrowProgramError(
"num_tiles_per_task calculation is wrong.");
102std::vector<dng_rect> compute_task_areas(
const int maxTasks,
const dng_rect& area,
103 const dng_point& tileSize) {
104 std::vector<dng_rect> taskAreas;
105 const dng_point tilesInArea = num_tiles_in_area(area.Size(), tileSize);
106 const dng_point tilesPerTask = num_tiles_per_task(maxTasks, tilesInArea);
107 const dng_point taskAreaSize = {tilesPerTask.v * tileSize.v,
108 tilesPerTask.h * tileSize.h};
109 for (
int v = 0; v < tilesInArea.v; v += tilesPerTask.v) {
110 for (
int h = 0;
h < tilesInArea.h;
h += tilesPerTask.h) {
112 taskArea.t = area.t + v * tileSize.v;
113 taskArea.l = area.l +
h * tileSize.h;
114 taskArea.b = Min_int32(taskArea.t + taskAreaSize.v, area.b);
115 taskArea.r = Min_int32(taskArea.l + taskAreaSize.h, area.r);
117 taskAreas.push_back(taskArea);
123class SkDngHost :
public dng_host {
125 explicit SkDngHost(dng_memory_allocator* allocater) : dng_host(allocater) {}
127 void PerformAreaTask(dng_area_task& task,
const dng_rect& area)
override {
131 const dng_point tileSize(task.FindTileSize(area));
132 const std::vector<dng_rect> taskAreas = compute_task_areas(this->PerformAreaTaskThreads(),
134 const int numTasks =
static_cast<int>(taskAreas.size());
139 for (
int taskIndex = 0; taskIndex < numTasks; ++taskIndex) {
140 taskGroup.
add([&mutex, &exceptions, &task,
this, taskIndex, taskAreas, tileSize] {
142 task.ProcessOnThread(taskIndex, taskAreas[taskIndex], tileSize, this->
Sniffer());
143 }
catch (dng_exception& exception) {
148 exceptions.
push_back(dng_exception(dng_error_unknown));
154 task.Finish(numTasks);
157 if (!exceptions.
empty()) {
158 Throw_dng_error(exceptions.
front().ErrorCode(),
nullptr,
nullptr);
162 uint32 PerformAreaTaskThreads()
override {
163#ifdef SK_BUILD_FOR_ANDROID
171 return kMaxMPThreads;
181bool safe_add_to_size_t(
T arg1,
T arg2,
size_t*
result) {
187 *
result =
static_cast<size_t>(sum);
226 if (!safe_add_to_size_t(this->
bytesWritten(), size, &newSize) ||
227 newSize > kMaxStreamSize)
238 const size_t kMaxStreamSize = 100 * 1024 * 1024;
248 , fWholeStreamRead(
false)
251 SkASSERT(!is_asset_stream(*fStream));
257 if (!this->bufferMoreData(kReadToEnd)) {
281 if (fStream->skip(skipLength) != skipLength) {
284 const size_t bytesRead = fStream->read(
data->writable_data(),
size);
285 if (bytesRead <
size) {
290 if (alreadyBuffered > 0 &&
291 !fStreamBuffer.
read(
data->writable_data(),
offset, alreadyBuffered)) {
295 const size_t remaining =
size - alreadyBuffered;
297 auto*
dst =
static_cast<uint8_t*
>(
data->writable_data()) + alreadyBuffered;
298 const size_t bytesRead = fStream->read(
dst, remaining);
300 if (bytesRead < remaining) {
301 if (!safe_add_to_size_t(alreadyBuffered, bytesRead, &newSize)) {
313 bool bufferMoreData(
size_t newSize) {
314 if (newSize == kReadToEnd) {
315 if (fWholeStreamRead) {
326 if (fWholeStreamRead) {
331 const size_t kMinSizeToRead = 8192;
332 const size_t sizeRequested = newSize - fStreamBuffer.
bytesWritten();
333 const size_t sizeToRead =
std::max(kMinSizeToRead, sizeRequested);
335 const size_t bytesRead = fStream->read(tempBuffer.get(), sizeToRead);
336 if (bytesRead < sizeRequested) {
339 return fStreamBuffer.
write(tempBuffer.get(), bytesRead);
342 std::unique_ptr<SkStream> fStream;
343 bool fWholeStreamRead;
348 const size_t kReadToEnd = 0;
357 SkASSERT(is_asset_stream(*fStream));
363 return fStream->getLength();
381 if (fStream->getLength() <
offset) {
386 if (!safe_add_to_size_t(
offset,
size, &sum)) {
392 const size_t bytesToRead =
std::min(sum, fStream->getLength()) -
offset;
393 if (bytesToRead == 0) {
397 if (fStream->getMemoryBase()) {
399 static_cast<const uint8_t*
>(fStream->getMemoryBase()) +
offset, bytesToRead));
404 if (!fStream->seek(
offset)) {
407 const size_t bytesRead = fStream->read(
data->writable_data(), bytesToRead);
408 if (bytesRead < bytesToRead) {
415 std::unique_ptr<SkStream> fStream;
446 if (!safe_add_to_size_t(
static_cast<uint64
>(
count),
offset, &sum) ||
466#if defined(SK_BUILD_FOR_LIBFUZZER)
472 if (!dngImage->initFromPiex() && !dngImage->readDng()) {
476 return dngImage.release();
489 if (!fHost || !fInfo || !fNegative || !fDngStream) {
490 if (!this->readDng()) {
499 std::unique_ptr<dng_host>
host(fHost.release());
500 std::unique_ptr<dng_info>
info(fInfo.release());
501 std::unique_ptr<dng_negative> negative(fNegative.release());
502 std::unique_ptr<dng_stream> dngStream(fDngStream.release());
504 host->SetPreferredSize(preferredSize);
505 host->ValidateSizes();
507 negative->ReadStage1Image(*
host, *dngStream, *
info);
509 if (
info->fMaskIndex != -1) {
510 negative->ReadTransparencyMask(*
host, *dngStream, *
info);
513 negative->ValidateRawImageDigest(*
host);
514 if (negative->IsDamaged()) {
518 const int32 kMosaicPlane = -1;
519 negative->BuildStage2Image(*
host);
520 negative->BuildStage3Image(*
host, kMosaicPlane);
524 render.SetFinalPixelType(ttByte);
526 dng_point stage3_size = negative->Stage3Image()->Size();
548 return fIsXtransImage;
570 bool init(
int width,
int height,
const dng_point& cfaPatternSize) {
576 fIsScalable = cfaPatternSize.v != 0 && cfaPatternSize.h != 0;
577 fIsXtransImage = fIsScalable ? (cfaPatternSize.v == 6 && cfaPatternSize.h == 6) :
false;
582 bool initFromPiex() {
585 ::piex::PreviewImageData imageData;
587 && ::piex::GetPreviewImageData(&piexStream, &imageData) == ::piex::Error::kOk)
589 dng_point cfaPatternSize(imageData.cfa_pattern_dim[1], imageData.cfa_pattern_dim[0]);
590 return this->init(
static_cast<int>(imageData.full_width),
591 static_cast<int>(imageData.full_height), cfaPatternSize);
599 fHost = std::make_unique<SkDngHost>(&fAllocator);
600 fInfo = std::make_unique<dng_info>();
601 fDngStream = std::make_unique<SkDngStream>(fStream.get());
603 fHost->ValidateSizes();
604 fInfo->Parse(*fHost, *fDngStream);
605 fInfo->PostParse(*fHost);
606 if (!fInfo->IsValidDNG()) {
610 fNegative.reset(fHost->Make_dng_negative());
611 fNegative->Parse(*fHost, *fDngStream, *fInfo);
612 fNegative->PostParse(*fHost, *fDngStream, *fInfo);
613 fNegative->SynchronizeMetadata();
615 dng_point cfaPatternSize(0, 0);
616 if (fNegative->GetMosaicInfo() !=
nullptr) {
617 cfaPatternSize = fNegative->GetMosaicInfo()->fCFAPatternSize;
619 return this->init(
static_cast<int>(fNegative->DefaultCropSizeH().As_real64()),
620 static_cast<int>(fNegative->DefaultCropSizeV().As_real64()),
631 dng_memory_allocator fAllocator;
632 std::unique_ptr<SkRawStream> fStream;
633 std::unique_ptr<dng_host> fHost;
634 std::unique_ptr<dng_info> fInfo;
635 std::unique_ptr<dng_negative> fNegative;
636 std::unique_ptr<dng_stream> fDngStream;
656 std::unique_ptr<SkRawStream> rawStream;
657 if (is_asset_stream(*
stream)) {
658 rawStream = std::make_unique<SkRawAssetStream>(std::move(
stream));
660 rawStream = std::make_unique<SkRawBufferedStream>(std::move(
stream));
665 ::piex::PreviewImageData imageData;
667 ::piex::Error
error = ::piex::GetPreviewImageData(&piexStream, &imageData);
673 std::unique_ptr<SkEncodedInfo::ICCProfile>
profile;
674 if (imageData.color_space == ::piex::PreviewImageData::kAdobeRgb) {
684 if (
error == ::piex::Error::kOk && imageData.preview.length > 0 &&
685 imageData.preview.format == ::piex::Image::kJpegCompressed)
690 auto memoryStream = rawStream->transferBuffer(imageData.preview.offset,
691 imageData.preview.length);
714 return std::unique_ptr<SkCodec>(
new SkRawCodec(dngImage.release()));
729 const float maxDiffRatio = 1.03f;
730 const dng_point& imageSize =
image->Size();
731 if (imageSize.h / (
float)
width > maxDiffRatio || imageSize.h <
width ||
732 imageSize.v / (
float)
height > maxDiffRatio || imageSize.v <
height) {
740 buffer.fData = &srcRow[0];
745 buffer.fPixelType = ttByte;
746 buffer.fPixelSize =
sizeof(uint8_t);
759 cs->toProfile(&dstProfileStorage);
760 dstProfile = &dstProfileStorage;
781 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes);
792 if (!fDngImage->isScalable()) {
798 if (desiredScale < 80.f / shortEdge) {
799 desiredScale = 80.f / shortEdge;
804 if (fDngImage->isXtransImage() && desiredScale > 1.f / 3.f && desiredScale < 1.f) {
805 desiredScale = 1.f / 3.f;
809 const float finalScale =
std::floor(1.f/ desiredScale);
821 return sizeFloor == dim || sizeCeil == dim;
831 , fDngImage(dngImage) {}
840 outResult = &resultStorage;
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static uint16_t get_endian_short(const uint8_t *data, bool littleEndian)
#define SkCodecPrintf(...)
static bool is_valid_endian_marker(const uint8_t *data, bool *isLittleEndian)
bool sk_select_xform_format(SkColorType colorType, bool forColorTable, skcms_PixelFormat *outFormat)
static constexpr size_t kHeaderSize
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
#define INHERITED(method,...)
bool SkStreamCopy(SkWStream *out, SkStream *input)
SkISize dimensions() const
const SkImageInfo & dstInfo() const
const SkEncodedInfo & getEncodedInfo() const
static sk_sp< SkData > MakeUninitialized(size_t length)
static sk_sp< SkData > MakeWithCopy(const void *data, size_t length)
static sk_sp< SkData > MakeSubset(const SkData *src, size_t offset, size_t length)
bool isXtransImage() const
static bool IsTiffHeaderValid(SkRawStream *stream)
static SkDngImage * NewFromStream(SkRawStream *stream)
dng_image * render(int width, int height)
SkDngStream(SkRawStream *stream)
void DoRead(void *data, uint32 count, uint64 offset) override
uint64 DoGetLength() override
size_t bytesWritten() const override
SkDynamicMemoryWStream()=default
bool write(const void *buffer, size_t size) override
bool read(void *buffer, size_t offset, size_t size)
static std::unique_ptr< ICCProfile > Make(sk_sp< SkData >)
static std::unique_ptr< SkCodec > MakeFromStream(std::unique_ptr< SkStream >, Result *)
static std::unique_ptr< SkMemoryStream > Make(sk_sp< SkData > data)
SkPiexStream(SkRawStream *stream)
::piex::Error GetData(const size_t offset, const size_t length, uint8 *data) override
SkRawAssetStream(std::unique_ptr< SkStream > stream)
uint64 getLength() override
~SkRawAssetStream() override
std::unique_ptr< SkMemoryStream > transferBuffer(size_t offset, size_t size) override
bool read(void *data, size_t offset, size_t length) override
SkRawBufferedStream(std::unique_ptr< SkStream > stream)
std::unique_ptr< SkMemoryStream > transferBuffer(size_t offset, size_t size) override
bool read(void *data, size_t offset, size_t length) override
~SkRawBufferedStream() override
uint64 getLength() override
static std::unique_ptr< SkCodec > MakeFromStream(std::unique_ptr< SkStream >, Result *)
Result onGetPixels(const SkImageInfo &dstInfo, void *dst, size_t dstRowBytes, const Options &, int *) override
bool onDimensionsSupported(const SkISize &) override
SkISize onGetScaledDimensions(float desiredScale) const override
~SkRawLimitedDynamicMemoryWStream() override
bool write(const void *buffer, size_t size) override
virtual std::unique_ptr< SkMemoryStream > transferBuffer(size_t offset, size_t size)=0
virtual uint64 getLength()=0
virtual bool read(void *data, size_t offset, size_t length)=0
void add(std::function< void(void)> fn)
const uint8_t uint32_t uint32_t GError ** error
static float max(float r, float g, float b)
static float min(float r, float g, float b)
const GrXPFactory * Get(SkBlendMode mode)
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
static constexpr skcms_Matrix3x3 kAdobeRGB
static constexpr skcms_TransferFunction k2Dot2
SK_API std::unique_ptr< SkCodec > Decode(std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
bool IsRaw(const void *, size_t)
sk_sp< const SkImage > image
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service host
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
SIN Vec< N, float > floor(const Vec< N, float > &x)
SIN Vec< N, float > ceil(const Vec< N, float > &x)
bool skcms_Transform(const void *src, skcms_PixelFormat srcFmt, skcms_AlphaFormat srcAlpha, const skcms_ICCProfile *srcProfile, void *dst, skcms_PixelFormat dstFmt, skcms_AlphaFormat dstAlpha, const skcms_ICCProfile *dstProfile, size_t nz)
@ skcms_PixelFormat_RGBA_8888
@ skcms_PixelFormat_RGB_888
static void skcms_SetXYZD50(skcms_ICCProfile *p, const skcms_Matrix3x3 *m)
static void skcms_SetTransferFunction(skcms_ICCProfile *p, const skcms_TransferFunction *tf)
@ skcms_AlphaFormat_Unpremul
static void skcms_Init(skcms_ICCProfile *p)
static const char header[]
const skcms_ICCProfile * profile() const
static constexpr SkISize Make(int32_t w, int32_t h)
SkColorSpace * colorSpace() const
SkColorType colorType() const
std::shared_ptr< const fml::Mapping > data