44#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
49#if defined(__GNUC__) && !defined(__clang__)
50 #pragma GCC diagnostic ignored "-Wclobbered"
54#define PNG_JMPBUF(x) png_jmpbuf((png_structp) x)
67static void sk_error_fn(png_structp png_ptr, png_const_charp msg) {
76#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
77static int sk_read_user_chunk(png_structp png_ptr, png_unknown_chunkp chunk) {
80 return chunkReader->
readChunk((
const char*)chunk->name, chunk->data, chunk->size) ? 1 : -1;
101 , fChunkReader(reader)
102 , fOutCodec(codecPtr)
108 png_infopp info_pp = fInfo_ptr ? &fInfo_ptr :
nullptr;
109 png_destroy_read_struct(&fPng_ptr, info_pp,
nullptr);
115 fInfo_ptr = info_ptr;
133 png_structp fPng_ptr;
139 void infoCallback(
size_t idatLength);
141 void releasePngPtrs() {
147static inline bool is_chunk(
const png_byte* chunk,
const char* tag) {
148 return memcmp(chunk + 4, tag, 4) == 0;
151static inline bool process_data(png_structp png_ptr, png_infop info_ptr,
154 const size_t bytesToProcess = std::min(bufferSize,
length);
155 const size_t bytesRead = stream->read(
buffer, bytesToProcess);
156 png_process_data(png_ptr, info_ptr, (png_bytep)
buffer, bytesRead);
157 if (bytesRead < bytesToProcess) {
171 png_set_progressive_read_fn(fPng_ptr,
nullptr,
nullptr,
nullptr,
nullptr);
185 png_process_data(fPng_ptr, fInfo_ptr, (png_bytep)
buffer, 8);
195 png_byte* chunk =
reinterpret_cast<png_byte*
>(
buffer);
196 const size_t length = png_get_uint_32(chunk);
199 this->infoCallback(
length);
203 png_process_data(fPng_ptr, fInfo_ptr, chunk, 8);
243 png_byte* chunk =
reinterpret_cast<png_byte*
>(
buffer);
249 length = png_get_uint_32(chunk);
252 png_byte idat[] = {0, 0, 0, 0,
'I',
'D',
'A',
'T'};
253 png_save_uint_32(idat,
length);
275bool SkPngCodec::createColorTable(
const SkImageInfo& dstInfo) {
289 int numColorsWithAlpha = 0;
297 for (
int i = 0; i < numColorsWithAlpha; i++) {
301 colorTable[i] = proc(alphas[i], palette->red, palette->green, palette->blue);
306 if (numColorsWithAlpha < numColors) {
309 static_assert(3 ==
sizeof(png_color),
"png_color struct has changed. Opts are broken.");
311 SkASSERT(&palette->red < &palette->green);
312 SkASSERT(&palette->green < &palette->blue);
317 numColors - numColorsWithAlpha);
320 numColors - numColorsWithAlpha);
331 if (numColors < maxColors) {
345 return !png_sig_cmp((png_const_bytep) buf, (png_size_t)0, bytesRead);
348#if (PNG_LIBPNG_VER_MAJOR > 1) || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 6)
350static float png_fixed_point_to_float(png_fixed_point
x) {
355 return ((
float)
x) * 0.00001f;
358static float png_inverted_fixed_point_to_float(png_fixed_point
x) {
360 return 1.0f / png_fixed_point_to_float(
x);
367 png_infop info_ptr) {
369#if (PNG_LIBPNG_VER_MAJOR > 1) || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 6)
381 if (PNG_INFO_iCCP == png_get_iCCP(png_ptr, info_ptr, &
name, &compression, &profile,
391 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sRGB)) {
403 png_fixed_point chrm[8];
404 png_fixed_point gamma;
405 if (png_get_cHRM_fixed(png_ptr, info_ptr, &chrm[0], &chrm[1], &chrm[2], &chrm[3], &chrm[4],
406 &chrm[5], &chrm[6], &chrm[7]))
408 float rx = png_fixed_point_to_float(chrm[2]);
409 float ry = png_fixed_point_to_float(chrm[3]);
410 float gx = png_fixed_point_to_float(chrm[4]);
411 float gy = png_fixed_point_to_float(chrm[5]);
412 float bx = png_fixed_point_to_float(chrm[6]);
413 float by = png_fixed_point_to_float(chrm[7]);
414 float wx = png_fixed_point_to_float(chrm[0]);
415 float wy = png_fixed_point_to_float(chrm[1]);
427 if (PNG_INFO_gAMA == png_get_gAMA_fixed(png_ptr, info_ptr, &gamma)) {
429 fn.
b = fn.
c = fn.
d = fn.
e = fn.
f = 0.0f;
430 fn.
g = png_inverted_fixed_point_to_float(gamma);
449void SkPngCodec::allocateStorage(
const SkImageInfo& dstInfo) {
450 switch (fXformMode) {
451 case kSwizzleOnly_XformMode:
453 case kColorOnly_XformMode:
457 case kSwizzleColor_XformMode: {
462 const size_t bytesPerPixel = (bitsPerPixel > 32) ? bitsPerPixel / 8 : 4;
463 const size_t colorXformBytes =
dstInfo.
width() * bytesPerPixel;
473 if (16 ==
info.bitsPerComponent()) {
487 switch (fXformMode) {
488 case kSwizzleOnly_XformMode:
489 fSwizzler->swizzle(dst, (
const uint8_t*) src);
491 case kColorOnly_XformMode:
494 case kSwizzleColor_XformMode:
503#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
504 SkAndroidFrameworkUtils::SafetyNetLog(
"117838472");
514 , fRowsWrittenToOutput(0)
522 GetDecoder(
png_ptr)->allRowsCallback(row, rowNum);
526 GetDecoder(
png_ptr)->rowCallback(row, rowNum);
530 int fRowsWrittenToOutput;
549 fRowBytes = rowBytes;
551 fRowsWrittenToOutput = 0;
556 if (success && fRowsWrittenToOutput ==
height) {
561 *rowsDecoded = fRowsWrittenToOutput;
567 void allRowsCallback(png_bytep row,
int rowNum) {
568 SkASSERT(rowNum == fRowsWrittenToOutput);
569 fRowsWrittenToOutput++;
571 fDst = SkTAddOffset<void>(fDst, fRowBytes);
574 void setRange(
int firstRow,
int lastRow,
void* dst,
size_t rowBytes)
override {
576 fFirstRow = firstRow;
579 fRowBytes = rowBytes;
580 fRowsWrittenToOutput = 0;
581 fRowsNeeded = fLastRow - fFirstRow + 1;
591 if (success && fRowsWrittenToOutput == fRowsNeeded) {
596 *rowsDecoded = fRowsWrittenToOutput;
602 void rowCallback(png_bytep row,
int rowNum) {
603 if (rowNum < fFirstRow) {
609 SkASSERT(fRowsWrittenToOutput < fRowsNeeded);
614 fDst = SkTAddOffset<void>(fDst, fRowBytes);
615 fRowsWrittenToOutput++;
618 if (fRowsWrittenToOutput == fRowsNeeded) {
629 png_infop
info_ptr,
int bitDepth,
int numberPasses)
631 , fNumberPasses(numberPasses)
635 , fInterlacedComplete(false)
641 decoder->interlacedRowCallback(row, rowNum, pass);
645 const int fNumberPasses;
651 bool fInterlacedComplete;
652 size_t fPng_rowbytes;
660 void interlacedRowCallback(png_bytep row,
int rowNum,
int pass) {
661 if (rowNum < fFirstRow || rowNum > fLastRow || fInterlacedComplete) {
666 png_bytep oldRow = fInterlaceBuffer.
get() + (rowNum - fFirstRow) * fPng_rowbytes;
667 png_progressive_combine_row(this->
png_ptr(), oldRow, row);
672 SkASSERT(fLinesDecoded == rowNum - fFirstRow);
675 SkASSERT(fLinesDecoded == fLastRow - fFirstRow + 1);
676 if (fNumberPasses - 1 == pass && rowNum == fLastRow) {
678 fInterlacedComplete =
true;
693 this->setUpInterlaceBuffer(
height);
702 png_bytep srcRow = fInterlaceBuffer.
get();
704 for (
int rowNum = 0; rowNum < fLinesDecoded; rowNum++) {
706 dst = SkTAddOffset<void>(dst, rowBytes);
707 srcRow = SkTAddOffset<png_byte>(srcRow, fPng_rowbytes);
709 if (success && fInterlacedComplete) {
714 *rowsDecoded = fLinesDecoded;
720 void setRange(
int firstRow,
int lastRow,
void* dst,
size_t rowBytes)
override {
722 this->setUpInterlaceBuffer(lastRow - firstRow + 1);
724 fFirstRow = firstRow;
727 fRowBytes = rowBytes;
735 if (!fLinesDecoded) {
752 int rowsWrittenToOutput = 0;
753 while (rowsWrittenToOutput < rowsNeeded && srcRow < fLinesDecoded) {
754 png_bytep src = SkTAddOffset<png_byte>(fInterlaceBuffer.
get(), fPng_rowbytes * srcRow);
756 dst = SkTAddOffset<void>(dst, fRowBytes);
758 rowsWrittenToOutput++;
762 if (success && fInterlacedComplete) {
767 *rowsDecoded = rowsWrittenToOutput;
772 void setUpInterlaceBuffer(
int height) {
775 fInterlacedComplete =
false;
797 png_structp* png_ptrp, png_infop* info_ptrp) {
799 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
nullptr,
805#ifdef PNG_SET_OPTION_SUPPORTED
808 png_set_option(png_ptr, PNG_MAXIMUM_INFLATE_WINDOW, PNG_OPTION_ON);
811 AutoCleanPng autoClean(png_ptr, stream, chunkReader, outCodec);
813 png_infop info_ptr = png_create_info_struct(png_ptr);
814 if (info_ptr ==
nullptr) {
824#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
829 png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, (png_const_bytep)
"", 0);
830 png_set_read_user_chunk_fn(png_ptr, (png_voidp) chunkReader, sk_read_user_chunk);
836 if (!decodedBounds) {
845 *info_ptrp = info_ptr;
855void AutoCleanPng::infoCallback(
size_t idatLength) {
856 png_uint_32 origWidth, origHeight;
857 int bitDepth, encodedColorType;
858 png_get_IHDR(fPng_ptr, fInfo_ptr, &origWidth, &origHeight, &bitDepth,
859 &encodedColorType,
nullptr,
nullptr,
nullptr);
862 if (bitDepth == 16 && (PNG_COLOR_TYPE_GRAY == encodedColorType ||
863 PNG_COLOR_TYPE_GRAY_ALPHA == encodedColorType)) {
865 png_set_strip_16(fPng_ptr);
873 switch (encodedColorType) {
874 case PNG_COLOR_TYPE_PALETTE:
880 png_set_packing(fPng_ptr);
885 alpha = png_get_valid(fPng_ptr, fInfo_ptr, PNG_INFO_tRNS) ?
888 case PNG_COLOR_TYPE_RGB:
889 if (png_get_valid(fPng_ptr, fInfo_ptr, PNG_INFO_tRNS)) {
891 png_set_tRNS_to_alpha(fPng_ptr);
899 case PNG_COLOR_TYPE_GRAY:
904 png_set_expand_gray_1_2_4_to_8(fPng_ptr);
907 if (png_get_valid(fPng_ptr, fInfo_ptr, PNG_INFO_tRNS)) {
908 png_set_tRNS_to_alpha(fPng_ptr);
916 case PNG_COLOR_TYPE_GRAY_ALPHA:
920 case PNG_COLOR_TYPE_RGBA:
931 const int numberPasses = png_set_interlace_handling(fPng_ptr);
937 switch (
profile->profile()->data_color_space) {
953 switch (encodedColorType) {
954 case PNG_COLOR_TYPE_GRAY_ALPHA:{
955 png_color_8p sigBits;
956 if (png_get_sBIT(fPng_ptr, fInfo_ptr, &sigBits)) {
963 case PNG_COLOR_TYPE_RGB:{
964 png_color_8p sigBits;
965 if (png_get_sBIT(fPng_ptr, fInfo_ptr, &sigBits)) {
966 if (5 == sigBits->red && 6 == sigBits->green && 5 == sigBits->blue) {
975#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
976 if (encodedColorType != PNG_COLOR_TYPE_GRAY_ALPHA
978 png_color_8p sigBits;
979 if (png_get_sBIT(fPng_ptr, fInfo_ptr, &sigBits)) {
980 if (5 == sigBits->red && 6 == sigBits->green && 5 == sigBits->blue) {
981 SkAndroidFrameworkUtils::SafetyNetLog(
"190188264");
988 bitDepth, std::move(profile));
989 if (1 == numberPasses) {
991 std::unique_ptr<SkStream>(fStream), fChunkReader, fPng_ptr, fInfo_ptr, bitDepth);
994 std::unique_ptr<SkStream>(fStream), fChunkReader, fPng_ptr, fInfo_ptr, bitDepth,
1002 this->releasePngPtrs();
1006 SkPngChunkReader* chunkReader,
void* png_ptr,
void* info_ptr,
int bitDepth)
1008 , fPngChunkReader(
SkSafeRef(chunkReader))
1010 , fInfo_ptr(info_ptr)
1011 , fColorXformSrcRow(nullptr)
1012 , fBitDepth(bitDepth)
1014 , fDecodedIdat(false)
1018 this->destroyReadStruct();
1021void SkPngCodec::destroyReadStruct() {
1025 png_destroy_read_struct((png_struct**)&
fPng_ptr, (png_info**)&
fInfo_ptr,
nullptr);
1048 bool skipFormatConversion =
false;
1063 fXformMode = kColorOnly_XformMode;
1068 if (!this->createColorTable(
dstInfo)) {
1073 this->initializeSwizzler(
dstInfo,
options, skipFormatConversion);
1078 switch (fXformMode) {
1079 case kColorOnly_XformMode:
1082 case kSwizzleColor_XformMode:
1090void SkPngCodec::initializeSwizzler(
const SkImageInfo& dstInfo,
const Options&
options,
1091 bool skipFormatConversion) {
1093 Options swizzlerOptions =
options;
1094 fXformMode = kSwizzleOnly_XformMode;
1105 fXformMode = kSwizzleColor_XformMode;
1113 if (skipFormatConversion) {
1146 this->initializeSwizzler(this->
dstInfo(), this->
options(),
true);
1156 this->destroyReadStruct();
1167 fDecodedIdat =
false;
1183 this->allocateStorage(
dstInfo);
1195 this->allocateStorage(
dstInfo);
1197 int firstRow, lastRow;
1205 this->
setRange(firstRow, lastRow, dst, rowBytes);
1213 return this->
decode(rowsDecoded);
1230 return std::unique_ptr<SkCodec>(outCodec);
1234bool IsPng(
const void* data,
size_t len) {
1238std::unique_ptr<SkCodec>
Decode(std::unique_ptr<SkStream> stream,
1240 SkCodecs::DecodeContext ctx) {
1243 outResult = &resultStorage;
1254 SkCodecs::DecodeContext ctx) {
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
uint32_t(* PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
static PackColorProc choose_pack_color_proc(bool isPremul, SkColorType colorType)
static const SkPMColor * get_color_ptr(SkColorPalette *colorTable)
static int get_scaled_dimension(int srcDimension, int sampleSize)
#define SkCodecPrintf(...)
static bool is_rgba(SkColorType colorType)
static int get_start_coord(int sampleFactor)
@ kGray_8_SkColorType
pixel with grayscale level in 8-bit byte
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
constexpr SkColor SK_ColorBLACK
static bool read(SkStream *stream, void *buffer, size_t amount)
static void sk_error_fn(png_structp png_ptr, png_const_charp msg)
static SkCodec::Result log_and_return_error(bool success)
static bool process_data(png_structp png_ptr, png_infop info_ptr, SkStream *stream, void *buffer, size_t bufferSize, size_t length)
constexpr int kSetJmpOkay
constexpr int kStopDecoding
void sk_warning_fn(png_structp, png_const_charp msg)
static SkCodec::Result read_header(SkStream *stream, SkPngChunkReader *chunkReader, SkCodec **outCodec, png_structp *png_ptrp, png_infop *info_ptrp)
std::unique_ptr< SkEncodedInfo::ICCProfile > read_color_profile(png_structp png_ptr, png_infop info_ptr)
static constexpr SkColorType kXformSrcColorType
static bool is_chunk(const png_byte *chunk, const char *tag)
static bool needs_premul(SkAlphaType dstAT, SkEncodedInfo::Alpha encodedAlpha)
static skcms_PixelFormat png_select_xform_format(const SkEncodedInfo &info)
static constexpr int kGraySigBit_GrayAlphaIsJustAlpha
static T * SkSafeRef(T *obj)
static const size_t kBufferSize
AutoCleanPng(png_structp png_ptr, SkStream *stream, SkPngChunkReader *reader, SkCodec **codecPtr)
void setInfoPtr(png_infop info_ptr)
SkISize dimensions() const
const SkImageInfo & dstInfo() const
bool xformOnDecode() const
void applyColorXform(void *dst, const void *src, int count) const
const SkEncodedInfo & getEncodedInfo() const
const Options & options() const
static sk_sp< SkData > MakeWithCopy(const void *data, size_t length)
static std::unique_ptr< ICCProfile > Make(sk_sp< SkData >)
static std::unique_ptr< SkMemoryStream > Make(sk_sp< SkData > data)
virtual bool readChunk(const char tag[], const void *data, size_t length)=0
SkPngCodec(SkEncodedInfo &&, std::unique_ptr< SkStream >, SkPngChunkReader *, void *png_ptr, void *info_ptr, int bitDepth)
void applyXformRow(void *dst, const void *src)
SkSampler * getSampler(bool createIfNecessary) override
skia_private::AutoTMalloc< uint8_t > fStorage
static std::unique_ptr< SkCodec > MakeFromStream(std::unique_ptr< SkStream >, Result *, SkPngChunkReader *=nullptr)
virtual Result decode(int *rowsDecoded)=0
Result onGetPixels(const SkImageInfo &, void *, size_t, const Options &, int *) override
Result onStartIncrementalDecode(const SkImageInfo &dstInfo, void *pixels, size_t rowBytes, const SkCodec::Options &) override
virtual Result decodeAllRows(void *dst, size_t rowBytes, int *rowsDecoded)=0
void initializeXformParams()
Result onIncrementalDecode(int *) override
std::unique_ptr< SkSwizzler > fSwizzler
sk_sp< SkPngChunkReader > fPngChunkReader
virtual void setRange(int firstRow, int lastRow, void *dst, size_t rowBytes)=0
sk_sp< SkColorPalette > fColorTable
static bool IsPng(const void *, size_t)
void setIdatLength(size_t len)
void setRange(int firstRow, int lastRow, void *dst, size_t rowBytes) override
Result decode(int *rowsDecoded) override
static void InterlacedRowCallback(png_structp png_ptr, png_bytep row, png_uint_32 rowNum, int pass)
SkPngInterlacedDecoder(SkEncodedInfo &&info, std::unique_ptr< SkStream > stream, SkPngChunkReader *reader, png_structp png_ptr, png_infop info_ptr, int bitDepth, int numberPasses)
Result decodeAllRows(void *dst, size_t rowBytes, int *rowsDecoded) override
SkPngNormalDecoder(SkEncodedInfo &&info, std::unique_ptr< SkStream > stream, SkPngChunkReader *reader, png_structp png_ptr, png_infop info_ptr, int bitDepth)
static void RowCallback(png_structp png_ptr, png_bytep row, png_uint_32 rowNum, int)
Result decodeAllRows(void *dst, size_t rowBytes, int *rowsDecoded) override
static void AllRowsCallback(png_structp png_ptr, png_bytep row, png_uint_32 rowNum, int)
Result decode(int *rowsDecoded) override
void setRange(int firstRow, int lastRow, void *dst, size_t rowBytes) override
virtual size_t read(void *buffer, size_t size)=0
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)
void reset(T *ptr=nullptr)
T * reset(size_t count=0)
static const uint8_t buffer[]
Swizzle_8888_u8 RGB_to_RGB1
Swizzle_8888_u8 RGB_to_BGR1
void(* memset32)(uint32_t[], uint32_t, int)
SK_API std::unique_ptr< SkCodec > Decode(std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
SK_API bool IsPng(const void *, size_t)
PODArray< SkColor > colors
bool skcms_PrimariesToXYZD50(float rx, float ry, float gx, float gy, float bx, float by, float wx, float wy, skcms_Matrix3x3 *toXYZD50)
const skcms_ICCProfile * skcms_sRGB_profile()
const skcms_TransferFunction * skcms_sRGB_TransferFunction()
@ skcms_PixelFormat_RGBA_16161616BE
@ skcms_PixelFormat_RGBA_8888
@ skcms_PixelFormat_RGB_161616BE
static void skcms_SetXYZD50(skcms_ICCProfile *p, const skcms_Matrix3x3 *m)
static void skcms_SetTransferFunction(skcms_ICCProfile *p, const skcms_TransferFunction *tf)
static void skcms_Init(skcms_ICCProfile *p)
uint8_t bitsPerPixel() const
uint8_t bitsPerComponent() const
static SkEncodedInfo Make(int width, int height, Color color, Alpha alpha, int bitsPerComponent)
constexpr int32_t top() const
constexpr int32_t bottom() const
constexpr int32_t height() const
SkImageInfo makeAlphaType(SkAlphaType newAlphaType) const
SkAlphaType alphaType() const
SkColorType colorType() const
SkImageInfo makeColorType(SkColorType newColorType) const