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