33#ifdef SK_CODEC_DECODES_JPEG_GAINMAPS
53#if defined(__GNUC__) && !defined(__clang__)
54 #pragma GCC diagnostic ignored "-Wclobbered"
71 markerList.emplace_back(
marker->marker,
82 const uint32_t targetMarker,
83 const uint8_t* signature,
84 size_t signatureSize) {
85 if (targetMarker !=
marker.fMarker) {
88 if (
marker.fData->size() <= signatureSize) {
91 if (memcmp(
marker.fData->bytes(), signature, signatureSize) != 0) {
121 const uint32_t targetMarker,
122 const uint8_t* signature,
123 size_t signatureSize,
124 size_t signaturePadding,
126 bool alwaysCopyData) {
129 const size_t headerSize = signatureSize + signaturePadding + 2 * bytesInIndex;
132 std::vector<sk_sp<SkData>> parts;
135 size_t partsTotalSize = 0;
138 uint32_t foundPartCount = 0;
141 uint32_t expectedPartCount = 0;
144 for (
const auto&
marker : markerList) {
151 const size_t dataLength =
marker.fData->size();
152 if (dataLength <= headerSize) {
158 const uint8_t* data =
marker.fData->bytes();
159 uint32_t partIndex = 0;
160 uint32_t partCount = 0;
161 if (bytesInIndex == 0) {
165 for (
size_t i = 0; i < bytesInIndex; ++i) {
166 const size_t offset = signatureSize + signaturePadding;
167 partIndex = (partIndex << 8) + data[
offset + i];
168 partCount = (partCount << 8) + data[
offset + bytesInIndex + i];
179 if (partIndex <= 0 || partIndex > partCount) {
180 SkCodecPrintf(
"Invalid marker index %u for count %u\n", partIndex, partCount);
185 if (expectedPartCount == 0) {
186 expectedPartCount = partCount;
187 parts.resize(expectedPartCount);
191 if (partCount != expectedPartCount) {
192 SkCodecPrintf(
"Conflicting marker counts %u vs %u\n", partCount, expectedPartCount);
200 if (parts[partIndex-1]) {
201 SkCodecPrintf(
"Duplicate parts for index %u of %u\n", partIndex, expectedPartCount);
206 partsTotalSize += partData->size();
207 parts[partIndex-1] = std::move(partData);
211 if (foundPartCount == expectedPartCount) {
217 if (expectedPartCount == 0) {
222 if (foundPartCount != expectedPartCount) {
223 SkCodecPrintf(
"Incomplete set of markers (expected %u got %u)\n",
230 if (!alwaysCopyData && expectedPartCount == 1) {
231 return std::move(parts[0]);
236 void* copyDest =
result->writable_data();
237 for (
const auto& part : parts) {
238 memcpy(copyDest, part->data(), part->size());
239 copyDest = SkTAddOffset<void>(copyDest, part->size());
256 std::unique_ptr<SkEncodedInfo::ICCProfile> defaultColorProfile) {
263 return decoderMgr->returnFailure(
"ReadHeader",
kInvalidInput);
268 auto* dinfo = decoderMgr->dinfo();
281 switch (jpeg_read_header(dinfo,
true)) {
287 return decoderMgr->returnFailure(
"ReadHeader",
kInvalidInput);
293 if (!decoderMgr->getEncodedColor(&
color)) {
302 std::unique_ptr<SkEncodedInfo::ICCProfile>
profile;
303 if (
auto iccProfileData = metadataDecoder->getICCProfileData(
true)) {
308 switch (decoderMgr->dinfo()->jpeg_color_space) {
330 profile = std::move(defaultColorProfile);
338 std::unique_ptr<SkStream>(
stream),
339 decoderMgr.release(),
344 *decoderMgrOut = decoderMgr.release();
355 Result*
result, std::unique_ptr<SkEncodedInfo::ICCProfile> defaultColorProfile) {
362 *
result = ReadHeader(
stream.get(), &codec,
nullptr, std::move(defaultColorProfile));
367 return std::unique_ptr<SkCodec>(codec);
373 std::unique_ptr<SkStream> stream,
377 , fDecoderMgr(decoderMgr)
378 , fReadyState(decoderMgr->dinfo()->global_state) {}
385 const size_t colorBytes = (dinfo->out_color_space == JCS_RGB565) ? 2 :
386 dinfo->out_color_components;
387 return dinfo->output_width * colorBytes;
398 dinfo->num_components = 0;
399 dinfo->scale_num = num;
400 dinfo->scale_denom = denom;
401 jpeg_calc_output_dimensions(dinfo);
411 unsigned int denom = 8;
412 if (desiredScale >= 0.9375) {
414 }
else if (desiredScale >= 0.8125) {
416 }
else if (desiredScale >= 0.6875f) {
418 }
else if (desiredScale >= 0.5625f) {
420 }
else if (desiredScale >= 0.4375f) {
422 }
else if (desiredScale >= 0.3125f) {
424 }
else if (desiredScale >= 0.1875f) {
431 jpeg_decompress_struct dinfo;
435 dinfo.global_state = fReadyState;
439 return SkISize::Make(dinfo.output_width, dinfo.output_height);
444 if (
kSuccess != ReadHeader(this->
stream(),
nullptr, &decoderMgr,
nullptr)) {
445 return fDecoderMgr->returnFalse(
"onRewind");
448 fDecoderMgr.reset(decoderMgr);
450 fSwizzler.reset(
nullptr);
451 fSwizzleSrcRow =
nullptr;
452 fColorXformSrcRow =
nullptr;
459 bool needsColorXform) {
467 SkCodecPrintf(
"Warning: an opaque image should be decoded as opaque "
468 "- it is being decoded as non-opaque, which will draw slower\n");
471 J_COLOR_SPACE encodedColorType = fDecoderMgr->dinfo()->jpeg_color_space;
476 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
479 if (needsColorXform) {
482 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
484 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_BGRA;
488 if (needsColorXform) {
489 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
491 fDecoderMgr->dinfo()->dither_mode = JDITHER_NONE;
492 fDecoderMgr->dinfo()->out_color_space = JCS_RGB565;
496 if (JCS_GRAYSCALE != encodedColorType) {
500 if (needsColorXform) {
501 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
503 fDecoderMgr->dinfo()->out_color_space = JCS_GRAYSCALE;
510 fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
518 if (JCS_CMYK == encodedColorType || JCS_YCCK == encodedColorType) {
519 fDecoderMgr->dinfo()->out_color_space = JCS_CMYK;
532 return fDecoderMgr->returnFalse(
"onDimensionsSupported");
535 const unsigned int dstWidth = size.width();
536 const unsigned int dstHeight = size.height();
540 jpeg_decompress_struct dinfo;
544 dinfo.global_state = fReadyState;
547 unsigned int num = 8;
548 const unsigned int denom = 8;
550 while (dinfo.output_width != dstWidth || dinfo.output_height != dstHeight) {
553 if (1 == num || dstWidth > dinfo.output_width || dstHeight > dinfo.output_height) {
562 fDecoderMgr->dinfo()->scale_num = num;
563 fDecoderMgr->dinfo()->scale_denom = denom;
567int SkJpegCodec::readRows(
const SkImageInfo& dstInfo,
void* dst,
size_t rowBytes,
int count,
568 const Options& opts) {
583 JSAMPLE* decodeDst = (JSAMPLE*) dst;
584 uint32_t* swizzleDst = (uint32_t*) dst;
585 size_t decodeDstRowBytes = rowBytes;
586 size_t swizzleDstRowBytes = rowBytes;
587 int dstWidth = opts.fSubset ? opts.fSubset->width() :
dstInfo.
width();
588 if (fSwizzleSrcRow && fColorXformSrcRow) {
589 decodeDst = (JSAMPLE*) fSwizzleSrcRow;
590 swizzleDst = fColorXformSrcRow;
591 decodeDstRowBytes = 0;
592 swizzleDstRowBytes = 0;
593 dstWidth = fSwizzler->swizzleWidth();
594 }
else if (fColorXformSrcRow) {
595 decodeDst = (JSAMPLE*) fColorXformSrcRow;
596 swizzleDst = fColorXformSrcRow;
597 decodeDstRowBytes = 0;
598 swizzleDstRowBytes = 0;
599 }
else if (fSwizzleSrcRow) {
600 decodeDst = (JSAMPLE*) fSwizzleSrcRow;
601 decodeDstRowBytes = 0;
602 dstWidth = fSwizzler->swizzleWidth();
606 uint32_t
lines = jpeg_read_scanlines(fDecoderMgr->dinfo(), &decodeDst, 1);
612 fSwizzler->swizzle(swizzleDst, decodeDst);
617 dst = SkTAddOffset<void>(dst, rowBytes);
620 decodeDst = SkTAddOffset<JSAMPLE>(decodeDst, decodeDstRowBytes);
621 swizzleDst = SkTAddOffset<uint32_t>(swizzleDst, swizzleDstRowBytes);
635 bool hasColorSpaceXform) {
636 if (JCS_CMYK != jpegColorType) {
641 return !hasCMYKColorSpace || !hasColorSpaceXform;
648 void* dst,
size_t dstRowBytes,
657 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
665 if (!jpeg_start_decompress(dinfo)) {
666 return fDecoderMgr->returnFailure(
"startDecompress",
kInvalidInput);
671 SkASSERT(1 == dinfo->rec_outbuf_height);
674 this->getEncodedInfo().profile(), this->colorXform())) {
678 if (!this->allocateStorage(
dstInfo)) {
685 return fDecoderMgr->returnFailure(
"Incomplete image data",
kIncompleteInput);
691bool SkJpegCodec::allocateStorage(
const SkImageInfo& dstInfo) {
694 size_t swizzleBytes = 0;
697 dstWidth = fSwizzler->swizzleWidth();
701 size_t xformBytes = 0;
704 xformBytes = dstWidth *
sizeof(uint32_t);
707 size_t totalBytes = swizzleBytes + xformBytes;
708 if (totalBytes > 0) {
709 if (!fStorage.
reset(totalBytes)) {
712 fSwizzleSrcRow = (swizzleBytes > 0) ? fStorage.
get() :
nullptr;
713 fColorXformSrcRow = (xformBytes > 0) ?
714 SkTAddOffset<uint32_t>(fStorage.
get(), swizzleBytes) : nullptr;
719void SkJpegCodec::initializeSwizzler(
const SkImageInfo& dstInfo,
const Options&
options,
720 bool needsCMYKToRGB) {
721 Options swizzlerOptions =
options;
728 swizzlerOptions.fSubset = &fSwizzlerSubset;
737 if (needsCMYKToRGB) {
742 fSwizzler =
SkSwizzler::Make(swizzlerInfo,
nullptr, swizzlerDstInfo, swizzlerOptions);
745 switch (fDecoderMgr->dinfo()->out_color_space) {
767 if (!createIfNecessary || fSwizzler) {
768 SkASSERT(!fSwizzler || (fSwizzleSrcRow && fStorage.
get() == fSwizzleSrcRow));
769 return fSwizzler.get();
773 fDecoderMgr->dinfo()->out_color_space, this->getEncodedInfo().profile(),
775 this->initializeSwizzler(this->
dstInfo(), this->
options(), needsCMYKToRGB);
776 if (!this->allocateStorage(this->
dstInfo())) {
779 return fSwizzler.get();
791 if (!jpeg_start_decompress(fDecoderMgr->dinfo())) {
797 fDecoderMgr->dinfo()->out_color_space, this->getEncodedInfo().profile(),
808 jpeg_crop_scanline(fDecoderMgr->dinfo(), &startX, &
width);
837 if (!fSwizzler && needsCMYKToRGB) {
841 if (!this->allocateStorage(
dstInfo)) {
852 fDecoderMgr->dinfo()->output_scanline = this->
dstInfo().
height();
862 return fDecoderMgr->returnFalse(
"onSkipScanlines");
865 return (uint32_t)
count == jpeg_skip_scanlines(fDecoderMgr->dinfo(),
count);
873 SkASSERT(dinfo->scale_num == dinfo->scale_denom);
876 static_assert(8 == DCTSIZE,
"DCTSIZE (defined in jpeg library) should always be 8.");
878 if (JCS_YCbCr != dinfo->jpeg_color_space) {
882 SkASSERT(3 == dinfo->num_components);
900 if ((1 != dinfo->comp_info[1].h_samp_factor) ||
901 (1 != dinfo->comp_info[1].v_samp_factor) ||
902 (1 != dinfo->comp_info[2].h_samp_factor) ||
903 (1 != dinfo->comp_info[2].v_samp_factor))
916 int hSampY = dinfo->comp_info[0].h_samp_factor;
917 int vSampY = dinfo->comp_info[0].v_samp_factor;
918 SkASSERT(hSampY == dinfo->max_h_samp_factor);
919 SkASSERT(vSampY == dinfo->max_v_samp_factor);
922 if (1 == hSampY && 1 == vSampY) {
924 }
else if (2 == hSampY && 1 == vSampY) {
926 }
else if (2 == hSampY && 2 == vSampY) {
928 }
else if (1 == hSampY && 2 == vSampY) {
930 }
else if (4 == hSampY && 1 == vSampY) {
932 }
else if (4 == hSampY && 2 == vSampY) {
937 if (supportedDataTypes &&
942 if (yuvaPixmapInfo) {
945 for (
int i = 0; i < 3; ++i) {
947 rowBytes[i] = dinfo->comp_info[i].width_in_blocks * DCTSIZE;
963 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
969 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
971 return fDecoderMgr->returnFailure(
"onGetYUVAPlanes",
kInvalidInput);
979 dinfo->raw_data_out =
TRUE;
980 if (!jpeg_start_decompress(dinfo)) {
981 return fDecoderMgr->returnFailure(
"startDecompress",
kInvalidInput);
984 const std::array<SkPixmap, SkYUVAPixmaps::kMaxPlanes>& planes = yuvaPixmaps.
planes();
995 for (
int i = 0; i <
info.numPlanes(); ++i) {
1009 JSAMPROW rowptrs[2 * DCTSIZE + DCTSIZE + DCTSIZE];
1010 yuv[0] = &rowptrs[0];
1011 yuv[1] = &rowptrs[2 * DCTSIZE];
1012 yuv[2] = &rowptrs[3 * DCTSIZE];
1015 int numYRowsPerBlock = DCTSIZE * dinfo->comp_info[0].v_samp_factor;
1016 static_assert(
sizeof(JSAMPLE) == 1);
1017 for (
int i = 0; i < numYRowsPerBlock; i++) {
1018 rowptrs[i] =
static_cast<JSAMPLE*
>(planes[0].writable_addr()) + i* planes[0].rowBytes();
1020 for (
int i = 0; i < DCTSIZE; i++) {
1021 rowptrs[i + 2 * DCTSIZE] =
1022 static_cast<JSAMPLE*
>(planes[1].writable_addr()) + i* planes[1].rowBytes();
1023 rowptrs[i + 3 * DCTSIZE] =
1024 static_cast<JSAMPLE*
>(planes[2].writable_addr()) + i* planes[2].rowBytes();
1028 size_t blockIncrementY = numYRowsPerBlock * planes[0].rowBytes();
1029 size_t blockIncrementU = DCTSIZE * planes[1].rowBytes();
1030 size_t blockIncrementV = DCTSIZE * planes[2].rowBytes();
1032 uint32_t numRowsPerBlock = numYRowsPerBlock;
1037 const int numIters = dinfo->output_height / numRowsPerBlock;
1038 for (
int i = 0; i < numIters; i++) {
1039 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock);
1040 if (linesRead < numRowsPerBlock) {
1046 for (
int j = 0; j < numYRowsPerBlock; j++) {
1047 rowptrs[j] += blockIncrementY;
1049 for (
int j = 0; j < DCTSIZE; j++) {
1050 rowptrs[j + 2 * DCTSIZE] += blockIncrementU;
1051 rowptrs[j + 3 * DCTSIZE] += blockIncrementV;
1055 uint32_t remainingRows = dinfo->output_height - dinfo->output_scanline;
1056 SkASSERT(remainingRows == dinfo->output_height % numRowsPerBlock);
1057 SkASSERT(dinfo->output_scanline == numIters * numRowsPerBlock);
1058 if (remainingRows > 0) {
1064 for (
int i = remainingRows; i < numYRowsPerBlock; i++) {
1065 rowptrs[i] = extraRow.
get();
1067 int remainingUVRows = dinfo->comp_info[1].downsampled_height - DCTSIZE * numIters;
1068 for (
int i = remainingUVRows; i < DCTSIZE; i++) {
1069 rowptrs[i + 2 * DCTSIZE] = extraRow.
get();
1070 rowptrs[i + 3 * DCTSIZE] = extraRow.
get();
1073 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock);
1074 if (linesRead < remainingRows) {
1083#ifdef SK_CODEC_DECODES_JPEG_GAINMAPS
1085static std::unique_ptr<SkXmp> get_xmp_metadata(
const SkJpegMarkerList& markerList) {
1086 std::vector<sk_sp<SkData>> decoderApp1Params;
1087 for (
const auto&
marker : markerList) {
1089 decoderApp1Params.push_back(
marker.fData);
1098static std::unique_ptr<SkJpegMultiPictureParameters> find_mp_params(
1102 std::unique_ptr<SkJpegMultiPictureParameters> mpParams;
1103 size_t skippedSegmentCount = 0;
1107 for (
const auto&
marker : markerList) {
1115 ++skippedSegmentCount;
1130 for (
const auto& segment : sourceMgr->getAllSegments()) {
1134 if (skippedSegmentCount == 0) {
1135 *outMpParamsSegment = segment;
1138 skippedSegmentCount--;
1149 bool base_image_has_hdrgm,
1151 std::unique_ptr<SkStream>* outGainmapImageStream) {
1153 bool imageDataWasCopied =
false;
1154 auto imageData = decoderSource->getSubsetData(
offset, size, &imageDataWasCopied);
1162 scan.onBytes(imageData->data(), imageData->size());
1163 if (scan.hadError() || !scan.isDone()) {
1169 std::vector<sk_sp<SkData>> app1Params;
1170 for (
const auto& segment : scan.getSegments()) {
1178 app1Params.push_back(std::move(parameters));
1186 bool did_populate_info =
false;
1190 did_populate_info = base_image_has_hdrgm && xmp->getGainmapInfoHDRGM(&
info);
1193 if (!did_populate_info) {
1194 did_populate_info = xmp->getGainmapInfoHDRGainMap(&
info);
1198 if (!did_populate_info) {
1203 if (outGainmapImageStream) {
1204 if (imageDataWasCopied) {
1217 std::unique_ptr<SkStream>* gainmapImageStream) {
1219 std::unique_ptr<SkXmp> xmp = get_xmp_metadata(markerList);
1226 const bool base_image_has_hdrgm = xmp && xmp->getGainmapInfoHDRGM(&base_image_info);
1229 size_t containerGainmapOffset = 0;
1230 size_t containerGainmapSize = 0;
1231 if (xmp && xmp->getContainerGainmapLocation(&containerGainmapOffset, &containerGainmapSize)) {
1232 const auto& segments = sourceMgr->getAllSegments();
1233 if (!segments.empty()) {
1234 const auto& lastSegment = segments.back();
1243 auto mpParams = find_mp_params(markerList, sourceMgr, &mpParamsSegment);
1247 for (
size_t mpImageIndex = 1; mpImageIndex < mpParams->images.size(); ++mpImageIndex) {
1249 mpParams->images[mpImageIndex].dataOffset, mpParamsSegment.
offset);
1250 size_t mpImageSize = mpParams->images[mpImageIndex].size;
1252 if (extract_gainmap(sourceMgr,
1255 base_image_has_hdrgm,
1257 gainmapImageStream)) {
1260 if (containerGainmapOffset) {
1261 SkASSERT(containerGainmapOffset == mpImageOffset);
1262 SkASSERT(containerGainmapSize == mpImageSize);
1270 if (containerGainmapOffset) {
1271 if (extract_gainmap(sourceMgr,
1272 containerGainmapOffset,
1273 containerGainmapSize,
1274 base_image_has_hdrgm,
1276 gainmapImageStream)) {
1279 SkCodecPrintf(
"Failed to extract container-specified gainmap.\n");
1284 if (xmp && base_image_has_hdrgm) {
1294 if (*gainmapImageStream) {
1295 *
info = base_image_info;
1299 SkCodecPrintf(
"Parsed HDRGM metadata but did not find image\n");
1306 std::unique_ptr<SkStream>* gainmapImageStream) {
1308 return get_gainmap_info(markerList, fDecoderMgr->getSourceMgr(),
info, gainmapImageStream);
1313 std::unique_ptr<SkStream>* gainmapImageStream) {
1343#ifdef SK_CODEC_DECODES_JPEG_GAINMAPS
1345 return find_mp_params(fMarkerList,
nullptr,
nullptr) !=
nullptr;
1354#ifdef SK_CODEC_DECODES_JPEG_GAINMAPS
1358 std::unique_ptr<SkStream> gainmapImageStream;
1359 if (!get_gainmap_info(fMarkerList, sourceMgr.get(), &gainmapInfo, &gainmapImageStream)) {
1366 SkASSERT(gainmapImageStream->getMemoryBase());
1368 gainmapImageStream->getLength());
1369 outGainmapInfo = gainmapInfo;
1382 for (
const auto& segment : segments) {
1383 markerList.emplace_back(segment.fMarker, segment.fData);
1385 return std::make_unique<SkJpegMetadataDecoderImpl>(std::move(markerList));
1393std::unique_ptr<SkCodec>
Decode(std::unique_ptr<SkStream> stream,
1395 SkCodecs::DecodeContext) {
1398 outResult = &resultStorage;
1405 SkCodecs::DecodeContext) {
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static const char marker[]
static constexpr bool SkIsAlign4(T x)
@ kUnknown_SkAlphaType
uninitialized
@ kOpaque_SkAlphaType
pixel is opaque
#define SkCodecPrintf(...)
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
@ kRGBA_F16_SkColorType
pixel with half floats for red, green, blue, alpha;
@ kAlpha_8_SkColorType
pixel with alpha in 8-bit byte
@ kGray_8_SkColorType
pixel with grayscale level in 8-bit byte
@ kRGB_565_SkColorType
pixel with 5 bits red, 6 bits green, 5 bits blue, in 16-bit word
@ kBGRA_10101010_XR_SkColorType
pixel with 10 bits each for blue, green, red, alpha; in 64-bit word, extended range
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
@ kBGR_101010x_XR_SkColorType
pixel with 10 bits each for blue, green, red; in 32-bit word, extended range
@ kDefault_SkEncodedOrigin
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
@ kJPEG_Full_SkYUVColorSpace
describes full range
static sk_sp< SkData > read_metadata(const SkJpegMarkerList &markerList, const uint32_t targetMarker, const uint8_t *signature, size_t signatureSize, size_t signaturePadding, size_t bytesInIndex, bool alwaysCopyData)
static size_t get_row_bytes(const j_decompress_ptr dinfo)
void calc_output_dimensions(jpeg_decompress_struct *dinfo, unsigned int num, unsigned int denom)
static bool is_yuv_supported(const jpeg_decompress_struct *dinfo, const SkJpegCodec &codec, const SkYUVAPixmapInfo::SupportedDataTypes *supportedDataTypes, SkYUVAPixmapInfo *yuvaPixmapInfo)
static SkEncodedOrigin get_exif_orientation(sk_sp< SkData > exifData)
static bool marker_has_signature(const SkJpegMarker &marker, const uint32_t targetMarker, const uint8_t *signature, size_t signatureSize)
std::vector< SkJpegMarker > SkJpegMarkerList
SkJpegMarkerList get_sk_marker_list(jpeg_decompress_struct *dinfo)
static bool needs_swizzler_to_convert_from_cmyk(J_COLOR_SPACE jpegColorType, const skcms_ICCProfile *srcProfile, bool hasColorSpaceXform)
static constexpr uint32_t kExifMarker
static constexpr uint8_t kICCSig[]
static constexpr uint32_t kMpfMarker
static constexpr uint32_t kGainmapMarkerIndexSize
static constexpr uint8_t kJpegMarkerStartOfScan
static constexpr uint32_t kICCMarker
static constexpr uint32_t kXMPMarker
static constexpr uint8_t kJpegMarkerEndOfImage
static constexpr uint32_t kGainmapMarker
static constexpr size_t kJpegMarkerCodeSize
static constexpr uint8_t kJpegSig[]
constexpr uint8_t kExifSig[]
static constexpr uint32_t kICCMarkerIndexSize
static constexpr uint8_t kGainmapSig[]
std::unique_ptr< SkXmp > SkJpegMakeXmp(const std::vector< sk_sp< SkData > > &decoderApp1Params)
static void sk_bzero(void *buffer, size_t size)
bool SkParseEncodedOrigin(const void *data, size_t data_length, SkEncodedOrigin *orientation)
#define INHERITED(method,...)
SkISize dimensions() const
const SkImageInfo & dstInfo() const
void applyColorXform(void *dst, const void *src, int count) const
SkEncodedOrigin getOrigin() const
const Options & options() const
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)
static std::unique_ptr< ICCProfile > Make(sk_sp< SkData >)
bool onQueryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes &, SkYUVAPixmapInfo *) const override
static bool IsJpeg(const void *, size_t)
bool onSkipScanlines(int count) override
Result onGetYUVAPlanes(const SkYUVAPixmaps &yuvaPixmaps) override
Result onStartScanlineDecode(const SkImageInfo &dstInfo, const Options &options) override
Result onGetPixels(const SkImageInfo &dstInfo, void *dst, size_t dstRowBytes, const Options &, int *) override
bool onDimensionsSupported(const SkISize &) override
int onGetScanlines(void *dst, int count, size_t rowBytes) override
SkISize onGetScaledDimensions(float desiredScale) const override
bool conversionSupported(const SkImageInfo &, bool, bool) override
SkSampler * getSampler(bool createIfNecessary) override
bool onGetGainmapInfo(SkGainmapInfo *info, std::unique_ptr< SkStream > *gainmapImageStream) override
static std::unique_ptr< SkCodec > MakeFromStream(std::unique_ptr< SkStream >, Result *)
static sk_sp< SkData > GetParameters(const SkData *scannedData, const SkJpegSegment &segment)
static std::unique_ptr< SkJpegSourceMgr > Make(SkStream *stream, size_t bufferSize=1024)
static std::unique_ptr< SkMemoryStream > Make(sk_sp< SkData > data)
static std::unique_ptr< SkMemoryStream > MakeCopy(const void *data, size_t length)
static std::unique_ptr< SkSwizzler > MakeSimple(int srcBPP, const SkImageInfo &dstInfo, const SkCodec::Options &)
static std::unique_ptr< SkSwizzler > Make(const SkEncodedInfo &encodedInfo, const SkPMColor *ctable, const SkImageInfo &dstInfo, const SkCodec::Options &, const SkIRect *frame=nullptr)
@ kY_U_V
Plane 0: Y, Plane 1: U, Plane 2: V.
@ k440
1 set of UV values for each 1x2 block of Y values.
@ k420
1 set of UV values for each 2x2 block of Y values.
@ k410
1 set of UV values for each 4x2 block of Y values.
@ k411
1 set of UV values for each 4x1 block of Y values.
@ k422
1 set of UV values for each 2x1 block of Y values.
@ k444
No subsampling. UV values for each Y.
constexpr bool supported(PlaneConfig, DataType) const
@ kUnorm8
8 bit unsigned normalized
static constexpr auto kMaxPlanes
const SkYUVAInfo & yuvaInfo() const
const std::array< SkPixmap, kMaxPlanes > & planes() const
T * reset(size_t count=0)
static const uint8_t buffer[]
SK_API bool IsJpeg(const void *, size_t)
SK_API std::unique_ptr< SkCodec > Decode(std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
@ skcms_PixelFormat_RGBA_8888
static SkEncodedInfo Make(int width, int height, Color color, Alpha alpha, int bitsPerComponent)
constexpr int32_t x() const
constexpr int32_t height() const
constexpr int32_t right() const
constexpr int32_t width() const
void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height)
static constexpr SkISize Make(int32_t w, int32_t h)
constexpr int32_t width() const
constexpr int32_t height() const
int bytesPerPixel() const
SkAlphaType alphaType() const
SkColorType colorType() const
SkImageInfo makeColorType(SkColorType newColorType) const
static size_t GetAbsoluteOffset(uint32_t dataOffset, size_t mpSegmentOffset)
static std::unique_ptr< SkJpegMultiPictureParameters > Make(const sk_sp< const SkData > &segmentParameters)
uint32_t data_color_space