Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: src/images/SkImageDecoder_libpng.cpp

Issue 322963002: hide SkBitmap::setConfig (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/images/SkImageDecoder_libjpeg.cpp ('k') | src/images/SkImageDecoder_libwebp.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1
2 /* 1 /*
3 * Copyright 2006 The Android Open Source Project 2 * Copyright 2006 The Android Open Source Project
4 * 3 *
5 * 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
6 * found in the LICENSE file. 5 * found in the LICENSE file.
7 */ 6 */
8 7
9
10 #include "SkImageDecoder.h" 8 #include "SkImageDecoder.h"
11 #include "SkImageEncoder.h" 9 #include "SkImageEncoder.h"
12 #include "SkColor.h" 10 #include "SkColor.h"
13 #include "SkColorPriv.h" 11 #include "SkColorPriv.h"
14 #include "SkDither.h" 12 #include "SkDither.h"
15 #include "SkMath.h" 13 #include "SkMath.h"
16 #include "SkRTConf.h" 14 #include "SkRTConf.h"
17 #include "SkScaledBitmapSampler.h" 15 #include "SkScaledBitmapSampler.h"
18 #include "SkStream.h" 16 #include "SkStream.h"
19 #include "SkTemplates.h" 17 #include "SkTemplates.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 "functions."); 50 "functions.");
53 51
54 52
55 53
56 class SkPNGImageIndex { 54 class SkPNGImageIndex {
57 public: 55 public:
58 SkPNGImageIndex(SkStreamRewindable* stream, png_structp png_ptr, png_infop i nfo_ptr) 56 SkPNGImageIndex(SkStreamRewindable* stream, png_structp png_ptr, png_infop i nfo_ptr)
59 : fStream(stream) 57 : fStream(stream)
60 , fPng_ptr(png_ptr) 58 , fPng_ptr(png_ptr)
61 , fInfo_ptr(info_ptr) 59 , fInfo_ptr(info_ptr)
62 , fConfig(SkBitmap::kNo_Config) { 60 , fColorType(kUnknown_SkColorType) {
63 SkASSERT(stream != NULL); 61 SkASSERT(stream != NULL);
64 stream->ref(); 62 stream->ref();
65 } 63 }
66 ~SkPNGImageIndex() { 64 ~SkPNGImageIndex() {
67 if (NULL != fPng_ptr) { 65 if (NULL != fPng_ptr) {
68 png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, png_infopp_NULL); 66 png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, png_infopp_NULL);
69 } 67 }
70 } 68 }
71 69
72 SkAutoTUnref<SkStreamRewindable> fStream; 70 SkAutoTUnref<SkStreamRewindable> fStream;
73 png_structp fPng_ptr; 71 png_structp fPng_ptr;
74 png_infop fInfo_ptr; 72 png_infop fInfo_ptr;
75 SkBitmap::Config fConfig; 73 SkColorType fColorType;
76 }; 74 };
77 75
78 class SkPNGImageDecoder : public SkImageDecoder { 76 class SkPNGImageDecoder : public SkImageDecoder {
79 public: 77 public:
80 SkPNGImageDecoder() { 78 SkPNGImageDecoder() {
81 fImageIndex = NULL; 79 fImageIndex = NULL;
82 } 80 }
83 virtual Format getFormat() const SK_OVERRIDE { 81 virtual Format getFormat() const SK_OVERRIDE {
84 return kPNG_Format; 82 return kPNG_Format;
85 } 83 }
86 84
87 virtual ~SkPNGImageDecoder() { 85 virtual ~SkPNGImageDecoder() {
88 SkDELETE(fImageIndex); 86 SkDELETE(fImageIndex);
89 } 87 }
90 88
91 protected: 89 protected:
92 #ifdef SK_BUILD_FOR_ANDROID 90 #ifdef SK_BUILD_FOR_ANDROID
93 virtual bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *h eight) SK_OVERRIDE; 91 virtual bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *h eight) SK_OVERRIDE;
94 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& region) SK_OVER RIDE; 92 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& region) SK_OVER RIDE;
95 #endif 93 #endif
96 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; 94 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE;
97 95
98 private: 96 private:
99 SkPNGImageIndex* fImageIndex; 97 SkPNGImageIndex* fImageIndex;
100 98
101 bool onDecodeInit(SkStream* stream, png_structp *png_ptrp, png_infop *info_p trp); 99 bool onDecodeInit(SkStream* stream, png_structp *png_ptrp, png_infop *info_p trp);
102 bool decodePalette(png_structp png_ptr, png_infop info_ptr, 100 bool decodePalette(png_structp png_ptr, png_infop info_ptr,
103 bool * SK_RESTRICT hasAlphap, bool *reallyHasAlphap, 101 bool * SK_RESTRICT hasAlphap, bool *reallyHasAlphap,
104 SkColorTable **colorTablep); 102 SkColorTable **colorTablep);
105 bool getBitmapConfig(png_structp png_ptr, png_infop info_ptr, 103 bool getBitmapConfig(png_structp, png_infop, SkColorType*, bool* hasAlpha,
106 SkBitmap::Config *config, bool *hasAlpha, 104 SkPMColor* theTranspColor);
107 SkPMColor *theTranspColor);
108 105
109 typedef SkImageDecoder INHERITED; 106 typedef SkImageDecoder INHERITED;
110 }; 107 };
111 108
112 #ifndef png_jmpbuf 109 #ifndef png_jmpbuf
113 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) 110 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
114 #endif 111 #endif
115 112
116 #define PNG_BYTES_TO_CHECK 4 113 #define PNG_BYTES_TO_CHECK 4
117 114
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 if (match == *p) { 176 if (match == *p) {
180 *p = 0; 177 *p = 0;
181 reallyHasAlpha = true; 178 reallyHasAlpha = true;
182 } 179 }
183 p += 1; 180 p += 1;
184 } 181 }
185 } 182 }
186 return reallyHasAlpha; 183 return reallyHasAlpha;
187 } 184 }
188 185
189 static bool canUpscalePaletteToConfig(SkBitmap::Config dstConfig, 186 static bool canUpscalePaletteToConfig(SkColorType dstColorType, bool srcHasAlpha ) {
190 bool srcHasAlpha) { 187 switch (dstColorType) {
191 switch (dstConfig) { 188 case kN32_SkColorType:
192 case SkBitmap::kARGB_8888_Config: 189 case kARGB_4444_SkColorType:
193 case SkBitmap::kARGB_4444_Config:
194 return true; 190 return true;
195 case SkBitmap::kRGB_565_Config: 191 case kRGB_565_SkColorType:
196 // only return true if the src is opaque (since 565 is opaque) 192 // only return true if the src is opaque (since 565 is opaque)
197 return !srcHasAlpha; 193 return !srcHasAlpha;
198 default: 194 default:
199 return false; 195 return false;
200 } 196 }
201 } 197 }
202 198
203 // call only if color_type is PALETTE. Returns true if the ctable has alpha 199 // call only if color_type is PALETTE. Returns true if the ctable has alpha
204 static bool hasTransparencyInPalette(png_structp png_ptr, png_infop info_ptr) { 200 static bool hasTransparencyInPalette(png_structp png_ptr, png_infop info_ptr) {
205 png_bytep trans; 201 png_bytep trans;
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 return false; 306 return false;
311 } 307 }
312 308
313 PNGAutoClean autoClean(png_ptr, info_ptr); 309 PNGAutoClean autoClean(png_ptr, info_ptr);
314 310
315 if (setjmp(png_jmpbuf(png_ptr))) { 311 if (setjmp(png_jmpbuf(png_ptr))) {
316 return false; 312 return false;
317 } 313 }
318 314
319 png_uint_32 origWidth, origHeight; 315 png_uint_32 origWidth, origHeight;
320 int bitDepth, colorType, interlaceType; 316 int bitDepth, pngColorType, interlaceType;
321 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, 317 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
322 &colorType, &interlaceType, int_p_NULL, int_p_NULL); 318 &pngColorType, &interlaceType, int_p_NULL, int_p_NULL);
323 319
324 SkBitmap::Config config; 320 SkColorType colorType;
325 bool hasAlpha = false; 321 bool hasAlpha = false;
326 SkPMColor theTranspColor = 0; // 0 tells us not to try to match 322 SkPMColor theTranspColor = 0; // 0 tells us not to try to match
327 323
328 if (!this->getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha, &theTransp Color)) { 324 if (!this->getBitmapConfig(png_ptr, info_ptr, &colorType, &hasAlpha, &theTra nspColor)) {
329 return false; 325 return false;
330 } 326 }
331 327
328 SkAlphaType alphaType = this->getRequireUnpremultipliedColors() ?
329 kUnpremul_SkAlphaType : kPremul_SkAlphaType;
332 const int sampleSize = this->getSampleSize(); 330 const int sampleSize = this->getSampleSize();
333 SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize); 331 SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize);
334 decodedBitmap->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight ()); 332 decodedBitmap->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scal edHeight(),
335 333 colorType, alphaType));
336 // we should communicate alphaType, even if we early-return in bounds-only-m ode.
337 if (this->getRequireUnpremultipliedColors()) {
338 decodedBitmap->setAlphaType(kUnpremul_SkAlphaType);
339 }
340 334
341 if (SkImageDecoder::kDecodeBounds_Mode == mode) { 335 if (SkImageDecoder::kDecodeBounds_Mode == mode) {
342 return true; 336 return true;
343 } 337 }
344 338
345 // from here down we are concerned with colortables and pixels 339 // from here down we are concerned with colortables and pixels
346 340
347 // we track if we actually see a non-opaque pixels, since sometimes a PNG se ts its colortype 341 // 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 342 // 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 343 // draw lots faster if we can flag the bitmap has being opaque
350 bool reallyHasAlpha = false; 344 bool reallyHasAlpha = false;
351 SkColorTable* colorTable = NULL; 345 SkColorTable* colorTable = NULL;
352 346
353 if (colorType == PNG_COLOR_TYPE_PALETTE) { 347 if (pngColorType == PNG_COLOR_TYPE_PALETTE) {
354 decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable ); 348 decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable );
355 } 349 }
356 350
357 SkAutoUnref aur(colorTable); 351 SkAutoUnref aur(colorTable);
358 352
359 if (!this->allocPixelRef(decodedBitmap, 353 if (!this->allocPixelRef(decodedBitmap,
360 SkBitmap::kIndex8_Config == config ? colorTable : N ULL)) { 354 kIndex_8_SkColorType == colorType ? colorTable : NU LL)) {
361 return false; 355 return false;
362 } 356 }
363 357
364 SkAutoLockPixels alp(*decodedBitmap); 358 SkAutoLockPixels alp(*decodedBitmap);
365 359
366 /* Turn on interlace handling. REQUIRED if you are not using 360 /* Turn on interlace handling. REQUIRED if you are not using
367 * png_read_image(). To see how to handle interlacing passes, 361 * png_read_image(). To see how to handle interlacing passes,
368 * see the png_read_row() method below: 362 * see the png_read_row() method below:
369 */ 363 */
370 const int number_passes = (interlaceType != PNG_INTERLACE_NONE) ? 364 const int number_passes = (interlaceType != PNG_INTERLACE_NONE) ?
371 png_set_interlace_handling(png_ptr) : 1; 365 png_set_interlace_handling(png_ptr) : 1;
372 366
373 /* Optional call to gamma correct and add the background to the palette 367 /* Optional call to gamma correct and add the background to the palette
374 * and update info structure. REQUIRED if you are expecting libpng to 368 * and update info structure. REQUIRED if you are expecting libpng to
375 * update the palette for you (ie you selected such a transform above). 369 * update the palette for you (ie you selected such a transform above).
376 */ 370 */
377 png_read_update_info(png_ptr, info_ptr); 371 png_read_update_info(png_ptr, info_ptr);
378 372
379 if ((SkBitmap::kA8_Config == config || SkBitmap::kIndex8_Config == config) 373 if ((kAlpha_8_SkColorType == colorType || kIndex_8_SkColorType == colorType) &&
380 && 1 == sampleSize) { 374 1 == sampleSize) {
381 if (SkBitmap::kA8_Config == config) { 375 if (kAlpha_8_SkColorType == colorType) {
382 // For an A8 bitmap, we assume there is an alpha for speed. It is 376 // For an A8 bitmap, we assume there is an alpha for speed. It is
383 // possible the bitmap is opaque, but that is an unlikely use case 377 // possible the bitmap is opaque, but that is an unlikely use case
384 // since it would not be very interesting. 378 // since it would not be very interesting.
385 reallyHasAlpha = true; 379 reallyHasAlpha = true;
386 // A8 is only allowed if the original was GRAY. 380 // A8 is only allowed if the original was GRAY.
387 SkASSERT(PNG_COLOR_TYPE_GRAY == colorType); 381 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType);
388 } 382 }
389 for (int i = 0; i < number_passes; i++) { 383 for (int i = 0; i < number_passes; i++) {
390 for (png_uint_32 y = 0; y < origHeight; y++) { 384 for (png_uint_32 y = 0; y < origHeight; y++) {
391 uint8_t* bmRow = decodedBitmap->getAddr8(0, y); 385 uint8_t* bmRow = decodedBitmap->getAddr8(0, y);
392 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); 386 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
393 } 387 }
394 } 388 }
395 } else { 389 } else {
396 SkScaledBitmapSampler::SrcConfig sc; 390 SkScaledBitmapSampler::SrcConfig sc;
397 int srcBytesPerPixel = 4; 391 int srcBytesPerPixel = 4;
398 392
399 if (colorTable != NULL) { 393 if (colorTable != NULL) {
400 sc = SkScaledBitmapSampler::kIndex; 394 sc = SkScaledBitmapSampler::kIndex;
401 srcBytesPerPixel = 1; 395 srcBytesPerPixel = 1;
402 } else if (SkBitmap::kA8_Config == config) { 396 } else if (kAlpha_8_SkColorType == colorType) {
403 // A8 is only allowed if the original was GRAY. 397 // A8 is only allowed if the original was GRAY.
404 SkASSERT(PNG_COLOR_TYPE_GRAY == colorType); 398 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType);
405 sc = SkScaledBitmapSampler::kGray; 399 sc = SkScaledBitmapSampler::kGray;
406 srcBytesPerPixel = 1; 400 srcBytesPerPixel = 1;
407 } else if (hasAlpha) { 401 } else if (hasAlpha) {
408 sc = SkScaledBitmapSampler::kRGBA; 402 sc = SkScaledBitmapSampler::kRGBA;
409 } else { 403 } else {
410 sc = SkScaledBitmapSampler::kRGBX; 404 sc = SkScaledBitmapSampler::kRGBX;
411 } 405 }
412 406
413 /* We have to pass the colortable explicitly, since we may have one 407 /* We have to pass the colortable explicitly, since we may have one
414 even if our decodedBitmap doesn't, due to the request that we 408 even if our decodedBitmap doesn't, due to the request that we
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 479
486 if (!reallyHasAlpha) { 480 if (!reallyHasAlpha) {
487 decodedBitmap->setAlphaType(kOpaque_SkAlphaType); 481 decodedBitmap->setAlphaType(kOpaque_SkAlphaType);
488 } 482 }
489 return true; 483 return true;
490 } 484 }
491 485
492 486
493 487
494 bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr, 488 bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr,
495 SkBitmap::Config* SK_RESTRICT configp, 489 SkColorType* colorTypep,
496 bool* SK_RESTRICT hasAlphap, 490 bool* hasAlphap,
497 SkPMColor* SK_RESTRICT theTranspColorp) { 491 SkPMColor* SK_RESTRICT theTranspColorp) {
498 png_uint_32 origWidth, origHeight; 492 png_uint_32 origWidth, origHeight;
499 int bitDepth, colorType; 493 int bitDepth, colorType;
500 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, 494 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
501 &colorType, int_p_NULL, int_p_NULL, int_p_NULL); 495 &colorType, int_p_NULL, int_p_NULL, int_p_NULL);
502 496
503 // check for sBIT chunk data, in case we should disable dithering because 497 // check for sBIT chunk data, in case we should disable dithering because
504 // our data is not truely 8bits per component 498 // our data is not truely 8bits per component
505 png_color_8p sig_bit; 499 png_color_8p sig_bit;
506 if (this->getDitherImage() && png_get_sBIT(png_ptr, info_ptr, &sig_bit)) { 500 if (this->getDitherImage() && png_get_sBIT(png_ptr, info_ptr, &sig_bit)) {
507 #if 0 501 #if 0
508 SkDebugf("----- sBIT %d %d %d %d\n", sig_bit->red, sig_bit->green, 502 SkDebugf("----- sBIT %d %d %d %d\n", sig_bit->red, sig_bit->green,
509 sig_bit->blue, sig_bit->alpha); 503 sig_bit->blue, sig_bit->alpha);
510 #endif 504 #endif
511 // 0 seems to indicate no information available 505 // 0 seems to indicate no information available
512 if (pos_le(sig_bit->red, SK_R16_BITS) && 506 if (pos_le(sig_bit->red, SK_R16_BITS) &&
513 pos_le(sig_bit->green, SK_G16_BITS) && 507 pos_le(sig_bit->green, SK_G16_BITS) &&
514 pos_le(sig_bit->blue, SK_B16_BITS)) { 508 pos_le(sig_bit->blue, SK_B16_BITS)) {
515 this->setDitherImage(false); 509 this->setDitherImage(false);
516 } 510 }
517 } 511 }
518 512
519 if (colorType == PNG_COLOR_TYPE_PALETTE) { 513 if (colorType == PNG_COLOR_TYPE_PALETTE) {
520 bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr); 514 bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr);
521 *configp = this->getPrefConfig(kIndex_SrcDepth, paletteHasAlpha); 515 *colorTypep = this->getPrefColorType(kIndex_SrcDepth, paletteHasAlpha);
522 // now see if we can upscale to their requested config 516 // now see if we can upscale to their requested config
523 if (!canUpscalePaletteToConfig(*configp, paletteHasAlpha)) { 517 if (!canUpscalePaletteToConfig(*colorTypep, paletteHasAlpha)) {
524 *configp = SkBitmap::kIndex8_Config; 518 *colorTypep = kIndex_8_SkColorType;
525 } 519 }
526 } else { 520 } else {
527 png_color_16p transpColor = NULL; 521 png_color_16p transpColor = NULL;
528 int numTransp = 0; 522 int numTransp = 0;
529 523
530 png_get_tRNS(png_ptr, info_ptr, NULL, &numTransp, &transpColor); 524 png_get_tRNS(png_ptr, info_ptr, NULL, &numTransp, &transpColor);
531 525
532 bool valid = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS); 526 bool valid = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS);
533 527
534 if (valid && numTransp == 1 && transpColor != NULL) { 528 if (valid && numTransp == 1 && transpColor != NULL) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 *hasAlphap = true; 572 *hasAlphap = true;
579 } 573 }
580 574
581 SrcDepth srcDepth = k32Bit_SrcDepth; 575 SrcDepth srcDepth = k32Bit_SrcDepth;
582 if (PNG_COLOR_TYPE_GRAY == colorType) { 576 if (PNG_COLOR_TYPE_GRAY == colorType) {
583 srcDepth = k8BitGray_SrcDepth; 577 srcDepth = k8BitGray_SrcDepth;
584 // Remove this assert, which fails on desk_pokemonwiki.skp 578 // Remove this assert, which fails on desk_pokemonwiki.skp
585 //SkASSERT(!*hasAlphap); 579 //SkASSERT(!*hasAlphap);
586 } 580 }
587 581
588 *configp = this->getPrefConfig(srcDepth, *hasAlphap); 582 *colorTypep = this->getPrefColorType(srcDepth, *hasAlphap);
589 // now match the request against our capabilities 583 // now match the request against our capabilities
590 if (*hasAlphap) { 584 if (*hasAlphap) {
591 if (*configp != SkBitmap::kARGB_4444_Config) { 585 if (*colorTypep != kARGB_4444_SkColorType) {
592 *configp = SkBitmap::kARGB_8888_Config; 586 *colorTypep = kN32_SkColorType;
593 } 587 }
594 } else { 588 } else {
595 if (SkBitmap::kA8_Config == *configp) { 589 if (kAlpha_8_SkColorType == *colorTypep) {
596 if (k8BitGray_SrcDepth != srcDepth) { 590 if (k8BitGray_SrcDepth != srcDepth) {
597 // Converting a non grayscale image to A8 is not currently s upported. 591 // Converting a non grayscale image to A8 is not currently s upported.
598 *configp = SkBitmap::kARGB_8888_Config; 592 *colorTypep = kN32_SkColorType;
599 } 593 }
600 } else if (*configp != SkBitmap::kRGB_565_Config && 594 } else if (*colorTypep != kRGB_565_SkColorType &&
601 *configp != SkBitmap::kARGB_4444_Config) { 595 *colorTypep != kARGB_4444_SkColorType) {
602 *configp = SkBitmap::kARGB_8888_Config; 596 *colorTypep = kN32_SkColorType;
603 } 597 }
604 } 598 }
605 } 599 }
606 600
607 // sanity check for size 601 // sanity check for size
608 { 602 {
609 int64_t size = sk_64_mul(origWidth, origHeight); 603 int64_t size = sk_64_mul(origWidth, origHeight);
610 // now check that if we are 4-bytes per pixel, we also don't overflow 604 // now check that if we are 4-bytes per pixel, we also don't overflow
611 if (size < 0 || size > (0x7FFFFFFF >> 2)) { 605 if (size < 0 || size > (0x7FFFFFFF >> 2)) {
612 return false; 606 return false;
613 } 607 }
614 } 608 }
615 609
616 if (!this->chooseFromOneChoice(*configp, origWidth, origHeight)) { 610 if (!this->chooseFromOneChoice(*colorTypep, origWidth, origHeight)) {
617 return false; 611 return false;
618 } 612 }
619 613
620 // If the image has alpha and the decoder wants unpremultiplied 614 // If the image has alpha and the decoder wants unpremultiplied
621 // colors, the only supported config is 8888. 615 // colors, the only supported config is 8888.
622 if (this->getRequireUnpremultipliedColors() && *hasAlphap) { 616 if (this->getRequireUnpremultipliedColors() && *hasAlphap) {
623 *configp = SkBitmap::kARGB_8888_Config; 617 *colorTypep = kN32_SkColorType;
624 } 618 }
625 619
626 if (fImageIndex != NULL) { 620 if (fImageIndex != NULL) {
627 if (SkBitmap::kNo_Config == fImageIndex->fConfig) { 621 if (kUnknown_SkColorType == fImageIndex->fColorType) {
628 // This is the first time for this subset decode. From now on, 622 // This is the first time for this subset decode. From now on,
629 // all decodes must be in the same config. 623 // all decodes must be in the same config.
630 fImageIndex->fConfig = *configp; 624 fImageIndex->fColorType = *colorTypep;
631 } else if (fImageIndex->fConfig != *configp) { 625 } else if (fImageIndex->fColorType != *colorTypep) {
632 // Requesting a different config for a subsequent decode is not 626 // Requesting a different colortype for a subsequent decode is not
633 // supported. Report failure before we make changes to png_ptr. 627 // supported. Report failure before we make changes to png_ptr.
634 return false; 628 return false;
635 } 629 }
636 } 630 }
637 631
638 bool convertGrayToRGB = PNG_COLOR_TYPE_GRAY == colorType 632 bool convertGrayToRGB = PNG_COLOR_TYPE_GRAY == colorType && *colorTypep != k Alpha_8_SkColorType;
639 && *configp != SkBitmap::kA8_Config;
640 633
641 // Unless the user is requesting A8, convert a grayscale image into RGB. 634 // Unless the user is requesting A8, convert a grayscale image into RGB.
642 // GRAY_ALPHA will always be converted to RGB 635 // GRAY_ALPHA will always be converted to RGB
643 if (convertGrayToRGB || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) { 636 if (convertGrayToRGB || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) {
644 png_set_gray_to_rgb(png_ptr); 637 png_set_gray_to_rgb(png_ptr);
645 } 638 }
646 639
647 // Add filler (or alpha) byte (after each RGB triplet) if necessary. 640 // Add filler (or alpha) byte (after each RGB triplet) if necessary.
648 if (colorType == PNG_COLOR_TYPE_RGB || convertGrayToRGB) { 641 if (colorType == PNG_COLOR_TYPE_RGB || convertGrayToRGB) {
649 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); 642 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
767 return false; 760 return false;
768 } 761 }
769 762
770 png_structp png_ptr = fImageIndex->fPng_ptr; 763 png_structp png_ptr = fImageIndex->fPng_ptr;
771 png_infop info_ptr = fImageIndex->fInfo_ptr; 764 png_infop info_ptr = fImageIndex->fInfo_ptr;
772 if (setjmp(png_jmpbuf(png_ptr))) { 765 if (setjmp(png_jmpbuf(png_ptr))) {
773 return false; 766 return false;
774 } 767 }
775 768
776 png_uint_32 origWidth, origHeight; 769 png_uint_32 origWidth, origHeight;
777 int bitDepth, colorType, interlaceType; 770 int bitDepth, pngColorType, interlaceType;
778 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, 771 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
779 &colorType, &interlaceType, int_p_NULL, int_p_NULL); 772 &pngColorType, &interlaceType, int_p_NULL, int_p_NULL);
780 773
781 SkIRect rect = SkIRect::MakeWH(origWidth, origHeight); 774 SkIRect rect = SkIRect::MakeWH(origWidth, origHeight);
782 775
783 if (!rect.intersect(region)) { 776 if (!rect.intersect(region)) {
784 // If the requested region is entirely outside the image, just 777 // If the requested region is entirely outside the image, just
785 // returns false 778 // returns false
786 return false; 779 return false;
787 } 780 }
788 781
789 SkBitmap::Config config; 782 SkColorType colorType;
790 bool hasAlpha = false; 783 bool hasAlpha = false;
791 SkPMColor theTranspColor = 0; // 0 tells us not to try to match 784 SkPMColor theTranspColor = 0; // 0 tells us not to try to match
792 785
793 if (!this->getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha, &theTransp Color)) { 786 if (!this->getBitmapConfig(png_ptr, info_ptr, &colorType, &hasAlpha, &theTra nspColor)) {
794 return false; 787 return false;
795 } 788 }
796 789
797 const int sampleSize = this->getSampleSize(); 790 const int sampleSize = this->getSampleSize();
798 SkScaledBitmapSampler sampler(origWidth, rect.height(), sampleSize); 791 SkScaledBitmapSampler sampler(origWidth, rect.height(), sampleSize);
799 792
800 SkBitmap decodedBitmap; 793 SkBitmap decodedBitmap;
801 decodedBitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight( )); 794 decodedBitmap.setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scale dHeight(),
795 colorType, kPremul_SkAlphaType));
802 796
803 // from here down we are concerned with colortables and pixels 797 // from here down we are concerned with colortables and pixels
804 798
805 // we track if we actually see a non-opaque pixels, since sometimes a PNG se ts its colortype 799 // we track if we actually see a non-opaque pixels, since sometimes a PNG se ts its colortype
806 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we 800 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we
807 // draw lots faster if we can flag the bitmap has being opaque 801 // draw lots faster if we can flag the bitmap has being opaque
808 bool reallyHasAlpha = false; 802 bool reallyHasAlpha = false;
809 SkColorTable* colorTable = NULL; 803 SkColorTable* colorTable = NULL;
810 804
811 if (colorType == PNG_COLOR_TYPE_PALETTE) { 805 if (pngColorType == PNG_COLOR_TYPE_PALETTE) {
812 decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable ); 806 decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable );
813 } 807 }
814 808
815 SkAutoUnref aur(colorTable); 809 SkAutoUnref aur(colorTable);
816 810
817 // Check ahead of time if the swap(dest, src) is possible. 811 // Check ahead of time if the swap(dest, src) is possible.
818 // If yes, then we will stick to AllocPixelRef since it's cheaper with the s wap happening. 812 // If yes, then we will stick to AllocPixelRef since it's cheaper with the s wap happening.
819 // If no, then we will use alloc to allocate pixels to prevent garbage colle ction. 813 // If no, then we will use alloc to allocate pixels to prevent garbage colle ction.
820 int w = rect.width() / sampleSize; 814 int w = rect.width() / sampleSize;
821 int h = rect.height() / sampleSize; 815 int h = rect.height() / sampleSize;
822 const bool swapOnly = (rect == region) && (w == decodedBitmap.width()) && 816 const bool swapOnly = (rect == region) && (w == decodedBitmap.width()) &&
823 (h == decodedBitmap.height()) && bm->isNull(); 817 (h == decodedBitmap.height()) && bm->isNull();
824 const bool needColorTable = SkBitmap::kIndex8_Config == config; 818 const bool needColorTable = kIndex_8_SkColorType == colorType;
825 if (swapOnly) { 819 if (swapOnly) {
826 if (!this->allocPixelRef(&decodedBitmap, needColorTable ? colorTable : N ULL)) { 820 if (!this->allocPixelRef(&decodedBitmap, needColorTable ? colorTable : N ULL)) {
827 return false; 821 return false;
828 } 822 }
829 } else { 823 } else {
830 if (!decodedBitmap.allocPixels(NULL, needColorTable ? colorTable : NULL) ) { 824 if (!decodedBitmap.allocPixels(NULL, needColorTable ? colorTable : NULL) ) {
831 return false; 825 return false;
832 } 826 }
833 } 827 }
834 SkAutoLockPixels alp(decodedBitmap); 828 SkAutoLockPixels alp(decodedBitmap);
(...skipping 14 matching lines...) Expand all
849 #if defined(PNG_1_0_X) || defined (PNG_1_2_X) 843 #if defined(PNG_1_0_X) || defined (PNG_1_2_X)
850 png_ptr->pass = 0; 844 png_ptr->pass = 0;
851 #else 845 #else
852 // FIXME: This sets pass as desired, but also sets iwidth. Is that ok? 846 // FIXME: This sets pass as desired, but also sets iwidth. Is that ok?
853 png_set_interlaced_pass(png_ptr, 0); 847 png_set_interlaced_pass(png_ptr, 0);
854 #endif 848 #endif
855 png_read_update_info(png_ptr, info_ptr); 849 png_read_update_info(png_ptr, info_ptr);
856 850
857 int actualTop = rect.fTop; 851 int actualTop = rect.fTop;
858 852
859 if ((SkBitmap::kA8_Config == config || SkBitmap::kIndex8_Config == config) 853 if ((kAlpha_8_SkColorType == colorType || kIndex_8_SkColorType == colorType)
860 && 1 == sampleSize) { 854 && 1 == sampleSize) {
861 if (SkBitmap::kA8_Config == config) { 855 if (kAlpha_8_SkColorType == colorType) {
862 // For an A8 bitmap, we assume there is an alpha for speed. It is 856 // For an A8 bitmap, we assume there is an alpha for speed. It is
863 // possible the bitmap is opaque, but that is an unlikely use case 857 // possible the bitmap is opaque, but that is an unlikely use case
864 // since it would not be very interesting. 858 // since it would not be very interesting.
865 reallyHasAlpha = true; 859 reallyHasAlpha = true;
866 // A8 is only allowed if the original was GRAY. 860 // A8 is only allowed if the original was GRAY.
867 SkASSERT(PNG_COLOR_TYPE_GRAY == colorType); 861 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType);
868 } 862 }
869 863
870 for (int i = 0; i < number_passes; i++) { 864 for (int i = 0; i < number_passes; i++) {
871 png_configure_decoder(png_ptr, &actualTop, i); 865 png_configure_decoder(png_ptr, &actualTop, i);
872 for (int j = 0; j < rect.fTop - actualTop; j++) { 866 for (int j = 0; j < rect.fTop - actualTop; j++) {
873 uint8_t* bmRow = decodedBitmap.getAddr8(0, 0); 867 uint8_t* bmRow = decodedBitmap.getAddr8(0, 0);
874 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); 868 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
875 } 869 }
876 png_uint_32 bitmapHeight = (png_uint_32) decodedBitmap.height(); 870 png_uint_32 bitmapHeight = (png_uint_32) decodedBitmap.height();
877 for (png_uint_32 y = 0; y < bitmapHeight; y++) { 871 for (png_uint_32 y = 0; y < bitmapHeight; y++) {
878 uint8_t* bmRow = decodedBitmap.getAddr8(0, y); 872 uint8_t* bmRow = decodedBitmap.getAddr8(0, y);
879 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); 873 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
880 } 874 }
881 } 875 }
882 } else { 876 } else {
883 SkScaledBitmapSampler::SrcConfig sc; 877 SkScaledBitmapSampler::SrcConfig sc;
884 int srcBytesPerPixel = 4; 878 int srcBytesPerPixel = 4;
885 879
886 if (colorTable != NULL) { 880 if (colorTable != NULL) {
887 sc = SkScaledBitmapSampler::kIndex; 881 sc = SkScaledBitmapSampler::kIndex;
888 srcBytesPerPixel = 1; 882 srcBytesPerPixel = 1;
889 } else if (SkBitmap::kA8_Config == config) { 883 } else if (kAlpha_8_SkColorType == colorType) {
890 // A8 is only allowed if the original was GRAY. 884 // A8 is only allowed if the original was GRAY.
891 SkASSERT(PNG_COLOR_TYPE_GRAY == colorType); 885 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType);
892 sc = SkScaledBitmapSampler::kGray; 886 sc = SkScaledBitmapSampler::kGray;
893 srcBytesPerPixel = 1; 887 srcBytesPerPixel = 1;
894 } else if (hasAlpha) { 888 } else if (hasAlpha) {
895 sc = SkScaledBitmapSampler::kRGBA; 889 sc = SkScaledBitmapSampler::kRGBA;
896 } else { 890 } else {
897 sc = SkScaledBitmapSampler::kRGBX; 891 sc = SkScaledBitmapSampler::kRGBX;
898 } 892 }
899 893
900 /* We have to pass the colortable explicitly, since we may have one 894 /* We have to pass the colortable explicitly, since we may have one
901 even if our decodedBitmap doesn't, due to the request that we 895 even if our decodedBitmap doesn't, due to the request that we
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
950 skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1); 944 skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1);
951 } 945 }
952 } 946 }
953 } 947 }
954 } 948 }
955 949
956 if (0 != theTranspColor) { 950 if (0 != theTranspColor) {
957 reallyHasAlpha |= substituteTranspColor(&decodedBitmap, theTranspColor); 951 reallyHasAlpha |= substituteTranspColor(&decodedBitmap, theTranspColor);
958 } 952 }
959 if (reallyHasAlpha && this->getRequireUnpremultipliedColors()) { 953 if (reallyHasAlpha && this->getRequireUnpremultipliedColors()) {
960 switch (decodedBitmap.config()) { 954 switch (decodedBitmap.colorType()) {
961 case SkBitmap::kIndex8_Config: 955 case kIndex_8_SkColorType:
962 // Fall through. 956 // Fall through.
963 case SkBitmap::kARGB_4444_Config: 957 case kARGB_4444_SkColorType:
964 // We have chosen not to support unpremul for these configs. 958 // We have chosen not to support unpremul for these colortypess.
965 return false; 959 return false;
966 default: { 960 default: {
967 // Fall through to finish the decode. This config either 961 // Fall through to finish the decode. This config either
968 // supports unpremul or it is irrelevant because it has no 962 // supports unpremul or it is irrelevant because it has no
969 // alpha (or only alpha). 963 // alpha (or only alpha).
970 // These brackets prevent a warning. 964 // These brackets prevent a warning.
971 } 965 }
972 } 966 }
973 } 967 }
974 SkAlphaType alphaType = kOpaque_SkAlphaType; 968 SkAlphaType alphaType = kOpaque_SkAlphaType;
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
1287 return SkImageDecoder::kUnknown_Format; 1281 return SkImageDecoder::kUnknown_Format;
1288 } 1282 }
1289 1283
1290 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { 1284 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) {
1291 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; 1285 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL;
1292 } 1286 }
1293 1287
1294 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory); 1288 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory);
1295 static SkImageDecoder_FormatReg gFormatReg(get_format_png); 1289 static SkImageDecoder_FormatReg gFormatReg(get_format_png);
1296 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); 1290 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory);
OLDNEW
« no previous file with comments | « src/images/SkImageDecoder_libjpeg.cpp ('k') | src/images/SkImageDecoder_libwebp.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698