1 /*
2 * Copyright 2006 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "SkImageDecoder.h"
9 #include "SkImageEncoder.h"
10 #include "SkColor.h"
11 #include "SkColorPriv.h"
12 #include "SkDither.h"
13 #include "SkMath.h"
14 #include "SkRTConf.h"
15 #include "SkScaledBitmapSampler.h"
16 #include "SkStream.h"
17 #include "SkTemplates.h"
18 #include "SkUtils.h"
19 #include "transform_scanline.h"
20
21 #ifdef SKIA_PNG_PREFIXED
22 // this must proceed png.h
23 #include "pngprefix.h"
24 #endif
25 #include "png.h"
26
27 /* These were dropped in libpng >= 1.4 */
28 #ifndef png_infopp_NULL
29 #define png_infopp_NULL NULL
30 #endif
31
32 #ifndef png_bytepp_NULL
33 #define png_bytepp_NULL NULL
34 #endif
35
36 #ifndef int_p_NULL
37 #define int_p_NULL NULL
38 #endif
39
40 #ifndef png_flush_ptr_NULL
41 #define png_flush_ptr_NULL NULL
42 #endif
43
44 #if defined(SK_DEBUG)
45 #define DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS false
46 #else // !defined(SK_DEBUG)
47 #define DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS true
48 #endif // defined(SK_DEBUG)
49 SK_CONF_DECLARE(bool, c_suppressPNGImageDecoderWarnings,
50 "images.png.suppressDecoderWarnings",
51 DEFAULT_FOR_SUPPRESS_PNG_IMAGE_DECODER_WARNINGS,
52 "Suppress most PNG warnings when calling image decode "
53 "functions.");
54
55
56
57 class SkPNGImageIndex {
58 public:
59 // Takes ownership of stream.
SkPNGImageIndex(SkStreamRewindable * stream,png_structp png_ptr,png_infop info_ptr)60 SkPNGImageIndex(SkStreamRewindable* stream, png_structp png_ptr, png_infop info_ptr)
61 : fStream(stream)
62 , fPng_ptr(png_ptr)
63 , fInfo_ptr(info_ptr)
64 , fColorType(kUnknown_SkColorType) {
65 SkASSERT(stream != NULL);
66 }
~SkPNGImageIndex()67 ~SkPNGImageIndex() {
68 if (fPng_ptr) {
69 png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, png_infopp_NULL);
70 }
71 }
72
73 SkAutoTDelete<SkStreamRewindable> fStream;
74 png_structp fPng_ptr;
75 png_infop fInfo_ptr;
76 SkColorType fColorType;
77 };
78
79 class SkPNGImageDecoder : public SkImageDecoder {
80 public:
SkPNGImageDecoder()81 SkPNGImageDecoder() {
82 fImageIndex = NULL;
83 }
getFormat() const84 Format getFormat() const override {
85 return kPNG_Format;
86 }
87
~SkPNGImageDecoder()88 virtual ~SkPNGImageDecoder() {
89 SkDELETE(fImageIndex);
90 }
91
92 protected:
93 #ifdef SK_BUILD_FOR_ANDROID
94 bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *height) override;
95 bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& region) override;
96 #endif
97 Result onDecode(SkStream* stream, SkBitmap* bm, Mode) override;
98
99 private:
100 SkPNGImageIndex* fImageIndex;
101
102 bool onDecodeInit(SkStream* stream, png_structp *png_ptrp, png_infop *info_ptrp);
103 bool decodePalette(png_structp png_ptr, png_infop info_ptr, int bitDepth,
104 bool * SK_RESTRICT hasAlphap, bool *reallyHasAlphap,
105 SkColorTable **colorTablep);
106 bool getBitmapColorType(png_structp, png_infop, SkColorType*, bool* hasAlpha,
107 SkPMColor* theTranspColor);
108
109 typedef SkImageDecoder INHERITED;
110 };
111
112 #ifndef png_jmpbuf
113 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
114 #endif
115
116 #define PNG_BYTES_TO_CHECK 4
117
118 /* Automatically clean up after throwing an exception */
119 struct PNGAutoClean {
PNGAutoCleanPNGAutoClean120 PNGAutoClean(png_structp p, png_infop i): png_ptr(p), info_ptr(i) {}
~PNGAutoCleanPNGAutoClean121 ~PNGAutoClean() {
122 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
123 }
124 private:
125 png_structp png_ptr;
126 png_infop info_ptr;
127 };
128
sk_read_fn(png_structp png_ptr,png_bytep data,png_size_t length)129 static void sk_read_fn(png_structp png_ptr, png_bytep data, png_size_t length) {
130 SkStream* sk_stream = (SkStream*) png_get_io_ptr(png_ptr);
131 size_t bytes = sk_stream->read(data, length);
132 if (bytes != length) {
133 png_error(png_ptr, "Read Error!");
134 }
135 }
136
137 #ifdef SK_BUILD_FOR_ANDROID
sk_seek_fn(png_structp png_ptr,png_uint_32 offset)138 static void sk_seek_fn(png_structp png_ptr, png_uint_32 offset) {
139 SkStreamRewindable* sk_stream = (SkStreamRewindable*) png_get_io_ptr(png_ptr);
140 if (!sk_stream->rewind()) {
141 png_error(png_ptr, "Failed to rewind stream!");
142 }
143 (void)sk_stream->skip(offset);
144 }
145 #endif
146
147 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
sk_read_user_chunk(png_structp png_ptr,png_unknown_chunkp chunk)148 static int sk_read_user_chunk(png_structp png_ptr, png_unknown_chunkp chunk) {
149 SkImageDecoder::Peeker* peeker =
150 (SkImageDecoder::Peeker*)png_get_user_chunk_ptr(png_ptr);
151 // peek() returning true means continue decoding
152 return peeker->peek((const char*)chunk->name, chunk->data, chunk->size) ?
153 1 : -1;
154 }
155 #endif
156
sk_error_fn(png_structp png_ptr,png_const_charp msg)157 static void sk_error_fn(png_structp png_ptr, png_const_charp msg) {
158 SkDEBUGF(("------ png error %s\n", msg));
159 longjmp(png_jmpbuf(png_ptr), 1);
160 }
161
skip_src_rows(png_structp png_ptr,uint8_t storage[],int count)162 static void skip_src_rows(png_structp png_ptr, uint8_t storage[], int count) {
163 for (int i = 0; i < count; i++) {
164 uint8_t* tmp = storage;
165 png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1);
166 }
167 }
168
pos_le(int value,int max)169 static bool pos_le(int value, int max) {
170 return value > 0 && value <= max;
171 }
172
substituteTranspColor(SkBitmap * bm,SkPMColor match)173 static bool substituteTranspColor(SkBitmap* bm, SkPMColor match) {
174 SkASSERT(bm->colorType() == kN32_SkColorType);
175
176 bool reallyHasAlpha = false;
177
178 for (int y = bm->height() - 1; y >= 0; --y) {
179 SkPMColor* p = bm->getAddr32(0, y);
180 for (int x = bm->width() - 1; x >= 0; --x) {
181 if (match == *p) {
182 *p = 0;
183 reallyHasAlpha = true;
184 }
185 p += 1;
186 }
187 }
188 return reallyHasAlpha;
189 }
190
canUpscalePaletteToConfig(SkColorType dstColorType,bool srcHasAlpha)191 static bool canUpscalePaletteToConfig(SkColorType dstColorType, bool srcHasAlpha) {
192 switch (dstColorType) {
193 case kN32_SkColorType:
194 case kARGB_4444_SkColorType:
195 return true;
196 case kRGB_565_SkColorType:
197 // only return true if the src is opaque (since 565 is opaque)
198 return !srcHasAlpha;
199 default:
200 return false;
201 }
202 }
203
204 // call only if color_type is PALETTE. Returns true if the ctable has alpha
hasTransparencyInPalette(png_structp png_ptr,png_infop info_ptr)205 static bool hasTransparencyInPalette(png_structp png_ptr, png_infop info_ptr) {
206 png_bytep trans;
207 int num_trans;
208
209 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
210 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
211 return num_trans > 0;
212 }
213 return false;
214 }
215
do_nothing_warning_fn(png_structp,png_const_charp)216 void do_nothing_warning_fn(png_structp, png_const_charp) {
217 /* do nothing */
218 }
219
onDecodeInit(SkStream * sk_stream,png_structp * png_ptrp,png_infop * info_ptrp)220 bool SkPNGImageDecoder::onDecodeInit(SkStream* sk_stream, png_structp *png_ptrp,
221 png_infop *info_ptrp) {
222 /* Create and initialize the png_struct with the desired error handler
223 * functions. If you want to use the default stderr and longjump method,
224 * you can supply NULL for the last three parameters. We also supply the
225 * the compiler header file version, so that we know if the application
226 * was compiled with a compatible version of the library. */
227
228 png_error_ptr user_warning_fn =
229 (c_suppressPNGImageDecoderWarnings) ? (&do_nothing_warning_fn) : NULL;
230 /* NULL means to leave as default library behavior. */
231 /* c_suppressPNGImageDecoderWarnings default depends on SK_DEBUG. */
232 /* To suppress warnings with a SK_DEBUG binary, set the
233 * environment variable "skia_images_png_suppressDecoderWarnings"
234 * to "true". Inside a program that links to skia:
235 * SK_CONF_SET("images.png.suppressDecoderWarnings", true); */
236
237 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
238 NULL, sk_error_fn, user_warning_fn);
239 // png_voidp user_error_ptr, user_error_fn, user_warning_fn);
240 if (png_ptr == NULL) {
241 return false;
242 }
243
244 *png_ptrp = png_ptr;
245
246 /* Allocate/initialize the memory for image information. */
247 png_infop info_ptr = png_create_info_struct(png_ptr);
248 if (info_ptr == NULL) {
249 png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
250 return false;
251 }
252 *info_ptrp = info_ptr;
253
254 /* Set error handling if you are using the setjmp/longjmp method (this is
255 * the normal method of doing things with libpng). REQUIRED unless you
256 * set up your own error handlers in the png_create_read_struct() earlier.
257 */
258 if (setjmp(png_jmpbuf(png_ptr))) {
259 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
260 return false;
261 }
262
263 /* If you are using replacement read functions, instead of calling
264 * png_init_io() here you would call:
265 */
266 png_set_read_fn(png_ptr, (void *)sk_stream, sk_read_fn);
267 #ifdef SK_BUILD_FOR_ANDROID
268 png_set_seek_fn(png_ptr, sk_seek_fn);
269 #endif
270 /* where user_io_ptr is a structure you want available to the callbacks */
271 /* If we have already read some of the signature */
272 // png_set_sig_bytes(png_ptr, 0 /* sig_read */ );
273
274 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
275 // hookup our peeker so we can see any user-chunks the caller may be interested in
276 png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, (png_byte*)"", 0);
277 if (this->getPeeker()) {
278 png_set_read_user_chunk_fn(png_ptr, (png_voidp)this->getPeeker(), sk_read_user_chunk);
279 }
280 #endif
281 /* The call to png_read_info() gives us all of the information from the
282 * PNG file before the first IDAT (image data chunk). */
283 png_read_info(png_ptr, info_ptr);
284 png_uint_32 origWidth, origHeight;
285 int bitDepth, colorType;
286 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
287 &colorType, int_p_NULL, int_p_NULL, int_p_NULL);
288
289 /* tell libpng to strip 16 bit/color files down to 8 bits/color */
290 if (bitDepth == 16) {
291 png_set_strip_16(png_ptr);
292 }
293 #ifdef PNG_READ_PACK_SUPPORTED
294 /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
295 * byte into separate bytes (useful for paletted and grayscale images). */
296 if (bitDepth < 8) {
297 png_set_packing(png_ptr);
298 }
299 #endif
300 /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
301 if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) {
302 png_set_expand_gray_1_2_4_to_8(png_ptr);
303 }
304
305 return true;
306 }
307
onDecode(SkStream * sk_stream,SkBitmap * decodedBitmap,Mode mode)308 SkImageDecoder::Result SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
309 Mode mode) {
310 png_structp png_ptr;
311 png_infop info_ptr;
312
313 if (!onDecodeInit(sk_stream, &png_ptr, &info_ptr)) {
314 return kFailure;
315 }
316
317 PNGAutoClean autoClean(png_ptr, info_ptr);
318
319 if (setjmp(png_jmpbuf(png_ptr))) {
320 return kFailure;
321 }
322
323 png_uint_32 origWidth, origHeight;
324 int bitDepth, pngColorType, interlaceType;
325 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
326 &pngColorType, &interlaceType, int_p_NULL, int_p_NULL);
327
328 SkColorType colorType;
329 bool hasAlpha = false;
330 SkPMColor theTranspColor = 0; // 0 tells us not to try to match
331
332 if (!this->getBitmapColorType(png_ptr, info_ptr, &colorType, &hasAlpha, &theTranspColor)) {
333 return kFailure;
334 }
335
336 SkAlphaType alphaType = this->getRequireUnpremultipliedColors() ?
337 kUnpremul_SkAlphaType : kPremul_SkAlphaType;
338 const int sampleSize = this->getSampleSize();
339 SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize);
340 decodedBitmap->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(),
341 colorType, alphaType));
342
343 if (SkImageDecoder::kDecodeBounds_Mode == mode) {
344 return kSuccess;
345 }
346
347 // from here down we are concerned with colortables and pixels
348
349 // we track if we actually see a non-opaque pixels, since sometimes a PNG sets its colortype
350 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we
351 // draw lots faster if we can flag the bitmap has being opaque
352 bool reallyHasAlpha = false;
353 SkColorTable* colorTable = NULL;
354
355 if (pngColorType == PNG_COLOR_TYPE_PALETTE) {
356 decodePalette(png_ptr, info_ptr, bitDepth, &hasAlpha, &reallyHasAlpha, &colorTable);
357 }
358
359 SkAutoUnref aur(colorTable);
360
361 if (!this->allocPixelRef(decodedBitmap,
362 kIndex_8_SkColorType == colorType ? colorTable : NULL)) {
363 return kFailure;
364 }
365
366 SkAutoLockPixels alp(*decodedBitmap);
367
368 // Repeat setjmp, otherwise variables declared since the last call (e.g. alp
369 // and aur) won't get their destructors called in case of a failure.
370 if (setjmp(png_jmpbuf(png_ptr))) {
371 return kFailure;
372 }
373
374 /* Turn on interlace handling. REQUIRED if you are not using
375 * png_read_image(). To see how to handle interlacing passes,
376 * see the png_read_row() method below:
377 */
378 const int number_passes = (interlaceType != PNG_INTERLACE_NONE) ?
379 png_set_interlace_handling(png_ptr) : 1;
380
381 /* Optional call to gamma correct and add the background to the palette
382 * and update info structure. REQUIRED if you are expecting libpng to
383 * update the palette for you (ie you selected such a transform above).
384 */
385 png_read_update_info(png_ptr, info_ptr);
386
387 if ((kAlpha_8_SkColorType == colorType || kIndex_8_SkColorType == colorType) &&
388 1 == sampleSize) {
389 if (kAlpha_8_SkColorType == colorType) {
390 // For an A8 bitmap, we assume there is an alpha for speed. It is
391 // possible the bitmap is opaque, but that is an unlikely use case
392 // since it would not be very interesting.
393 reallyHasAlpha = true;
394 // A8 is only allowed if the original was GRAY.
395 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType);
396 }
397 for (int i = 0; i < number_passes; i++) {
398 for (png_uint_32 y = 0; y < origHeight; y++) {
399 uint8_t* bmRow = decodedBitmap->getAddr8(0, y);
400 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
401 }
402 }
403 } else {
404 SkScaledBitmapSampler::SrcConfig sc;
405 int srcBytesPerPixel = 4;
406
407 if (colorTable != NULL) {
408 sc = SkScaledBitmapSampler::kIndex;
409 srcBytesPerPixel = 1;
410 } else if (kAlpha_8_SkColorType == colorType) {
411 // A8 is only allowed if the original was GRAY.
412 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType);
413 sc = SkScaledBitmapSampler::kGray;
414 srcBytesPerPixel = 1;
415 } else if (hasAlpha) {
416 sc = SkScaledBitmapSampler::kRGBA;
417 } else {
418 sc = SkScaledBitmapSampler::kRGBX;
419 }
420
421 /* We have to pass the colortable explicitly, since we may have one
422 even if our decodedBitmap doesn't, due to the request that we
423 upscale png's palette to a direct model
424 */
425 const SkPMColor* colors = colorTable ? colorTable->readColors() : NULL;
426 if (!sampler.begin(decodedBitmap, sc, *this, colors)) {
427 return kFailure;
428 }
429 const int height = decodedBitmap->height();
430
431 if (number_passes > 1) {
432 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel);
433 uint8_t* base = (uint8_t*)storage.get();
434 size_t rowBytes = origWidth * srcBytesPerPixel;
435
436 for (int i = 0; i < number_passes; i++) {
437 uint8_t* row = base;
438 for (png_uint_32 y = 0; y < origHeight; y++) {
439 uint8_t* bmRow = row;
440 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
441 row += rowBytes;
442 }
443 }
444 // now sample it
445 base += sampler.srcY0() * rowBytes;
446 for (int y = 0; y < height; y++) {
447 reallyHasAlpha |= sampler.next(base);
448 base += sampler.srcDY() * rowBytes;
449 }
450 } else {
451 SkAutoMalloc storage(origWidth * srcBytesPerPixel);
452 uint8_t* srcRow = (uint8_t*)storage.get();
453 skip_src_rows(png_ptr, srcRow, sampler.srcY0());
454
455 for (int y = 0; y < height; y++) {
456 uint8_t* tmp = srcRow;
457 png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1);
458 reallyHasAlpha |= sampler.next(srcRow);
459 if (y < height - 1) {
460 skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1);
461 }
462 }
463
464 // skip the rest of the rows (if any)
465 png_uint_32 read = (height - 1) * sampler.srcDY() +
466 sampler.srcY0() + 1;
467 SkASSERT(read <= origHeight);
468 skip_src_rows(png_ptr, srcRow, origHeight - read);
469 }
470 }
471
472 /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
473 png_read_end(png_ptr, info_ptr);
474
475 if (0 != theTranspColor) {
476 reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor);
477 }
478 if (reallyHasAlpha && this->getRequireUnpremultipliedColors()) {
479 switch (decodedBitmap->colorType()) {
480 case kIndex_8_SkColorType:
481 // Fall through.
482 case kARGB_4444_SkColorType:
483 // We have chosen not to support unpremul for these colortypes.
484 return kFailure;
485 default: {
486 // Fall through to finish the decode. This colortype either
487 // supports unpremul or it is irrelevant because it has no
488 // alpha (or only alpha).
489 // These brackets prevent a warning.
490 }
491 }
492 }
493
494 if (!reallyHasAlpha) {
495 decodedBitmap->setAlphaType(kOpaque_SkAlphaType);
496 }
497 return kSuccess;
498 }
499
500
501
getBitmapColorType(png_structp png_ptr,png_infop info_ptr,SkColorType * colorTypep,bool * hasAlphap,SkPMColor * SK_RESTRICT theTranspColorp)502 bool SkPNGImageDecoder::getBitmapColorType(png_structp png_ptr, png_infop info_ptr,
503 SkColorType* colorTypep,
504 bool* hasAlphap,
505 SkPMColor* SK_RESTRICT theTranspColorp) {
506 png_uint_32 origWidth, origHeight;
507 int bitDepth, colorType;
508 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
509 &colorType, int_p_NULL, int_p_NULL, int_p_NULL);
510
511 #ifdef PNG_sBIT_SUPPORTED
512 // check for sBIT chunk data, in case we should disable dithering because
513 // our data is not truely 8bits per component
514 png_color_8p sig_bit;
515 if (this->getDitherImage() && png_get_sBIT(png_ptr, info_ptr, &sig_bit)) {
516 #if 0
517 SkDebugf("----- sBIT %d %d %d %d\n", sig_bit->red, sig_bit->green,
518 sig_bit->blue, sig_bit->alpha);
519 #endif
520 // 0 seems to indicate no information available
521 if (pos_le(sig_bit->red, SK_R16_BITS) &&
522 pos_le(sig_bit->green, SK_G16_BITS) &&
523 pos_le(sig_bit->blue, SK_B16_BITS)) {
524 this->setDitherImage(false);
525 }
526 }
527 #endif
528
529 if (colorType == PNG_COLOR_TYPE_PALETTE) {
530 bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr);
531 *colorTypep = this->getPrefColorType(kIndex_SrcDepth, paletteHasAlpha);
532 // now see if we can upscale to their requested colortype
533 if (!canUpscalePaletteToConfig(*colorTypep, paletteHasAlpha)) {
534 *colorTypep = kIndex_8_SkColorType;
535 }
536 } else {
537 png_color_16p transpColor = NULL;
538 int numTransp = 0;
539
540 png_get_tRNS(png_ptr, info_ptr, NULL, &numTransp, &transpColor);
541
542 bool valid = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS);
543
544 if (valid && numTransp == 1 && transpColor != NULL) {
545 /* Compute our transparent color, which we'll match against later.
546 We don't really handle 16bit components properly here, since we
547 do our compare *after* the values have been knocked down to 8bit
548 which means we will find more matches than we should. The real
549 fix seems to be to see the actual 16bit components, do the
550 compare, and then knock it down to 8bits ourselves.
551 */
552 if (colorType & PNG_COLOR_MASK_COLOR) {
553 if (16 == bitDepth) {
554 *theTranspColorp = SkPackARGB32(0xFF, transpColor->red >> 8,
555 transpColor->green >> 8,
556 transpColor->blue >> 8);
557 } else {
558 /* We apply the mask because in a very small
559 number of corrupt PNGs, (transpColor->red > 255)
560 and (bitDepth == 8), for certain versions of libpng. */
561 *theTranspColorp = SkPackARGB32(0xFF,
562 0xFF & (transpColor->red),
563 0xFF & (transpColor->green),
564 0xFF & (transpColor->blue));
565 }
566 } else { // gray
567 if (16 == bitDepth) {
568 *theTranspColorp = SkPackARGB32(0xFF, transpColor->gray >> 8,
569 transpColor->gray >> 8,
570 transpColor->gray >> 8);
571 } else {
572 /* We apply the mask because in a very small
573 number of corrupt PNGs, (transpColor->red >
574 255) and (bitDepth == 8), for certain versions
575 of libpng. For safety we assume the same could
576 happen with a grayscale PNG. */
577 *theTranspColorp = SkPackARGB32(0xFF,
578 0xFF & (transpColor->gray),
579 0xFF & (transpColor->gray),
580 0xFF & (transpColor->gray));
581 }
582 }
583 }
584
585 if (valid ||
586 PNG_COLOR_TYPE_RGB_ALPHA == colorType ||
587 PNG_COLOR_TYPE_GRAY_ALPHA == colorType) {
588 *hasAlphap = true;
589 }
590
591 SrcDepth srcDepth = k32Bit_SrcDepth;
592 if (PNG_COLOR_TYPE_GRAY == colorType) {
593 srcDepth = k8BitGray_SrcDepth;
594 // Remove this assert, which fails on desk_pokemonwiki.skp
595 //SkASSERT(!*hasAlphap);
596 }
597
598 *colorTypep = this->getPrefColorType(srcDepth, *hasAlphap);
599 // now match the request against our capabilities
600 if (*hasAlphap) {
601 if (*colorTypep != kARGB_4444_SkColorType) {
602 *colorTypep = kN32_SkColorType;
603 }
604 } else {
605 if (kAlpha_8_SkColorType == *colorTypep) {
606 if (k8BitGray_SrcDepth != srcDepth) {
607 // Converting a non grayscale image to A8 is not currently supported.
608 *colorTypep = kN32_SkColorType;
609 }
610 } else if (*colorTypep != kRGB_565_SkColorType &&
611 *colorTypep != kARGB_4444_SkColorType) {
612 *colorTypep = kN32_SkColorType;
613 }
614 }
615 }
616
617 // sanity check for size
618 {
619 int64_t size = sk_64_mul(origWidth, origHeight);
620 // now check that if we are 4-bytes per pixel, we also don't overflow
621 if (size < 0 || size > (0x7FFFFFFF >> 2)) {
622 return false;
623 }
624 }
625
626 // If the image has alpha and the decoder wants unpremultiplied
627 // colors, the only supported colortype is 8888.
628 if (this->getRequireUnpremultipliedColors() && *hasAlphap) {
629 *colorTypep = kN32_SkColorType;
630 }
631
632 if (fImageIndex != NULL) {
633 if (kUnknown_SkColorType == fImageIndex->fColorType) {
634 // This is the first time for this subset decode. From now on,
635 // all decodes must be in the same colortype.
636 fImageIndex->fColorType = *colorTypep;
637 } else if (fImageIndex->fColorType != *colorTypep) {
638 // Requesting a different colortype for a subsequent decode is not
639 // supported. Report failure before we make changes to png_ptr.
640 return false;
641 }
642 }
643
644 bool convertGrayToRGB = PNG_COLOR_TYPE_GRAY == colorType && *colorTypep != kAlpha_8_SkColorType;
645
646 // Unless the user is requesting A8, convert a grayscale image into RGB.
647 // GRAY_ALPHA will always be converted to RGB
648 if (convertGrayToRGB || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) {
649 png_set_gray_to_rgb(png_ptr);
650 }
651
652 // Add filler (or alpha) byte (after each RGB triplet) if necessary.
653 if (colorType == PNG_COLOR_TYPE_RGB || convertGrayToRGB) {
654 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
655 }
656
657 return true;
658 }
659
660 typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
661
decodePalette(png_structp png_ptr,png_infop info_ptr,int bitDepth,bool * hasAlphap,bool * reallyHasAlphap,SkColorTable ** colorTablep)662 bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr,
663 int bitDepth, bool *hasAlphap,
664 bool *reallyHasAlphap,
665 SkColorTable **colorTablep) {
666 int numPalette;
667 png_colorp palette;
668 png_bytep trans;
669 int numTrans;
670
671 png_get_PLTE(png_ptr, info_ptr, &palette, &numPalette);
672
673 SkPMColor colorStorage[256]; // worst-case storage
674 SkPMColor* colorPtr = colorStorage;
675
676 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
677 png_get_tRNS(png_ptr, info_ptr, &trans, &numTrans, NULL);
678 *hasAlphap = (numTrans > 0);
679 } else {
680 numTrans = 0;
681 }
682
683 // check for bad images that might make us crash
684 if (numTrans > numPalette) {
685 numTrans = numPalette;
686 }
687
688 int index = 0;
689 int transLessThanFF = 0;
690
691 // Choose which function to use to create the color table. If the final destination's
692 // colortype is unpremultiplied, the color table will store unpremultiplied colors.
693 PackColorProc proc;
694 if (this->getRequireUnpremultipliedColors()) {
695 proc = &SkPackARGB32NoCheck;
696 } else {
697 proc = &SkPreMultiplyARGB;
698 }
699 for (; index < numTrans; index++) {
700 transLessThanFF |= (int)*trans - 0xFF;
701 *colorPtr++ = proc(*trans++, palette->red, palette->green, palette->blue);
702 palette++;
703 }
704 bool reallyHasAlpha = (transLessThanFF < 0);
705
706 for (; index < numPalette; index++) {
707 *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette->blue);
708 palette++;
709 }
710
711 /* BUGGY IMAGE WORKAROUND
712
713 Invalid images could contain pixel values that are greater than the number of palette
714 entries. Since we use pixel values as indices into the palette this could result in reading
715 beyond the end of the palette which could leak the contents of uninitialized memory. To
716 ensure this doesn't happen, we grow the colortable to the maximum size that can be
717 addressed by the bitdepth of the image and fill it with the last palette color or black if
718 the palette is empty (really broken image).
719 */
720 int colorCount = SkTMax(numPalette, 1 << SkTMin(bitDepth, 8));
721 SkPMColor lastColor = index > 0 ? colorPtr[-1] : SkPackARGB32(0xFF, 0, 0, 0);
722 for (; index < colorCount; index++) {
723 *colorPtr++ = lastColor;
724 }
725
726 *colorTablep = SkNEW_ARGS(SkColorTable, (colorStorage, colorCount));
727 *reallyHasAlphap = reallyHasAlpha;
728 return true;
729 }
730
731 #ifdef SK_BUILD_FOR_ANDROID
732
onBuildTileIndex(SkStreamRewindable * sk_stream,int * width,int * height)733 bool SkPNGImageDecoder::onBuildTileIndex(SkStreamRewindable* sk_stream, int *width, int *height) {
734 SkAutoTDelete<SkStreamRewindable> streamDeleter(sk_stream);
735 png_structp png_ptr;
736 png_infop info_ptr;
737
738 if (!onDecodeInit(sk_stream, &png_ptr, &info_ptr)) {
739 return false;
740 }
741
742 if (setjmp(png_jmpbuf(png_ptr)) != 0) {
743 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
744 return false;
745 }
746
747 png_uint_32 origWidth, origHeight;
748 int bitDepth, colorType;
749 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
750 &colorType, int_p_NULL, int_p_NULL, int_p_NULL);
751
752 *width = origWidth;
753 *height = origHeight;
754
755 png_build_index(png_ptr);
756
757 if (fImageIndex) {
758 SkDELETE(fImageIndex);
759 }
760 fImageIndex = SkNEW_ARGS(SkPNGImageIndex, (streamDeleter.detach(), png_ptr, info_ptr));
761
762 return true;
763 }
764
onDecodeSubset(SkBitmap * bm,const SkIRect & region)765 bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
766 if (NULL == fImageIndex) {
767 return false;
768 }
769
770 png_structp png_ptr = fImageIndex->fPng_ptr;
771 png_infop info_ptr = fImageIndex->fInfo_ptr;
772 if (setjmp(png_jmpbuf(png_ptr))) {
773 return false;
774 }
775
776 png_uint_32 origWidth, origHeight;
777 int bitDepth, pngColorType, interlaceType;
778 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
779 &pngColorType, &interlaceType, int_p_NULL, int_p_NULL);
780
781 SkIRect rect = SkIRect::MakeWH(origWidth, origHeight);
782
783 if (!rect.intersect(region)) {
784 // If the requested region is entirely outside the image, just
785 // returns false
786 return false;
787 }
788
789 SkColorType colorType;
790 bool hasAlpha = false;
791 SkPMColor theTranspColor = 0; // 0 tells us not to try to match
792
793 if (!this->getBitmapColorType(png_ptr, info_ptr, &colorType, &hasAlpha, &theTranspColor)) {
794 return false;
795 }
796
797 const int sampleSize = this->getSampleSize();
798 SkScaledBitmapSampler sampler(origWidth, rect.height(), sampleSize);
799
800 SkBitmap decodedBitmap;
801 decodedBitmap.setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(),
802 colorType, kPremul_SkAlphaType));
803
804 // from here down we are concerned with colortables and pixels
805
806 // we track if we actually see a non-opaque pixels, since sometimes a PNG sets its colortype
807 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we
808 // draw lots faster if we can flag the bitmap has being opaque
809 bool reallyHasAlpha = false;
810 SkColorTable* colorTable = NULL;
811
812 if (pngColorType == PNG_COLOR_TYPE_PALETTE) {
813 decodePalette(png_ptr, info_ptr, bitDepth, &hasAlpha, &reallyHasAlpha, &colorTable);
814 }
815
816 SkAutoUnref aur(colorTable);
817
818 // Check ahead of time if the swap(dest, src) is possible.
819 // If yes, then we will stick to AllocPixelRef since it's cheaper with the swap happening.
820 // If no, then we will use alloc to allocate pixels to prevent garbage collection.
821 int w = rect.width() / sampleSize;
822 int h = rect.height() / sampleSize;
823 const bool swapOnly = (rect == region) && (w == decodedBitmap.width()) &&
824 (h == decodedBitmap.height()) && bm->isNull();
825 const bool needColorTable = kIndex_8_SkColorType == colorType;
826 if (swapOnly) {
827 if (!this->allocPixelRef(&decodedBitmap, needColorTable ? colorTable : NULL)) {
828 return false;
829 }
830 } else {
831 if (!decodedBitmap.tryAllocPixels(NULL, needColorTable ? colorTable : NULL)) {
832 return false;
833 }
834 }
835 SkAutoLockPixels alp(decodedBitmap);
836
837 /* Turn on interlace handling. REQUIRED if you are not using
838 * png_read_image(). To see how to handle interlacing passes,
839 * see the png_read_row() method below:
840 */
841 const int number_passes = (interlaceType != PNG_INTERLACE_NONE) ?
842 png_set_interlace_handling(png_ptr) : 1;
843
844 /* Optional call to gamma correct and add the background to the palette
845 * and update info structure. REQUIRED if you are expecting libpng to
846 * update the palette for you (ie you selected such a transform above).
847 */
848
849 // Direct access to png_ptr fields is deprecated in libpng > 1.2.
850 #if defined(PNG_1_0_X) || defined (PNG_1_2_X)
851 png_ptr->pass = 0;
852 #else
853 // FIXME: This sets pass as desired, but also sets iwidth. Is that ok?
854 png_set_interlaced_pass(png_ptr, 0);
855 #endif
856 png_read_update_info(png_ptr, info_ptr);
857
858 int actualTop = rect.fTop;
859
860 if ((kAlpha_8_SkColorType == colorType || kIndex_8_SkColorType == colorType)
861 && 1 == sampleSize) {
862 if (kAlpha_8_SkColorType == colorType) {
863 // For an A8 bitmap, we assume there is an alpha for speed. It is
864 // possible the bitmap is opaque, but that is an unlikely use case
865 // since it would not be very interesting.
866 reallyHasAlpha = true;
867 // A8 is only allowed if the original was GRAY.
868 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType);
869 }
870
871 for (int i = 0; i < number_passes; i++) {
872 png_configure_decoder(png_ptr, &actualTop, i);
873 for (int j = 0; j < rect.fTop - actualTop; j++) {
874 uint8_t* bmRow = decodedBitmap.getAddr8(0, 0);
875 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
876 }
877 png_uint_32 bitmapHeight = (png_uint_32) decodedBitmap.height();
878 for (png_uint_32 y = 0; y < bitmapHeight; y++) {
879 uint8_t* bmRow = decodedBitmap.getAddr8(0, y);
880 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
881 }
882 }
883 } else {
884 SkScaledBitmapSampler::SrcConfig sc;
885 int srcBytesPerPixel = 4;
886
887 if (colorTable != NULL) {
888 sc = SkScaledBitmapSampler::kIndex;
889 srcBytesPerPixel = 1;
890 } else if (kAlpha_8_SkColorType == colorType) {
891 // A8 is only allowed if the original was GRAY.
892 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType);
893 sc = SkScaledBitmapSampler::kGray;
894 srcBytesPerPixel = 1;
895 } else if (hasAlpha) {
896 sc = SkScaledBitmapSampler::kRGBA;
897 } else {
898 sc = SkScaledBitmapSampler::kRGBX;
899 }
900
901 /* We have to pass the colortable explicitly, since we may have one
902 even if our decodedBitmap doesn't, due to the request that we
903 upscale png's palette to a direct model
904 */
905 const SkPMColor* colors = colorTable ? colorTable->readColors() : NULL;
906 if (!sampler.begin(&decodedBitmap, sc, *this, colors)) {
907 return false;
908 }
909 const int height = decodedBitmap.height();
910
911 if (number_passes > 1) {
912 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel);
913 uint8_t* base = (uint8_t*)storage.get();
914 size_t rb = origWidth * srcBytesPerPixel;
915
916 for (int i = 0; i < number_passes; i++) {
917 png_configure_decoder(png_ptr, &actualTop, i);
918 for (int j = 0; j < rect.fTop - actualTop; j++) {
919 png_read_rows(png_ptr, &base, png_bytepp_NULL, 1);
920 }
921 uint8_t* row = base;
922 for (int32_t y = 0; y < rect.height(); y++) {
923 uint8_t* bmRow = row;
924 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
925 row += rb;
926 }
927 }
928 // now sample it
929 base += sampler.srcY0() * rb;
930 for (int y = 0; y < height; y++) {
931 reallyHasAlpha |= sampler.next(base);
932 base += sampler.srcDY() * rb;
933 }
934 } else {
935 SkAutoMalloc storage(origWidth * srcBytesPerPixel);
936 uint8_t* srcRow = (uint8_t*)storage.get();
937
938 png_configure_decoder(png_ptr, &actualTop, 0);
939 skip_src_rows(png_ptr, srcRow, sampler.srcY0());
940
941 for (int i = 0; i < rect.fTop - actualTop; i++) {
942 png_read_rows(png_ptr, &srcRow, png_bytepp_NULL, 1);
943 }
944 for (int y = 0; y < height; y++) {
945 uint8_t* tmp = srcRow;
946 png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1);
947 reallyHasAlpha |= sampler.next(srcRow);
948 if (y < height - 1) {
949 skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1);
950 }
951 }
952 }
953 }
954
955 if (0 != theTranspColor) {
956 reallyHasAlpha |= substituteTranspColor(&decodedBitmap, theTranspColor);
957 }
958 if (reallyHasAlpha && this->getRequireUnpremultipliedColors()) {
959 switch (decodedBitmap.colorType()) {
960 case kIndex_8_SkColorType:
961 // Fall through.
962 case kARGB_4444_SkColorType:
963 // We have chosen not to support unpremul for these colortypess.
964 return false;
965 default: {
966 // Fall through to finish the decode. This config either
967 // supports unpremul or it is irrelevant because it has no
968 // alpha (or only alpha).
969 // These brackets prevent a warning.
970 }
971 }
972 }
973 SkAlphaType alphaType = kOpaque_SkAlphaType;
974 if (reallyHasAlpha) {
975 if (this->getRequireUnpremultipliedColors()) {
976 alphaType = kUnpremul_SkAlphaType;
977 } else {
978 alphaType = kPremul_SkAlphaType;
979 }
980 }
981 decodedBitmap.setAlphaType(alphaType);
982
983 if (swapOnly) {
984 bm->swap(decodedBitmap);
985 return true;
986 }
987 return this->cropBitmap(bm, &decodedBitmap, sampleSize, region.x(), region.y(),
988 region.width(), region.height(), 0, rect.y());
989 }
990 #endif
991
992 ///////////////////////////////////////////////////////////////////////////////
993
994 #include "SkColorPriv.h"
995 #include "SkUnPreMultiply.h"
996
sk_write_fn(png_structp png_ptr,png_bytep data,png_size_t len)997 static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) {
998 SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr);
999 if (!sk_stream->write(data, len)) {
1000 png_error(png_ptr, "sk_write_fn Error!");
1001 }
1002 }
1003
choose_proc(SkColorType ct,bool hasAlpha)1004 static transform_scanline_proc choose_proc(SkColorType ct, bool hasAlpha) {
1005 // we don't care about search on alpha if we're kIndex8, since only the
1006 // colortable packing cares about that distinction, not the pixels
1007 if (kIndex_8_SkColorType == ct) {
1008 hasAlpha = false; // we store false in the table entries for kIndex8
1009 }
1010
1011 static const struct {
1012 SkColorType fColorType;
1013 bool fHasAlpha;
1014 transform_scanline_proc fProc;
1015 } gMap[] = {
1016 { kRGB_565_SkColorType, false, transform_scanline_565 },
1017 { kN32_SkColorType, false, transform_scanline_888 },
1018 { kN32_SkColorType, true, transform_scanline_8888 },
1019 { kARGB_4444_SkColorType, false, transform_scanline_444 },
1020 { kARGB_4444_SkColorType, true, transform_scanline_4444 },
1021 { kIndex_8_SkColorType, false, transform_scanline_memcpy },
1022 };
1023
1024 for (int i = SK_ARRAY_COUNT(gMap) - 1; i >= 0; --i) {
1025 if (gMap[i].fColorType == ct && gMap[i].fHasAlpha == hasAlpha) {
1026 return gMap[i].fProc;
1027 }
1028 }
1029 sk_throw();
1030 return NULL;
1031 }
1032
1033 // return the minimum legal bitdepth (by png standards) for this many colortable
1034 // entries. SkBitmap always stores in 8bits per pixel, but for colorcount <= 16,
1035 // we can use fewer bits per in png
computeBitDepth(int colorCount)1036 static int computeBitDepth(int colorCount) {
1037 #if 0
1038 int bits = SkNextLog2(colorCount);
1039 SkASSERT(bits >= 1 && bits <= 8);
1040 // now we need bits itself to be a power of 2 (e.g. 1, 2, 4, 8)
1041 return SkNextPow2(bits);
1042 #else
1043 // for the moment, we don't know how to pack bitdepth < 8
1044 return 8;
1045 #endif
1046 }
1047
1048 /* Pack palette[] with the corresponding colors, and if hasAlpha is true, also
1049 pack trans[] and return the number of trans[] entries written. If hasAlpha
1050 is false, the return value will always be 0.
1051
1052 Note: this routine takes care of unpremultiplying the RGB values when we
1053 have alpha in the colortable, since png doesn't support premul colors
1054 */
pack_palette(SkColorTable * ctable,png_color * SK_RESTRICT palette,png_byte * SK_RESTRICT trans,bool hasAlpha)1055 static inline int pack_palette(SkColorTable* ctable,
1056 png_color* SK_RESTRICT palette,
1057 png_byte* SK_RESTRICT trans, bool hasAlpha) {
1058 const SkPMColor* SK_RESTRICT colors = ctable ? ctable->readColors() : NULL;
1059 const int ctCount = ctable->count();
1060 int i, num_trans = 0;
1061
1062 if (hasAlpha) {
1063 /* first see if we have some number of fully opaque at the end of the
1064 ctable. PNG allows num_trans < num_palette, but all of the trans
1065 entries must come first in the palette. If I was smarter, I'd
1066 reorder the indices and ctable so that all non-opaque colors came
1067 first in the palette. But, since that would slow down the encode,
1068 I'm leaving the indices and ctable order as is, and just looking
1069 at the tail of the ctable for opaqueness.
1070 */
1071 num_trans = ctCount;
1072 for (i = ctCount - 1; i >= 0; --i) {
1073 if (SkGetPackedA32(colors[i]) != 0xFF) {
1074 break;
1075 }
1076 num_trans -= 1;
1077 }
1078
1079 const SkUnPreMultiply::Scale* SK_RESTRICT table =
1080 SkUnPreMultiply::GetScaleTable();
1081
1082 for (i = 0; i < num_trans; i++) {
1083 const SkPMColor c = *colors++;
1084 const unsigned a = SkGetPackedA32(c);
1085 const SkUnPreMultiply::Scale s = table[a];
1086 trans[i] = a;
1087 palette[i].red = SkUnPreMultiply::ApplyScale(s, SkGetPackedR32(c));
1088 palette[i].green = SkUnPreMultiply::ApplyScale(s,SkGetPackedG32(c));
1089 palette[i].blue = SkUnPreMultiply::ApplyScale(s, SkGetPackedB32(c));
1090 }
1091 // now fall out of this if-block to use common code for the trailing
1092 // opaque entries
1093 }
1094
1095 // these (remaining) entries are opaque
1096 for (i = num_trans; i < ctCount; i++) {
1097 SkPMColor c = *colors++;
1098 palette[i].red = SkGetPackedR32(c);
1099 palette[i].green = SkGetPackedG32(c);
1100 palette[i].blue = SkGetPackedB32(c);
1101 }
1102 return num_trans;
1103 }
1104
1105 class SkPNGImageEncoder : public SkImageEncoder {
1106 protected:
1107 bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) override;
1108 private:
1109 bool doEncode(SkWStream* stream, const SkBitmap& bm,
1110 const bool& hasAlpha, int colorType,
1111 int bitDepth, SkColorType ct,
1112 png_color_8& sig_bit);
1113
1114 typedef SkImageEncoder INHERITED;
1115 };
1116
onEncode(SkWStream * stream,const SkBitmap & bitmap,int)1117 bool SkPNGImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap, int /*quality*/) {
1118 SkColorType ct = bitmap.colorType();
1119
1120 const bool hasAlpha = !bitmap.isOpaque();
1121 int colorType = PNG_COLOR_MASK_COLOR;
1122 int bitDepth = 8; // default for color
1123 png_color_8 sig_bit;
1124
1125 switch (ct) {
1126 case kIndex_8_SkColorType:
1127 colorType |= PNG_COLOR_MASK_PALETTE;
1128 // fall through to the ARGB_8888 case
1129 case kN32_SkColorType:
1130 sig_bit.red = 8;
1131 sig_bit.green = 8;
1132 sig_bit.blue = 8;
1133 sig_bit.alpha = 8;
1134 break;
1135 case kARGB_4444_SkColorType:
1136 sig_bit.red = 4;
1137 sig_bit.green = 4;
1138 sig_bit.blue = 4;
1139 sig_bit.alpha = 4;
1140 break;
1141 case kRGB_565_SkColorType:
1142 sig_bit.red = 5;
1143 sig_bit.green = 6;
1144 sig_bit.blue = 5;
1145 sig_bit.alpha = 0;
1146 break;
1147 default:
1148 return false;
1149 }
1150
1151 if (hasAlpha) {
1152 // don't specify alpha if we're a palette, even if our ctable has alpha
1153 if (!(colorType & PNG_COLOR_MASK_PALETTE)) {
1154 colorType |= PNG_COLOR_MASK_ALPHA;
1155 }
1156 } else {
1157 sig_bit.alpha = 0;
1158 }
1159
1160 SkAutoLockPixels alp(bitmap);
1161 // readyToDraw checks for pixels (and colortable if that is required)
1162 if (!bitmap.readyToDraw()) {
1163 return false;
1164 }
1165
1166 // we must do this after we have locked the pixels
1167 SkColorTable* ctable = bitmap.getColorTable();
1168 if (ctable) {
1169 if (ctable->count() == 0) {
1170 return false;
1171 }
1172 // check if we can store in fewer than 8 bits
1173 bitDepth = computeBitDepth(ctable->count());
1174 }
1175
1176 return doEncode(stream, bitmap, hasAlpha, colorType, bitDepth, ct, sig_bit);
1177 }
1178
doEncode(SkWStream * stream,const SkBitmap & bitmap,const bool & hasAlpha,int colorType,int bitDepth,SkColorType ct,png_color_8 & sig_bit)1179 bool SkPNGImageEncoder::doEncode(SkWStream* stream, const SkBitmap& bitmap,
1180 const bool& hasAlpha, int colorType,
1181 int bitDepth, SkColorType ct,
1182 png_color_8& sig_bit) {
1183
1184 png_structp png_ptr;
1185 png_infop info_ptr;
1186
1187 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, sk_error_fn,
1188 NULL);
1189 if (NULL == png_ptr) {
1190 return false;
1191 }
1192
1193 info_ptr = png_create_info_struct(png_ptr);
1194 if (NULL == info_ptr) {
1195 png_destroy_write_struct(&png_ptr, png_infopp_NULL);
1196 return false;
1197 }
1198
1199 /* Set error handling. REQUIRED if you aren't supplying your own
1200 * error handling functions in the png_create_write_struct() call.
1201 */
1202 if (setjmp(png_jmpbuf(png_ptr))) {
1203 png_destroy_write_struct(&png_ptr, &info_ptr);
1204 return false;
1205 }
1206
1207 png_set_write_fn(png_ptr, (void*)stream, sk_write_fn, png_flush_ptr_NULL);
1208
1209 /* Set the image information here. Width and height are up to 2^31,
1210 * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
1211 * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
1212 * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
1213 * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
1214 * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
1215 * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
1216 */
1217
1218 png_set_IHDR(png_ptr, info_ptr, bitmap.width(), bitmap.height(),
1219 bitDepth, colorType,
1220 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
1221 PNG_FILTER_TYPE_BASE);
1222
1223 // set our colortable/trans arrays if needed
1224 png_color paletteColors[256];
1225 png_byte trans[256];
1226 if (kIndex_8_SkColorType == ct) {
1227 SkColorTable* ct = bitmap.getColorTable();
1228 int numTrans = pack_palette(ct, paletteColors, trans, hasAlpha);
1229 png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count());
1230 if (numTrans > 0) {
1231 png_set_tRNS(png_ptr, info_ptr, trans, numTrans, NULL);
1232 }
1233 }
1234 #ifdef PNG_sBIT_SUPPORTED
1235 png_set_sBIT(png_ptr, info_ptr, &sig_bit);
1236 #endif
1237 png_write_info(png_ptr, info_ptr);
1238
1239 const char* srcImage = (const char*)bitmap.getPixels();
1240 SkAutoSMalloc<1024> rowStorage(bitmap.width() << 2);
1241 char* storage = (char*)rowStorage.get();
1242 transform_scanline_proc proc = choose_proc(ct, hasAlpha);
1243
1244 for (int y = 0; y < bitmap.height(); y++) {
1245 png_bytep row_ptr = (png_bytep)storage;
1246 proc(srcImage, bitmap.width(), storage);
1247 png_write_rows(png_ptr, &row_ptr, 1);
1248 srcImage += bitmap.rowBytes();
1249 }
1250
1251 png_write_end(png_ptr, info_ptr);
1252
1253 /* clean up after the write, and free any memory allocated */
1254 png_destroy_write_struct(&png_ptr, &info_ptr);
1255 return true;
1256 }
1257
1258 ///////////////////////////////////////////////////////////////////////////////
1259 DEFINE_DECODER_CREATOR(PNGImageDecoder);
1260 DEFINE_ENCODER_CREATOR(PNGImageEncoder);
1261 ///////////////////////////////////////////////////////////////////////////////
1262
is_png(SkStreamRewindable * stream)1263 static bool is_png(SkStreamRewindable* stream) {
1264 char buf[PNG_BYTES_TO_CHECK];
1265 if (stream->read(buf, PNG_BYTES_TO_CHECK) == PNG_BYTES_TO_CHECK &&
1266 !png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) {
1267 return true;
1268 }
1269 return false;
1270 }
1271
sk_libpng_dfactory(SkStreamRewindable * stream)1272 SkImageDecoder* sk_libpng_dfactory(SkStreamRewindable* stream) {
1273 if (is_png(stream)) {
1274 return SkNEW(SkPNGImageDecoder);
1275 }
1276 return NULL;
1277 }
1278
get_format_png(SkStreamRewindable * stream)1279 static SkImageDecoder::Format get_format_png(SkStreamRewindable* stream) {
1280 if (is_png(stream)) {
1281 return SkImageDecoder::kPNG_Format;
1282 }
1283 return SkImageDecoder::kUnknown_Format;
1284 }
1285
sk_libpng_efactory(SkImageEncoder::Type t)1286 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) {
1287 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL;
1288 }
1289
1290 static SkImageDecoder_DecodeReg gDReg(sk_libpng_dfactory);
1291 static SkImageDecoder_FormatReg gFormatReg(get_format_png);
1292 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory);
1293