OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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); |
OLD | NEW |