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,
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:
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;
545 Result decodeAllRows(
void*
dst,
size_t rowBytes,
int* rowsDecoded)
override {
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;
584 Result decode(
int* rowsDecoded)
override {
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;
691 Result decodeAllRows(
void*
dst,
size_t rowBytes,
int* rowsDecoded)
override {
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;
731 Result decode(
int* rowsDecoded)
override {
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);
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");
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;
1213 return this->
decode(rowsDecoded);
1230 return std::unique_ptr<SkCodec>(outCodec);
1243 outResult = &resultStorage;
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)
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)
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)
static void AllRowsCallback(png_structp png_ptr, png_bytep row, png_uint_32 rowNum, int)
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 float min(float r, float g, float b)
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
DEF_SWITCHES_START aot vmservice shared library name
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
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
std::shared_ptr< const fml::Mapping > data