| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * Copyright 2015 Google Inc. | 2  * Copyright 2015 Google Inc. | 
| 3  * | 3  * | 
| 4  * Use of this source code is governed by a BSD-style license that can be | 4  * Use of this source code is governed by a BSD-style license that can be | 
| 5  * found in the LICENSE file. | 5  * found in the LICENSE file. | 
| 6  */ | 6  */ | 
| 7 | 7 | 
| 8 #include "SkCodec_libpng.h" | 8 #include "SkCodec_libpng.h" | 
| 9 #include "SkCodecPriv.h" | 9 #include "SkCodecPriv.h" | 
| 10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" | 
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 207     } | 207     } | 
| 208     return true; | 208     return true; | 
| 209 } | 209 } | 
| 210 | 210 | 
| 211 // Reads the header, and initializes the passed in fields, if not NULL (except | 211 // Reads the header, and initializes the passed in fields, if not NULL (except | 
| 212 // stream, which is passed to the read function). | 212 // stream, which is passed to the read function). | 
| 213 // Returns true on success, in which case the caller is responsible for calling | 213 // Returns true on success, in which case the caller is responsible for calling | 
| 214 // png_destroy_read_struct. If it returns false, the passed in fields (except | 214 // png_destroy_read_struct. If it returns false, the passed in fields (except | 
| 215 // stream) are unchanged. | 215 // stream) are unchanged. | 
| 216 static bool read_header(SkStream* stream, png_structp* png_ptrp, | 216 static bool read_header(SkStream* stream, png_structp* png_ptrp, | 
| 217                         png_infop* info_ptrp, SkImageInfo* imageInfo) { | 217                         png_infop* info_ptrp, SkImageInfo* imageInfo, int* bitDe
     pthPtr) { | 
| 218     // The image is known to be a PNG. Decode enough to know the SkImageInfo. | 218     // The image is known to be a PNG. Decode enough to know the SkImageInfo. | 
| 219     png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, | 219     png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, | 
| 220                                                  sk_error_fn, sk_warning_fn); | 220                                                  sk_error_fn, sk_warning_fn); | 
| 221     if (!png_ptr) { | 221     if (!png_ptr) { | 
| 222         return false; | 222         return false; | 
| 223     } | 223     } | 
| 224 | 224 | 
| 225     AutoCleanPng autoClean(png_ptr); | 225     AutoCleanPng autoClean(png_ptr); | 
| 226 | 226 | 
| 227     png_infop info_ptr = png_create_info_struct(png_ptr); | 227     png_infop info_ptr = png_create_info_struct(png_ptr); | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
| 245     // If it does, we need to figure out a way to set it here. | 245     // If it does, we need to figure out a way to set it here. | 
| 246 | 246 | 
| 247     // The call to png_read_info() gives us all of the information from the | 247     // The call to png_read_info() gives us all of the information from the | 
| 248     // PNG file before the first IDAT (image data chunk). | 248     // PNG file before the first IDAT (image data chunk). | 
| 249     png_read_info(png_ptr, info_ptr); | 249     png_read_info(png_ptr, info_ptr); | 
| 250     png_uint_32 origWidth, origHeight; | 250     png_uint_32 origWidth, origHeight; | 
| 251     int bitDepth, colorType; | 251     int bitDepth, colorType; | 
| 252     png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, | 252     png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, | 
| 253                  &colorType, int_p_NULL, int_p_NULL, int_p_NULL); | 253                  &colorType, int_p_NULL, int_p_NULL, int_p_NULL); | 
| 254 | 254 | 
|  | 255     if (bitDepthPtr) { | 
|  | 256         *bitDepthPtr = bitDepth; | 
|  | 257     } | 
|  | 258 | 
| 255     // sanity check for size | 259     // sanity check for size | 
| 256     { | 260     { | 
| 257         int64_t size = sk_64_mul(origWidth, origHeight); | 261         int64_t size = sk_64_mul(origWidth, origHeight); | 
| 258         // now check that if we are 4-bytes per pixel, we also don't overflow | 262         // now check that if we are 4-bytes per pixel, we also don't overflow | 
| 259         if (size < 0 || size > (0x7FFFFFFF >> 2)) { | 263         if (size < 0 || size > (0x7FFFFFFF >> 2)) { | 
| 260             return false; | 264             return false; | 
| 261         } | 265         } | 
| 262     } | 266     } | 
| 263 | 267 | 
| 264     // Tell libpng to strip 16 bit/color files down to 8 bits/color | 268     // Tell libpng to strip 16 bit/color files down to 8 bits/color | 
| 265     if (bitDepth == 16) { | 269     if (bitDepth == 16) { | 
| 266         png_set_strip_16(png_ptr); | 270         png_set_strip_16(png_ptr); | 
| 267     } | 271     } | 
| 268 #ifdef PNG_READ_PACK_SUPPORTED | 272 #ifdef PNG_READ_PACK_SUPPORTED | 
| 269     // Extract multiple pixels with bit depths of 1, 2, and 4 from a single | 273     // Extract multiple pixels with bit depths of 1, 2, and 4 from a single | 
| 270     // byte into separate bytes (useful for paletted and grayscale images). | 274     // byte into separate bytes (useful for paletted and grayscale images). | 
| 271     if (bitDepth < 8) { | 275     if (bitDepth < 8) { | 
| 272         png_set_packing(png_ptr); | 276         png_set_packing(png_ptr); | 
| 273     } | 277     } | 
| 274 #endif | 278 #endif | 
| 275     // Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel. | 279     // Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel. | 
| 276     if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) { | 280     if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) { | 
| 277         png_set_expand_gray_1_2_4_to_8(png_ptr); | 281         png_set_expand_gray_1_2_4_to_8(png_ptr); | 
| 278     } | 282     } | 
| 279 | 283 | 
| 280 | 284     // Now determine the default SkColorType and SkAlphaType and set required tr
     ansforms | 
| 281     // Now determine the default SkColorType and SkAlphaType. |  | 
| 282     SkColorType skColorType; | 285     SkColorType skColorType; | 
| 283     SkAlphaType skAlphaType; | 286     SkAlphaType skAlphaType; | 
| 284     switch (colorType) { | 287     switch (colorType) { | 
| 285         case PNG_COLOR_TYPE_PALETTE: | 288         case PNG_COLOR_TYPE_PALETTE: | 
| 286             skColorType = kIndex_8_SkColorType; | 289             skColorType = kIndex_8_SkColorType; | 
| 287             skAlphaType = has_transparency_in_palette(png_ptr, info_ptr) ? | 290             skAlphaType = has_transparency_in_palette(png_ptr, info_ptr) ? | 
| 288                     kUnpremul_SkAlphaType : kOpaque_SkAlphaType; | 291                     kUnpremul_SkAlphaType : kOpaque_SkAlphaType; | 
| 289             break; | 292             break; | 
| 290         case PNG_COLOR_TYPE_GRAY: | 293         case PNG_COLOR_TYPE_RGB: | 
| 291             if (false) { | 294             if (has_transparency_in_palette(png_ptr, info_ptr)) { | 
| 292                 // FIXME: Is this the wrong default behavior? This means if the | 295                 //convert to RGBA with tranparency information in tRNS chunk if 
     it exists | 
| 293                 // caller supplies the info we gave them, they'll get Alpha 8. | 296                 png_set_tRNS_to_alpha(png_ptr); | 
| 294                 skColorType = kAlpha_8_SkColorType; |  | 
| 295                 // FIXME: Strangely, the canonical type for Alpha 8 is Premul. |  | 
| 296                 skAlphaType = kPremul_SkAlphaType; |  | 
| 297             } else { |  | 
| 298                 skColorType = kN32_SkColorType; |  | 
| 299                 skAlphaType = kOpaque_SkAlphaType; |  | 
| 300             } |  | 
| 301             break; |  | 
| 302         default: |  | 
| 303             // Note: This *almost* mimics the code in SkImageDecoder_libpng. |  | 
| 304             // has_transparency_in_palette makes an additional check - whether |  | 
| 305             // numTrans is greater than 0. Why does the other code not make that |  | 
| 306             // check? |  | 
| 307             if (has_transparency_in_palette(png_ptr, info_ptr) |  | 
| 308                 || PNG_COLOR_TYPE_RGB_ALPHA == colorType |  | 
| 309                 || PNG_COLOR_TYPE_GRAY_ALPHA == colorType) |  | 
| 310             { |  | 
| 311                 skAlphaType = kUnpremul_SkAlphaType; | 297                 skAlphaType = kUnpremul_SkAlphaType; | 
| 312             } else { | 298             } else { | 
|  | 299                 //convert to RGBA with Opaque Alpha | 
|  | 300                 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); | 
| 313                 skAlphaType = kOpaque_SkAlphaType; | 301                 skAlphaType = kOpaque_SkAlphaType; | 
| 314             } | 302             } | 
| 315             skColorType = kN32_SkColorType; | 303             skColorType = kN32_SkColorType; | 
| 316             break; | 304             break; | 
| 317     } | 305         case PNG_COLOR_TYPE_GRAY: | 
| 318 | 306             if (has_transparency_in_palette(png_ptr, info_ptr)) { | 
| 319     { | 307                 //FIXME: support gray with alpha as a color type | 
| 320         // FIXME: Again, this block needs to go into onGetPixels. | 308                 //convert to RGBA if there is transparentcy info in the tRNS chu
     nk | 
| 321         bool convertGrayToRGB = PNG_COLOR_TYPE_GRAY == colorType && skColorType 
     != kAlpha_8_SkColorType; | 309                 png_set_tRNS_to_alpha(png_ptr); | 
| 322 | 310                 png_set_gray_to_rgb(png_ptr); | 
| 323         // Unless the user is requesting A8, convert a grayscale image into RGB. | 311                 skColorType = kN32_SkColorType; | 
| 324         // GRAY_ALPHA will always be converted to RGB | 312                 skAlphaType = kUnpremul_SkAlphaType; | 
| 325         if (convertGrayToRGB || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) { | 313             } else { | 
|  | 314                 skColorType = kGray_8_SkColorType; | 
|  | 315                 skAlphaType = kOpaque_SkAlphaType; | 
|  | 316             } | 
|  | 317             break; | 
|  | 318         case PNG_COLOR_TYPE_GRAY_ALPHA: | 
|  | 319             //FIXME: support gray with alpha as a color type | 
|  | 320             //convert to RGBA | 
| 326             png_set_gray_to_rgb(png_ptr); | 321             png_set_gray_to_rgb(png_ptr); | 
| 327         } | 322             skColorType = kN32_SkColorType; | 
| 328 | 323             skAlphaType = kUnpremul_SkAlphaType; | 
| 329         // Add filler (or alpha) byte (after each RGB triplet) if necessary. | 324             break; | 
| 330         // FIXME: It seems like we could just use RGB as the SrcConfig here. | 325         case PNG_COLOR_TYPE_RGBA: | 
| 331         if (colorType == PNG_COLOR_TYPE_RGB || convertGrayToRGB) { | 326             skColorType = kN32_SkColorType; | 
| 332             png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); | 327             skAlphaType = kUnpremul_SkAlphaType; | 
| 333         } | 328             break; | 
|  | 329         default: | 
|  | 330             //all the color types have been covered above | 
|  | 331             SkASSERT(false); | 
| 334     } | 332     } | 
| 335 | 333 | 
| 336     // FIXME: Also need to check for sRGB (skbug.com/3471). | 334     // FIXME: Also need to check for sRGB (skbug.com/3471). | 
| 337 | 335 | 
| 338     if (imageInfo) { | 336     if (imageInfo) { | 
| 339         *imageInfo = SkImageInfo::Make(origWidth, origHeight, skColorType, | 337         *imageInfo = SkImageInfo::Make(origWidth, origHeight, skColorType, skAlp
     haType); | 
| 340                                        skAlphaType); |  | 
| 341     } | 338     } | 
| 342     autoClean.detach(); | 339     autoClean.detach(); | 
| 343     if (png_ptrp) { | 340     if (png_ptrp) { | 
| 344         *png_ptrp = png_ptr; | 341         *png_ptrp = png_ptr; | 
| 345     } | 342     } | 
| 346     if (info_ptrp) { | 343     if (info_ptrp) { | 
| 347         *info_ptrp = info_ptr; | 344         *info_ptrp = info_ptr; | 
| 348     } | 345     } | 
| 349     return true; | 346     return true; | 
| 350 } | 347 } | 
| 351 | 348 | 
| 352 SkCodec* SkPngCodec::NewFromStream(SkStream* stream) { | 349 SkCodec* SkPngCodec::NewFromStream(SkStream* stream) { | 
| 353     SkAutoTDelete<SkStream> streamDeleter(stream); | 350     SkAutoTDelete<SkStream> streamDeleter(stream); | 
| 354     png_structp png_ptr; | 351     png_structp png_ptr; | 
| 355     png_infop info_ptr; | 352     png_infop info_ptr; | 
| 356     SkImageInfo imageInfo; | 353     SkImageInfo imageInfo; | 
| 357     if (read_header(stream, &png_ptr, &info_ptr, &imageInfo)) { | 354     int bitDepth; | 
| 358         return SkNEW_ARGS(SkPngCodec, (imageInfo, streamDeleter.detach(), png_pt
     r, info_ptr)); | 355     if (read_header(stream, &png_ptr, &info_ptr, &imageInfo, &bitDepth)) { | 
|  | 356         return SkNEW_ARGS(SkPngCodec, (imageInfo, streamDeleter.detach(), | 
|  | 357                 png_ptr, info_ptr, bitDepth)); | 
| 359     } | 358     } | 
| 360     return NULL; | 359     return NULL; | 
| 361 } | 360 } | 
| 362 | 361 | 
| 363 #define INVALID_NUMBER_PASSES -1 | 362 #define INVALID_NUMBER_PASSES -1 | 
| 364 SkPngCodec::SkPngCodec(const SkImageInfo& info, SkStream* stream, | 363 SkPngCodec::SkPngCodec(const SkImageInfo& info, SkStream* stream, | 
| 365                        png_structp png_ptr, png_infop info_ptr) | 364                        png_structp png_ptr, png_infop info_ptr, int bitDepth) | 
| 366     : INHERITED(info, stream) | 365     : INHERITED(info, stream) | 
| 367     , fPng_ptr(png_ptr) | 366     , fPng_ptr(png_ptr) | 
| 368     , fInfo_ptr(info_ptr) | 367     , fInfo_ptr(info_ptr) | 
| 369     , fSrcConfig(SkSwizzler::kUnknown) | 368     , fSrcConfig(SkSwizzler::kUnknown) | 
| 370     , fNumberPasses(INVALID_NUMBER_PASSES) | 369     , fNumberPasses(INVALID_NUMBER_PASSES) | 
| 371     , fReallyHasAlpha(false) | 370     , fReallyHasAlpha(false) | 
|  | 371     , fBitDepth(bitDepth) | 
| 372 {} | 372 {} | 
| 373 | 373 | 
| 374 SkPngCodec::~SkPngCodec() { | 374 SkPngCodec::~SkPngCodec() { | 
| 375     this->destroyReadStruct(); | 375     this->destroyReadStruct(); | 
| 376 } | 376 } | 
| 377 | 377 | 
| 378 void SkPngCodec::destroyReadStruct() { | 378 void SkPngCodec::destroyReadStruct() { | 
| 379     if (fPng_ptr) { | 379     if (fPng_ptr) { | 
| 380         // We will never have a NULL fInfo_ptr with a non-NULL fPng_ptr | 380         // We will never have a NULL fInfo_ptr with a non-NULL fPng_ptr | 
| 381         SkASSERT(fInfo_ptr); | 381         SkASSERT(fInfo_ptr); | 
| (...skipping 24 matching lines...) Expand all  Loading... | 
| 406         switch (dst.alphaType()) { | 406         switch (dst.alphaType()) { | 
| 407             case kPremul_SkAlphaType: | 407             case kPremul_SkAlphaType: | 
| 408             case kUnpremul_SkAlphaType: | 408             case kUnpremul_SkAlphaType: | 
| 409                 // The source is not opaque, so either of these is okay | 409                 // The source is not opaque, so either of these is okay | 
| 410                 break; | 410                 break; | 
| 411             default: | 411             default: | 
| 412                 // We cannot decode a non-opaque image to opaque (or unknown) | 412                 // We cannot decode a non-opaque image to opaque (or unknown) | 
| 413                 return false; | 413                 return false; | 
| 414         } | 414         } | 
| 415     } | 415     } | 
| 416 |  | 
| 417     // Check for supported color types | 416     // Check for supported color types | 
| 418     switch (dst.colorType()) { | 417     switch (dst.colorType()) { | 
| 419         // Allow output to kN32 from any type of input | 418         case kRGBA_8888_SkColorType: | 
| 420         case kN32_SkColorType: | 419             return true; | 
|  | 420         case kBGRA_8888_SkColorType: | 
| 421             return true; | 421             return true; | 
| 422         default: | 422         default: | 
| 423             return dst.colorType() == src.colorType(); | 423             return dst.colorType() == src.colorType(); | 
| 424     } | 424     } | 
| 425 } | 425 } | 
| 426 | 426 | 
| 427 SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo, | 427 SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo, | 
| 428                                                void* dst, size_t rowBytes, | 428                                                void* dst, size_t rowBytes, | 
| 429                                                const Options& options, | 429                                                const Options& options, | 
| 430                                                SkPMColor ctable[], | 430                                                SkPMColor ctable[], | 
| 431                                                int* ctableCount) { | 431                                                int* ctableCount) { | 
| 432     // FIXME: Could we use the return value of setjmp to specify the type of | 432     // FIXME: Could we use the return value of setjmp to specify the type of | 
| 433     // error? | 433     // error? | 
| 434     if (setjmp(png_jmpbuf(fPng_ptr))) { | 434     if (setjmp(png_jmpbuf(fPng_ptr))) { | 
| 435         SkCodecPrintf("setjmp long jump!\n"); | 435         SkCodecPrintf("setjmp long jump!\n"); | 
| 436         return kInvalidInput; | 436         return kInvalidInput; | 
| 437     } | 437     } | 
| 438 | 438 | 
| 439     // FIXME: We already retrieved this information. Store it in SkPngCodec? |  | 
| 440     png_uint_32 origWidth, origHeight; |  | 
| 441     int bitDepth, pngColorType, interlaceType; |  | 
| 442     png_get_IHDR(fPng_ptr, fInfo_ptr, &origWidth, &origHeight, &bitDepth, |  | 
| 443                  &pngColorType, &interlaceType, int_p_NULL, int_p_NULL); |  | 
| 444 |  | 
| 445     fNumberPasses = (interlaceType != PNG_INTERLACE_NONE) ? |  | 
| 446             png_set_interlace_handling(fPng_ptr) : 1; |  | 
| 447 |  | 
| 448     // Set to the default before calling decodePalette, which may change it. | 439     // Set to the default before calling decodePalette, which may change it. | 
| 449     fReallyHasAlpha = false; | 440     fReallyHasAlpha = false; | 
| 450     if (PNG_COLOR_TYPE_PALETTE == pngColorType) { | 441 | 
| 451         fSrcConfig = SkSwizzler::kIndex; | 442     //srcColorType was determined in readHeader() which determined png color typ
     e | 
| 452         if (!this->decodePalette(kPremul_SkAlphaType == requestedInfo.alphaType(
     ), bitDepth, | 443     const SkColorType srcColorType = this->getInfo().colorType(); | 
| 453                 ctableCount)) { | 444     const SkColorType dstColorType = requestedInfo.colorType(); | 
| 454             return kInvalidInput; | 445     //set swizzler fSrcConfig to dstColorType, as libbpng will convert from srcC
     olorType | 
| 455         } | 446     //to dstColorType thanks to the transforms we have specified in setDataForma
     t() | 
| 456     } else if (kAlpha_8_SkColorType == requestedInfo.colorType()) { | 447     //Swizzler still needed for premultiplying | 
| 457         // Note: we check the destination, since otherwise we would have | 448     switch (dstColorType) { | 
| 458         // told png to upscale. | 449         case kIndex_8_SkColorType: | 
| 459         SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); | 450             //decode palette to Skia format | 
| 460         fSrcConfig = SkSwizzler::kGray; | 451             fSrcConfig = SkSwizzler::kIndex; | 
| 461     } else if (this->getInfo().alphaType() == kOpaque_SkAlphaType) { | 452             if (!this->decodePalette(kPremul_SkAlphaType == requestedInfo.alphaT
     ype(), fBitDepth, | 
| 462         fSrcConfig = SkSwizzler::kRGBX; | 453                     ctableCount)) { | 
| 463     } else { | 454                 return kInvalidInput; | 
| 464         fSrcConfig = SkSwizzler::kRGBA; | 455             } | 
| 465     } | 456             break; | 
|  | 457         case kGray_8_SkColorType: | 
|  | 458             fSrcConfig = SkSwizzler::kGray; | 
|  | 459             break; | 
|  | 460         case kRGBA_8888_SkColorType: | 
|  | 461             if (this->getInfo().alphaType() == kOpaque_SkAlphaType) { | 
|  | 462                     fSrcConfig = SkSwizzler::kRGBX; | 
|  | 463                 } else { | 
|  | 464                     fSrcConfig = SkSwizzler::kRGBA; | 
|  | 465             } | 
|  | 466             break; | 
|  | 467         case kBGRA_8888_SkColorType: | 
|  | 468             if (this->getInfo().alphaType() == kOpaque_SkAlphaType) { | 
|  | 469                 fSrcConfig = SkSwizzler::kBGRX; | 
|  | 470             } else { | 
|  | 471                 fSrcConfig = SkSwizzler::kBGRA; | 
|  | 472             } | 
|  | 473             break; | 
|  | 474         default: | 
|  | 475             //would have excited before now if the colorType was supported by pn
     g | 
|  | 476             SkASSERT(false); | 
|  | 477     } | 
| 466 | 478 | 
| 467     // Copy the color table to the client if they request kIndex8 mode | 479     // Copy the color table to the client if they request kIndex8 mode | 
| 468     copy_color_table(requestedInfo, fColorTable, ctable, ctableCount); | 480     copy_color_table(requestedInfo, fColorTable, ctable, ctableCount); | 
| 469 | 481 | 
| 470     // Create the swizzler.  SkPngCodec retains ownership of the color table. | 482     // Create the swizzler.  SkPngCodec retains ownership of the color table. | 
| 471     const SkPMColor* colors = fColorTable ? fColorTable->readColors() : NULL; | 483     const SkPMColor* colors = fColorTable ? fColorTable->readColors() : NULL; | 
| 472     fSwizzler.reset(SkSwizzler::CreateSwizzler(fSrcConfig, colors, requestedInfo
     , | 484     fSwizzler.reset(SkSwizzler::CreateSwizzler(fSrcConfig, colors, requestedInfo
     , | 
| 473             dst, rowBytes, options.fZeroInitialized)); | 485             dst, rowBytes, options.fZeroInitialized)); | 
| 474     if (!fSwizzler) { | 486     if (!fSwizzler) { | 
| 475         // FIXME: CreateSwizzler could fail for another reason. | 487         // FIXME: CreateSwizzler could fail for another reason. | 
| 476         return kUnimplemented; | 488         return kUnimplemented; | 
| 477     } | 489     } | 
| 478 |  | 
| 479     // FIXME: Here is where we should likely insert some of the modifications |  | 
| 480     // made in the factory. |  | 
| 481     png_read_update_info(fPng_ptr, fInfo_ptr); |  | 
| 482 |  | 
| 483     return kSuccess; | 490     return kSuccess; | 
| 484 } | 491 } | 
| 485 | 492 | 
| 486 bool SkPngCodec::handleRewind() { | 493 SkCodec::Result SkPngCodec::setDataFormat(const SkImageInfo& requestedInfo) { | 
|  | 494     if (setjmp(png_jmpbuf(fPng_ptr))) { | 
|  | 495         SkCodecPrintf("setjmp long jump in SkPngCodec::setDataFormat()\n"); | 
|  | 496         return kInvalidInput; | 
|  | 497     } | 
|  | 498 | 
|  | 499     fNumberPasses = png_set_interlace_handling(fPng_ptr); | 
|  | 500 | 
|  | 501      //srcColorType was determined in readHeader() which determined png color ty
     pe | 
|  | 502     const SkColorType srcColorType = this->getInfo().colorType(); | 
|  | 503     const SkColorType dstColorType = requestedInfo.colorType(); | 
|  | 504     if (kRGBA_8888_SkColorType == dstColorType || kBGRA_8888_SkColorType == dstC
     olorType) { | 
|  | 505         if (kIndex_8_SkColorType == srcColorType) { | 
|  | 506             //convert paletted images to RGBA | 
|  | 507             png_set_palette_to_rgb(fPng_ptr); | 
|  | 508             if (png_get_valid(fPng_ptr, fInfo_ptr, PNG_INFO_tRNS)) { | 
|  | 509                 png_set_tRNS_to_alpha(fPng_ptr); | 
|  | 510             } else { | 
|  | 511                 png_set_filler(fPng_ptr, 0xff, PNG_FILLER_AFTER); | 
|  | 512             } | 
|  | 513         } else if (kGray_8_SkColorType == srcColorType) { | 
|  | 514             //convert from Gray to RGBA (need to add filler for alpha as gray ha
     s no alpha) | 
|  | 515             png_set_gray_to_rgb(fPng_ptr); | 
|  | 516             png_set_filler(fPng_ptr, 0xff, PNG_FILLER_AFTER); | 
|  | 517         } | 
|  | 518         if (kBGRA_8888_SkColorType == dstColorType) { | 
|  | 519             //convert RGBA to BGRA | 
|  | 520             png_set_bgr(fPng_ptr); | 
|  | 521         } | 
|  | 522     } | 
|  | 523 | 
|  | 524     png_read_update_info(fPng_ptr, fInfo_ptr); | 
|  | 525     return kSuccess; | 
|  | 526 } | 
|  | 527 | 
|  | 528 bool SkPngCodec::handleRewind(const SkImageInfo& requestedInfo) { | 
| 487     switch (this->rewindIfNeeded()) { | 529     switch (this->rewindIfNeeded()) { | 
| 488         case kNoRewindNecessary_RewindState: | 530         case kNoRewindNecessary_RewindState: | 
|  | 531             //set transforms needed for requestedInfo format | 
|  | 532             if (kSuccess != this->setDataFormat(requestedInfo)) { | 
|  | 533                 return false; | 
|  | 534             } | 
| 489             return true; | 535             return true; | 
| 490         case kCouldNotRewind_RewindState: | 536         case kCouldNotRewind_RewindState: | 
| 491             return false; | 537             return false; | 
| 492         case kRewound_RewindState: { | 538         case kRewound_RewindState: { | 
| 493             // This sets fPng_ptr and fInfo_ptr to NULL. If read_header | 539             // This sets fPng_ptr and fInfo_ptr to NULL. If read_header | 
| 494             // succeeds, they will be repopulated, and if it fails, they will | 540             // succeeds, they will be repopulated, and if it fails, they will | 
| 495             // remain NULL. Any future accesses to fPng_ptr and fInfo_ptr will | 541             // remain NULL. Any future accesses to fPng_ptr and fInfo_ptr will | 
| 496             // come through this function which will rewind and again attempt | 542             // come through this function which will rewind and again attempt | 
| 497             // to reinitialize them. | 543             // to reinitialize them. | 
| 498             this->destroyReadStruct(); | 544             this->destroyReadStruct(); | 
| 499             png_structp png_ptr; | 545             png_structp png_ptr; | 
| 500             png_infop info_ptr; | 546             png_infop info_ptr; | 
| 501             if (read_header(this->stream(), &png_ptr, &info_ptr, NULL)) { | 547             if (read_header(this->stream(), &png_ptr, &info_ptr, NULL, NULL)) { | 
| 502                 fPng_ptr = png_ptr; | 548                 fPng_ptr = png_ptr; | 
| 503                 fInfo_ptr = info_ptr; | 549                 fInfo_ptr = info_ptr; | 
|  | 550                 //set transforms needed for requestedInfo format | 
|  | 551                 if (kSuccess != this->setDataFormat(requestedInfo)) { | 
|  | 552                     return false; | 
|  | 553                 } | 
| 504                 return true; | 554                 return true; | 
| 505             } | 555             } | 
| 506             return false; | 556             return false; | 
| 507         } | 557         } | 
| 508         default: | 558         default: | 
| 509             SkASSERT(false); | 559             SkASSERT(false); | 
| 510             return false; | 560             return false; | 
| 511     } | 561     } | 
| 512 } | 562 } | 
| 513 | 563 | 
| 514 SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void* 
     dst, | 564 SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void* 
     dst, | 
| 515                                         size_t rowBytes, const Options& options, | 565                                         size_t rowBytes, const Options& options, | 
| 516                                         SkPMColor ctable[], int* ctableCount) { | 566                                         SkPMColor ctable[], int* ctableCount) { | 
| 517     if (!this->handleRewind()) { | 567     if (!conversion_possible(requestedInfo, this->getInfo())) { | 
| 518         return kCouldNotRewind; | 568         return kInvalidConversion; | 
| 519     } | 569     } | 
| 520     if (requestedInfo.dimensions() != this->getInfo().dimensions()) { | 570     if (requestedInfo.dimensions() != this->getInfo().dimensions()) { | 
| 521         return kInvalidScale; | 571         return kInvalidScale; | 
| 522     } | 572     } | 
| 523     if (!conversion_possible(requestedInfo, this->getInfo())) { | 573     if (!this->handleRewind(requestedInfo)) { | 
| 524         return kInvalidConversion; | 574         return kCouldNotRewind; | 
| 525     } | 575     } | 
| 526 | 576 | 
| 527     // Note that ctable and ctableCount may be modified if there is a color tabl
     e | 577     // Note that ctable and ctableCount may be modified if there is a color tabl
     e | 
| 528     const Result result = this->initializeSwizzler(requestedInfo, dst, rowBytes, | 578     const Result result = this->initializeSwizzler(requestedInfo, dst, rowBytes, | 
| 529                                                    options, ctable, ctableCount)
     ; | 579                                                    options, ctable, ctableCount)
     ; | 
| 530 |  | 
| 531     if (result != kSuccess) { | 580     if (result != kSuccess) { | 
| 532         return result; | 581         return result; | 
| 533     } | 582     } | 
| 534 |  | 
| 535     // FIXME: Could we use the return value of setjmp to specify the type of | 583     // FIXME: Could we use the return value of setjmp to specify the type of | 
| 536     // error? | 584     // error? | 
| 537     if (setjmp(png_jmpbuf(fPng_ptr))) { | 585     if (setjmp(png_jmpbuf(fPng_ptr))) { | 
| 538         SkCodecPrintf("setjmp long jump!\n"); | 586         SkCodecPrintf("setjmp long jump!\n"); | 
| 539         return kInvalidInput; | 587         return kInvalidInput; | 
| 540     } | 588     } | 
| 541 | 589 | 
| 542     SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES); | 590     SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES); | 
| 543     SkAutoMalloc storage; | 591     SkAutoMalloc storage; | 
| 544     if (fNumberPasses > 1) { | 592     if (fNumberPasses > 1) { | 
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 650 | 698 | 
| 651 | 699 | 
| 652 class SkPngInterlacedScanlineDecoder : public SkScanlineDecoder { | 700 class SkPngInterlacedScanlineDecoder : public SkScanlineDecoder { | 
| 653 public: | 701 public: | 
| 654     SkPngInterlacedScanlineDecoder(const SkImageInfo& dstInfo, SkPngCodec* codec
     ) | 702     SkPngInterlacedScanlineDecoder(const SkImageInfo& dstInfo, SkPngCodec* codec
     ) | 
| 655         : INHERITED(dstInfo) | 703         : INHERITED(dstInfo) | 
| 656         , fCodec(codec) | 704         , fCodec(codec) | 
| 657         , fHasAlpha(false) | 705         , fHasAlpha(false) | 
| 658         , fCurrentRow(0) | 706         , fCurrentRow(0) | 
| 659         , fHeight(dstInfo.height()) | 707         , fHeight(dstInfo.height()) | 
| 660         , fSrcRowBytes(dstInfo.minRowBytes()) |  | 
| 661         , fRewindNeeded(false) | 708         , fRewindNeeded(false) | 
| 662     { | 709     { | 
|  | 710         fSrcRowBytes = dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcC
     onfig); | 
| 663         fGarbageRow.reset(fSrcRowBytes); | 711         fGarbageRow.reset(fSrcRowBytes); | 
| 664         fGarbageRowPtr = static_cast<uint8_t*>(fGarbageRow.get()); | 712         fGarbageRowPtr = static_cast<uint8_t*>(fGarbageRow.get()); | 
| 665     } | 713     } | 
| 666 | 714 | 
| 667     SkImageGenerator::Result onGetScanlines(void* dst, int count, size_t dstRowB
     ytes) override { | 715     SkImageGenerator::Result onGetScanlines(void* dst, int count, size_t dstRowB
     ytes) override { | 
| 668         //rewind stream if have previously called onGetScanlines, | 716         //rewind stream if have previously called onGetScanlines, | 
| 669         //since we need entire progressive image to get scanlines | 717         //since we need entire progressive image to get scanlines | 
|  | 718         //need to reset transforms in setDataFormat if stream is rewound | 
| 670         if (fRewindNeeded) { | 719         if (fRewindNeeded) { | 
| 671             if(false == fCodec->handleRewind()) { | 720             if(false == fCodec->handleRewind(this->dstInfo())) { | 
| 672                 return SkImageGenerator::kCouldNotRewind; | 721                 return SkImageGenerator::kCouldNotRewind; | 
| 673             } | 722             } | 
| 674         } else { | 723         } else { | 
| 675             fRewindNeeded = true; | 724             fRewindNeeded = true; | 
| 676         } | 725         } | 
| 677         if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { | 726         if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { | 
| 678             SkCodecPrintf("setjmp long jump!\n"); | 727             SkCodecPrintf("setjmp long jump!\n"); | 
| 679             return SkImageGenerator::kInvalidInput; | 728             return SkImageGenerator::kInvalidInput; | 
| 680         } | 729         } | 
| 681         const int number_passes = png_set_interlace_handling(fCodec->fPng_ptr); | 730         const int number_passes = png_set_interlace_handling(fCodec->fPng_ptr); | 
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 724 | 773 | 
| 725 private: | 774 private: | 
| 726     SkPngCodec*         fCodec;     // Unowned. | 775     SkPngCodec*         fCodec;     // Unowned. | 
| 727     bool                fHasAlpha; | 776     bool                fHasAlpha; | 
| 728     int                 fCurrentRow; | 777     int                 fCurrentRow; | 
| 729     int                 fHeight; | 778     int                 fHeight; | 
| 730     size_t              fSrcRowBytes; | 779     size_t              fSrcRowBytes; | 
| 731     bool                fRewindNeeded; | 780     bool                fRewindNeeded; | 
| 732     SkAutoMalloc        fGarbageRow; | 781     SkAutoMalloc        fGarbageRow; | 
| 733     uint8_t*            fGarbageRowPtr; | 782     uint8_t*            fGarbageRowPtr; | 
| 734 |  | 
| 735 |  | 
| 736 |  | 
| 737 |  | 
| 738 |  | 
| 739     typedef SkScanlineDecoder INHERITED; | 783     typedef SkScanlineDecoder INHERITED; | 
| 740 }; | 784 }; | 
| 741 | 785 | 
| 742 | 786 | 
| 743 SkScanlineDecoder* SkPngCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo, | 787 SkScanlineDecoder* SkPngCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo, | 
| 744         const Options& options, SkPMColor ctable[], int* ctableCount) { | 788         const Options& options, SkPMColor ctable[], int* ctableCount) { | 
| 745     if (!this->handleRewind()) { | 789     if (!conversion_possible(dstInfo, this->getInfo())) { | 
|  | 790         SkCodecPrintf("no conversion possible\n"); | 
| 746         return NULL; | 791         return NULL; | 
| 747     } | 792     } | 
| 748 |  | 
| 749     // Check to see if scaling was requested. | 793     // Check to see if scaling was requested. | 
| 750     if (dstInfo.dimensions() != this->getInfo().dimensions()) { | 794     if (dstInfo.dimensions() != this->getInfo().dimensions()) { | 
| 751         return NULL; | 795         return NULL; | 
| 752     } | 796     } | 
| 753 | 797     if (!this->handleRewind(dstInfo)) { | 
| 754     if (!conversion_possible(dstInfo, this->getInfo())) { |  | 
| 755         SkCodecPrintf("no conversion possible\n"); |  | 
| 756         return NULL; | 798         return NULL; | 
| 757     } | 799     } | 
| 758 | 800 | 
| 759     // Note: We set dst to NULL since we do not know it yet. rowBytes is not nee
     ded, | 801     // Note: We set dst to NULL since we do not know it yet. rowBytes is not nee
     ded, | 
| 760     // since we'll be manually updating the dstRow, but the SkSwizzler requires 
     it to | 802     // since we'll be manually updating the dstRow, but the SkSwizzler requires 
     it to | 
| 761     // be at least dstInfo.minRowBytes. | 803     // be at least dstInfo.minRowBytes. | 
| 762     if (this->initializeSwizzler(dstInfo, NULL, dstInfo.minRowBytes(), options, 
     ctable, | 804     if (this->initializeSwizzler(dstInfo, NULL, dstInfo.minRowBytes(), options, 
     ctable, | 
| 763             ctableCount) != kSuccess) { | 805             ctableCount) != kSuccess) { | 
| 764         SkCodecPrintf("failed to initialize the swizzler.\n"); | 806         SkCodecPrintf("failed to initialize the swizzler.\n"); | 
| 765         return NULL; | 807         return NULL; | 
| 766     } | 808     } | 
| 767 | 809 | 
| 768     SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES); | 810     SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES); | 
| 769     if (fNumberPasses > 1) { | 811     if (fNumberPasses > 1) { | 
| 770         // interlaced image | 812         // interlaced image | 
| 771         return SkNEW_ARGS(SkPngInterlacedScanlineDecoder, (dstInfo, this)); | 813         return SkNEW_ARGS(SkPngInterlacedScanlineDecoder, (dstInfo, this)); | 
| 772     } | 814     } | 
| 773 | 815 | 
| 774     return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, this)); | 816     return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, this)); | 
| 775 } | 817 } | 
| 776 | 818 | 
| OLD | NEW | 
|---|