OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
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 "SkImageDecoder.h" | 8 #include "SkImageDecoder.h" |
9 #include "SkImageEncoder.h" | 9 #include "SkImageEncoder.h" |
10 #include "SkColor.h" | 10 #include "SkColor.h" |
11 #include "SkColorPriv.h" | 11 #include "SkColorPriv.h" |
12 #include "SkDither.h" | 12 #include "SkDither.h" |
13 #include "SkMath.h" | 13 #include "SkMath.h" |
14 #include "SkRTConf.h" | 14 #include "SkRTConf.h" |
15 #include "SkScaledBitmapSampler.h" | 15 #include "SkScaledBitmapSampler.h" |
16 #include "SkStream.h" | 16 #include "SkStream.h" |
17 #include "SkTemplates.h" | 17 #include "SkTemplates.h" |
18 #include "SkUtils.h" | 18 #include "SkUtils.h" |
19 #include "transform_scanline.h" | 19 #include "transform_scanline.h" |
20 | 20 |
21 #ifdef SKIA_PNG_PREFIXED | 21 #ifdef SKIA_PNG_PREFIXED |
22 // this must proceed png.h | 22 // this must proceed png.h |
23 #include "pngprefix.h" | 23 #include "pngprefix.h" |
24 #endif | 24 #endif |
25 #include "png.h" | 25 #include "png.h" |
26 | 26 |
27 /* These were dropped in libpng >= 1.4 */ | 27 /* These were dropped in libpng >= 1.4 */ |
28 #ifndef png_infopp_NULL | 28 #ifndef png_infopp_NULL |
29 #define png_infopp_NULL NULL | 29 #define png_infopp_NULL nullptr |
30 #endif | 30 #endif |
31 | 31 |
32 #ifndef png_bytepp_NULL | 32 #ifndef png_bytepp_NULL |
33 #define png_bytepp_NULL NULL | 33 #define png_bytepp_NULL nullptr |
34 #endif | 34 #endif |
35 | 35 |
36 #ifndef int_p_NULL | 36 #ifndef int_p_NULL |
37 #define int_p_NULL NULL | 37 #define int_p_NULL nullptr |
38 #endif | 38 #endif |
39 | 39 |
40 #ifndef png_flush_ptr_NULL | 40 #ifndef png_flush_ptr_NULL |
41 #define png_flush_ptr_NULL NULL | 41 #define png_flush_ptr_NULL nullptr |
42 #endif | 42 #endif |
43 | 43 |
44 #if defined(SK_DEBUG) | 44 #if defined(SK_DEBUG) |
45 #define DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS false | 45 #define DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS false |
46 #else // !defined(SK_DEBUG) | 46 #else // !defined(SK_DEBUG) |
47 #define DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS true | 47 #define DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS true |
48 #endif // defined(SK_DEBUG) | 48 #endif // defined(SK_DEBUG) |
49 SK_CONF_DECLARE(bool, c_suppressPNGImageDecoderWarnings, | 49 SK_CONF_DECLARE(bool, c_suppressPNGImageDecoderWarnings, |
50 "images.png.suppressDecoderWarnings", | 50 "images.png.suppressDecoderWarnings", |
51 DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS, | 51 DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS, |
52 "Suppress most PNG warnings when calling image decode " | 52 "Suppress most PNG warnings when calling image decode " |
53 "functions."); | 53 "functions."); |
54 | 54 |
55 | 55 |
56 | 56 |
57 class SkPNGImageIndex { | 57 class SkPNGImageIndex { |
58 public: | 58 public: |
59 // Takes ownership of stream. | 59 // Takes ownership of stream. |
60 SkPNGImageIndex(SkStreamRewindable* stream, png_structp png_ptr, png_infop i
nfo_ptr) | 60 SkPNGImageIndex(SkStreamRewindable* stream, png_structp png_ptr, png_infop i
nfo_ptr) |
61 : fStream(stream) | 61 : fStream(stream) |
62 , fPng_ptr(png_ptr) | 62 , fPng_ptr(png_ptr) |
63 , fInfo_ptr(info_ptr) | 63 , fInfo_ptr(info_ptr) |
64 , fColorType(kUnknown_SkColorType) { | 64 , fColorType(kUnknown_SkColorType) { |
65 SkASSERT(stream != NULL); | 65 SkASSERT(stream != nullptr); |
66 } | 66 } |
67 ~SkPNGImageIndex() { | 67 ~SkPNGImageIndex() { |
68 if (fPng_ptr) { | 68 if (fPng_ptr) { |
69 png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, png_infopp_NULL); | 69 png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, png_infopp_NULL); |
70 } | 70 } |
71 } | 71 } |
72 | 72 |
73 SkAutoTDelete<SkStreamRewindable> fStream; | 73 SkAutoTDelete<SkStreamRewindable> fStream; |
74 png_structp fPng_ptr; | 74 png_structp fPng_ptr; |
75 png_infop fInfo_ptr; | 75 png_infop fInfo_ptr; |
76 SkColorType fColorType; | 76 SkColorType fColorType; |
77 }; | 77 }; |
78 | 78 |
79 class SkPNGImageDecoder : public SkImageDecoder { | 79 class SkPNGImageDecoder : public SkImageDecoder { |
80 public: | 80 public: |
81 SkPNGImageDecoder() { | 81 SkPNGImageDecoder() { |
82 fImageIndex = NULL; | 82 fImageIndex = nullptr; |
83 } | 83 } |
84 Format getFormat() const override { | 84 Format getFormat() const override { |
85 return kPNG_Format; | 85 return kPNG_Format; |
86 } | 86 } |
87 | 87 |
88 virtual ~SkPNGImageDecoder() { delete fImageIndex; } | 88 virtual ~SkPNGImageDecoder() { delete fImageIndex; } |
89 | 89 |
90 protected: | 90 protected: |
91 #ifdef SK_BUILD_FOR_ANDROID | 91 #ifdef SK_BUILD_FOR_ANDROID |
92 bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *height) o
verride; | 92 bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *height) o
verride; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 return false; | 198 return false; |
199 } | 199 } |
200 } | 200 } |
201 | 201 |
202 // call only if color_type is PALETTE. Returns true if the ctable has alpha | 202 // call only if color_type is PALETTE. Returns true if the ctable has alpha |
203 static bool hasTransparencyInPalette(png_structp png_ptr, png_infop info_ptr) { | 203 static bool hasTransparencyInPalette(png_structp png_ptr, png_infop info_ptr) { |
204 png_bytep trans; | 204 png_bytep trans; |
205 int num_trans; | 205 int num_trans; |
206 | 206 |
207 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { | 207 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { |
208 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); | 208 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, nullptr); |
209 return num_trans > 0; | 209 return num_trans > 0; |
210 } | 210 } |
211 return false; | 211 return false; |
212 } | 212 } |
213 | 213 |
214 void do_nothing_warning_fn(png_structp, png_const_charp) { | 214 void do_nothing_warning_fn(png_structp, png_const_charp) { |
215 /* do nothing */ | 215 /* do nothing */ |
216 } | 216 } |
217 | 217 |
218 bool SkPNGImageDecoder::onDecodeInit(SkStream* sk_stream, png_structp *png_ptrp, | 218 bool SkPNGImageDecoder::onDecodeInit(SkStream* sk_stream, png_structp *png_ptrp, |
219 png_infop *info_ptrp) { | 219 png_infop *info_ptrp) { |
220 /* Create and initialize the png_struct with the desired error handler | 220 /* Create and initialize the png_struct with the desired error handler |
221 * functions. If you want to use the default stderr and longjump method, | 221 * functions. If you want to use the default stderr and longjump method, |
222 * you can supply NULL for the last three parameters. We also supply the | 222 * you can supply nullptr for the last three parameters. We also supply the |
223 * the compiler header file version, so that we know if the application | 223 * the compiler header file version, so that we know if the application |
224 * was compiled with a compatible version of the library. */ | 224 * was compiled with a compatible version of the library. */ |
225 | 225 |
226 png_error_ptr user_warning_fn = | 226 png_error_ptr user_warning_fn = |
227 (c_suppressPNGImageDecoderWarnings) ? (&do_nothing_warning_fn) : NULL; | 227 (c_suppressPNGImageDecoderWarnings) ? (&do_nothing_warning_fn) : nullptr
; |
228 /* NULL means to leave as default library behavior. */ | 228 /* nullptr means to leave as default library behavior. */ |
229 /* c_suppressPNGImageDecoderWarnings default depends on SK_DEBUG. */ | 229 /* c_suppressPNGImageDecoderWarnings default depends on SK_DEBUG. */ |
230 /* To suppress warnings with a SK_DEBUG binary, set the | 230 /* To suppress warnings with a SK_DEBUG binary, set the |
231 * environment variable "skia_images_png_suppressDecoderWarnings" | 231 * environment variable "skia_images_png_suppressDecoderWarnings" |
232 * to "true". Inside a program that links to skia: | 232 * to "true". Inside a program that links to skia: |
233 * SK_CONF_SET("images.png.suppressDecoderWarnings", true); */ | 233 * SK_CONF_SET("images.png.suppressDecoderWarnings", true); */ |
234 | 234 |
235 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, | 235 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, |
236 NULL, sk_error_fn, user_warning_fn); | 236 nullptr, sk_error_fn, user_warning_fn); |
237 // png_voidp user_error_ptr, user_error_fn, user_warning_fn); | 237 // png_voidp user_error_ptr, user_error_fn, user_warning_fn); |
238 if (png_ptr == NULL) { | 238 if (png_ptr == nullptr) { |
239 return false; | 239 return false; |
240 } | 240 } |
241 | 241 |
242 *png_ptrp = png_ptr; | 242 *png_ptrp = png_ptr; |
243 | 243 |
244 /* Allocate/initialize the memory for image information. */ | 244 /* Allocate/initialize the memory for image information. */ |
245 png_infop info_ptr = png_create_info_struct(png_ptr); | 245 png_infop info_ptr = png_create_info_struct(png_ptr); |
246 if (info_ptr == NULL) { | 246 if (info_ptr == nullptr) { |
247 png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); | 247 png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); |
248 return false; | 248 return false; |
249 } | 249 } |
250 *info_ptrp = info_ptr; | 250 *info_ptrp = info_ptr; |
251 | 251 |
252 /* Set error handling if you are using the setjmp/longjmp method (this is | 252 /* Set error handling if you are using the setjmp/longjmp method (this is |
253 * the normal method of doing things with libpng). REQUIRED unless you | 253 * the normal method of doing things with libpng). REQUIRED unless you |
254 * set up your own error handlers in the png_create_read_struct() earlier. | 254 * set up your own error handlers in the png_create_read_struct() earlier. |
255 */ | 255 */ |
256 if (setjmp(png_jmpbuf(png_ptr))) { | 256 if (setjmp(png_jmpbuf(png_ptr))) { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
341 if (SkImageDecoder::kDecodeBounds_Mode == mode) { | 341 if (SkImageDecoder::kDecodeBounds_Mode == mode) { |
342 return kSuccess; | 342 return kSuccess; |
343 } | 343 } |
344 | 344 |
345 // from here down we are concerned with colortables and pixels | 345 // from here down we are concerned with colortables and pixels |
346 | 346 |
347 // we track if we actually see a non-opaque pixels, since sometimes a PNG se
ts its colortype | 347 // we track if we actually see a non-opaque pixels, since sometimes a PNG se
ts its colortype |
348 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We
care, since we | 348 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We
care, since we |
349 // draw lots faster if we can flag the bitmap has being opaque | 349 // draw lots faster if we can flag the bitmap has being opaque |
350 bool reallyHasAlpha = false; | 350 bool reallyHasAlpha = false; |
351 SkColorTable* colorTable = NULL; | 351 SkColorTable* colorTable = nullptr; |
352 | 352 |
353 if (pngColorType == PNG_COLOR_TYPE_PALETTE) { | 353 if (pngColorType == PNG_COLOR_TYPE_PALETTE) { |
354 decodePalette(png_ptr, info_ptr, bitDepth, &hasAlpha, &reallyHasAlpha, &
colorTable); | 354 decodePalette(png_ptr, info_ptr, bitDepth, &hasAlpha, &reallyHasAlpha, &
colorTable); |
355 } | 355 } |
356 | 356 |
357 SkAutoUnref aur(colorTable); | 357 SkAutoUnref aur(colorTable); |
358 | 358 |
359 if (!this->allocPixelRef(decodedBitmap, | 359 if (!this->allocPixelRef(decodedBitmap, |
360 kIndex_8_SkColorType == colorType ? colorTable : NU
LL)) { | 360 kIndex_8_SkColorType == colorType ? colorTable : nu
llptr)) { |
361 return kFailure; | 361 return kFailure; |
362 } | 362 } |
363 | 363 |
364 SkAutoLockPixels alp(*decodedBitmap); | 364 SkAutoLockPixels alp(*decodedBitmap); |
365 | 365 |
366 // Repeat setjmp, otherwise variables declared since the last call (e.g. alp | 366 // Repeat setjmp, otherwise variables declared since the last call (e.g. alp |
367 // and aur) won't get their destructors called in case of a failure. | 367 // and aur) won't get their destructors called in case of a failure. |
368 if (setjmp(png_jmpbuf(png_ptr))) { | 368 if (setjmp(png_jmpbuf(png_ptr))) { |
369 return kFailure; | 369 return kFailure; |
370 } | 370 } |
(...skipping 24 matching lines...) Expand all Loading... |
395 for (int i = 0; i < number_passes; i++) { | 395 for (int i = 0; i < number_passes; i++) { |
396 for (png_uint_32 y = 0; y < origHeight; y++) { | 396 for (png_uint_32 y = 0; y < origHeight; y++) { |
397 uint8_t* bmRow = decodedBitmap->getAddr8(0, y); | 397 uint8_t* bmRow = decodedBitmap->getAddr8(0, y); |
398 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); | 398 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); |
399 } | 399 } |
400 } | 400 } |
401 } else { | 401 } else { |
402 SkScaledBitmapSampler::SrcConfig sc; | 402 SkScaledBitmapSampler::SrcConfig sc; |
403 int srcBytesPerPixel = 4; | 403 int srcBytesPerPixel = 4; |
404 | 404 |
405 if (colorTable != NULL) { | 405 if (colorTable != nullptr) { |
406 sc = SkScaledBitmapSampler::kIndex; | 406 sc = SkScaledBitmapSampler::kIndex; |
407 srcBytesPerPixel = 1; | 407 srcBytesPerPixel = 1; |
408 } else if (kAlpha_8_SkColorType == colorType) { | 408 } else if (kAlpha_8_SkColorType == colorType) { |
409 // A8 is only allowed if the original was GRAY. | 409 // A8 is only allowed if the original was GRAY. |
410 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); | 410 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); |
411 sc = SkScaledBitmapSampler::kGray; | 411 sc = SkScaledBitmapSampler::kGray; |
412 srcBytesPerPixel = 1; | 412 srcBytesPerPixel = 1; |
413 } else if (hasAlpha) { | 413 } else if (hasAlpha) { |
414 sc = SkScaledBitmapSampler::kRGBA; | 414 sc = SkScaledBitmapSampler::kRGBA; |
415 } else { | 415 } else { |
416 sc = SkScaledBitmapSampler::kRGBX; | 416 sc = SkScaledBitmapSampler::kRGBX; |
417 } | 417 } |
418 | 418 |
419 /* We have to pass the colortable explicitly, since we may have one | 419 /* We have to pass the colortable explicitly, since we may have one |
420 even if our decodedBitmap doesn't, due to the request that we | 420 even if our decodedBitmap doesn't, due to the request that we |
421 upscale png's palette to a direct model | 421 upscale png's palette to a direct model |
422 */ | 422 */ |
423 const SkPMColor* colors = colorTable ? colorTable->readColors() : NULL; | 423 const SkPMColor* colors = colorTable ? colorTable->readColors() : nullpt
r; |
424 if (!sampler.begin(decodedBitmap, sc, *this, colors)) { | 424 if (!sampler.begin(decodedBitmap, sc, *this, colors)) { |
425 return kFailure; | 425 return kFailure; |
426 } | 426 } |
427 const int height = decodedBitmap->height(); | 427 const int height = decodedBitmap->height(); |
428 | 428 |
429 if (number_passes > 1) { | 429 if (number_passes > 1) { |
430 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel); | 430 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel); |
431 uint8_t* base = (uint8_t*)storage.get(); | 431 uint8_t* base = (uint8_t*)storage.get(); |
432 size_t rowBytes = origWidth * srcBytesPerPixel; | 432 size_t rowBytes = origWidth * srcBytesPerPixel; |
433 | 433 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 #endif | 525 #endif |
526 | 526 |
527 if (colorType == PNG_COLOR_TYPE_PALETTE) { | 527 if (colorType == PNG_COLOR_TYPE_PALETTE) { |
528 bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr); | 528 bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr); |
529 *colorTypep = this->getPrefColorType(kIndex_SrcDepth, paletteHasAlpha); | 529 *colorTypep = this->getPrefColorType(kIndex_SrcDepth, paletteHasAlpha); |
530 // now see if we can upscale to their requested colortype | 530 // now see if we can upscale to their requested colortype |
531 if (!canUpscalePaletteToConfig(*colorTypep, paletteHasAlpha)) { | 531 if (!canUpscalePaletteToConfig(*colorTypep, paletteHasAlpha)) { |
532 *colorTypep = kIndex_8_SkColorType; | 532 *colorTypep = kIndex_8_SkColorType; |
533 } | 533 } |
534 } else { | 534 } else { |
535 png_color_16p transpColor = NULL; | 535 png_color_16p transpColor = nullptr; |
536 int numTransp = 0; | 536 int numTransp = 0; |
537 | 537 |
538 png_get_tRNS(png_ptr, info_ptr, NULL, &numTransp, &transpColor); | 538 png_get_tRNS(png_ptr, info_ptr, nullptr, &numTransp, &transpColor); |
539 | 539 |
540 bool valid = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS); | 540 bool valid = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS); |
541 | 541 |
542 if (valid && numTransp == 1 && transpColor != NULL) { | 542 if (valid && numTransp == 1 && transpColor != nullptr) { |
543 /* Compute our transparent color, which we'll match against later. | 543 /* Compute our transparent color, which we'll match against later. |
544 We don't really handle 16bit components properly here, since we | 544 We don't really handle 16bit components properly here, since we |
545 do our compare *after* the values have been knocked down to 8bit | 545 do our compare *after* the values have been knocked down to 8bit |
546 which means we will find more matches than we should. The real | 546 which means we will find more matches than we should. The real |
547 fix seems to be to see the actual 16bit components, do the | 547 fix seems to be to see the actual 16bit components, do the |
548 compare, and then knock it down to 8bits ourselves. | 548 compare, and then knock it down to 8bits ourselves. |
549 */ | 549 */ |
550 if (colorType & PNG_COLOR_MASK_COLOR) { | 550 if (colorType & PNG_COLOR_MASK_COLOR) { |
551 if (16 == bitDepth) { | 551 if (16 == bitDepth) { |
552 *theTranspColorp = SkPackARGB32(0xFF, transpColor->red >> 8, | 552 *theTranspColorp = SkPackARGB32(0xFF, transpColor->red >> 8, |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
620 return false; | 620 return false; |
621 } | 621 } |
622 } | 622 } |
623 | 623 |
624 // If the image has alpha and the decoder wants unpremultiplied | 624 // If the image has alpha and the decoder wants unpremultiplied |
625 // colors, the only supported colortype is 8888. | 625 // colors, the only supported colortype is 8888. |
626 if (this->getRequireUnpremultipliedColors() && *hasAlphap) { | 626 if (this->getRequireUnpremultipliedColors() && *hasAlphap) { |
627 *colorTypep = kN32_SkColorType; | 627 *colorTypep = kN32_SkColorType; |
628 } | 628 } |
629 | 629 |
630 if (fImageIndex != NULL) { | 630 if (fImageIndex != nullptr) { |
631 if (kUnknown_SkColorType == fImageIndex->fColorType) { | 631 if (kUnknown_SkColorType == fImageIndex->fColorType) { |
632 // This is the first time for this subset decode. From now on, | 632 // This is the first time for this subset decode. From now on, |
633 // all decodes must be in the same colortype. | 633 // all decodes must be in the same colortype. |
634 fImageIndex->fColorType = *colorTypep; | 634 fImageIndex->fColorType = *colorTypep; |
635 } else if (fImageIndex->fColorType != *colorTypep) { | 635 } else if (fImageIndex->fColorType != *colorTypep) { |
636 // Requesting a different colortype for a subsequent decode is not | 636 // Requesting a different colortype for a subsequent decode is not |
637 // supported. Report failure before we make changes to png_ptr. | 637 // supported. Report failure before we make changes to png_ptr. |
638 return false; | 638 return false; |
639 } | 639 } |
640 } | 640 } |
(...skipping 24 matching lines...) Expand all Loading... |
665 png_colorp palette; | 665 png_colorp palette; |
666 png_bytep trans; | 666 png_bytep trans; |
667 int numTrans; | 667 int numTrans; |
668 | 668 |
669 png_get_PLTE(png_ptr, info_ptr, &palette, &numPalette); | 669 png_get_PLTE(png_ptr, info_ptr, &palette, &numPalette); |
670 | 670 |
671 SkPMColor colorStorage[256]; // worst-case storage | 671 SkPMColor colorStorage[256]; // worst-case storage |
672 SkPMColor* colorPtr = colorStorage; | 672 SkPMColor* colorPtr = colorStorage; |
673 | 673 |
674 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { | 674 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { |
675 png_get_tRNS(png_ptr, info_ptr, &trans, &numTrans, NULL); | 675 png_get_tRNS(png_ptr, info_ptr, &trans, &numTrans, nullptr); |
676 *hasAlphap = (numTrans > 0); | 676 *hasAlphap = (numTrans > 0); |
677 } else { | 677 } else { |
678 numTrans = 0; | 678 numTrans = 0; |
679 } | 679 } |
680 | 680 |
681 // check for bad images that might make us crash | 681 // check for bad images that might make us crash |
682 if (numTrans > numPalette) { | 682 if (numTrans > numPalette) { |
683 numTrans = numPalette; | 683 numTrans = numPalette; |
684 } | 684 } |
685 | 685 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
754 | 754 |
755 if (fImageIndex) { | 755 if (fImageIndex) { |
756 delete fImageIndex; | 756 delete fImageIndex; |
757 } | 757 } |
758 fImageIndex = new SkPNGImageIndex(streamDeleter.detach(), png_ptr, info_ptr)
; | 758 fImageIndex = new SkPNGImageIndex(streamDeleter.detach(), png_ptr, info_ptr)
; |
759 | 759 |
760 return true; | 760 return true; |
761 } | 761 } |
762 | 762 |
763 bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { | 763 bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { |
764 if (NULL == fImageIndex) { | 764 if (nullptr == fImageIndex) { |
765 return false; | 765 return false; |
766 } | 766 } |
767 | 767 |
768 png_structp png_ptr = fImageIndex->fPng_ptr; | 768 png_structp png_ptr = fImageIndex->fPng_ptr; |
769 png_infop info_ptr = fImageIndex->fInfo_ptr; | 769 png_infop info_ptr = fImageIndex->fInfo_ptr; |
770 if (setjmp(png_jmpbuf(png_ptr))) { | 770 if (setjmp(png_jmpbuf(png_ptr))) { |
771 return false; | 771 return false; |
772 } | 772 } |
773 | 773 |
774 png_uint_32 origWidth, origHeight; | 774 png_uint_32 origWidth, origHeight; |
(...skipping 23 matching lines...) Expand all Loading... |
798 SkBitmap decodedBitmap; | 798 SkBitmap decodedBitmap; |
799 decodedBitmap.setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scale
dHeight(), | 799 decodedBitmap.setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scale
dHeight(), |
800 colorType, kPremul_SkAlphaType)); | 800 colorType, kPremul_SkAlphaType)); |
801 | 801 |
802 // from here down we are concerned with colortables and pixels | 802 // from here down we are concerned with colortables and pixels |
803 | 803 |
804 // we track if we actually see a non-opaque pixels, since sometimes a PNG se
ts its colortype | 804 // we track if we actually see a non-opaque pixels, since sometimes a PNG se
ts its colortype |
805 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We
care, since we | 805 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We
care, since we |
806 // draw lots faster if we can flag the bitmap has being opaque | 806 // draw lots faster if we can flag the bitmap has being opaque |
807 bool reallyHasAlpha = false; | 807 bool reallyHasAlpha = false; |
808 SkColorTable* colorTable = NULL; | 808 SkColorTable* colorTable = nullptr; |
809 | 809 |
810 if (pngColorType == PNG_COLOR_TYPE_PALETTE) { | 810 if (pngColorType == PNG_COLOR_TYPE_PALETTE) { |
811 decodePalette(png_ptr, info_ptr, bitDepth, &hasAlpha, &reallyHasAlpha, &
colorTable); | 811 decodePalette(png_ptr, info_ptr, bitDepth, &hasAlpha, &reallyHasAlpha, &
colorTable); |
812 } | 812 } |
813 | 813 |
814 SkAutoUnref aur(colorTable); | 814 SkAutoUnref aur(colorTable); |
815 | 815 |
816 // Check ahead of time if the swap(dest, src) is possible. | 816 // Check ahead of time if the swap(dest, src) is possible. |
817 // If yes, then we will stick to AllocPixelRef since it's cheaper with the s
wap happening. | 817 // If yes, then we will stick to AllocPixelRef since it's cheaper with the s
wap happening. |
818 // If no, then we will use alloc to allocate pixels to prevent garbage colle
ction. | 818 // If no, then we will use alloc to allocate pixels to prevent garbage colle
ction. |
819 int w = rect.width() / sampleSize; | 819 int w = rect.width() / sampleSize; |
820 int h = rect.height() / sampleSize; | 820 int h = rect.height() / sampleSize; |
821 const bool swapOnly = (rect == region) && (w == decodedBitmap.width()) && | 821 const bool swapOnly = (rect == region) && (w == decodedBitmap.width()) && |
822 (h == decodedBitmap.height()) && bm->isNull(); | 822 (h == decodedBitmap.height()) && bm->isNull(); |
823 const bool needColorTable = kIndex_8_SkColorType == colorType; | 823 const bool needColorTable = kIndex_8_SkColorType == colorType; |
824 if (swapOnly) { | 824 if (swapOnly) { |
825 if (!this->allocPixelRef(&decodedBitmap, needColorTable ? colorTable : N
ULL)) { | 825 if (!this->allocPixelRef(&decodedBitmap, needColorTable ? colorTable : n
ullptr)) { |
826 return false; | 826 return false; |
827 } | 827 } |
828 } else { | 828 } else { |
829 if (!decodedBitmap.tryAllocPixels(NULL, needColorTable ? colorTable : NU
LL)) { | 829 if (!decodedBitmap.tryAllocPixels(nullptr, needColorTable ? colorTable :
nullptr)) { |
830 return false; | 830 return false; |
831 } | 831 } |
832 } | 832 } |
833 SkAutoLockPixels alp(decodedBitmap); | 833 SkAutoLockPixels alp(decodedBitmap); |
834 | 834 |
835 /* Turn on interlace handling. REQUIRED if you are not using | 835 /* Turn on interlace handling. REQUIRED if you are not using |
836 * png_read_image(). To see how to handle interlacing passes, | 836 * png_read_image(). To see how to handle interlacing passes, |
837 * see the png_read_row() method below: | 837 * see the png_read_row() method below: |
838 */ | 838 */ |
839 const int number_passes = (interlaceType != PNG_INTERLACE_NONE) ? | 839 const int number_passes = (interlaceType != PNG_INTERLACE_NONE) ? |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
875 png_uint_32 bitmapHeight = (png_uint_32) decodedBitmap.height(); | 875 png_uint_32 bitmapHeight = (png_uint_32) decodedBitmap.height(); |
876 for (png_uint_32 y = 0; y < bitmapHeight; y++) { | 876 for (png_uint_32 y = 0; y < bitmapHeight; y++) { |
877 uint8_t* bmRow = decodedBitmap.getAddr8(0, y); | 877 uint8_t* bmRow = decodedBitmap.getAddr8(0, y); |
878 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); | 878 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); |
879 } | 879 } |
880 } | 880 } |
881 } else { | 881 } else { |
882 SkScaledBitmapSampler::SrcConfig sc; | 882 SkScaledBitmapSampler::SrcConfig sc; |
883 int srcBytesPerPixel = 4; | 883 int srcBytesPerPixel = 4; |
884 | 884 |
885 if (colorTable != NULL) { | 885 if (colorTable != nullptr) { |
886 sc = SkScaledBitmapSampler::kIndex; | 886 sc = SkScaledBitmapSampler::kIndex; |
887 srcBytesPerPixel = 1; | 887 srcBytesPerPixel = 1; |
888 } else if (kAlpha_8_SkColorType == colorType) { | 888 } else if (kAlpha_8_SkColorType == colorType) { |
889 // A8 is only allowed if the original was GRAY. | 889 // A8 is only allowed if the original was GRAY. |
890 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); | 890 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); |
891 sc = SkScaledBitmapSampler::kGray; | 891 sc = SkScaledBitmapSampler::kGray; |
892 srcBytesPerPixel = 1; | 892 srcBytesPerPixel = 1; |
893 } else if (hasAlpha) { | 893 } else if (hasAlpha) { |
894 sc = SkScaledBitmapSampler::kRGBA; | 894 sc = SkScaledBitmapSampler::kRGBA; |
895 } else { | 895 } else { |
896 sc = SkScaledBitmapSampler::kRGBX; | 896 sc = SkScaledBitmapSampler::kRGBX; |
897 } | 897 } |
898 | 898 |
899 /* We have to pass the colortable explicitly, since we may have one | 899 /* We have to pass the colortable explicitly, since we may have one |
900 even if our decodedBitmap doesn't, due to the request that we | 900 even if our decodedBitmap doesn't, due to the request that we |
901 upscale png's palette to a direct model | 901 upscale png's palette to a direct model |
902 */ | 902 */ |
903 const SkPMColor* colors = colorTable ? colorTable->readColors() : NULL; | 903 const SkPMColor* colors = colorTable ? colorTable->readColors() : nullpt
r; |
904 if (!sampler.begin(&decodedBitmap, sc, *this, colors)) { | 904 if (!sampler.begin(&decodedBitmap, sc, *this, colors)) { |
905 return false; | 905 return false; |
906 } | 906 } |
907 const int height = decodedBitmap.height(); | 907 const int height = decodedBitmap.height(); |
908 | 908 |
909 if (number_passes > 1) { | 909 if (number_passes > 1) { |
910 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel); | 910 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel); |
911 uint8_t* base = (uint8_t*)storage.get(); | 911 uint8_t* base = (uint8_t*)storage.get(); |
912 size_t rb = origWidth * srcBytesPerPixel; | 912 size_t rb = origWidth * srcBytesPerPixel; |
913 | 913 |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1018 { kARGB_4444_SkColorType, true, transform_scanline_4444 }, | 1018 { kARGB_4444_SkColorType, true, transform_scanline_4444 }, |
1019 { kIndex_8_SkColorType, false, transform_scanline_memcpy }, | 1019 { kIndex_8_SkColorType, false, transform_scanline_memcpy }, |
1020 }; | 1020 }; |
1021 | 1021 |
1022 for (int i = SK_ARRAY_COUNT(gMap) - 1; i >= 0; --i) { | 1022 for (int i = SK_ARRAY_COUNT(gMap) - 1; i >= 0; --i) { |
1023 if (gMap[i].fColorType == ct && gMap[i].fHasAlpha == hasAlpha) { | 1023 if (gMap[i].fColorType == ct && gMap[i].fHasAlpha == hasAlpha) { |
1024 return gMap[i].fProc; | 1024 return gMap[i].fProc; |
1025 } | 1025 } |
1026 } | 1026 } |
1027 sk_throw(); | 1027 sk_throw(); |
1028 return NULL; | 1028 return nullptr; |
1029 } | 1029 } |
1030 | 1030 |
1031 // return the minimum legal bitdepth (by png standards) for this many colortable | 1031 // return the minimum legal bitdepth (by png standards) for this many colortable |
1032 // entries. SkBitmap always stores in 8bits per pixel, but for colorcount <= 16, | 1032 // entries. SkBitmap always stores in 8bits per pixel, but for colorcount <= 16, |
1033 // we can use fewer bits per in png | 1033 // we can use fewer bits per in png |
1034 static int computeBitDepth(int colorCount) { | 1034 static int computeBitDepth(int colorCount) { |
1035 #if 0 | 1035 #if 0 |
1036 int bits = SkNextLog2(colorCount); | 1036 int bits = SkNextLog2(colorCount); |
1037 SkASSERT(bits >= 1 && bits <= 8); | 1037 SkASSERT(bits >= 1 && bits <= 8); |
1038 // now we need bits itself to be a power of 2 (e.g. 1, 2, 4, 8) | 1038 // now we need bits itself to be a power of 2 (e.g. 1, 2, 4, 8) |
1039 return SkNextPow2(bits); | 1039 return SkNextPow2(bits); |
1040 #else | 1040 #else |
1041 // for the moment, we don't know how to pack bitdepth < 8 | 1041 // for the moment, we don't know how to pack bitdepth < 8 |
1042 return 8; | 1042 return 8; |
1043 #endif | 1043 #endif |
1044 } | 1044 } |
1045 | 1045 |
1046 /* Pack palette[] with the corresponding colors, and if hasAlpha is true, also | 1046 /* Pack palette[] with the corresponding colors, and if hasAlpha is true, also |
1047 pack trans[] and return the number of trans[] entries written. If hasAlpha | 1047 pack trans[] and return the number of trans[] entries written. If hasAlpha |
1048 is false, the return value will always be 0. | 1048 is false, the return value will always be 0. |
1049 | 1049 |
1050 Note: this routine takes care of unpremultiplying the RGB values when we | 1050 Note: this routine takes care of unpremultiplying the RGB values when we |
1051 have alpha in the colortable, since png doesn't support premul colors | 1051 have alpha in the colortable, since png doesn't support premul colors |
1052 */ | 1052 */ |
1053 static inline int pack_palette(SkColorTable* ctable, | 1053 static inline int pack_palette(SkColorTable* ctable, |
1054 png_color* SK_RESTRICT palette, | 1054 png_color* SK_RESTRICT palette, |
1055 png_byte* SK_RESTRICT trans, bool hasAlpha) { | 1055 png_byte* SK_RESTRICT trans, bool hasAlpha) { |
1056 const SkPMColor* SK_RESTRICT colors = ctable ? ctable->readColors() : NULL; | 1056 const SkPMColor* SK_RESTRICT colors = ctable ? ctable->readColors() : nullpt
r; |
1057 const int ctCount = ctable->count(); | 1057 const int ctCount = ctable->count(); |
1058 int i, num_trans = 0; | 1058 int i, num_trans = 0; |
1059 | 1059 |
1060 if (hasAlpha) { | 1060 if (hasAlpha) { |
1061 /* first see if we have some number of fully opaque at the end of the | 1061 /* first see if we have some number of fully opaque at the end of the |
1062 ctable. PNG allows num_trans < num_palette, but all of the trans | 1062 ctable. PNG allows num_trans < num_palette, but all of the trans |
1063 entries must come first in the palette. If I was smarter, I'd | 1063 entries must come first in the palette. If I was smarter, I'd |
1064 reorder the indices and ctable so that all non-opaque colors came | 1064 reorder the indices and ctable so that all non-opaque colors came |
1065 first in the palette. But, since that would slow down the encode, | 1065 first in the palette. But, since that would slow down the encode, |
1066 I'm leaving the indices and ctable order as is, and just looking | 1066 I'm leaving the indices and ctable order as is, and just looking |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1175 } | 1175 } |
1176 | 1176 |
1177 bool SkPNGImageEncoder::doEncode(SkWStream* stream, const SkBitmap& bitmap, | 1177 bool SkPNGImageEncoder::doEncode(SkWStream* stream, const SkBitmap& bitmap, |
1178 const bool& hasAlpha, int colorType, | 1178 const bool& hasAlpha, int colorType, |
1179 int bitDepth, SkColorType ct, | 1179 int bitDepth, SkColorType ct, |
1180 png_color_8& sig_bit) { | 1180 png_color_8& sig_bit) { |
1181 | 1181 |
1182 png_structp png_ptr; | 1182 png_structp png_ptr; |
1183 png_infop info_ptr; | 1183 png_infop info_ptr; |
1184 | 1184 |
1185 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, sk_error_fn, | 1185 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, sk_error_f
n, |
1186 NULL); | 1186 nullptr); |
1187 if (NULL == png_ptr) { | 1187 if (nullptr == png_ptr) { |
1188 return false; | 1188 return false; |
1189 } | 1189 } |
1190 | 1190 |
1191 info_ptr = png_create_info_struct(png_ptr); | 1191 info_ptr = png_create_info_struct(png_ptr); |
1192 if (NULL == info_ptr) { | 1192 if (nullptr == info_ptr) { |
1193 png_destroy_write_struct(&png_ptr, png_infopp_NULL); | 1193 png_destroy_write_struct(&png_ptr, png_infopp_NULL); |
1194 return false; | 1194 return false; |
1195 } | 1195 } |
1196 | 1196 |
1197 /* Set error handling. REQUIRED if you aren't supplying your own | 1197 /* Set error handling. REQUIRED if you aren't supplying your own |
1198 * error handling functions in the png_create_write_struct() call. | 1198 * error handling functions in the png_create_write_struct() call. |
1199 */ | 1199 */ |
1200 if (setjmp(png_jmpbuf(png_ptr))) { | 1200 if (setjmp(png_jmpbuf(png_ptr))) { |
1201 png_destroy_write_struct(&png_ptr, &info_ptr); | 1201 png_destroy_write_struct(&png_ptr, &info_ptr); |
1202 return false; | 1202 return false; |
(...skipping 16 matching lines...) Expand all Loading... |
1219 PNG_FILTER_TYPE_BASE); | 1219 PNG_FILTER_TYPE_BASE); |
1220 | 1220 |
1221 // set our colortable/trans arrays if needed | 1221 // set our colortable/trans arrays if needed |
1222 png_color paletteColors[256]; | 1222 png_color paletteColors[256]; |
1223 png_byte trans[256]; | 1223 png_byte trans[256]; |
1224 if (kIndex_8_SkColorType == ct) { | 1224 if (kIndex_8_SkColorType == ct) { |
1225 SkColorTable* ct = bitmap.getColorTable(); | 1225 SkColorTable* ct = bitmap.getColorTable(); |
1226 int numTrans = pack_palette(ct, paletteColors, trans, hasAlpha); | 1226 int numTrans = pack_palette(ct, paletteColors, trans, hasAlpha); |
1227 png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count()); | 1227 png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count()); |
1228 if (numTrans > 0) { | 1228 if (numTrans > 0) { |
1229 png_set_tRNS(png_ptr, info_ptr, trans, numTrans, NULL); | 1229 png_set_tRNS(png_ptr, info_ptr, trans, numTrans, nullptr); |
1230 } | 1230 } |
1231 } | 1231 } |
1232 #ifdef PNG_sBIT_SUPPORTED | 1232 #ifdef PNG_sBIT_SUPPORTED |
1233 png_set_sBIT(png_ptr, info_ptr, &sig_bit); | 1233 png_set_sBIT(png_ptr, info_ptr, &sig_bit); |
1234 #endif | 1234 #endif |
1235 png_write_info(png_ptr, info_ptr); | 1235 png_write_info(png_ptr, info_ptr); |
1236 | 1236 |
1237 const char* srcImage = (const char*)bitmap.getPixels(); | 1237 const char* srcImage = (const char*)bitmap.getPixels(); |
1238 SkAutoSMalloc<1024> rowStorage(bitmap.width() << 2); | 1238 SkAutoSMalloc<1024> rowStorage(bitmap.width() << 2); |
1239 char* storage = (char*)rowStorage.get(); | 1239 char* storage = (char*)rowStorage.get(); |
(...skipping 24 matching lines...) Expand all Loading... |
1264 !png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) { | 1264 !png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) { |
1265 return true; | 1265 return true; |
1266 } | 1266 } |
1267 return false; | 1267 return false; |
1268 } | 1268 } |
1269 | 1269 |
1270 SkImageDecoder* sk_libpng_dfactory(SkStreamRewindable* stream) { | 1270 SkImageDecoder* sk_libpng_dfactory(SkStreamRewindable* stream) { |
1271 if (is_png(stream)) { | 1271 if (is_png(stream)) { |
1272 return new SkPNGImageDecoder; | 1272 return new SkPNGImageDecoder; |
1273 } | 1273 } |
1274 return NULL; | 1274 return nullptr; |
1275 } | 1275 } |
1276 | 1276 |
1277 static SkImageDecoder::Format get_format_png(SkStreamRewindable* stream) { | 1277 static SkImageDecoder::Format get_format_png(SkStreamRewindable* stream) { |
1278 if (is_png(stream)) { | 1278 if (is_png(stream)) { |
1279 return SkImageDecoder::kPNG_Format; | 1279 return SkImageDecoder::kPNG_Format; |
1280 } | 1280 } |
1281 return SkImageDecoder::kUnknown_Format; | 1281 return SkImageDecoder::kUnknown_Format; |
1282 } | 1282 } |
1283 | 1283 |
1284 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { | 1284 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { |
1285 return (SkImageEncoder::kPNG_Type == t) ? new SkPNGImageEncoder : NULL; | 1285 return (SkImageEncoder::kPNG_Type == t) ? new SkPNGImageEncoder : nullptr; |
1286 } | 1286 } |
1287 | 1287 |
1288 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory); | 1288 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory); |
1289 static SkImageDecoder_FormatReg gFormatReg(get_format_png); | 1289 static SkImageDecoder_FormatReg gFormatReg(get_format_png); |
1290 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); | 1290 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); |
OLD | NEW |