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