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

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

Issue 1828433004: Revert of Delete SkImageDecoder (Closed) Base URL: https://skia.googlesource.com/skia.git@fix-animator
Patch Set: Created 4 years, 9 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 /* 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 "SkImageEncoder.h" 9 #include "SkImageEncoder.h"
9 #include "SkColor.h" 10 #include "SkColor.h"
10 #include "SkColorPriv.h" 11 #include "SkColorPriv.h"
11 #include "SkDither.h" 12 #include "SkDither.h"
12 #include "SkMath.h" 13 #include "SkMath.h"
13 #include "SkRTConf.h" 14 #include "SkRTConf.h"
15 #include "SkScaledBitmapSampler.h"
14 #include "SkStream.h" 16 #include "SkStream.h"
15 #include "SkTemplates.h" 17 #include "SkTemplates.h"
16 #include "SkUtils.h" 18 #include "SkUtils.h"
17 #include "transform_scanline.h" 19 #include "transform_scanline.h"
18 20
19 #include "png.h" 21 #include "png.h"
20 22
21 /* These were dropped in libpng >= 1.4 */ 23 /* These were dropped in libpng >= 1.4 */
22 #ifndef png_infopp_NULL 24 #ifndef png_infopp_NULL
23 #define png_infopp_NULL nullptr 25 #define png_infopp_NULL nullptr
(...skipping 11 matching lines...) Expand all
35 #define png_flush_ptr_NULL nullptr 37 #define png_flush_ptr_NULL nullptr
36 #endif 38 #endif
37 39
38 #define DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS true 40 #define DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS true
39 SK_CONF_DECLARE(bool, c_suppressPNGImageDecoderWarnings, 41 SK_CONF_DECLARE(bool, c_suppressPNGImageDecoderWarnings,
40 "images.png.suppressDecoderWarnings", 42 "images.png.suppressDecoderWarnings",
41 DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS, 43 DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS,
42 "Suppress most PNG warnings when calling image decode " 44 "Suppress most PNG warnings when calling image decode "
43 "functions."); 45 "functions.");
44 46
45 /////////////////////////////////////////////////////////////////////////////// 47 class SkPNGImageIndex {
48 public:
49 // Takes ownership of stream.
50 SkPNGImageIndex(SkStreamRewindable* stream, png_structp png_ptr, png_infop i nfo_ptr)
51 : fStream(stream)
52 , fPng_ptr(png_ptr)
53 , fInfo_ptr(info_ptr)
54 , fColorType(kUnknown_SkColorType) {
55 SkASSERT(stream != nullptr);
56 }
57 ~SkPNGImageIndex() {
58 if (fPng_ptr) {
59 png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, png_infopp_NULL);
60 }
61 }
46 62
47 #include "SkColorPriv.h" 63 SkAutoTDelete<SkStreamRewindable> fStream;
48 #include "SkUnPreMultiply.h" 64 png_structp fPng_ptr;
65 png_infop fInfo_ptr;
66 SkColorType fColorType;
67 };
68
69 class SkPNGImageDecoder : public SkImageDecoder {
70 public:
71 SkPNGImageDecoder() {
72 fImageIndex = nullptr;
73 }
74 Format getFormat() const override {
75 return kPNG_Format;
76 }
77
78 virtual ~SkPNGImageDecoder() { delete fImageIndex; }
79
80 protected:
81 Result onDecode(SkStream* stream, SkBitmap* bm, Mode) override;
82
83 private:
84 SkPNGImageIndex* fImageIndex;
85
86 bool onDecodeInit(SkStream* stream, png_structp *png_ptrp, png_infop *info_p trp);
87 bool decodePalette(png_structp png_ptr, png_infop info_ptr, int bitDepth,
88 bool * SK_RESTRICT hasAlphap, bool *reallyHasAlphap,
89 SkColorTable **colorTablep);
90 bool getBitmapColorType(png_structp, png_infop, SkColorType*, bool* hasAlpha ,
91 SkPMColor* theTranspColor);
92
93 typedef SkImageDecoder INHERITED;
94 };
95
96 #ifndef png_jmpbuf
97 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
98 #endif
99
100 #define PNG_BYTES_TO_CHECK 4
101
102 /* Automatically clean up after throwing an exception */
103 struct PNGAutoClean {
104 PNGAutoClean(png_structp p, png_infop i): png_ptr(p), info_ptr(i) {}
105 ~PNGAutoClean() {
106 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
107 }
108 private:
109 png_structp png_ptr;
110 png_infop info_ptr;
111 };
112
113 static void sk_read_fn(png_structp png_ptr, png_bytep data, png_size_t length) {
114 SkStream* sk_stream = (SkStream*) png_get_io_ptr(png_ptr);
115 size_t bytes = sk_stream->read(data, length);
116 if (bytes != length) {
117 png_error(png_ptr, "Read Error!");
118 }
119 }
120
121 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
122 static int sk_read_user_chunk(png_structp png_ptr, png_unknown_chunkp chunk) {
123 SkPngChunkReader* peeker = (SkPngChunkReader*)png_get_user_chunk_ptr(png_ptr );
124 // readChunk() returning true means continue decoding
125 return peeker->readChunk((const char*)chunk->name, chunk->data, chunk->size) ?
126 1 : -1;
127 }
128 #endif
49 129
50 static void sk_error_fn(png_structp png_ptr, png_const_charp msg) { 130 static void sk_error_fn(png_structp png_ptr, png_const_charp msg) {
51 if (!c_suppressPNGImageDecoderWarnings) { 131 if (!c_suppressPNGImageDecoderWarnings) {
52 SkDEBUGF(("------ png error %s\n", msg)); 132 SkDEBUGF(("------ png error %s\n", msg));
53 } 133 }
54 longjmp(png_jmpbuf(png_ptr), 1); 134 longjmp(png_jmpbuf(png_ptr), 1);
55 } 135 }
56 136
137 static void skip_src_rows(png_structp png_ptr, uint8_t storage[], int count) {
138 for (int i = 0; i < count; i++) {
139 uint8_t* tmp = storage;
140 png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1);
141 }
142 }
143
144 static bool pos_le(int value, int max) {
145 return value > 0 && value <= max;
146 }
147
148 static bool substituteTranspColor(SkBitmap* bm, SkPMColor match) {
149 SkASSERT(bm->colorType() == kN32_SkColorType);
150
151 bool reallyHasAlpha = false;
152
153 for (int y = bm->height() - 1; y >= 0; --y) {
154 SkPMColor* p = bm->getAddr32(0, y);
155 for (int x = bm->width() - 1; x >= 0; --x) {
156 if (match == *p) {
157 *p = 0;
158 reallyHasAlpha = true;
159 }
160 p += 1;
161 }
162 }
163 return reallyHasAlpha;
164 }
165
166 static bool canUpscalePaletteToConfig(SkColorType dstColorType, bool srcHasAlpha ) {
167 switch (dstColorType) {
168 case kN32_SkColorType:
169 case kARGB_4444_SkColorType:
170 return true;
171 case kRGB_565_SkColorType:
172 // only return true if the src is opaque (since 565 is opaque)
173 return !srcHasAlpha;
174 default:
175 return false;
176 }
177 }
178
179 // call only if color_type is PALETTE. Returns true if the ctable has alpha
180 static bool hasTransparencyInPalette(png_structp png_ptr, png_infop info_ptr) {
181 png_bytep trans;
182 int num_trans;
183
184 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
185 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, nullptr);
186 return num_trans > 0;
187 }
188 return false;
189 }
190
191 void do_nothing_warning_fn(png_structp, png_const_charp) {
192 /* do nothing */
193 }
194
195 bool SkPNGImageDecoder::onDecodeInit(SkStream* sk_stream, png_structp *png_ptrp,
196 png_infop *info_ptrp) {
197 /* Create and initialize the png_struct with the desired error handler
198 * functions. If you want to use the default stderr and longjump method,
199 * you can supply nullptr for the last three parameters. We also supply the
200 * the compiler header file version, so that we know if the application
201 * was compiled with a compatible version of the library. */
202
203 png_error_ptr user_warning_fn =
204 (c_suppressPNGImageDecoderWarnings) ? (&do_nothing_warning_fn) : nullptr ;
205 /* nullptr means to leave as default library behavior. */
206 /* c_suppressPNGImageDecoderWarnings default depends on SK_DEBUG. */
207 /* To suppress warnings with a SK_DEBUG binary, set the
208 * environment variable "skia_images_png_suppressDecoderWarnings"
209 * to "true". Inside a program that links to skia:
210 * SK_CONF_SET("images.png.suppressDecoderWarnings", true); */
211
212 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
213 nullptr, sk_error_fn, user_warning_fn);
214 // png_voidp user_error_ptr, user_error_fn, user_warning_fn);
215 if (png_ptr == nullptr) {
216 return false;
217 }
218
219 *png_ptrp = png_ptr;
220
221 /* Allocate/initialize the memory for image information. */
222 png_infop info_ptr = png_create_info_struct(png_ptr);
223 if (info_ptr == nullptr) {
224 png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
225 return false;
226 }
227 *info_ptrp = info_ptr;
228
229 /* Set error handling if you are using the setjmp/longjmp method (this is
230 * the normal method of doing things with libpng). REQUIRED unless you
231 * set up your own error handlers in the png_create_read_struct() earlier.
232 */
233 if (setjmp(png_jmpbuf(png_ptr))) {
234 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
235 return false;
236 }
237
238 /* If you are using replacement read functions, instead of calling
239 * png_init_io() here you would call:
240 */
241 png_set_read_fn(png_ptr, (void *)sk_stream, sk_read_fn);
242 /* where user_io_ptr is a structure you want available to the callbacks */
243 /* If we have already read some of the signature */
244 // png_set_sig_bytes(png_ptr, 0 /* sig_read */ );
245
246 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
247 // hookup our peeker so we can see any user-chunks the caller may be interes ted in
248 png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, (png_byte*)"", 0);
249 if (this->getPeeker()) {
250 png_set_read_user_chunk_fn(png_ptr, (png_voidp)this->getPeeker(), sk_rea d_user_chunk);
251 }
252 #endif
253 /* The call to png_read_info() gives us all of the information from the
254 * PNG file before the first IDAT (image data chunk). */
255 png_read_info(png_ptr, info_ptr);
256 png_uint_32 origWidth, origHeight;
257 int bitDepth, colorType;
258 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
259 &colorType, int_p_NULL, int_p_NULL, int_p_NULL);
260
261 /* tell libpng to strip 16 bit/color files down to 8 bits/color */
262 if (bitDepth == 16) {
263 png_set_strip_16(png_ptr);
264 }
265 #ifdef PNG_READ_PACK_SUPPORTED
266 /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
267 * byte into separate bytes (useful for paletted and grayscale images). */
268 if (bitDepth < 8) {
269 png_set_packing(png_ptr);
270 }
271 #endif
272 /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
273 if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) {
274 png_set_expand_gray_1_2_4_to_8(png_ptr);
275 }
276
277 return true;
278 }
279
280 SkImageDecoder::Result SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap * decodedBitmap,
281 Mode mode) {
282 png_structp png_ptr;
283 png_infop info_ptr;
284
285 if (!onDecodeInit(sk_stream, &png_ptr, &info_ptr)) {
286 return kFailure;
287 }
288
289 PNGAutoClean autoClean(png_ptr, info_ptr);
290
291 if (setjmp(png_jmpbuf(png_ptr))) {
292 return kFailure;
293 }
294
295 png_uint_32 origWidth, origHeight;
296 int bitDepth, pngColorType, interlaceType;
297 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
298 &pngColorType, &interlaceType, int_p_NULL, int_p_NULL);
299
300 SkColorType colorType;
301 bool hasAlpha = false;
302 SkPMColor theTranspColor = 0; // 0 tells us not to try to match
303
304 if (!this->getBitmapColorType(png_ptr, info_ptr, &colorType, &hasAlpha, &the TranspColor)) {
305 return kFailure;
306 }
307
308 SkAlphaType alphaType = this->getRequireUnpremultipliedColors() ?
309 kUnpremul_SkAlphaType : kPremul_SkAlphaType;
310 const int sampleSize = this->getSampleSize();
311 SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize);
312 decodedBitmap->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scal edHeight(),
313 colorType, alphaType));
314
315 if (SkImageDecoder::kDecodeBounds_Mode == mode) {
316 return kSuccess;
317 }
318
319 // from here down we are concerned with colortables and pixels
320
321 // we track if we actually see a non-opaque pixels, since sometimes a PNG se ts its colortype
322 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we
323 // draw lots faster if we can flag the bitmap has being opaque
324 bool reallyHasAlpha = false;
325 SkColorTable* colorTable = nullptr;
326
327 if (pngColorType == PNG_COLOR_TYPE_PALETTE) {
328 decodePalette(png_ptr, info_ptr, bitDepth, &hasAlpha, &reallyHasAlpha, & colorTable);
329 }
330
331 SkAutoUnref aur(colorTable);
332
333 if (!this->allocPixelRef(decodedBitmap,
334 kIndex_8_SkColorType == colorType ? colorTable : nu llptr)) {
335 return kFailure;
336 }
337
338 SkAutoLockPixels alp(*decodedBitmap);
339
340 // Repeat setjmp, otherwise variables declared since the last call (e.g. alp
341 // and aur) won't get their destructors called in case of a failure.
342 if (setjmp(png_jmpbuf(png_ptr))) {
343 return kFailure;
344 }
345
346 /* Turn on interlace handling. REQUIRED if you are not using
347 * png_read_image(). To see how to handle interlacing passes,
348 * see the png_read_row() method below:
349 */
350 const int number_passes = (interlaceType != PNG_INTERLACE_NONE) ?
351 png_set_interlace_handling(png_ptr) : 1;
352
353 /* Optional call to gamma correct and add the background to the palette
354 * and update info structure. REQUIRED if you are expecting libpng to
355 * update the palette for you (ie you selected such a transform above).
356 */
357 png_read_update_info(png_ptr, info_ptr);
358
359 if ((kAlpha_8_SkColorType == colorType || kIndex_8_SkColorType == colorType) &&
360 1 == sampleSize) {
361 if (kAlpha_8_SkColorType == colorType) {
362 // For an A8 bitmap, we assume there is an alpha for speed. It is
363 // possible the bitmap is opaque, but that is an unlikely use case
364 // since it would not be very interesting.
365 reallyHasAlpha = true;
366 // A8 is only allowed if the original was GRAY.
367 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType);
368 }
369 for (int i = 0; i < number_passes; i++) {
370 for (png_uint_32 y = 0; y < origHeight; y++) {
371 uint8_t* bmRow = decodedBitmap->getAddr8(0, y);
372 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
373 }
374 }
375 } else {
376 SkScaledBitmapSampler::SrcConfig sc;
377 int srcBytesPerPixel = 4;
378
379 if (colorTable != nullptr) {
380 sc = SkScaledBitmapSampler::kIndex;
381 srcBytesPerPixel = 1;
382 } else if (kAlpha_8_SkColorType == colorType) {
383 // A8 is only allowed if the original was GRAY.
384 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType);
385 sc = SkScaledBitmapSampler::kGray;
386 srcBytesPerPixel = 1;
387 } else if (hasAlpha) {
388 sc = SkScaledBitmapSampler::kRGBA;
389 } else {
390 sc = SkScaledBitmapSampler::kRGBX;
391 }
392
393 /* We have to pass the colortable explicitly, since we may have one
394 even if our decodedBitmap doesn't, due to the request that we
395 upscale png's palette to a direct model
396 */
397 const SkPMColor* colors = colorTable ? colorTable->readColors() : nullpt r;
398 if (!sampler.begin(decodedBitmap, sc, *this, colors)) {
399 return kFailure;
400 }
401 const int height = decodedBitmap->height();
402
403 if (number_passes > 1) {
404 SkAutoTMalloc<uint8_t> storage(origWidth * origHeight * srcBytesPerP ixel);
405 uint8_t* base = storage.get();
406 size_t rowBytes = origWidth * srcBytesPerPixel;
407
408 for (int i = 0; i < number_passes; i++) {
409 uint8_t* row = base;
410 for (png_uint_32 y = 0; y < origHeight; y++) {
411 uint8_t* bmRow = row;
412 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
413 row += rowBytes;
414 }
415 }
416 // now sample it
417 base += sampler.srcY0() * rowBytes;
418 for (int y = 0; y < height; y++) {
419 reallyHasAlpha |= sampler.next(base);
420 base += sampler.srcDY() * rowBytes;
421 }
422 } else {
423 SkAutoTMalloc<uint8_t> storage(origWidth * srcBytesPerPixel);
424 uint8_t* srcRow = storage.get();
425 skip_src_rows(png_ptr, srcRow, sampler.srcY0());
426
427 for (int y = 0; y < height; y++) {
428 uint8_t* tmp = srcRow;
429 png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1);
430 reallyHasAlpha |= sampler.next(srcRow);
431 if (y < height - 1) {
432 skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1);
433 }
434 }
435
436 // skip the rest of the rows (if any)
437 png_uint_32 read = (height - 1) * sampler.srcDY() +
438 sampler.srcY0() + 1;
439 SkASSERT(read <= origHeight);
440 skip_src_rows(png_ptr, srcRow, origHeight - read);
441 }
442 }
443
444 /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
445 png_read_end(png_ptr, info_ptr);
446
447 if (0 != theTranspColor) {
448 reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor);
449 }
450 if (reallyHasAlpha && this->getRequireUnpremultipliedColors()) {
451 switch (decodedBitmap->colorType()) {
452 case kIndex_8_SkColorType:
453 // Fall through.
454 case kARGB_4444_SkColorType:
455 // We have chosen not to support unpremul for these colortypes.
456 return kFailure;
457 default: {
458 // Fall through to finish the decode. This colortype either
459 // supports unpremul or it is irrelevant because it has no
460 // alpha (or only alpha).
461 // These brackets prevent a warning.
462 }
463 }
464 }
465
466 if (!reallyHasAlpha) {
467 decodedBitmap->setAlphaType(kOpaque_SkAlphaType);
468 }
469 return kSuccess;
470 }
471
472
473
474 bool SkPNGImageDecoder::getBitmapColorType(png_structp png_ptr, png_infop info_p tr,
475 SkColorType* colorTypep,
476 bool* hasAlphap,
477 SkPMColor* SK_RESTRICT theTranspColor p) {
478 png_uint_32 origWidth, origHeight;
479 int bitDepth, colorType;
480 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
481 &colorType, int_p_NULL, int_p_NULL, int_p_NULL);
482
483 #ifdef PNG_sBIT_SUPPORTED
484 // check for sBIT chunk data, in case we should disable dithering because
485 // our data is not truely 8bits per component
486 png_color_8p sig_bit;
487 if (this->getDitherImage() && png_get_sBIT(png_ptr, info_ptr, &sig_bit)) {
488 #if 0
489 SkDebugf("----- sBIT %d %d %d %d\n", sig_bit->red, sig_bit->green,
490 sig_bit->blue, sig_bit->alpha);
491 #endif
492 // 0 seems to indicate no information available
493 if (pos_le(sig_bit->red, SK_R16_BITS) &&
494 pos_le(sig_bit->green, SK_G16_BITS) &&
495 pos_le(sig_bit->blue, SK_B16_BITS)) {
496 this->setDitherImage(false);
497 }
498 }
499 #endif
500
501 if (colorType == PNG_COLOR_TYPE_PALETTE) {
502 bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr);
503 *colorTypep = this->getPrefColorType(kIndex_SrcDepth, paletteHasAlpha);
504 // now see if we can upscale to their requested colortype
505 if (!canUpscalePaletteToConfig(*colorTypep, paletteHasAlpha)) {
506 *colorTypep = kIndex_8_SkColorType;
507 }
508 } else {
509 png_color_16p transpColor = nullptr;
510 int numTransp = 0;
511
512 png_get_tRNS(png_ptr, info_ptr, nullptr, &numTransp, &transpColor);
513
514 bool valid = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS);
515
516 if (valid && numTransp == 1 && transpColor != nullptr) {
517 /* Compute our transparent color, which we'll match against later.
518 We don't really handle 16bit components properly here, since we
519 do our compare *after* the values have been knocked down to 8bit
520 which means we will find more matches than we should. The real
521 fix seems to be to see the actual 16bit components, do the
522 compare, and then knock it down to 8bits ourselves.
523 */
524 if (colorType & PNG_COLOR_MASK_COLOR) {
525 if (16 == bitDepth) {
526 *theTranspColorp = SkPackARGB32(0xFF, transpColor->red >> 8,
527 transpColor->green >> 8,
528 transpColor->blue >> 8);
529 } else {
530 /* We apply the mask because in a very small
531 number of corrupt PNGs, (transpColor->red > 255)
532 and (bitDepth == 8), for certain versions of libpng. */
533 *theTranspColorp = SkPackARGB32(0xFF,
534 0xFF & (transpColor->red),
535 0xFF & (transpColor->green),
536 0xFF & (transpColor->blue));
537 }
538 } else { // gray
539 if (16 == bitDepth) {
540 *theTranspColorp = SkPackARGB32(0xFF, transpColor->gray >> 8 ,
541 transpColor->gray >> 8,
542 transpColor->gray >> 8);
543 } else {
544 /* We apply the mask because in a very small
545 number of corrupt PNGs, (transpColor->red >
546 255) and (bitDepth == 8), for certain versions
547 of libpng. For safety we assume the same could
548 happen with a grayscale PNG. */
549 *theTranspColorp = SkPackARGB32(0xFF,
550 0xFF & (transpColor->gray),
551 0xFF & (transpColor->gray),
552 0xFF & (transpColor->gray));
553 }
554 }
555 }
556
557 if (valid ||
558 PNG_COLOR_TYPE_RGB_ALPHA == colorType ||
559 PNG_COLOR_TYPE_GRAY_ALPHA == colorType) {
560 *hasAlphap = true;
561 }
562
563 SrcDepth srcDepth = k32Bit_SrcDepth;
564 if (PNG_COLOR_TYPE_GRAY == colorType) {
565 srcDepth = k8BitGray_SrcDepth;
566 // Remove this assert, which fails on desk_pokemonwiki.skp
567 //SkASSERT(!*hasAlphap);
568 }
569
570 *colorTypep = this->getPrefColorType(srcDepth, *hasAlphap);
571 // now match the request against our capabilities
572 if (*hasAlphap) {
573 if (*colorTypep != kARGB_4444_SkColorType) {
574 *colorTypep = kN32_SkColorType;
575 }
576 } else {
577 if (kAlpha_8_SkColorType == *colorTypep) {
578 if (k8BitGray_SrcDepth != srcDepth) {
579 // Converting a non grayscale image to A8 is not currently s upported.
580 *colorTypep = kN32_SkColorType;
581 }
582 } else if (*colorTypep != kRGB_565_SkColorType &&
583 *colorTypep != kARGB_4444_SkColorType) {
584 *colorTypep = kN32_SkColorType;
585 }
586 }
587 }
588
589 // sanity check for size
590 {
591 int64_t size = sk_64_mul(origWidth, origHeight);
592 // now check that if we are 4-bytes per pixel, we also don't overflow
593 if (size < 0 || size > (0x7FFFFFFF >> 2)) {
594 return false;
595 }
596 }
597
598 // If the image has alpha and the decoder wants unpremultiplied
599 // colors, the only supported colortype is 8888.
600 if (this->getRequireUnpremultipliedColors() && *hasAlphap) {
601 *colorTypep = kN32_SkColorType;
602 }
603
604 if (fImageIndex != nullptr) {
605 if (kUnknown_SkColorType == fImageIndex->fColorType) {
606 // This is the first time for this subset decode. From now on,
607 // all decodes must be in the same colortype.
608 fImageIndex->fColorType = *colorTypep;
609 } else if (fImageIndex->fColorType != *colorTypep) {
610 // Requesting a different colortype for a subsequent decode is not
611 // supported. Report failure before we make changes to png_ptr.
612 return false;
613 }
614 }
615
616 bool convertGrayToRGB = PNG_COLOR_TYPE_GRAY == colorType && *colorTypep != k Alpha_8_SkColorType;
617
618 // Unless the user is requesting A8, convert a grayscale image into RGB.
619 // GRAY_ALPHA will always be converted to RGB
620 if (convertGrayToRGB || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) {
621 png_set_gray_to_rgb(png_ptr);
622 }
623
624 // Add filler (or alpha) byte (after each RGB triplet) if necessary.
625 if (colorType == PNG_COLOR_TYPE_RGB || convertGrayToRGB) {
626 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
627 }
628
629 return true;
630 }
631
632 typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
633
634 bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr,
635 int bitDepth, bool *hasAlphap,
636 bool *reallyHasAlphap,
637 SkColorTable **colorTablep) {
638 int numPalette;
639 png_colorp palette;
640 png_bytep trans;
641 int numTrans;
642
643 png_get_PLTE(png_ptr, info_ptr, &palette, &numPalette);
644
645 SkPMColor colorStorage[256]; // worst-case storage
646 SkPMColor* colorPtr = colorStorage;
647
648 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
649 png_get_tRNS(png_ptr, info_ptr, &trans, &numTrans, nullptr);
650 *hasAlphap = (numTrans > 0);
651 } else {
652 numTrans = 0;
653 }
654
655 // check for bad images that might make us crash
656 if (numTrans > numPalette) {
657 numTrans = numPalette;
658 }
659
660 int index = 0;
661 int transLessThanFF = 0;
662
663 // Choose which function to use to create the color table. If the final dest ination's
664 // colortype is unpremultiplied, the color table will store unpremultiplied colors.
665 PackColorProc proc;
666 if (this->getRequireUnpremultipliedColors()) {
667 proc = &SkPackARGB32NoCheck;
668 } else {
669 proc = &SkPreMultiplyARGB;
670 }
671 for (; index < numTrans; index++) {
672 transLessThanFF |= (int)*trans - 0xFF;
673 *colorPtr++ = proc(*trans++, palette->red, palette->green, palette->blue );
674 palette++;
675 }
676 bool reallyHasAlpha = (transLessThanFF < 0);
677
678 for (; index < numPalette; index++) {
679 *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette-> blue);
680 palette++;
681 }
682
683 /* BUGGY IMAGE WORKAROUND
684
685 Invalid images could contain pixel values that are greater than the numb er of palette
686 entries. Since we use pixel values as indices into the palette this coul d result in reading
687 beyond the end of the palette which could leak the contents of uninitial ized memory. To
688 ensure this doesn't happen, we grow the colortable to the maximum size t hat can be
689 addressed by the bitdepth of the image and fill it with the last palette color or black if
690 the palette is empty (really broken image).
691 */
692 int colorCount = SkTMax(numPalette, 1 << SkTMin(bitDepth, 8));
693 SkPMColor lastColor = index > 0 ? colorPtr[-1] : SkPackARGB32(0xFF, 0, 0, 0) ;
694 for (; index < colorCount; index++) {
695 *colorPtr++ = lastColor;
696 }
697
698 *colorTablep = new SkColorTable(colorStorage, colorCount);
699 *reallyHasAlphap = reallyHasAlpha;
700 return true;
701 }
702
703 ///////////////////////////////////////////////////////////////////////////////
704
705 #include "SkColorPriv.h"
706 #include "SkUnPreMultiply.h"
707
57 static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) { 708 static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) {
58 SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr); 709 SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr);
59 if (!sk_stream->write(data, len)) { 710 if (!sk_stream->write(data, len)) {
60 png_error(png_ptr, "sk_write_fn Error!"); 711 png_error(png_ptr, "sk_write_fn Error!");
61 } 712 }
62 } 713 }
63 714
64 static transform_scanline_proc choose_proc(SkColorType ct, bool hasAlpha) { 715 static transform_scanline_proc choose_proc(SkColorType ct, bool hasAlpha) {
65 // we don't care about search on alpha if we're kIndex8, since only the 716 // we don't care about search on alpha if we're kIndex8, since only the
66 // colortable packing cares about that distinction, not the pixels 717 // colortable packing cares about that distinction, not the pixels
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 } 978 }
328 979
329 png_write_end(png_ptr, info_ptr); 980 png_write_end(png_ptr, info_ptr);
330 981
331 /* clean up after the write, and free any memory allocated */ 982 /* clean up after the write, and free any memory allocated */
332 png_destroy_write_struct(&png_ptr, &info_ptr); 983 png_destroy_write_struct(&png_ptr, &info_ptr);
333 return true; 984 return true;
334 } 985 }
335 986
336 /////////////////////////////////////////////////////////////////////////////// 987 ///////////////////////////////////////////////////////////////////////////////
988 DEFINE_DECODER_CREATOR(PNGImageDecoder);
337 DEFINE_ENCODER_CREATOR(PNGImageEncoder); 989 DEFINE_ENCODER_CREATOR(PNGImageEncoder);
338 /////////////////////////////////////////////////////////////////////////////// 990 ///////////////////////////////////////////////////////////////////////////////
339 991
992 static bool is_png(SkStreamRewindable* stream) {
993 char buf[PNG_BYTES_TO_CHECK];
994 if (stream->read(buf, PNG_BYTES_TO_CHECK) == PNG_BYTES_TO_CHECK &&
995 !png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) {
996 return true;
997 }
998 return false;
999 }
1000
1001 SkImageDecoder* sk_libpng_dfactory(SkStreamRewindable* stream) {
1002 if (is_png(stream)) {
1003 return new SkPNGImageDecoder;
1004 }
1005 return nullptr;
1006 }
1007
1008 static SkImageDecoder::Format get_format_png(SkStreamRewindable* stream) {
1009 if (is_png(stream)) {
1010 return SkImageDecoder::kPNG_Format;
1011 }
1012 return SkImageDecoder::kUnknown_Format;
1013 }
1014
340 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { 1015 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) {
341 return (SkImageEncoder::kPNG_Type == t) ? new SkPNGImageEncoder : nullptr; 1016 return (SkImageEncoder::kPNG_Type == t) ? new SkPNGImageEncoder : nullptr;
342 } 1017 }
343 1018
1019 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory);
1020 static SkImageDecoder_FormatReg gFormatReg(get_format_png);
344 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); 1021 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