1 2 /* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #include "SkImageDecoder.h" 11 #include "SkImageEncoder.h" 12 #include "SkColor.h" 13 #include "SkColorPriv.h" 14 #include "SkDither.h" 15 #include "SkMath.h" 16 #include "SkScaledBitmapSampler.h" 17 #include "SkStream.h" 18 #include "SkTemplates.h" 19 #include "SkUtils.h" 20 #include "transform_scanline.h" 21 22 extern "C" { 23 #include "png.h" 24 } 25 26 class SkPNGImageIndex { 27 public: 28 SkPNGImageIndex() { 29 inputStream = NULL; 30 png_ptr = NULL; 31 } 32 virtual ~SkPNGImageIndex() { 33 if (png_ptr) { 34 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); 35 } 36 if (inputStream) { 37 delete inputStream; 38 } 39 } 40 png_structp png_ptr; 41 png_infop info_ptr; 42 SkStream *inputStream; 43 }; 44 45 class SkPNGImageDecoder : public SkImageDecoder { 46 public: 47 SkPNGImageDecoder() { 48 index = NULL; 49 } 50 virtual Format getFormat() const { 51 return kPNG_Format; 52 } 53 virtual ~SkPNGImageDecoder() { 54 if (index) { 55 delete index; 56 } 57 } 58 59 protected: 60 virtual bool onBuildTileIndex(SkStream *stream, 61 int *width, int *height); 62 virtual bool onDecodeRegion(SkBitmap* bitmap, SkIRect region); 63 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode); 64 65 private: 66 bool onDecodeInit(SkStream* stream, png_structp *png_ptrp, 67 png_infop *info_ptrp); 68 bool decodePalette(png_structp png_ptr, png_infop info_ptr, 69 bool *hasAlphap, bool *reallyHasAlphap, SkColorTable **colorTablep); 70 bool getBitmapConfig(png_structp png_ptr, png_infop info_ptr, 71 SkBitmap::Config *config, bool *hasAlpha, bool *doDither, 72 SkPMColor *theTranspColor); 73 SkPNGImageIndex *index; 74 }; 75 76 #ifndef png_jmpbuf 77 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) 78 #endif 79 80 #define PNG_BYTES_TO_CHECK 4 81 82 /* Automatically clean up after throwing an exception */ 83 struct PNGAutoClean { 84 PNGAutoClean(png_structp p, png_infop i): png_ptr(p), info_ptr(i) {} 85 ~PNGAutoClean() { 86 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); 87 } 88 private: 89 png_structp png_ptr; 90 png_infop info_ptr; 91 }; 92 93 static void sk_read_fn(png_structp png_ptr, png_bytep data, png_size_t length) { 94 SkStream* sk_stream = (SkStream*) png_ptr->io_ptr; 95 size_t bytes = sk_stream->read(data, length); 96 if (bytes != length) { 97 png_error(png_ptr, "Read Error!"); 98 } 99 } 100 101 static void sk_seek_fn(png_structp png_ptr, png_uint_32 offset) { 102 SkStream* sk_stream = (SkStream*) png_ptr->io_ptr; 103 sk_stream->rewind(); 104 (void)sk_stream->skip(offset); 105 } 106 107 static int sk_read_user_chunk(png_structp png_ptr, png_unknown_chunkp chunk) { 108 SkImageDecoder::Peeker* peeker = 109 (SkImageDecoder::Peeker*)png_get_user_chunk_ptr(png_ptr); 110 // peek() returning true means continue decoding 111 return peeker->peek((const char*)chunk->name, chunk->data, chunk->size) ? 112 1 : -1; 113 } 114 115 static void sk_error_fn(png_structp png_ptr, png_const_charp msg) { 116 #if 0 117 SkDebugf("------ png error %s\n", msg); 118 #endif 119 longjmp(png_jmpbuf(png_ptr), 1); 120 } 121 122 static void skip_src_rows(png_structp png_ptr, uint8_t storage[], int count) { 123 for (int i = 0; i < count; i++) { 124 uint8_t* tmp = storage; 125 png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1); 126 } 127 } 128 129 static bool pos_le(int value, int max) { 130 return value > 0 && value <= max; 131 } 132 133 static bool substituteTranspColor(SkBitmap* bm, SkPMColor match) { 134 SkASSERT(bm->config() == SkBitmap::kARGB_8888_Config); 135 136 bool reallyHasAlpha = false; 137 138 for (int y = bm->height() - 1; y >= 0; --y) { 139 SkPMColor* p = bm->getAddr32(0, y); 140 for (int x = bm->width() - 1; x >= 0; --x) { 141 if (match == *p) { 142 *p = 0; 143 reallyHasAlpha = true; 144 } 145 p += 1; 146 } 147 } 148 return reallyHasAlpha; 149 } 150 151 static bool canUpscalePaletteToConfig(SkBitmap::Config dstConfig, 152 bool srcHasAlpha) { 153 switch (dstConfig) { 154 case SkBitmap::kARGB_8888_Config: 155 case SkBitmap::kARGB_4444_Config: 156 return true; 157 case SkBitmap::kRGB_565_Config: 158 // only return true if the src is opaque (since 565 is opaque) 159 return !srcHasAlpha; 160 default: 161 return false; 162 } 163 } 164 165 // call only if color_type is PALETTE. Returns true if the ctable has alpha 166 static bool hasTransparencyInPalette(png_structp png_ptr, png_infop info_ptr) { 167 png_bytep trans; 168 int num_trans; 169 170 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { 171 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); 172 return num_trans > 0; 173 } 174 return false; 175 } 176 177 bool SkPNGImageDecoder::onDecodeInit(SkStream* sk_stream, 178 png_structp *png_ptrp, png_infop *info_ptrp) 179 { 180 /* Create and initialize the png_struct with the desired error handler 181 * functions. If you want to use the default stderr and longjump method, 182 * you can supply NULL for the last three parameters. We also supply the 183 * the compiler header file version, so that we know if the application 184 * was compiled with a compatible version of the library. */ 185 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 186 NULL, sk_error_fn, NULL); 187 // png_voidp user_error_ptr, user_error_fn, user_warning_fn); 188 if (png_ptr == NULL) { 189 return false; 190 } 191 *png_ptrp = png_ptr; 192 193 /* Allocate/initialize the memory for image information. */ 194 png_infop info_ptr = png_create_info_struct(png_ptr); 195 if (info_ptr == NULL) { 196 png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); 197 return false; 198 } 199 *info_ptrp = info_ptr; 200 201 /* Set error handling if you are using the setjmp/longjmp method (this is 202 * the normal method of doing things with libpng). REQUIRED unless you 203 * set up your own error handlers in the png_create_read_struct() earlier. 204 */ 205 if (setjmp(png_jmpbuf(png_ptr))) { 206 return false; 207 } 208 209 /* If you are using replacement read functions, instead of calling 210 * png_init_io() here you would call: 211 */ 212 png_set_read_fn(png_ptr, (void *)sk_stream, sk_read_fn); 213 png_set_seek_fn(png_ptr, sk_seek_fn); 214 /* where user_io_ptr is a structure you want available to the callbacks */ 215 /* If we have already read some of the signature */ 216 // png_set_sig_bytes(png_ptr, 0 /* sig_read */ ); 217 218 // hookup our peeker so we can see any user-chunks the caller may be interested in 219 png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, (png_byte*)"", 0); 220 if (this->getPeeker()) { 221 png_set_read_user_chunk_fn(png_ptr, (png_voidp)this->getPeeker(), sk_read_user_chunk); 222 } 223 224 /* The call to png_read_info() gives us all of the information from the 225 * PNG file before the first IDAT (image data chunk). */ 226 png_read_info(png_ptr, info_ptr); 227 png_uint_32 origWidth, origHeight; 228 int bit_depth, color_type, interlace_type; 229 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth, 230 &color_type, &interlace_type, int_p_NULL, int_p_NULL); 231 232 /* tell libpng to strip 16 bit/color files down to 8 bits/color */ 233 if (bit_depth == 16) { 234 png_set_strip_16(png_ptr); 235 } 236 /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single 237 * byte into separate bytes (useful for paletted and grayscale images). */ 238 if (bit_depth < 8) { 239 png_set_packing(png_ptr); 240 } 241 /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ 242 if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { 243 png_set_gray_1_2_4_to_8(png_ptr); 244 } 245 246 /* Make a grayscale image into RGB. */ 247 if (color_type == PNG_COLOR_TYPE_GRAY || 248 color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { 249 png_set_gray_to_rgb(png_ptr); 250 } 251 return true; 252 } 253 254 bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap, 255 Mode mode) { 256 png_structp png_ptr; 257 png_infop info_ptr; 258 259 if (onDecodeInit(sk_stream, &png_ptr, &info_ptr) == false) { 260 return false; 261 } 262 263 if (setjmp(png_jmpbuf(png_ptr))) { 264 return false; 265 } 266 267 PNGAutoClean autoClean(png_ptr, info_ptr); 268 269 png_uint_32 origWidth, origHeight; 270 int bit_depth, color_type, interlace_type; 271 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth, 272 &color_type, &interlace_type, int_p_NULL, int_p_NULL); 273 274 SkBitmap::Config config; 275 bool hasAlpha = false; 276 bool doDither = this->getDitherImage(); 277 SkPMColor theTranspColor = 0; // 0 tells us not to try to match 278 279 if (getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha, 280 &doDither, &theTranspColor) == false) { 281 return false; 282 } 283 284 const int sampleSize = this->getSampleSize(); 285 SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize); 286 287 decodedBitmap->lockPixels(); 288 void* rowptr = (void*) decodedBitmap->getPixels(); 289 bool reuseBitmap = (rowptr != NULL); 290 decodedBitmap->unlockPixels(); 291 if (reuseBitmap && (sampler.scaledWidth() != decodedBitmap->width() || 292 sampler.scaledHeight() != decodedBitmap->height())) { 293 // Dimensions must match 294 return false; 295 } 296 297 if (!reuseBitmap) { 298 decodedBitmap->setConfig(config, sampler.scaledWidth(), 299 sampler.scaledHeight(), 0); 300 } 301 if (SkImageDecoder::kDecodeBounds_Mode == mode) { 302 return true; 303 } 304 305 // from here down we are concerned with colortables and pixels 306 307 // we track if we actually see a non-opaque pixels, since sometimes a PNG sets its colortype 308 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we 309 // draw lots faster if we can flag the bitmap has being opaque 310 bool reallyHasAlpha = false; 311 SkColorTable* colorTable = NULL; 312 313 if (color_type == PNG_COLOR_TYPE_PALETTE) { 314 decodePalette(png_ptr, info_ptr, &hasAlpha, 315 &reallyHasAlpha, &colorTable); 316 } 317 318 SkAutoUnref aur(colorTable); 319 320 if (!reuseBitmap) { 321 if (!this->allocPixelRef(decodedBitmap, 322 SkBitmap::kIndex8_Config == config ? 323 colorTable : NULL)) { 324 return false; 325 } 326 } 327 328 SkAutoLockPixels alp(*decodedBitmap); 329 330 /* Add filler (or alpha) byte (before/after each RGB triplet) */ 331 if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY) { 332 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); 333 } 334 335 /* Turn on interlace handling. REQUIRED if you are not using 336 * png_read_image(). To see how to handle interlacing passes, 337 * see the png_read_row() method below: 338 */ 339 const int number_passes = interlace_type != PNG_INTERLACE_NONE ? 340 png_set_interlace_handling(png_ptr) : 1; 341 342 /* Optional call to gamma correct and add the background to the palette 343 * and update info structure. REQUIRED if you are expecting libpng to 344 * update the palette for you (ie you selected such a transform above). 345 */ 346 png_read_update_info(png_ptr, info_ptr); 347 348 if (SkBitmap::kIndex8_Config == config && 1 == sampleSize) { 349 for (int i = 0; i < number_passes; i++) { 350 for (png_uint_32 y = 0; y < origHeight; y++) { 351 uint8_t* bmRow = decodedBitmap->getAddr8(0, y); 352 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); 353 } 354 } 355 } else { 356 SkScaledBitmapSampler::SrcConfig sc; 357 int srcBytesPerPixel = 4; 358 359 if (colorTable != NULL) { 360 sc = SkScaledBitmapSampler::kIndex; 361 srcBytesPerPixel = 1; 362 } else if (hasAlpha) { 363 sc = SkScaledBitmapSampler::kRGBA; 364 } else { 365 sc = SkScaledBitmapSampler::kRGBX; 366 } 367 368 /* We have to pass the colortable explicitly, since we may have one 369 even if our decodedBitmap doesn't, due to the request that we 370 upscale png's palette to a direct model 371 */ 372 SkAutoLockColors ctLock(colorTable); 373 if (!sampler.begin(decodedBitmap, sc, doDither, ctLock.colors())) { 374 return false; 375 } 376 const int height = decodedBitmap->height(); 377 378 if (number_passes > 1) { 379 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel); 380 uint8_t* base = (uint8_t*)storage.get(); 381 size_t rb = origWidth * srcBytesPerPixel; 382 383 for (int i = 0; i < number_passes; i++) { 384 uint8_t* row = base; 385 for (png_uint_32 y = 0; y < origHeight; y++) { 386 uint8_t* bmRow = row; 387 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); 388 row += rb; 389 } 390 } 391 // now sample it 392 base += sampler.srcY0() * rb; 393 for (int y = 0; y < height; y++) { 394 reallyHasAlpha |= sampler.next(base); 395 base += sampler.srcDY() * rb; 396 } 397 } else { 398 SkAutoMalloc storage(origWidth * srcBytesPerPixel); 399 uint8_t* srcRow = (uint8_t*)storage.get(); 400 skip_src_rows(png_ptr, srcRow, sampler.srcY0()); 401 402 for (int y = 0; y < height; y++) { 403 uint8_t* tmp = srcRow; 404 png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1); 405 reallyHasAlpha |= sampler.next(srcRow); 406 if (y < height - 1) { 407 skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1); 408 } 409 } 410 411 // skip the rest of the rows (if any) 412 png_uint_32 read = (height - 1) * sampler.srcDY() + 413 sampler.srcY0() + 1; 414 SkASSERT(read <= origHeight); 415 skip_src_rows(png_ptr, srcRow, origHeight - read); 416 } 417 } 418 419 /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ 420 png_read_end(png_ptr, info_ptr); 421 422 if (0 != theTranspColor) { 423 reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor); 424 } 425 decodedBitmap->setIsOpaque(!reallyHasAlpha); 426 if (reuseBitmap) { 427 decodedBitmap->notifyPixelsChanged(); 428 } 429 return true; 430 } 431 432 bool SkPNGImageDecoder::onBuildTileIndex(SkStream* sk_stream, int *width, 433 int *height) { 434 png_structp png_ptr; 435 png_infop info_ptr; 436 437 this->index = new SkPNGImageIndex(); 438 439 if (onDecodeInit(sk_stream, &png_ptr, &info_ptr) == false) { 440 return false; 441 } 442 443 if (setjmp(png_jmpbuf(png_ptr)) != 0) { 444 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); 445 return false; 446 } 447 448 int bit_depth, color_type, interlace_type; 449 png_uint_32 origWidth, origHeight; 450 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth, 451 &color_type, &interlace_type, int_p_NULL, int_p_NULL); 452 453 *width = origWidth; 454 *height = origHeight; 455 456 png_build_index(png_ptr); 457 this->index->png_ptr = png_ptr; 458 this->index->info_ptr = info_ptr; 459 return true; 460 } 461 462 bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr, 463 SkBitmap::Config *configp, bool *hasAlphap, bool *doDitherp, 464 SkPMColor *theTranspColorp) { 465 png_uint_32 origWidth, origHeight; 466 int bit_depth, color_type, interlace_type; 467 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth, 468 &color_type, &interlace_type, int_p_NULL, int_p_NULL); 469 470 // check for sBIT chunk data, in case we should disable dithering because 471 // our data is not truely 8bits per component 472 if (*doDitherp) { 473 #if 0 474 SkDebugf("----- sBIT %d %d %d %d\n", info_ptr->sig_bit.red, 475 info_ptr->sig_bit.green, info_ptr->sig_bit.blue, 476 info_ptr->sig_bit.alpha); 477 #endif 478 // 0 seems to indicate no information available 479 if (pos_le(info_ptr->sig_bit.red, SK_R16_BITS) && 480 pos_le(info_ptr->sig_bit.green, SK_G16_BITS) && 481 pos_le(info_ptr->sig_bit.blue, SK_B16_BITS)) { 482 *doDitherp = false; 483 } 484 } 485 486 if (color_type == PNG_COLOR_TYPE_PALETTE) { 487 bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr); 488 *configp = this->getPrefConfig(kIndex_SrcDepth, paletteHasAlpha); 489 // now see if we can upscale to their requested config 490 if (!canUpscalePaletteToConfig(*configp, paletteHasAlpha)) { 491 *configp = SkBitmap::kIndex8_Config; 492 } 493 } else { 494 png_color_16p transpColor = NULL; 495 int numTransp = 0; 496 497 png_get_tRNS(png_ptr, info_ptr, NULL, &numTransp, &transpColor); 498 499 bool valid = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS); 500 501 if (valid && numTransp == 1 && transpColor != NULL) { 502 /* Compute our transparent color, which we'll match against later. 503 We don't really handle 16bit components properly here, since we 504 do our compare *after* the values have been knocked down to 8bit 505 which means we will find more matches than we should. The real 506 fix seems to be to see the actual 16bit components, do the 507 compare, and then knock it down to 8bits ourselves. 508 */ 509 if (color_type & PNG_COLOR_MASK_COLOR) { 510 if (16 == bit_depth) { 511 *theTranspColorp = SkPackARGB32(0xFF, transpColor->red >> 8, 512 transpColor->green >> 8, transpColor->blue >> 8); 513 } else { 514 *theTranspColorp = SkPackARGB32(0xFF, transpColor->red, 515 transpColor->green, transpColor->blue); 516 } 517 } else { // gray 518 if (16 == bit_depth) { 519 *theTranspColorp = SkPackARGB32(0xFF, transpColor->gray >> 8, 520 transpColor->gray >> 8, transpColor->gray >> 8); 521 } else { 522 *theTranspColorp = SkPackARGB32(0xFF, transpColor->gray, 523 transpColor->gray, transpColor->gray); 524 } 525 } 526 } 527 528 if (valid || 529 PNG_COLOR_TYPE_RGB_ALPHA == color_type || 530 PNG_COLOR_TYPE_GRAY_ALPHA == color_type) { 531 *hasAlphap = true; 532 } 533 *configp = this->getPrefConfig(k32Bit_SrcDepth, *hasAlphap); 534 // now match the request against our capabilities 535 if (*hasAlphap) { 536 if (*configp != SkBitmap::kARGB_4444_Config) { 537 *configp = SkBitmap::kARGB_8888_Config; 538 } 539 } else { 540 if (*configp != SkBitmap::kRGB_565_Config && 541 *configp != SkBitmap::kARGB_4444_Config) { 542 *configp = SkBitmap::kARGB_8888_Config; 543 } 544 } 545 } 546 547 // sanity check for size 548 { 549 Sk64 size; 550 size.setMul(origWidth, origHeight); 551 if (size.isNeg() || !size.is32()) { 552 return false; 553 } 554 // now check that if we are 4-bytes per pixel, we also don't overflow 555 if (size.get32() > (0x7FFFFFFF >> 2)) { 556 return false; 557 } 558 } 559 560 if (!this->chooseFromOneChoice(*configp, origWidth, origHeight)) { 561 return false; 562 } 563 return true; 564 } 565 566 bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr, 567 bool *hasAlphap, bool *reallyHasAlphap, SkColorTable **colorTablep) { 568 int num_palette; 569 png_colorp palette; 570 png_bytep trans; 571 int num_trans; 572 bool reallyHasAlpha = false; 573 SkColorTable* colorTable = NULL; 574 575 png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); 576 577 /* BUGGY IMAGE WORKAROUND 578 579 We hit some images (e.g. fruit_.png) who contain bytes that are == colortable_count 580 which is a problem since we use the byte as an index. To work around this we grow 581 the colortable by 1 (if its < 256) and duplicate the last color into that slot. 582 */ 583 int colorCount = num_palette + (num_palette < 256); 584 585 colorTable = SkNEW_ARGS(SkColorTable, (colorCount)); 586 587 SkPMColor* colorPtr = colorTable->lockColors(); 588 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { 589 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); 590 *hasAlphap = (num_trans > 0); 591 } else { 592 num_trans = 0; 593 colorTable->setFlags(colorTable->getFlags() | SkColorTable::kColorsAreOpaque_Flag); 594 } 595 // check for bad images that might make us crash 596 if (num_trans > num_palette) { 597 num_trans = num_palette; 598 } 599 600 int index = 0; 601 int transLessThanFF = 0; 602 603 for (; index < num_trans; index++) { 604 transLessThanFF |= (int)*trans - 0xFF; 605 *colorPtr++ = SkPreMultiplyARGB(*trans++, palette->red, palette->green, palette->blue); 606 palette++; 607 } 608 reallyHasAlpha |= (transLessThanFF < 0); 609 610 for (; index < num_palette; index++) { 611 *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette->blue); 612 palette++; 613 } 614 615 // see BUGGY IMAGE WORKAROUND comment above 616 if (num_palette < 256) { 617 *colorPtr = colorPtr[-1]; 618 } 619 colorTable->unlockColors(true); 620 *colorTablep = colorTable; 621 *reallyHasAlphap = reallyHasAlpha; 622 return true; 623 } 624 625 bool SkPNGImageDecoder::onDecodeRegion(SkBitmap* bm, SkIRect region) { 626 int i; 627 png_structp png_ptr = this->index->png_ptr; 628 png_infop info_ptr = this->index->info_ptr; 629 if (setjmp(png_jmpbuf(png_ptr))) { 630 return false; 631 } 632 633 png_uint_32 origWidth, origHeight; 634 int bit_depth, color_type, interlace_type; 635 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth, 636 &color_type, &interlace_type, int_p_NULL, int_p_NULL); 637 638 SkIRect rect = SkIRect::MakeWH(origWidth, origHeight); 639 640 if (!rect.intersect(region)) { 641 // If the requested region is entirely outsides the image, just 642 // returns false 643 return false; 644 } 645 646 SkBitmap::Config config; 647 bool hasAlpha = false; 648 bool doDither = this->getDitherImage(); 649 SkPMColor theTranspColor = 0; // 0 tells us not to try to match 650 651 if (getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha, 652 &doDither, &theTranspColor) == false) { 653 return false; 654 } 655 656 const int sampleSize = this->getSampleSize(); 657 SkScaledBitmapSampler sampler(origWidth, rect.height(), sampleSize); 658 659 SkBitmap *decodedBitmap = new SkBitmap; 660 SkAutoTDelete<SkBitmap> adb(decodedBitmap); 661 662 decodedBitmap->setConfig(config, sampler.scaledWidth(), 663 sampler.scaledHeight(), 0); 664 665 // from here down we are concerned with colortables and pixels 666 667 // we track if we actually see a non-opaque pixels, since sometimes a PNG sets its colortype 668 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we 669 // draw lots faster if we can flag the bitmap has being opaque 670 bool reallyHasAlpha = false; 671 SkColorTable* colorTable = NULL; 672 673 if (color_type == PNG_COLOR_TYPE_PALETTE) { 674 decodePalette(png_ptr, info_ptr, &hasAlpha, 675 &reallyHasAlpha, &colorTable); 676 } 677 678 SkAutoUnref aur(colorTable); 679 680 // Check ahead of time if the swap(dest, src) is possible in crop or not. 681 // If yes, then we will stick to AllocPixelRef since it's cheaper with the swap happening. 682 // If no, then we will use alloc to allocate pixels to prevent garbage collection. 683 int w = rect.width() / sampleSize; 684 int h = rect.height() / sampleSize; 685 bool swapOnly = (rect == region) && (w == decodedBitmap->width()) && 686 (h == decodedBitmap->height()) && 687 ((0 - rect.x()) / sampleSize == 0) && bm->isNull(); 688 if (swapOnly) { 689 if (!this->allocPixelRef(decodedBitmap, 690 SkBitmap::kIndex8_Config == config ? colorTable : NULL)) { 691 return false; 692 } 693 } else { 694 if (!decodedBitmap->allocPixels( 695 NULL, SkBitmap::kIndex8_Config == config ? colorTable : NULL)) { 696 return false; 697 } 698 } 699 SkAutoLockPixels alp(*decodedBitmap); 700 701 /* Add filler (or alpha) byte (before/after each RGB triplet) */ 702 if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY) { 703 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); 704 } 705 706 /* Turn on interlace handling. REQUIRED if you are not using 707 * png_read_image(). To see how to handle interlacing passes, 708 * see the png_read_row() method below: 709 */ 710 const int number_passes = interlace_type != PNG_INTERLACE_NONE ? 711 png_set_interlace_handling(png_ptr) : 1; 712 713 /* Optional call to gamma correct and add the background to the palette 714 * and update info structure. REQUIRED if you are expecting libpng to 715 * update the palette for you (ie you selected such a transform above). 716 */ 717 png_ptr->pass = 0; 718 png_read_update_info(png_ptr, info_ptr); 719 720 int actualTop = rect.fTop; 721 722 if (SkBitmap::kIndex8_Config == config && 1 == sampleSize) { 723 for (int i = 0; i < number_passes; i++) { 724 png_configure_decoder(png_ptr, &actualTop, i); 725 for (int j = 0; j < rect.fTop - actualTop; j++) { 726 uint8_t* bmRow = decodedBitmap->getAddr8(0, 0); 727 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); 728 } 729 for (png_uint_32 y = 0; y < origHeight; y++) { 730 uint8_t* bmRow = decodedBitmap->getAddr8(0, y); 731 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); 732 } 733 } 734 } else { 735 SkScaledBitmapSampler::SrcConfig sc; 736 int srcBytesPerPixel = 4; 737 738 if (colorTable != NULL) { 739 sc = SkScaledBitmapSampler::kIndex; 740 srcBytesPerPixel = 1; 741 } else if (hasAlpha) { 742 sc = SkScaledBitmapSampler::kRGBA; 743 } else { 744 sc = SkScaledBitmapSampler::kRGBX; 745 } 746 747 /* We have to pass the colortable explicitly, since we may have one 748 even if our decodedBitmap doesn't, due to the request that we 749 upscale png's palette to a direct model 750 */ 751 SkAutoLockColors ctLock(colorTable); 752 if (!sampler.begin(decodedBitmap, sc, doDither, ctLock.colors())) { 753 return false; 754 } 755 const int height = decodedBitmap->height(); 756 757 if (number_passes > 1) { 758 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel); 759 uint8_t* base = (uint8_t*)storage.get(); 760 size_t rb = origWidth * srcBytesPerPixel; 761 762 for (int i = 0; i < number_passes; i++) { 763 png_configure_decoder(png_ptr, &actualTop, i); 764 for (int j = 0; j < rect.fTop - actualTop; j++) { 765 uint8_t* bmRow = (uint8_t*)decodedBitmap->getPixels(); 766 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); 767 } 768 uint8_t* row = base; 769 for (png_uint_32 y = 0; y < rect.height(); y++) { 770 uint8_t* bmRow = row; 771 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); 772 row += rb; 773 } 774 } 775 // now sample it 776 base += sampler.srcY0() * rb; 777 for (int y = 0; y < height; y++) { 778 reallyHasAlpha |= sampler.next(base); 779 base += sampler.srcDY() * rb; 780 } 781 } else { 782 SkAutoMalloc storage(origWidth * srcBytesPerPixel); 783 uint8_t* srcRow = (uint8_t*)storage.get(); 784 785 png_configure_decoder(png_ptr, &actualTop, 0); 786 skip_src_rows(png_ptr, srcRow, sampler.srcY0()); 787 788 for (int i = 0; i < rect.fTop - actualTop; i++) { 789 uint8_t* bmRow = (uint8_t*)decodedBitmap->getPixels(); 790 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); 791 } 792 for (int y = 0; y < height; y++) { 793 uint8_t* tmp = srcRow; 794 png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1); 795 reallyHasAlpha |= sampler.next(srcRow); 796 if (y < height - 1) { 797 skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1); 798 } 799 } 800 } 801 } 802 if (swapOnly) { 803 bm->swap(*decodedBitmap); 804 } else { 805 cropBitmap(bm, decodedBitmap, sampleSize, region.x(), region.y(), 806 region.width(), region.height(), 0, rect.y()); 807 } 808 809 if (0 != theTranspColor) { 810 reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor); 811 } 812 decodedBitmap->setIsOpaque(!reallyHasAlpha); 813 return true; 814 } 815 816 /////////////////////////////////////////////////////////////////////////////// 817 818 #include "SkColorPriv.h" 819 #include "SkUnPreMultiply.h" 820 821 static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) { 822 SkWStream* sk_stream = (SkWStream*)png_ptr->io_ptr; 823 if (!sk_stream->write(data, len)) { 824 png_error(png_ptr, "sk_write_fn Error!"); 825 } 826 } 827 828 static transform_scanline_proc choose_proc(SkBitmap::Config config, 829 bool hasAlpha) { 830 // we don't care about search on alpha if we're kIndex8, since only the 831 // colortable packing cares about that distinction, not the pixels 832 if (SkBitmap::kIndex8_Config == config) { 833 hasAlpha = false; // we store false in the table entries for kIndex8 834 } 835 836 static const struct { 837 SkBitmap::Config fConfig; 838 bool fHasAlpha; 839 transform_scanline_proc fProc; 840 } gMap[] = { 841 { SkBitmap::kRGB_565_Config, false, transform_scanline_565 }, 842 { SkBitmap::kARGB_8888_Config, false, transform_scanline_888 }, 843 { SkBitmap::kARGB_8888_Config, true, transform_scanline_8888 }, 844 { SkBitmap::kARGB_4444_Config, false, transform_scanline_444 }, 845 { SkBitmap::kARGB_4444_Config, true, transform_scanline_4444 }, 846 { SkBitmap::kIndex8_Config, false, transform_scanline_memcpy }, 847 }; 848 849 for (int i = SK_ARRAY_COUNT(gMap) - 1; i >= 0; --i) { 850 if (gMap[i].fConfig == config && gMap[i].fHasAlpha == hasAlpha) { 851 return gMap[i].fProc; 852 } 853 } 854 sk_throw(); 855 return NULL; 856 } 857 858 // return the minimum legal bitdepth (by png standards) for this many colortable 859 // entries. SkBitmap always stores in 8bits per pixel, but for colorcount <= 16, 860 // we can use fewer bits per in png 861 static int computeBitDepth(int colorCount) { 862 #if 0 863 int bits = SkNextLog2(colorCount); 864 SkASSERT(bits >= 1 && bits <= 8); 865 // now we need bits itself to be a power of 2 (e.g. 1, 2, 4, 8) 866 return SkNextPow2(bits); 867 #else 868 // for the moment, we don't know how to pack bitdepth < 8 869 return 8; 870 #endif 871 } 872 873 /* Pack palette[] with the corresponding colors, and if hasAlpha is true, also 874 pack trans[] and return the number of trans[] entries written. If hasAlpha 875 is false, the return value will always be 0. 876 877 Note: this routine takes care of unpremultiplying the RGB values when we 878 have alpha in the colortable, since png doesn't support premul colors 879 */ 880 static inline int pack_palette(SkColorTable* ctable, 881 png_color* SK_RESTRICT palette, 882 png_byte* SK_RESTRICT trans, bool hasAlpha) { 883 SkAutoLockColors alc(ctable); 884 const SkPMColor* SK_RESTRICT colors = alc.colors(); 885 const int ctCount = ctable->count(); 886 int i, num_trans = 0; 887 888 if (hasAlpha) { 889 /* first see if we have some number of fully opaque at the end of the 890 ctable. PNG allows num_trans < num_palette, but all of the trans 891 entries must come first in the palette. If I was smarter, I'd 892 reorder the indices and ctable so that all non-opaque colors came 893 first in the palette. But, since that would slow down the encode, 894 I'm leaving the indices and ctable order as is, and just looking 895 at the tail of the ctable for opaqueness. 896 */ 897 num_trans = ctCount; 898 for (i = ctCount - 1; i >= 0; --i) { 899 if (SkGetPackedA32(colors[i]) != 0xFF) { 900 break; 901 } 902 num_trans -= 1; 903 } 904 905 const SkUnPreMultiply::Scale* SK_RESTRICT table = 906 SkUnPreMultiply::GetScaleTable(); 907 908 for (i = 0; i < num_trans; i++) { 909 const SkPMColor c = *colors++; 910 const unsigned a = SkGetPackedA32(c); 911 const SkUnPreMultiply::Scale s = table[a]; 912 trans[i] = a; 913 palette[i].red = SkUnPreMultiply::ApplyScale(s, SkGetPackedR32(c)); 914 palette[i].green = SkUnPreMultiply::ApplyScale(s,SkGetPackedG32(c)); 915 palette[i].blue = SkUnPreMultiply::ApplyScale(s, SkGetPackedB32(c)); 916 } 917 // now fall out of this if-block to use common code for the trailing 918 // opaque entries 919 } 920 921 // these (remaining) entries are opaque 922 for (i = num_trans; i < ctCount; i++) { 923 SkPMColor c = *colors++; 924 palette[i].red = SkGetPackedR32(c); 925 palette[i].green = SkGetPackedG32(c); 926 palette[i].blue = SkGetPackedB32(c); 927 } 928 return num_trans; 929 } 930 931 class SkPNGImageEncoder : public SkImageEncoder { 932 protected: 933 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality); 934 private: 935 bool doEncode(SkWStream* stream, const SkBitmap& bm, 936 const bool& hasAlpha, int colorType, 937 int bitDepth, SkBitmap::Config config, 938 png_color_8& sig_bit); 939 }; 940 941 bool SkPNGImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap, 942 int /*quality*/) { 943 SkBitmap::Config config = bitmap.getConfig(); 944 945 const bool hasAlpha = !bitmap.isOpaque(); 946 int colorType = PNG_COLOR_MASK_COLOR; 947 int bitDepth = 8; // default for color 948 png_color_8 sig_bit; 949 950 switch (config) { 951 case SkBitmap::kIndex8_Config: 952 colorType |= PNG_COLOR_MASK_PALETTE; 953 // fall through to the ARGB_8888 case 954 case SkBitmap::kARGB_8888_Config: 955 sig_bit.red = 8; 956 sig_bit.green = 8; 957 sig_bit.blue = 8; 958 sig_bit.alpha = 8; 959 break; 960 case SkBitmap::kARGB_4444_Config: 961 sig_bit.red = 4; 962 sig_bit.green = 4; 963 sig_bit.blue = 4; 964 sig_bit.alpha = 4; 965 break; 966 case SkBitmap::kRGB_565_Config: 967 sig_bit.red = 5; 968 sig_bit.green = 6; 969 sig_bit.blue = 5; 970 sig_bit.alpha = 0; 971 break; 972 default: 973 return false; 974 } 975 976 if (hasAlpha) { 977 // don't specify alpha if we're a palette, even if our ctable has alpha 978 if (!(colorType & PNG_COLOR_MASK_PALETTE)) { 979 colorType |= PNG_COLOR_MASK_ALPHA; 980 } 981 } else { 982 sig_bit.alpha = 0; 983 } 984 985 SkAutoLockPixels alp(bitmap); 986 // readyToDraw checks for pixels (and colortable if that is required) 987 if (!bitmap.readyToDraw()) { 988 return false; 989 } 990 991 // we must do this after we have locked the pixels 992 SkColorTable* ctable = bitmap.getColorTable(); 993 if (NULL != ctable) { 994 if (ctable->count() == 0) { 995 return false; 996 } 997 // check if we can store in fewer than 8 bits 998 bitDepth = computeBitDepth(ctable->count()); 999 } 1000 1001 return doEncode(stream, bitmap, hasAlpha, colorType, 1002 bitDepth, config, sig_bit); 1003 } 1004 1005 bool SkPNGImageEncoder::doEncode(SkWStream* stream, const SkBitmap& bitmap, 1006 const bool& hasAlpha, int colorType, 1007 int bitDepth, SkBitmap::Config config, 1008 png_color_8& sig_bit) { 1009 1010 png_structp png_ptr; 1011 png_infop info_ptr; 1012 1013 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, sk_error_fn, 1014 NULL); 1015 if (NULL == png_ptr) { 1016 return false; 1017 } 1018 1019 info_ptr = png_create_info_struct(png_ptr); 1020 if (NULL == info_ptr) { 1021 png_destroy_write_struct(&png_ptr, png_infopp_NULL); 1022 return false; 1023 } 1024 1025 /* Set error handling. REQUIRED if you aren't supplying your own 1026 * error handling functions in the png_create_write_struct() call. 1027 */ 1028 if (setjmp(png_jmpbuf(png_ptr))) { 1029 png_destroy_write_struct(&png_ptr, &info_ptr); 1030 return false; 1031 } 1032 1033 png_set_write_fn(png_ptr, (void*)stream, sk_write_fn, png_flush_ptr_NULL); 1034 1035 /* Set the image information here. Width and height are up to 2^31, 1036 * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on 1037 * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, 1038 * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, 1039 * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or 1040 * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST 1041 * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED 1042 */ 1043 1044 png_set_IHDR(png_ptr, info_ptr, bitmap.width(), bitmap.height(), 1045 bitDepth, colorType, 1046 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, 1047 PNG_FILTER_TYPE_BASE); 1048 1049 // set our colortable/trans arrays if needed 1050 png_color paletteColors[256]; 1051 png_byte trans[256]; 1052 if (SkBitmap::kIndex8_Config == config) { 1053 SkColorTable* ct = bitmap.getColorTable(); 1054 int numTrans = pack_palette(ct, paletteColors, trans, hasAlpha); 1055 png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count()); 1056 if (numTrans > 0) { 1057 png_set_tRNS(png_ptr, info_ptr, trans, numTrans, NULL); 1058 } 1059 } 1060 1061 png_set_sBIT(png_ptr, info_ptr, &sig_bit); 1062 png_write_info(png_ptr, info_ptr); 1063 1064 const char* srcImage = (const char*)bitmap.getPixels(); 1065 SkAutoSMalloc<1024> rowStorage(bitmap.width() << 2); 1066 char* storage = (char*)rowStorage.get(); 1067 transform_scanline_proc proc = choose_proc(config, hasAlpha); 1068 1069 for (int y = 0; y < bitmap.height(); y++) { 1070 png_bytep row_ptr = (png_bytep)storage; 1071 proc(srcImage, bitmap.width(), storage); 1072 png_write_rows(png_ptr, &row_ptr, 1); 1073 srcImage += bitmap.rowBytes(); 1074 } 1075 1076 png_write_end(png_ptr, info_ptr); 1077 1078 /* clean up after the write, and free any memory allocated */ 1079 png_destroy_write_struct(&png_ptr, &info_ptr); 1080 return true; 1081 } 1082 1083 /////////////////////////////////////////////////////////////////////////////// 1084 DEFINE_DECODER_CREATOR(PNGImageDecoder); 1085 DEFINE_ENCODER_CREATOR(PNGImageEncoder); 1086 /////////////////////////////////////////////////////////////////////////////// 1087 1088 #include "SkTRegistry.h" 1089 1090 #ifdef SK_ENABLE_LIBPNG 1091 SkImageDecoder* sk_libpng_dfactory(SkStream*); 1092 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type); 1093 #endif 1094 1095 SkImageDecoder* sk_libpng_dfactory(SkStream* stream) { 1096 char buf[PNG_BYTES_TO_CHECK]; 1097 if (stream->read(buf, PNG_BYTES_TO_CHECK) == PNG_BYTES_TO_CHECK && 1098 !png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) { 1099 return SkNEW(SkPNGImageDecoder); 1100 } 1101 return NULL; 1102 } 1103 1104 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { 1105 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; 1106 } 1107 1108 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libpng_efactory); 1109 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libpng_dfactory); 1110