1/* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SkBitmap.h" 9#include "SkCodecPriv.h" 10#include "SkColorData.h" 11#include "SkColorSpace.h" 12#include "SkColorSpacePriv.h" 13#include "SkColorTable.h" 14#include "SkMath.h" 15#include "SkOpts.h" 16#include "SkPngCodec.h" 17#include "SkPngPriv.h" 18#include "SkPoint3.h" 19#include "SkSize.h" 20#include "SkStream.h" 21#include "SkSwizzler.h" 22#include "SkTemplates.h" 23#include "SkUtils.h" 24 25#include "png.h" 26#include <algorithm> 27 28// This warning triggers false postives way too often in here. 29#if defined(__GNUC__) && !defined(__clang__) 30 #pragma GCC diagnostic ignored "-Wclobbered" 31#endif 32 33// FIXME (scroggo): We can use png_jumpbuf directly once Google3 is on 1.6 34#define PNG_JMPBUF(x) png_jmpbuf((png_structp) x) 35 36/////////////////////////////////////////////////////////////////////////////// 37// Callback functions 38/////////////////////////////////////////////////////////////////////////////// 39 40// When setjmp is first called, it returns 0, meaning longjmp was not called. 41constexpr int kSetJmpOkay = 0; 42// An error internal to libpng. 43constexpr int kPngError = 1; 44// Passed to longjmp when we have decoded as many lines as we need. 45constexpr int kStopDecoding = 2; 46 47static void sk_error_fn(png_structp png_ptr, png_const_charp msg) { 48 SkCodecPrintf("------ png error %s\n", msg); 49 longjmp(PNG_JMPBUF(png_ptr), kPngError); 50} 51 52void sk_warning_fn(png_structp, png_const_charp msg) { 53 SkCodecPrintf("----- png warning %s\n", msg); 54} 55 56#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED 57static int sk_read_user_chunk(png_structp png_ptr, png_unknown_chunkp chunk) { 58 SkPngChunkReader* chunkReader = (SkPngChunkReader*)png_get_user_chunk_ptr(png_ptr); 59 // readChunk() returning true means continue decoding 60 return chunkReader->readChunk((const char*)chunk->name, chunk->data, chunk->size) ? 1 : -1; 61} 62#endif 63 64/////////////////////////////////////////////////////////////////////////////// 65// Helpers 66/////////////////////////////////////////////////////////////////////////////// 67 68class AutoCleanPng : public SkNoncopyable { 69public: 70 /* 71 * This class does not take ownership of stream or reader, but if codecPtr 72 * is non-NULL, and decodeBounds succeeds, it will have created a new 73 * SkCodec (pointed to by *codecPtr) which will own/ref them, as well as 74 * the png_ptr and info_ptr. 75 */ 76 AutoCleanPng(png_structp png_ptr, SkStream* stream, SkPngChunkReader* reader, 77 SkCodec** codecPtr) 78 : fPng_ptr(png_ptr) 79 , fInfo_ptr(nullptr) 80 , fStream(stream) 81 , fChunkReader(reader) 82 , fOutCodec(codecPtr) 83 {} 84 85 ~AutoCleanPng() { 86 // fInfo_ptr will never be non-nullptr unless fPng_ptr is. 87 if (fPng_ptr) { 88 png_infopp info_pp = fInfo_ptr ? &fInfo_ptr : nullptr; 89 png_destroy_read_struct(&fPng_ptr, info_pp, nullptr); 90 } 91 } 92 93 void setInfoPtr(png_infop info_ptr) { 94 SkASSERT(nullptr == fInfo_ptr); 95 fInfo_ptr = info_ptr; 96 } 97 98 /** 99 * Reads enough of the input stream to decode the bounds. 100 * @return false if the stream is not a valid PNG (or too short). 101 * true if it read enough of the stream to determine the bounds. 102 * In the latter case, the stream may have been read beyond the 103 * point to determine the bounds, and the png_ptr will have saved 104 * any extra data. Further, if the codecPtr supplied to the 105 * constructor was not NULL, it will now point to a new SkCodec, 106 * which owns (or refs, in the case of the SkPngChunkReader) the 107 * inputs. If codecPtr was NULL, the png_ptr and info_ptr are 108 * unowned, and it is up to the caller to destroy them. 109 */ 110 bool decodeBounds(); 111 112private: 113 png_structp fPng_ptr; 114 png_infop fInfo_ptr; 115 SkStream* fStream; 116 SkPngChunkReader* fChunkReader; 117 SkCodec** fOutCodec; 118 119 void infoCallback(size_t idatLength); 120 121 void releasePngPtrs() { 122 fPng_ptr = nullptr; 123 fInfo_ptr = nullptr; 124 } 125}; 126#define AutoCleanPng(...) SK_REQUIRE_LOCAL_VAR(AutoCleanPng) 127 128static inline bool is_chunk(const png_byte* chunk, const char* tag) { 129 return memcmp(chunk + 4, tag, 4) == 0; 130} 131 132static inline bool process_data(png_structp png_ptr, png_infop info_ptr, 133 SkStream* stream, void* buffer, size_t bufferSize, size_t length) { 134 while (length > 0) { 135 const size_t bytesToProcess = std::min(bufferSize, length); 136 const size_t bytesRead = stream->read(buffer, bytesToProcess); 137 png_process_data(png_ptr, info_ptr, (png_bytep) buffer, bytesRead); 138 if (bytesRead < bytesToProcess) { 139 return false; 140 } 141 length -= bytesToProcess; 142 } 143 return true; 144} 145 146bool AutoCleanPng::decodeBounds() { 147 if (setjmp(PNG_JMPBUF(fPng_ptr))) { 148 return false; 149 } 150 151 png_set_progressive_read_fn(fPng_ptr, nullptr, nullptr, nullptr, nullptr); 152 153 // Arbitrary buffer size, though note that it matches (below) 154 // SkPngCodec::processData(). FIXME: Can we better suit this to the size of 155 // the PNG header? 156 constexpr size_t kBufferSize = 4096; 157 char buffer[kBufferSize]; 158 159 { 160 // Parse the signature. 161 if (fStream->read(buffer, 8) < 8) { 162 return false; 163 } 164 165 png_process_data(fPng_ptr, fInfo_ptr, (png_bytep) buffer, 8); 166 } 167 168 while (true) { 169 // Parse chunk length and type. 170 if (fStream->read(buffer, 8) < 8) { 171 // We have read to the end of the input without decoding bounds. 172 break; 173 } 174 175 png_byte* chunk = reinterpret_cast<png_byte*>(buffer); 176 const size_t length = png_get_uint_32(chunk); 177 178 if (is_chunk(chunk, "IDAT")) { 179 this->infoCallback(length); 180 return true; 181 } 182 183 png_process_data(fPng_ptr, fInfo_ptr, chunk, 8); 184 // Process the full chunk + CRC. 185 if (!process_data(fPng_ptr, fInfo_ptr, fStream, buffer, kBufferSize, length + 4)) { 186 return false; 187 } 188 } 189 190 return false; 191} 192 193bool SkPngCodec::processData() { 194 switch (setjmp(PNG_JMPBUF(fPng_ptr))) { 195 case kPngError: 196 // There was an error. Stop processing data. 197 // FIXME: Do we need to discard png_ptr? 198 return false;; 199 case kStopDecoding: 200 // We decoded all the lines we want. 201 return true; 202 case kSetJmpOkay: 203 // Everything is okay. 204 break; 205 default: 206 // No other values should be passed to longjmp. 207 SkASSERT(false); 208 } 209 210 // Arbitrary buffer size 211 constexpr size_t kBufferSize = 4096; 212 char buffer[kBufferSize]; 213 214 bool iend = false; 215 while (true) { 216 size_t length; 217 if (fDecodedIdat) { 218 // Parse chunk length and type. 219 if (this->stream()->read(buffer, 8) < 8) { 220 break; 221 } 222 223 png_byte* chunk = reinterpret_cast<png_byte*>(buffer); 224 png_process_data(fPng_ptr, fInfo_ptr, chunk, 8); 225 if (is_chunk(chunk, "IEND")) { 226 iend = true; 227 } 228 229 length = png_get_uint_32(chunk); 230 } else { 231 length = fIdatLength; 232 png_byte idat[] = {0, 0, 0, 0, 'I', 'D', 'A', 'T'}; 233 png_save_uint_32(idat, length); 234 png_process_data(fPng_ptr, fInfo_ptr, idat, 8); 235 fDecodedIdat = true; 236 } 237 238 // Process the full chunk + CRC. 239 if (!process_data(fPng_ptr, fInfo_ptr, this->stream(), buffer, kBufferSize, length + 4) 240 || iend) { 241 break; 242 } 243 } 244 245 return true; 246} 247 248static constexpr SkColorType kXformSrcColorType = kRGBA_8888_SkColorType; 249 250// Note: SkColorTable claims to store SkPMColors, which is not necessarily the case here. 251bool SkPngCodec::createColorTable(const SkImageInfo& dstInfo) { 252 253 int numColors; 254 png_color* palette; 255 if (!png_get_PLTE(fPng_ptr, fInfo_ptr, &palette, &numColors)) { 256 return false; 257 } 258 259 // Contents depend on tableColorType and our choice of if/when to premultiply: 260 // { kPremul, kUnpremul, kOpaque } x { RGBA, BGRA } 261 SkPMColor colorTable[256]; 262 SkColorType tableColorType = this->colorXform() ? kXformSrcColorType : dstInfo.colorType(); 263 264 png_bytep alphas; 265 int numColorsWithAlpha = 0; 266 if (png_get_tRNS(fPng_ptr, fInfo_ptr, &alphas, &numColorsWithAlpha, nullptr)) { 267 // If we are performing a color xform, it will handle the premultiply. Otherwise, 268 // we'll do it here. 269 bool premultiply = !this->colorXform() && needs_premul(dstInfo.alphaType(), 270 this->getEncodedInfo().alpha()); 271 272 // Choose which function to use to create the color table. If the final destination's 273 // colortype is unpremultiplied, the color table will store unpremultiplied colors. 274 PackColorProc proc = choose_pack_color_proc(premultiply, tableColorType); 275 276 for (int i = 0; i < numColorsWithAlpha; i++) { 277 // We don't have a function in SkOpts that combines a set of alphas with a set 278 // of RGBs. We could write one, but it's hardly worth it, given that this 279 // is such a small fraction of the total decode time. 280 colorTable[i] = proc(alphas[i], palette->red, palette->green, palette->blue); 281 palette++; 282 } 283 } 284 285 if (numColorsWithAlpha < numColors) { 286 // The optimized code depends on a 3-byte png_color struct with the colors 287 // in RGB order. These checks make sure it is safe to use. 288 static_assert(3 == sizeof(png_color), "png_color struct has changed. Opts are broken."); 289#ifdef SK_DEBUG 290 SkASSERT(&palette->red < &palette->green); 291 SkASSERT(&palette->green < &palette->blue); 292#endif 293 294 if (is_rgba(tableColorType)) { 295 SkOpts::RGB_to_RGB1(colorTable + numColorsWithAlpha, palette, 296 numColors - numColorsWithAlpha); 297 } else { 298 SkOpts::RGB_to_BGR1(colorTable + numColorsWithAlpha, palette, 299 numColors - numColorsWithAlpha); 300 } 301 } 302 303 if (this->colorXform() && !this->xformOnDecode()) { 304 this->applyColorXform(colorTable, colorTable, numColors); 305 } 306 307 // Pad the color table with the last color in the table (or black) in the case that 308 // invalid pixel indices exceed the number of colors in the table. 309 const int maxColors = 1 << fBitDepth; 310 if (numColors < maxColors) { 311 SkPMColor lastColor = numColors > 0 ? colorTable[numColors - 1] : SK_ColorBLACK; 312 sk_memset32(colorTable + numColors, lastColor, maxColors - numColors); 313 } 314 315 fColorTable.reset(new SkColorTable(colorTable, maxColors)); 316 return true; 317} 318 319/////////////////////////////////////////////////////////////////////////////// 320// Creation 321/////////////////////////////////////////////////////////////////////////////// 322 323bool SkPngCodec::IsPng(const char* buf, size_t bytesRead) { 324 return !png_sig_cmp((png_bytep) buf, (png_size_t)0, bytesRead); 325} 326 327#if (PNG_LIBPNG_VER_MAJOR > 1) || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 6) 328 329static float png_fixed_point_to_float(png_fixed_point x) { 330 // We multiply by the same factor that libpng used to convert 331 // fixed point -> double. Since we want floats, we choose to 332 // do the conversion ourselves rather than convert 333 // fixed point -> double -> float. 334 return ((float) x) * 0.00001f; 335} 336 337static float png_inverted_fixed_point_to_float(png_fixed_point x) { 338 // This is necessary because the gAMA chunk actually stores 1/gamma. 339 return 1.0f / png_fixed_point_to_float(x); 340} 341 342#endif // LIBPNG >= 1.6 343 344// Returns a colorSpace object that represents any color space information in 345// the encoded data. If the encoded data contains an invalid/unsupported color space, 346// this will return NULL. If there is no color space information, it will guess sRGB 347sk_sp<SkColorSpace> read_color_space(png_structp png_ptr, png_infop info_ptr) { 348 349#if (PNG_LIBPNG_VER_MAJOR > 1) || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 6) 350 351 // First check for an ICC profile 352 png_bytep profile; 353 png_uint_32 length; 354 // The below variables are unused, however, we need to pass them in anyway or 355 // png_get_iCCP() will return nothing. 356 // Could knowing the |name| of the profile ever be interesting? Maybe for debugging? 357 png_charp name; 358 // The |compression| is uninteresting since: 359 // (1) libpng has already decompressed the profile for us. 360 // (2) "deflate" is the only mode of decompression that libpng supports. 361 int compression; 362 if (PNG_INFO_iCCP == png_get_iCCP(png_ptr, info_ptr, &name, &compression, &profile, 363 &length)) { 364 return SkColorSpace::MakeICC(profile, length); 365 } 366 367 // Second, check for sRGB. 368 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sRGB)) { 369 370 // sRGB chunks also store a rendering intent: Absolute, Relative, 371 // Perceptual, and Saturation. 372 // FIXME (msarett): Extract this information from the sRGB chunk once 373 // we are able to handle this information in 374 // SkColorSpace. 375 return SkColorSpace::MakeSRGB(); 376 } 377 378 // Next, check for chromaticities. 379 png_fixed_point chrm[8]; 380 png_fixed_point gamma; 381 if (png_get_cHRM_fixed(png_ptr, info_ptr, &chrm[0], &chrm[1], &chrm[2], &chrm[3], &chrm[4], 382 &chrm[5], &chrm[6], &chrm[7])) 383 { 384 SkColorSpacePrimaries primaries; 385 primaries.fRX = png_fixed_point_to_float(chrm[2]); 386 primaries.fRY = png_fixed_point_to_float(chrm[3]); 387 primaries.fGX = png_fixed_point_to_float(chrm[4]); 388 primaries.fGY = png_fixed_point_to_float(chrm[5]); 389 primaries.fBX = png_fixed_point_to_float(chrm[6]); 390 primaries.fBY = png_fixed_point_to_float(chrm[7]); 391 primaries.fWX = png_fixed_point_to_float(chrm[0]); 392 primaries.fWY = png_fixed_point_to_float(chrm[1]); 393 394 SkMatrix44 toXYZD50(SkMatrix44::kUninitialized_Constructor); 395 if (!primaries.toXYZD50(&toXYZD50)) { 396 toXYZD50.set3x3RowMajorf(gSRGB_toXYZD50); 397 } 398 399 if (PNG_INFO_gAMA == png_get_gAMA_fixed(png_ptr, info_ptr, &gamma)) { 400 SkColorSpaceTransferFn fn; 401 fn.fA = 1.0f; 402 fn.fB = fn.fC = fn.fD = fn.fE = fn.fF = 0.0f; 403 fn.fG = png_inverted_fixed_point_to_float(gamma); 404 405 return SkColorSpace::MakeRGB(fn, toXYZD50); 406 } 407 408 // Default to sRGB gamma if the image has color space information, 409 // but does not specify gamma. 410 return SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma, toXYZD50); 411 } 412 413 // Last, check for gamma. 414 if (PNG_INFO_gAMA == png_get_gAMA_fixed(png_ptr, info_ptr, &gamma)) { 415 SkColorSpaceTransferFn fn; 416 fn.fA = 1.0f; 417 fn.fB = fn.fC = fn.fD = fn.fE = fn.fF = 0.0f; 418 fn.fG = png_inverted_fixed_point_to_float(gamma); 419 420 // Since there is no cHRM, we will guess sRGB gamut. 421 SkMatrix44 toXYZD50(SkMatrix44::kUninitialized_Constructor); 422 toXYZD50.set3x3RowMajorf(gSRGB_toXYZD50); 423 424 return SkColorSpace::MakeRGB(fn, toXYZD50); 425 } 426 427#endif // LIBPNG >= 1.6 428 429 // Report that there is no color space information in the PNG. 430 // Guess sRGB in this case. 431 return SkColorSpace::MakeSRGB(); 432} 433 434void SkPngCodec::allocateStorage(const SkImageInfo& dstInfo) { 435 switch (fXformMode) { 436 case kSwizzleOnly_XformMode: 437 break; 438 case kColorOnly_XformMode: 439 // Intentional fall through. A swizzler hasn't been created yet, but one will 440 // be created later if we are sampling. We'll go ahead and allocate 441 // enough memory to swizzle if necessary. 442 case kSwizzleColor_XformMode: { 443 const int bitsPerPixel = this->getEncodedInfo().bitsPerPixel(); 444 445 // If we have more than 8-bits (per component) of precision, we will keep that 446 // extra precision. Otherwise, we will swizzle to RGBA_8888 before transforming. 447 const size_t bytesPerPixel = (bitsPerPixel > 32) ? bitsPerPixel / 8 : 4; 448 const size_t colorXformBytes = dstInfo.width() * bytesPerPixel; 449 fStorage.reset(colorXformBytes); 450 fColorXformSrcRow = fStorage.get(); 451 break; 452 } 453 } 454} 455 456static SkColorSpaceXform::ColorFormat png_select_xform_format(const SkEncodedInfo& info) { 457 // We use kRGB and kRGBA formats because color PNGs are always RGB or RGBA. 458 if (16 == info.bitsPerComponent()) { 459 if (SkEncodedInfo::kRGBA_Color == info.color()) { 460 return SkColorSpaceXform::kRGBA_U16_BE_ColorFormat; 461 } else if (SkEncodedInfo::kRGB_Color == info.color()) { 462 return SkColorSpaceXform::kRGB_U16_BE_ColorFormat; 463 } 464 } 465 466 return SkColorSpaceXform::kRGBA_8888_ColorFormat; 467} 468 469void SkPngCodec::applyXformRow(void* dst, const void* src) { 470 switch (fXformMode) { 471 case kSwizzleOnly_XformMode: 472 fSwizzler->swizzle(dst, (const uint8_t*) src); 473 break; 474 case kColorOnly_XformMode: 475 this->applyColorXform(dst, src, fXformWidth); 476 break; 477 case kSwizzleColor_XformMode: 478 fSwizzler->swizzle(fColorXformSrcRow, (const uint8_t*) src); 479 this->applyColorXform(dst, fColorXformSrcRow, fXformWidth); 480 break; 481 } 482} 483 484class SkPngNormalDecoder : public SkPngCodec { 485public: 486 SkPngNormalDecoder(const SkEncodedInfo& info, const SkImageInfo& imageInfo, 487 std::unique_ptr<SkStream> stream, SkPngChunkReader* reader, 488 png_structp png_ptr, png_infop info_ptr, int bitDepth) 489 : INHERITED(info, imageInfo, std::move(stream), reader, png_ptr, info_ptr, bitDepth) 490 , fRowsWrittenToOutput(0) 491 , fDst(nullptr) 492 , fRowBytes(0) 493 , fFirstRow(0) 494 , fLastRow(0) 495 {} 496 497 static void AllRowsCallback(png_structp png_ptr, png_bytep row, png_uint_32 rowNum, int /*pass*/) { 498 GetDecoder(png_ptr)->allRowsCallback(row, rowNum); 499 } 500 501 static void RowCallback(png_structp png_ptr, png_bytep row, png_uint_32 rowNum, int /*pass*/) { 502 GetDecoder(png_ptr)->rowCallback(row, rowNum); 503 } 504 505private: 506 int fRowsWrittenToOutput; 507 void* fDst; 508 size_t fRowBytes; 509 510 // Variables for partial decode 511 int fFirstRow; // FIXME: Move to baseclass? 512 int fLastRow; 513 int fRowsNeeded; 514 515 typedef SkPngCodec INHERITED; 516 517 static SkPngNormalDecoder* GetDecoder(png_structp png_ptr) { 518 return static_cast<SkPngNormalDecoder*>(png_get_progressive_ptr(png_ptr)); 519 } 520 521 Result decodeAllRows(void* dst, size_t rowBytes, int* rowsDecoded) override { 522 const int height = this->getInfo().height(); 523 png_set_progressive_read_fn(this->png_ptr(), this, nullptr, AllRowsCallback, nullptr); 524 fDst = dst; 525 fRowBytes = rowBytes; 526 527 fRowsWrittenToOutput = 0; 528 fFirstRow = 0; 529 fLastRow = height - 1; 530 531 if (!this->processData()) { 532 return kErrorInInput; 533 } 534 535 if (fRowsWrittenToOutput == height) { 536 return SkCodec::kSuccess; 537 } 538 539 if (rowsDecoded) { 540 *rowsDecoded = fRowsWrittenToOutput; 541 } 542 543 return SkCodec::kIncompleteInput; 544 } 545 546 void allRowsCallback(png_bytep row, int rowNum) { 547 SkASSERT(rowNum == fRowsWrittenToOutput); 548 fRowsWrittenToOutput++; 549 this->applyXformRow(fDst, row); 550 fDst = SkTAddOffset<void>(fDst, fRowBytes); 551 } 552 553 void setRange(int firstRow, int lastRow, void* dst, size_t rowBytes) override { 554 png_set_progressive_read_fn(this->png_ptr(), this, nullptr, RowCallback, nullptr); 555 fFirstRow = firstRow; 556 fLastRow = lastRow; 557 fDst = dst; 558 fRowBytes = rowBytes; 559 fRowsWrittenToOutput = 0; 560 fRowsNeeded = fLastRow - fFirstRow + 1; 561 } 562 563 SkCodec::Result decode(int* rowsDecoded) override { 564 if (this->swizzler()) { 565 const int sampleY = this->swizzler()->sampleY(); 566 fRowsNeeded = get_scaled_dimension(fLastRow - fFirstRow + 1, sampleY); 567 } 568 569 if (!this->processData()) { 570 return kErrorInInput; 571 } 572 573 if (fRowsWrittenToOutput == fRowsNeeded) { 574 return SkCodec::kSuccess; 575 } 576 577 if (rowsDecoded) { 578 *rowsDecoded = fRowsWrittenToOutput; 579 } 580 581 return SkCodec::kIncompleteInput; 582 } 583 584 void rowCallback(png_bytep row, int rowNum) { 585 if (rowNum < fFirstRow) { 586 // Ignore this row. 587 return; 588 } 589 590 SkASSERT(rowNum <= fLastRow); 591 SkASSERT(fRowsWrittenToOutput < fRowsNeeded); 592 593 // If there is no swizzler, all rows are needed. 594 if (!this->swizzler() || this->swizzler()->rowNeeded(rowNum - fFirstRow)) { 595 this->applyXformRow(fDst, row); 596 fDst = SkTAddOffset<void>(fDst, fRowBytes); 597 fRowsWrittenToOutput++; 598 } 599 600 if (fRowsWrittenToOutput == fRowsNeeded) { 601 // Fake error to stop decoding scanlines. 602 longjmp(PNG_JMPBUF(this->png_ptr()), kStopDecoding); 603 } 604 } 605}; 606 607class SkPngInterlacedDecoder : public SkPngCodec { 608public: 609 SkPngInterlacedDecoder(const SkEncodedInfo& info, const SkImageInfo& imageInfo, 610 std::unique_ptr<SkStream> stream, SkPngChunkReader* reader, png_structp png_ptr, 611 png_infop info_ptr, int bitDepth, int numberPasses) 612 : INHERITED(info, imageInfo, std::move(stream), reader, png_ptr, info_ptr, bitDepth) 613 , fNumberPasses(numberPasses) 614 , fFirstRow(0) 615 , fLastRow(0) 616 , fLinesDecoded(0) 617 , fInterlacedComplete(false) 618 , fPng_rowbytes(0) 619 {} 620 621 static void InterlacedRowCallback(png_structp png_ptr, png_bytep row, png_uint_32 rowNum, int pass) { 622 auto decoder = static_cast<SkPngInterlacedDecoder*>(png_get_progressive_ptr(png_ptr)); 623 decoder->interlacedRowCallback(row, rowNum, pass); 624 } 625 626private: 627 const int fNumberPasses; 628 int fFirstRow; 629 int fLastRow; 630 void* fDst; 631 size_t fRowBytes; 632 int fLinesDecoded; 633 bool fInterlacedComplete; 634 size_t fPng_rowbytes; 635 SkAutoTMalloc<png_byte> fInterlaceBuffer; 636 637 typedef SkPngCodec INHERITED; 638 639 // FIXME: Currently sharing interlaced callback for all rows and subset. It's not 640 // as expensive as the subset version of non-interlaced, but it still does extra 641 // work. 642 void interlacedRowCallback(png_bytep row, int rowNum, int pass) { 643 if (rowNum < fFirstRow || rowNum > fLastRow || fInterlacedComplete) { 644 // Ignore this row 645 return; 646 } 647 648 png_bytep oldRow = fInterlaceBuffer.get() + (rowNum - fFirstRow) * fPng_rowbytes; 649 png_progressive_combine_row(this->png_ptr(), oldRow, row); 650 651 if (0 == pass) { 652 // The first pass initializes all rows. 653 SkASSERT(row); 654 SkASSERT(fLinesDecoded == rowNum - fFirstRow); 655 fLinesDecoded++; 656 } else { 657 SkASSERT(fLinesDecoded == fLastRow - fFirstRow + 1); 658 if (fNumberPasses - 1 == pass && rowNum == fLastRow) { 659 // Last pass, and we have read all of the rows we care about. 660 fInterlacedComplete = true; 661 if (fLastRow != this->getInfo().height() - 1 || 662 (this->swizzler() && this->swizzler()->sampleY() != 1)) { 663 // Fake error to stop decoding scanlines. Only stop if we're not decoding the 664 // whole image, in which case processing the rest of the image might be 665 // expensive. When decoding the whole image, read through the IEND chunk to 666 // preserve Android behavior of leaving the input stream in the right place. 667 longjmp(PNG_JMPBUF(this->png_ptr()), kStopDecoding); 668 } 669 } 670 } 671 } 672 673 SkCodec::Result decodeAllRows(void* dst, size_t rowBytes, int* rowsDecoded) override { 674 const int height = this->getInfo().height(); 675 this->setUpInterlaceBuffer(height); 676 png_set_progressive_read_fn(this->png_ptr(), this, nullptr, InterlacedRowCallback, 677 nullptr); 678 679 fFirstRow = 0; 680 fLastRow = height - 1; 681 fLinesDecoded = 0; 682 683 if (!this->processData()) { 684 return kErrorInInput; 685 } 686 687 png_bytep srcRow = fInterlaceBuffer.get(); 688 // FIXME: When resuming, this may rewrite rows that did not change. 689 for (int rowNum = 0; rowNum < fLinesDecoded; rowNum++) { 690 this->applyXformRow(dst, srcRow); 691 dst = SkTAddOffset<void>(dst, rowBytes); 692 srcRow = SkTAddOffset<png_byte>(srcRow, fPng_rowbytes); 693 } 694 if (fInterlacedComplete) { 695 return SkCodec::kSuccess; 696 } 697 698 if (rowsDecoded) { 699 *rowsDecoded = fLinesDecoded; 700 } 701 702 return SkCodec::kIncompleteInput; 703 } 704 705 void setRange(int firstRow, int lastRow, void* dst, size_t rowBytes) override { 706 // FIXME: We could skip rows in the interlace buffer that we won't put in the output. 707 this->setUpInterlaceBuffer(lastRow - firstRow + 1); 708 png_set_progressive_read_fn(this->png_ptr(), this, nullptr, InterlacedRowCallback, nullptr); 709 fFirstRow = firstRow; 710 fLastRow = lastRow; 711 fDst = dst; 712 fRowBytes = rowBytes; 713 fLinesDecoded = 0; 714 } 715 716 SkCodec::Result decode(int* rowsDecoded) override { 717 if (this->processData() == false) { 718 return kErrorInInput; 719 } 720 721 // Now apply Xforms on all the rows that were decoded. 722 if (!fLinesDecoded) { 723 if (rowsDecoded) { 724 *rowsDecoded = 0; 725 } 726 return SkCodec::kIncompleteInput; 727 } 728 729 const int sampleY = this->swizzler() ? this->swizzler()->sampleY() : 1; 730 const int rowsNeeded = get_scaled_dimension(fLastRow - fFirstRow + 1, sampleY); 731 int rowsWrittenToOutput = 0; 732 733 // FIXME: For resuming interlace, we may swizzle a row that hasn't changed. But it 734 // may be too tricky/expensive to handle that correctly. 735 736 // Offset srcRow by get_start_coord rows. We do not need to account for fFirstRow, 737 // since the first row in fInterlaceBuffer corresponds to fFirstRow. 738 png_bytep srcRow = SkTAddOffset<png_byte>(fInterlaceBuffer.get(), 739 fPng_rowbytes * get_start_coord(sampleY)); 740 void* dst = fDst; 741 for (; rowsWrittenToOutput < rowsNeeded; rowsWrittenToOutput++) { 742 this->applyXformRow(dst, srcRow); 743 dst = SkTAddOffset<void>(dst, fRowBytes); 744 srcRow = SkTAddOffset<png_byte>(srcRow, fPng_rowbytes * sampleY); 745 } 746 747 if (fInterlacedComplete) { 748 return SkCodec::kSuccess; 749 } 750 751 if (rowsDecoded) { 752 *rowsDecoded = rowsWrittenToOutput; 753 } 754 return SkCodec::kIncompleteInput; 755 } 756 757 void setUpInterlaceBuffer(int height) { 758 fPng_rowbytes = png_get_rowbytes(this->png_ptr(), this->info_ptr()); 759 fInterlaceBuffer.reset(fPng_rowbytes * height); 760 fInterlacedComplete = false; 761 } 762}; 763 764// Reads the header and initializes the output fields, if not NULL. 765// 766// @param stream Input data. Will be read to get enough information to properly 767// setup the codec. 768// @param chunkReader SkPngChunkReader, for reading unknown chunks. May be NULL. 769// If not NULL, png_ptr will hold an *unowned* pointer to it. The caller is 770// expected to continue to own it for the lifetime of the png_ptr. 771// @param outCodec Optional output variable. If non-NULL, will be set to a new 772// SkPngCodec on success. 773// @param png_ptrp Optional output variable. If non-NULL, will be set to a new 774// png_structp on success. 775// @param info_ptrp Optional output variable. If non-NULL, will be set to a new 776// png_infop on success; 777// @return if kSuccess, the caller is responsible for calling 778// png_destroy_read_struct(png_ptrp, info_ptrp). 779// Otherwise, the passed in fields (except stream) are unchanged. 780static SkCodec::Result read_header(SkStream* stream, SkPngChunkReader* chunkReader, 781 SkCodec** outCodec, 782 png_structp* png_ptrp, png_infop* info_ptrp) { 783 // The image is known to be a PNG. Decode enough to know the SkImageInfo. 784 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, 785 sk_error_fn, sk_warning_fn); 786 if (!png_ptr) { 787 return SkCodec::kInternalError; 788 } 789 790#ifdef PNG_SET_OPTION_SUPPORTED 791 // This setting ensures that we display images with incorrect CMF bytes. 792 // See crbug.com/807324. 793 png_set_option(png_ptr, PNG_MAXIMUM_INFLATE_WINDOW, PNG_OPTION_ON); 794#endif 795 796 AutoCleanPng autoClean(png_ptr, stream, chunkReader, outCodec); 797 798 png_infop info_ptr = png_create_info_struct(png_ptr); 799 if (info_ptr == nullptr) { 800 return SkCodec::kInternalError; 801 } 802 803 autoClean.setInfoPtr(info_ptr); 804 805 if (setjmp(PNG_JMPBUF(png_ptr))) { 806 return SkCodec::kInvalidInput; 807 } 808 809#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED 810 // Hookup our chunkReader so we can see any user-chunks the caller may be interested in. 811 // This needs to be installed before we read the png header. Android may store ninepatch 812 // chunks in the header. 813 if (chunkReader) { 814 png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, (png_byte*)"", 0); 815 png_set_read_user_chunk_fn(png_ptr, (png_voidp) chunkReader, sk_read_user_chunk); 816 } 817#endif 818 819 const bool decodedBounds = autoClean.decodeBounds(); 820 821 if (!decodedBounds) { 822 return SkCodec::kIncompleteInput; 823 } 824 825 // On success, decodeBounds releases ownership of png_ptr and info_ptr. 826 if (png_ptrp) { 827 *png_ptrp = png_ptr; 828 } 829 if (info_ptrp) { 830 *info_ptrp = info_ptr; 831 } 832 833 // decodeBounds takes care of setting outCodec 834 if (outCodec) { 835 SkASSERT(*outCodec); 836 } 837 return SkCodec::kSuccess; 838} 839 840void AutoCleanPng::infoCallback(size_t idatLength) { 841 png_uint_32 origWidth, origHeight; 842 int bitDepth, encodedColorType; 843 png_get_IHDR(fPng_ptr, fInfo_ptr, &origWidth, &origHeight, &bitDepth, 844 &encodedColorType, nullptr, nullptr, nullptr); 845 846 // TODO: Should we support 16-bits of precision for gray images? 847 if (bitDepth == 16 && (PNG_COLOR_TYPE_GRAY == encodedColorType || 848 PNG_COLOR_TYPE_GRAY_ALPHA == encodedColorType)) { 849 bitDepth = 8; 850 png_set_strip_16(fPng_ptr); 851 } 852 853 // Now determine the default colorType and alphaType and set the required transforms. 854 // Often, we depend on SkSwizzler to perform any transforms that we need. However, we 855 // still depend on libpng for many of the rare and PNG-specific cases. 856 SkEncodedInfo::Color color; 857 SkEncodedInfo::Alpha alpha; 858 switch (encodedColorType) { 859 case PNG_COLOR_TYPE_PALETTE: 860 // Extract multiple pixels with bit depths of 1, 2, and 4 from a single 861 // byte into separate bytes (useful for paletted and grayscale images). 862 if (bitDepth < 8) { 863 // TODO: Should we use SkSwizzler here? 864 bitDepth = 8; 865 png_set_packing(fPng_ptr); 866 } 867 868 color = SkEncodedInfo::kPalette_Color; 869 // Set the alpha depending on if a transparency chunk exists. 870 alpha = png_get_valid(fPng_ptr, fInfo_ptr, PNG_INFO_tRNS) ? 871 SkEncodedInfo::kUnpremul_Alpha : SkEncodedInfo::kOpaque_Alpha; 872 break; 873 case PNG_COLOR_TYPE_RGB: 874 if (png_get_valid(fPng_ptr, fInfo_ptr, PNG_INFO_tRNS)) { 875 // Convert to RGBA if transparency chunk exists. 876 png_set_tRNS_to_alpha(fPng_ptr); 877 color = SkEncodedInfo::kRGBA_Color; 878 alpha = SkEncodedInfo::kBinary_Alpha; 879 } else { 880 color = SkEncodedInfo::kRGB_Color; 881 alpha = SkEncodedInfo::kOpaque_Alpha; 882 } 883 break; 884 case PNG_COLOR_TYPE_GRAY: 885 // Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel. 886 if (bitDepth < 8) { 887 // TODO: Should we use SkSwizzler here? 888 bitDepth = 8; 889 png_set_expand_gray_1_2_4_to_8(fPng_ptr); 890 } 891 892 if (png_get_valid(fPng_ptr, fInfo_ptr, PNG_INFO_tRNS)) { 893 png_set_tRNS_to_alpha(fPng_ptr); 894 color = SkEncodedInfo::kGrayAlpha_Color; 895 alpha = SkEncodedInfo::kBinary_Alpha; 896 } else { 897 color = SkEncodedInfo::kGray_Color; 898 alpha = SkEncodedInfo::kOpaque_Alpha; 899 } 900 break; 901 case PNG_COLOR_TYPE_GRAY_ALPHA: 902 color = SkEncodedInfo::kGrayAlpha_Color; 903 alpha = SkEncodedInfo::kUnpremul_Alpha; 904 break; 905 case PNG_COLOR_TYPE_RGBA: 906 color = SkEncodedInfo::kRGBA_Color; 907 alpha = SkEncodedInfo::kUnpremul_Alpha; 908 break; 909 default: 910 // All the color types have been covered above. 911 SkASSERT(false); 912 color = SkEncodedInfo::kRGBA_Color; 913 alpha = SkEncodedInfo::kUnpremul_Alpha; 914 } 915 916 const int numberPasses = png_set_interlace_handling(fPng_ptr); 917 918 if (fOutCodec) { 919 SkASSERT(nullptr == *fOutCodec); 920 sk_sp<SkColorSpace> colorSpace = read_color_space(fPng_ptr, fInfo_ptr); 921 if (colorSpace) { 922 switch (colorSpace->type()) { 923 case SkColorSpace::kCMYK_Type: 924 colorSpace = nullptr; 925 break; 926 case SkColorSpace::kGray_Type: 927 if (SkEncodedInfo::kGray_Color != color && 928 SkEncodedInfo::kGrayAlpha_Color != color) 929 { 930 colorSpace = nullptr; 931 } 932 break; 933 case SkColorSpace::kRGB_Type: 934 break; 935 } 936 } 937 if (!colorSpace) { 938 // Treat unsupported/invalid color spaces as sRGB. 939 colorSpace = SkColorSpace::MakeSRGB(); 940 } 941 942 SkEncodedInfo encodedInfo = SkEncodedInfo::Make(color, alpha, bitDepth); 943 SkImageInfo imageInfo = encodedInfo.makeImageInfo(origWidth, origHeight, colorSpace); 944 945 if (encodedColorType == PNG_COLOR_TYPE_GRAY_ALPHA) { 946 png_color_8p sigBits; 947 if (png_get_sBIT(fPng_ptr, fInfo_ptr, &sigBits)) { 948 if (8 == sigBits->alpha && kGraySigBit_GrayAlphaIsJustAlpha == sigBits->gray) { 949 imageInfo = imageInfo.makeColorType(kAlpha_8_SkColorType); 950 } 951 } 952 } else if (SkEncodedInfo::kOpaque_Alpha == alpha) { 953 png_color_8p sigBits; 954 if (png_get_sBIT(fPng_ptr, fInfo_ptr, &sigBits)) { 955 if (5 == sigBits->red && 6 == sigBits->green && 5 == sigBits->blue) { 956 // Recommend a decode to 565 if the sBIT indicates 565. 957 imageInfo = imageInfo.makeColorType(kRGB_565_SkColorType); 958 } 959 } 960 } 961 962 if (1 == numberPasses) { 963 *fOutCodec = new SkPngNormalDecoder(encodedInfo, imageInfo, 964 std::unique_ptr<SkStream>(fStream), fChunkReader, fPng_ptr, fInfo_ptr, bitDepth); 965 } else { 966 *fOutCodec = new SkPngInterlacedDecoder(encodedInfo, imageInfo, 967 std::unique_ptr<SkStream>(fStream), fChunkReader, fPng_ptr, fInfo_ptr, bitDepth, 968 numberPasses); 969 } 970 static_cast<SkPngCodec*>(*fOutCodec)->setIdatLength(idatLength); 971 } 972 973 // Release the pointers, which are now owned by the codec or the caller is expected to 974 // take ownership. 975 this->releasePngPtrs(); 976} 977 978SkPngCodec::SkPngCodec(const SkEncodedInfo& encodedInfo, const SkImageInfo& imageInfo, 979 std::unique_ptr<SkStream> stream, SkPngChunkReader* chunkReader, 980 void* png_ptr, void* info_ptr, int bitDepth) 981 : INHERITED(encodedInfo, imageInfo, png_select_xform_format(encodedInfo), std::move(stream)) 982 , fPngChunkReader(SkSafeRef(chunkReader)) 983 , fPng_ptr(png_ptr) 984 , fInfo_ptr(info_ptr) 985 , fColorXformSrcRow(nullptr) 986 , fBitDepth(bitDepth) 987 , fIdatLength(0) 988 , fDecodedIdat(false) 989{} 990 991SkPngCodec::~SkPngCodec() { 992 this->destroyReadStruct(); 993} 994 995void SkPngCodec::destroyReadStruct() { 996 if (fPng_ptr) { 997 // We will never have a nullptr fInfo_ptr with a non-nullptr fPng_ptr 998 SkASSERT(fInfo_ptr); 999 png_destroy_read_struct((png_struct**)&fPng_ptr, (png_info**)&fInfo_ptr, nullptr); 1000 fPng_ptr = nullptr; 1001 fInfo_ptr = nullptr; 1002 } 1003} 1004 1005/////////////////////////////////////////////////////////////////////////////// 1006// Getting the pixels 1007/////////////////////////////////////////////////////////////////////////////// 1008 1009SkCodec::Result SkPngCodec::initializeXforms(const SkImageInfo& dstInfo, const Options& options) { 1010 if (setjmp(PNG_JMPBUF((png_struct*)fPng_ptr))) { 1011 SkCodecPrintf("Failed on png_read_update_info.\n"); 1012 return kInvalidInput; 1013 } 1014 png_read_update_info(fPng_ptr, fInfo_ptr); 1015 1016 // Reset fSwizzler and this->colorXform(). We can't do this in onRewind() because the 1017 // interlaced scanline decoder may need to rewind. 1018 fSwizzler.reset(nullptr); 1019 1020 // If SkColorSpaceXform directly supports the encoded PNG format, we should skip format 1021 // conversion in the swizzler (or skip swizzling altogether). 1022 bool skipFormatConversion = false; 1023 switch (this->getEncodedInfo().color()) { 1024 case SkEncodedInfo::kRGB_Color: 1025 if (this->getEncodedInfo().bitsPerComponent() != 16) { 1026 break; 1027 } 1028 1029 // Fall through 1030 case SkEncodedInfo::kRGBA_Color: 1031 skipFormatConversion = this->colorXform(); 1032 break; 1033 default: 1034 break; 1035 } 1036 if (skipFormatConversion && !options.fSubset) { 1037 fXformMode = kColorOnly_XformMode; 1038 return kSuccess; 1039 } 1040 1041 if (SkEncodedInfo::kPalette_Color == this->getEncodedInfo().color()) { 1042 if (!this->createColorTable(dstInfo)) { 1043 return kInvalidInput; 1044 } 1045 } 1046 1047 this->initializeSwizzler(dstInfo, options, skipFormatConversion); 1048 return kSuccess; 1049} 1050 1051void SkPngCodec::initializeXformParams() { 1052 switch (fXformMode) { 1053 case kColorOnly_XformMode: 1054 fXformWidth = this->dstInfo().width(); 1055 break; 1056 case kSwizzleColor_XformMode: 1057 fXformWidth = this->swizzler()->swizzleWidth(); 1058 break; 1059 default: 1060 break; 1061 } 1062} 1063 1064void SkPngCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& options, 1065 bool skipFormatConversion) { 1066 SkImageInfo swizzlerInfo = dstInfo; 1067 Options swizzlerOptions = options; 1068 fXformMode = kSwizzleOnly_XformMode; 1069 if (this->colorXform() && this->xformOnDecode()) { 1070 swizzlerInfo = swizzlerInfo.makeColorType(kXformSrcColorType); 1071 if (kPremul_SkAlphaType == dstInfo.alphaType()) { 1072 swizzlerInfo = swizzlerInfo.makeAlphaType(kUnpremul_SkAlphaType); 1073 } 1074 1075 fXformMode = kSwizzleColor_XformMode; 1076 1077 // Here, we swizzle into temporary memory, which is not zero initialized. 1078 // FIXME (msarett): 1079 // Is this a problem? 1080 swizzlerOptions.fZeroInitialized = kNo_ZeroInitialized; 1081 } 1082 1083 const SkPMColor* colors = get_color_ptr(fColorTable.get()); 1084 fSwizzler.reset(SkSwizzler::CreateSwizzler(this->getEncodedInfo(), colors, swizzlerInfo, 1085 swizzlerOptions, nullptr, skipFormatConversion)); 1086 SkASSERT(fSwizzler); 1087} 1088 1089SkSampler* SkPngCodec::getSampler(bool createIfNecessary) { 1090 if (fSwizzler || !createIfNecessary) { 1091 return fSwizzler.get(); 1092 } 1093 1094 this->initializeSwizzler(this->dstInfo(), this->options(), true); 1095 return fSwizzler.get(); 1096} 1097 1098bool SkPngCodec::onRewind() { 1099 // This sets fPng_ptr and fInfo_ptr to nullptr. If read_header 1100 // succeeds, they will be repopulated, and if it fails, they will 1101 // remain nullptr. Any future accesses to fPng_ptr and fInfo_ptr will 1102 // come through this function which will rewind and again attempt 1103 // to reinitialize them. 1104 this->destroyReadStruct(); 1105 1106 png_structp png_ptr; 1107 png_infop info_ptr; 1108 if (kSuccess != read_header(this->stream(), fPngChunkReader.get(), nullptr, 1109 &png_ptr, &info_ptr)) { 1110 return false; 1111 } 1112 1113 fPng_ptr = png_ptr; 1114 fInfo_ptr = info_ptr; 1115 fDecodedIdat = false; 1116 return true; 1117} 1118 1119SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, 1120 size_t rowBytes, const Options& options, 1121 int* rowsDecoded) { 1122 Result result = this->initializeXforms(dstInfo, options); 1123 if (kSuccess != result) { 1124 return result; 1125 } 1126 1127 if (options.fSubset) { 1128 return kUnimplemented; 1129 } 1130 1131 this->allocateStorage(dstInfo); 1132 this->initializeXformParams(); 1133 return this->decodeAllRows(dst, rowBytes, rowsDecoded); 1134} 1135 1136SkCodec::Result SkPngCodec::onStartIncrementalDecode(const SkImageInfo& dstInfo, 1137 void* dst, size_t rowBytes, const SkCodec::Options& options) { 1138 Result result = this->initializeXforms(dstInfo, options); 1139 if (kSuccess != result) { 1140 return result; 1141 } 1142 1143 this->allocateStorage(dstInfo); 1144 1145 int firstRow, lastRow; 1146 if (options.fSubset) { 1147 firstRow = options.fSubset->top(); 1148 lastRow = options.fSubset->bottom() - 1; 1149 } else { 1150 firstRow = 0; 1151 lastRow = dstInfo.height() - 1; 1152 } 1153 this->setRange(firstRow, lastRow, dst, rowBytes); 1154 return kSuccess; 1155} 1156 1157SkCodec::Result SkPngCodec::onIncrementalDecode(int* rowsDecoded) { 1158 // FIXME: Only necessary on the first call. 1159 this->initializeXformParams(); 1160 1161 return this->decode(rowsDecoded); 1162} 1163 1164uint64_t SkPngCodec::onGetFillValue(const SkImageInfo& dstInfo) const { 1165 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 1166 if (colorPtr) { 1167 SkAlphaType alphaType = select_xform_alpha(dstInfo.alphaType(), 1168 this->getInfo().alphaType()); 1169 return get_color_table_fill_value(dstInfo.colorType(), alphaType, colorPtr, 0, 1170 this->colorXform(), true); 1171 } 1172 return INHERITED::onGetFillValue(dstInfo); 1173} 1174 1175std::unique_ptr<SkCodec> SkPngCodec::MakeFromStream(std::unique_ptr<SkStream> stream, 1176 Result* result, SkPngChunkReader* chunkReader) { 1177 SkCodec* outCodec = nullptr; 1178 *result = read_header(stream.get(), chunkReader, &outCodec, nullptr, nullptr); 1179 if (kSuccess == *result) { 1180 // Codec has taken ownership of the stream. 1181 SkASSERT(outCodec); 1182 stream.release(); 1183 } 1184 return std::unique_ptr<SkCodec>(outCodec); 1185} 1186