20#ifdef SK_CODEC_DECODES_JPEG_GAINMAPS
34#ifdef SK_CODEC_DECODES_JPEG_GAINMAPS
35std::unique_ptr<SkXmp> SkJpegMetadataDecoderImpl::getXmpMetadata()
const {
36 std::vector<sk_sp<SkData>> decoderApp1Params;
37 for (
const auto&
marker : fMarkerList) {
39 decoderApp1Params.push_back(
marker.fData);
48static std::unique_ptr<SkJpegMultiPictureParameters> find_mp_params(
52 std::unique_ptr<SkJpegMultiPictureParameters> mpParams;
53 size_t skippedSegmentCount = 0;
57 for (
const auto&
marker : markerList) {
65 ++skippedSegmentCount;
80 for (
const auto& segment : sourceMgr->getAllSegments()) {
84 if (skippedSegmentCount == 0) {
85 *outMpParamsSegment = segment;
88 skippedSegmentCount--;
99 bool baseImageHasIsoVersion,
100 bool baseImageHasAdobeXmp,
101 std::optional<float> baseImageAppleHdrHeadroom,
105 bool imageDataWasCopied =
false;
106 auto imageData = decoderSource->getSubsetData(
offset,
size, &imageDataWasCopied);
116 bool didPopulateInfo =
false;
120 if (baseImageHasIsoVersion) {
122 metadataDecoder.getISOGainmapMetadata(
false).get(),
info);
123 if (didPopulateInfo &&
info.fGainmapMathColorSpace) {
124 auto iccData = metadataDecoder.getICCProfileData(
false);
126 if (iccData &&
skcms_Parse(iccData->data(), iccData->size(), &iccProfile)) {
128 if (iccProfileSpace) {
129 info.fGainmapMathColorSpace = std::move(iccProfileSpace);
135 if (!didPopulateInfo) {
137 auto xmp = metadataDecoder.getXmpMetadata();
143 if (!didPopulateInfo && baseImageHasAdobeXmp) {
144 didPopulateInfo = xmp->getGainmapInfoAdobe(&
info);
149 if (!didPopulateInfo && baseImageAppleHdrHeadroom.has_value()) {
150 didPopulateInfo = xmp->getGainmapInfoApple(baseImageAppleHdrHeadroom.value(), &
info);
155 if (!didPopulateInfo) {
161 if (imageDataWasCopied) {
173#ifdef SK_CODEC_DECODES_JPEG_GAINMAPS
176 auto xmp = getXmpMetadata();
179 bool isoGainmapPresent =
183 bool adobeGainmapPresent = xmp && xmp->getGainmapInfoAdobe(
nullptr);
186 size_t containerGainmapOffset = 0;
187 size_t containerGainmapSize = 0;
188 if (xmp && xmp->getContainerGainmapLocation(&containerGainmapOffset, &containerGainmapSize)) {
189 const auto& segments = sourceMgr->getAllSegments();
190 if (!segments.empty()) {
191 const auto& lastSegment = segments.back();
200 auto mpParams = find_mp_params(fMarkerList, sourceMgr, &mpParamsSegment);
204 for (
size_t mpImageIndex = 1; mpImageIndex < mpParams->images.size(); ++mpImageIndex) {
206 mpParams->images[mpImageIndex].dataOffset, mpParamsSegment.
offset);
207 size_t mpImageSize = mpParams->images[mpImageIndex].size;
209 if (extract_gainmap(sourceMgr,
219 if (containerGainmapOffset) {
220 SkASSERT(containerGainmapOffset == mpImageOffset);
221 SkASSERT(containerGainmapSize == mpImageSize);
229 if (containerGainmapOffset) {
230 if (extract_gainmap(sourceMgr,
231 containerGainmapOffset,
232 containerGainmapSize,
240 SkCodecPrintf(
"Failed to extract container-specified gainmap.\n");
251 const uint32_t targetMarker,
252 const uint8_t* signature,
253 size_t signatureSize) {
254 if (targetMarker !=
marker.fMarker) {
257 if (
marker.fData->size() <= signatureSize) {
260 if (memcmp(
marker.fData->bytes(), signature, signatureSize) != 0) {
290 const uint32_t targetMarker,
291 const uint8_t* signature,
292 size_t signatureSize,
293 size_t signaturePadding,
295 bool alwaysCopyData) {
298 const size_t headerSize = signatureSize + signaturePadding + 2 * bytesInIndex;
301 std::vector<sk_sp<SkData>>
parts;
304 size_t partsTotalSize = 0;
307 uint32_t foundPartCount = 0;
310 uint32_t expectedPartCount = 0;
313 for (
const auto&
marker : markerList) {
320 const size_t dataLength =
marker.fData->size();
321 if (dataLength <= headerSize) {
328 uint32_t partIndex = 0;
329 uint32_t partCount = 0;
330 if (bytesInIndex == 0) {
334 for (
size_t i = 0;
i < bytesInIndex; ++
i) {
335 const size_t offset = signatureSize + signaturePadding;
337 partCount = (partCount << 8) +
data[
offset + bytesInIndex +
i];
348 if (partIndex <= 0 || partIndex > partCount) {
349 SkCodecPrintf(
"Invalid marker index %u for count %u\n", partIndex, partCount);
354 if (expectedPartCount == 0) {
355 expectedPartCount = partCount;
356 parts.resize(expectedPartCount);
360 if (partCount != expectedPartCount) {
361 SkCodecPrintf(
"Conflicting marker counts %u vs %u\n", partCount, expectedPartCount);
369 if (
parts[partIndex - 1]) {
370 SkCodecPrintf(
"Duplicate parts for index %u of %u\n", partIndex, expectedPartCount);
375 partsTotalSize += partData->size();
376 parts[partIndex - 1] = std::move(partData);
380 if (foundPartCount == expectedPartCount) {
386 if (expectedPartCount == 0) {
391 if (foundPartCount != expectedPartCount) {
392 SkCodecPrintf(
"Incomplete set of markers (expected %u got %u)\n",
399 if (!alwaysCopyData && expectedPartCount == 1) {
400 return std::move(
parts[0]);
405 void* copyDest =
result->writable_data();
406 for (
const auto& part :
parts) {
407 memcpy(copyDest, part->data(), part->size());
408 copyDest = SkTAddOffset<void>(copyDest, part->size());
414 : fMarkerList(
std::move(markerList)) {}
417#ifdef SK_CODEC_DECODES_JPEG_GAINMAPS
433 fMarkerList.emplace_back(segment.marker, std::move(parameters));
469#ifdef SK_CODEC_DECODES_JPEG_GAINMAPS
471 return find_mp_params(fMarkerList,
nullptr,
nullptr) !=
nullptr;
480#ifdef SK_CODEC_DECODES_JPEG_GAINMAPS
483 return findGainmapImage(sourceMgr.get(), outGainmapImageData, outGainmapInfo);
490 return std::make_unique<SkJpegMetadataDecoderImpl>(std::move(segments));
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static const char marker[]
#define SkCodecPrintf(...)
static constexpr uint32_t kExifMarker
static constexpr uint8_t kICCSig[]
static constexpr uint32_t kMpfMarker
static constexpr uint8_t kJpegMarkerStartOfScan
static constexpr uint32_t kICCMarker
static constexpr uint32_t kISOGainmapMarker
static constexpr uint32_t kXMPMarker
static constexpr uint8_t kJpegMarkerEndOfImage
static constexpr uint8_t kJpegMarkerAPP0
static constexpr size_t kJpegMarkerCodeSize
static constexpr uint8_t kISOGainmapSig[]
constexpr uint8_t kExifSig[]
static constexpr uint32_t kICCMarkerIndexSize
std::unique_ptr< SkXmp > SkJpegMakeXmp(const std::vector< sk_sp< SkData > > &decoderApp1Params)
static sk_sp< SkColorSpace > Make(const skcms_ICCProfile &)
static sk_sp< SkData > MakeWithoutCopy(const void *data, size_t length)
static sk_sp< SkData > MakeUninitialized(size_t length)
static sk_sp< SkData > MakeWithCopy(const void *data, size_t length)
const std::vector< SkJpegSegment > & getSegments() const
static sk_sp< SkData > GetParameters(const SkData *scannedData, const SkJpegSegment &segment)
void onBytes(const void *data, size_t size)
static std::unique_ptr< SkJpegSourceMgr > Make(SkStream *stream, size_t bufferSize=1024)
static std::unique_ptr< SkMemoryStream > Make(sk_sp< SkData > data)
void SK_API Parse(Metadata &metadata, const SkData *data)
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
const myers::Point & get(const myers::Segment &)
static bool skcms_Parse(const void *buf, size_t len, skcms_ICCProfile *profile)
static bool ParseVersion(const SkData *data)
static bool Parse(const SkData *data, SkGainmapInfo &info)
static size_t GetImageAbsoluteOffset(uint32_t dataOffset, size_t mpSegmentOffset)
static std::unique_ptr< SkJpegMultiPictureParameters > Make(const sk_sp< const SkData > &segmentParameters)
std::shared_ptr< const fml::Mapping > data