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

Side by Side Diff: src/codec/SkCodec_libpng.cpp

Issue 1055743003: Swizzler changes Index8 and 565 (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Fix windows errors Created 5 years, 8 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/codec/SkCodec_libpng.h ('k') | src/codec/SkMaskSwizzler.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 2015 Google Inc. 2 * Copyright 2015 Google Inc.
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 "SkCodec_libpng.h" 8 #include "SkCodec_libpng.h"
9 #include "SkCodecPriv.h" 9 #include "SkCodecPriv.h"
10 #include "SkColorPriv.h" 10 #include "SkColorPriv.h"
11 #include "SkColorTable.h" 11 #include "SkColorTable.h"
12 #include "SkBitmap.h" 12 #include "SkBitmap.h"
13 #include "SkMath.h" 13 #include "SkMath.h"
14 #include "SkScanlineDecoder.h" 14 #include "SkScanlineDecoder.h"
15 #include "SkSize.h" 15 #include "SkSize.h"
16 #include "SkStream.h" 16 #include "SkStream.h"
17 #include "SkSwizzler.h" 17 #include "SkSwizzler.h"
18 #include "SkUtils.h"
18 19
19 /////////////////////////////////////////////////////////////////////////////// 20 ///////////////////////////////////////////////////////////////////////////////
20 // Helper macros 21 // Helper macros
21 /////////////////////////////////////////////////////////////////////////////// 22 ///////////////////////////////////////////////////////////////////////////////
22 23
23 #ifndef png_jmpbuf 24 #ifndef png_jmpbuf
24 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) 25 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
25 #endif 26 #endif
26 27
27 /* These were dropped in libpng >= 1.4 */ 28 /* These were dropped in libpng >= 1.4 */
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); 113 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
113 return num_trans > 0; 114 return num_trans > 0;
114 } 115 }
115 116
116 // Method for coverting to either an SkPMColor or a similarly packed 117 // Method for coverting to either an SkPMColor or a similarly packed
117 // unpremultiplied color. 118 // unpremultiplied color.
118 typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b); 119 typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
119 120
120 // Note: SkColorTable claims to store SkPMColors, which is not necessarily 121 // Note: SkColorTable claims to store SkPMColors, which is not necessarily
121 // the case here. 122 // the case here.
122 bool SkPngCodec::decodePalette(bool premultiply) { 123 bool SkPngCodec::decodePalette(bool premultiply, int bitDepth, int* ctableCount) {
123 int numPalette; 124 int numPalette;
124 png_colorp palette; 125 png_colorp palette;
125 png_bytep trans; 126 png_bytep trans;
126 127
127 if (!png_get_PLTE(fPng_ptr, fInfo_ptr, &palette, &numPalette)) { 128 if (!png_get_PLTE(fPng_ptr, fInfo_ptr, &palette, &numPalette)) {
128 return false; 129 return false;
129 } 130 }
130 131
131 /* BUGGY IMAGE WORKAROUND 132 // Note: These are not necessarily SkPMColors
132
133 We hit some images (e.g. fruit_.png) who contain bytes that are == color table_count
134 which is a problem since we use the byte as an index. To work around thi s we grow
135 the colortable by 1 (if its < 256) and duplicate the last color into tha t slot.
136 */
137 const int colorCount = numPalette + (numPalette < 256);
138 // Note: These are not necessarily SkPMColors.
139 SkPMColor colorStorage[256]; // worst-case storage 133 SkPMColor colorStorage[256]; // worst-case storage
140 SkPMColor* colorPtr = colorStorage; 134 SkPMColor* colorPtr = colorStorage;
141 135
142 int numTrans; 136 int numTrans;
143 if (png_get_valid(fPng_ptr, fInfo_ptr, PNG_INFO_tRNS)) { 137 if (png_get_valid(fPng_ptr, fInfo_ptr, PNG_INFO_tRNS)) {
144 png_get_tRNS(fPng_ptr, fInfo_ptr, &trans, &numTrans, NULL); 138 png_get_tRNS(fPng_ptr, fInfo_ptr, &trans, &numTrans, NULL);
145 } else { 139 } else {
146 numTrans = 0; 140 numTrans = 0;
147 } 141 }
148 142
(...skipping 19 matching lines...) Expand all
168 palette++; 162 palette++;
169 } 163 }
170 164
171 fReallyHasAlpha = transLessThanFF < 0; 165 fReallyHasAlpha = transLessThanFF < 0;
172 166
173 for (; index < numPalette; index++) { 167 for (; index < numPalette; index++) {
174 *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette-> blue); 168 *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette-> blue);
175 palette++; 169 palette++;
176 } 170 }
177 171
178 // see BUGGY IMAGE WORKAROUND comment above 172 /* BUGGY IMAGE WORKAROUND
179 if (numPalette < 256) { 173 Invalid images could contain pixel values that are greater than the numb er of palette
180 *colorPtr = colorPtr[-1]; 174 entries. Since we use pixel values as indices into the palette this coul d result in reading
175 beyond the end of the palette which could leak the contents of uninitial ized memory. To
176 ensure this doesn't happen, we grow the colortable to the maximum size t hat can be
177 addressed by the bitdepth of the image and fill it with the last palette color or black if
178 the palette is empty (really broken image).
179 */
180 int colorCount = SkTMax(numPalette, 1 << SkTMin(bitDepth, 8));
181 SkPMColor lastColor = index > 0 ? colorPtr[-1] : SkPackARGB32(0xFF, 0, 0, 0) ;
182 for (; index < colorCount; index++) {
183 *colorPtr++ = lastColor;
184 }
185
186 // Set the new color count
187 if (ctableCount != NULL) {
188 SkASSERT(256 == *ctableCount);
189 *ctableCount = colorCount;
181 } 190 }
182 191
183 fColorTable.reset(SkNEW_ARGS(SkColorTable, (colorStorage, colorCount))); 192 fColorTable.reset(SkNEW_ARGS(SkColorTable, (colorStorage, colorCount)));
184 return true; 193 return true;
185 } 194 }
186 195
187 /////////////////////////////////////////////////////////////////////////////// 196 ///////////////////////////////////////////////////////////////////////////////
188 // Creation 197 // Creation
189 /////////////////////////////////////////////////////////////////////////////// 198 ///////////////////////////////////////////////////////////////////////////////
190 199
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
269 if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) { 278 if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) {
270 png_set_expand_gray_1_2_4_to_8(png_ptr); 279 png_set_expand_gray_1_2_4_to_8(png_ptr);
271 } 280 }
272 281
273 282
274 // Now determine the default SkColorType and SkAlphaType. 283 // Now determine the default SkColorType and SkAlphaType.
275 SkColorType skColorType; 284 SkColorType skColorType;
276 SkAlphaType skAlphaType; 285 SkAlphaType skAlphaType;
277 switch (colorType) { 286 switch (colorType) {
278 case PNG_COLOR_TYPE_PALETTE: 287 case PNG_COLOR_TYPE_PALETTE:
279 // Technically, this is true of the data, but I don't think we want 288 skColorType = kIndex_8_SkColorType;
280 // to support it.
281 // skColorType = kIndex8_SkColorType;
282 skColorType = kN32_SkColorType;
283 skAlphaType = has_transparency_in_palette(png_ptr, info_ptr) ? 289 skAlphaType = has_transparency_in_palette(png_ptr, info_ptr) ?
284 kUnpremul_SkAlphaType : kOpaque_SkAlphaType; 290 kUnpremul_SkAlphaType : kOpaque_SkAlphaType;
285 break; 291 break;
286 case PNG_COLOR_TYPE_GRAY: 292 case PNG_COLOR_TYPE_GRAY:
287 if (false) { 293 if (false) {
288 // FIXME: Is this the wrong default behavior? This means if the 294 // FIXME: Is this the wrong default behavior? This means if the
289 // caller supplies the info we gave them, they'll get Alpha 8. 295 // caller supplies the info we gave them, they'll get Alpha 8.
290 skColorType = kAlpha_8_SkColorType; 296 skColorType = kAlpha_8_SkColorType;
291 // FIXME: Strangely, the canonical type for Alpha 8 is Premul. 297 // FIXME: Strangely, the canonical type for Alpha 8 is Premul.
292 skAlphaType = kPremul_SkAlphaType; 298 skAlphaType = kPremul_SkAlphaType;
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 fInfo_ptr = NULL; 386 fInfo_ptr = NULL;
381 } 387 }
382 } 388 }
383 389
384 /////////////////////////////////////////////////////////////////////////////// 390 ///////////////////////////////////////////////////////////////////////////////
385 // Getting the pixels 391 // Getting the pixels
386 /////////////////////////////////////////////////////////////////////////////// 392 ///////////////////////////////////////////////////////////////////////////////
387 393
388 static bool conversion_possible(const SkImageInfo& dst, const SkImageInfo& src) { 394 static bool conversion_possible(const SkImageInfo& dst, const SkImageInfo& src) {
389 // TODO: Support other conversions 395 // TODO: Support other conversions
390 if (dst.colorType() != src.colorType()) {
391 return false;
392 }
393 if (dst.profileType() != src.profileType()) { 396 if (dst.profileType() != src.profileType()) {
394 return false; 397 return false;
395 } 398 }
396 if (dst.alphaType() == src.alphaType()) { 399
397 return true; 400 // Check for supported alpha types
401 if (src.alphaType() != dst.alphaType()) {
402 if (kOpaque_SkAlphaType == src.alphaType()) {
403 // If the source is opaque, we must decode to opaque
404 return false;
405 }
406
407 // The source is not opaque
408 switch (dst.alphaType()) {
409 case kPremul_SkAlphaType:
410 case kUnpremul_SkAlphaType:
411 // The source is not opaque, so either of these is okay
412 break;
413 default:
414 // We cannot decode a non-opaque image to opaque (or unknown)
415 return false;
416 }
398 } 417 }
399 return kPremul_SkAlphaType == dst.alphaType() && 418
400 kUnpremul_SkAlphaType == src.alphaType(); 419 // Check for supported color types
420 switch (dst.colorType()) {
421 // Allow output to kN32 from any type of input
422 case kN32_SkColorType:
423 return true;
424 default:
425 return dst.colorType() == src.colorType();
426 }
401 } 427 }
402 428
403 SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo, 429 SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo,
404 void* dst, size_t rowBytes, 430 void* dst, size_t rowBytes,
405 const Options& options) { 431 const Options& options,
432 int* ctableCount) {
406 // FIXME: Could we use the return value of setjmp to specify the type of 433 // FIXME: Could we use the return value of setjmp to specify the type of
407 // error? 434 // error?
408 if (setjmp(png_jmpbuf(fPng_ptr))) { 435 if (setjmp(png_jmpbuf(fPng_ptr))) {
409 SkCodecPrintf("setjmp long jump!\n"); 436 SkCodecPrintf("setjmp long jump!\n");
410 return kInvalidInput; 437 return kInvalidInput;
411 } 438 }
412 439
413 // FIXME: We already retrieved this information. Store it in SkPngCodec? 440 // FIXME: We already retrieved this information. Store it in SkPngCodec?
414 png_uint_32 origWidth, origHeight; 441 png_uint_32 origWidth, origHeight;
415 int bitDepth, pngColorType, interlaceType; 442 int bitDepth, pngColorType, interlaceType;
416 png_get_IHDR(fPng_ptr, fInfo_ptr, &origWidth, &origHeight, &bitDepth, 443 png_get_IHDR(fPng_ptr, fInfo_ptr, &origWidth, &origHeight, &bitDepth,
417 &pngColorType, &interlaceType, int_p_NULL, int_p_NULL); 444 &pngColorType, &interlaceType, int_p_NULL, int_p_NULL);
418 445
419 fNumberPasses = (interlaceType != PNG_INTERLACE_NONE) ? 446 fNumberPasses = (interlaceType != PNG_INTERLACE_NONE) ?
420 png_set_interlace_handling(fPng_ptr) : 1; 447 png_set_interlace_handling(fPng_ptr) : 1;
421 448
422 // Set to the default before calling decodePalette, which may change it. 449 // Set to the default before calling decodePalette, which may change it.
423 fReallyHasAlpha = false; 450 fReallyHasAlpha = false;
424 if (PNG_COLOR_TYPE_PALETTE == pngColorType) { 451 if (PNG_COLOR_TYPE_PALETTE == pngColorType) {
425 fSrcConfig = SkSwizzler::kIndex; 452 fSrcConfig = SkSwizzler::kIndex;
426 if (!this->decodePalette(kPremul_SkAlphaType == requestedInfo.alphaType( ))) { 453 if (!this->decodePalette(kPremul_SkAlphaType == requestedInfo.alphaType( ), bitDepth,
454 ctableCount)) {
427 return kInvalidInput; 455 return kInvalidInput;
428 } 456 }
429 } else if (kAlpha_8_SkColorType == requestedInfo.colorType()) { 457 } else if (kAlpha_8_SkColorType == requestedInfo.colorType()) {
430 // Note: we check the destination, since otherwise we would have 458 // Note: we check the destination, since otherwise we would have
431 // told png to upscale. 459 // told png to upscale.
432 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); 460 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType);
433 fSrcConfig = SkSwizzler::kGray; 461 fSrcConfig = SkSwizzler::kGray;
434 } else if (this->getInfo().alphaType() == kOpaque_SkAlphaType) { 462 } else if (this->getInfo().alphaType() == kOpaque_SkAlphaType) {
435 fSrcConfig = SkSwizzler::kRGBX; 463 fSrcConfig = SkSwizzler::kRGBX;
436 } else { 464 } else {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 if (!this->handleRewind()) { 513 if (!this->handleRewind()) {
486 return kCouldNotRewind; 514 return kCouldNotRewind;
487 } 515 }
488 if (requestedInfo.dimensions() != this->getInfo().dimensions()) { 516 if (requestedInfo.dimensions() != this->getInfo().dimensions()) {
489 return kInvalidScale; 517 return kInvalidScale;
490 } 518 }
491 if (!conversion_possible(requestedInfo, this->getInfo())) { 519 if (!conversion_possible(requestedInfo, this->getInfo())) {
492 return kInvalidConversion; 520 return kInvalidConversion;
493 } 521 }
494 522
523 // Note that ctableCount will be modified if there is a color table
495 const Result result = this->initializeSwizzler(requestedInfo, dst, rowBytes, 524 const Result result = this->initializeSwizzler(requestedInfo, dst, rowBytes,
496 options); 525 options, ctableCount);
526
527 // Copy the color table to the client if necessary
528 if (kIndex_8_SkColorType == requestedInfo.colorType()) {
529 SkASSERT(NULL != ctable);
530 SkASSERT(NULL != ctableCount);
531 SkASSERT(NULL != fColorTable.get());
532 sk_memcpy32(ctable, fColorTable->readColors(), *ctableCount);
533 }
534
497 if (result != kSuccess) { 535 if (result != kSuccess) {
498 return result; 536 return result;
499 } 537 }
500 538
501 // FIXME: Could we use the return value of setjmp to specify the type of 539 // FIXME: Could we use the return value of setjmp to specify the type of
502 // error? 540 // error?
503 if (setjmp(png_jmpbuf(fPng_ptr))) { 541 if (setjmp(png_jmpbuf(fPng_ptr))) {
504 SkCodecPrintf("setjmp long jump!\n"); 542 SkCodecPrintf("setjmp long jump!\n");
505 return kInvalidInput; 543 return kInvalidInput;
506 } 544 }
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 SkCodecPrintf("no conversion possible\n"); 662 SkCodecPrintf("no conversion possible\n");
625 return NULL; 663 return NULL;
626 } 664 }
627 665
628 // Note: We set dst to NULL since we do not know it yet. rowBytes is not nee ded, 666 // Note: We set dst to NULL since we do not know it yet. rowBytes is not nee ded,
629 // since we'll be manually updating the dstRow, but the SkSwizzler requires it to 667 // since we'll be manually updating the dstRow, but the SkSwizzler requires it to
630 // be at least dstInfo.minRowBytes. 668 // be at least dstInfo.minRowBytes.
631 Options opts; 669 Options opts;
632 // FIXME: Pass this in to getScanlineDecoder? 670 // FIXME: Pass this in to getScanlineDecoder?
633 opts.fZeroInitialized = kNo_ZeroInitialized; 671 opts.fZeroInitialized = kNo_ZeroInitialized;
634 if (this->initializeSwizzler(dstInfo, NULL, dstInfo.minRowBytes(), opts) != kSuccess) { 672 // FIXME: onGetScanlineDecoder does not currently have a way to get color ta ble information
673 // for a kIndex8 decoder.
674 if (this->initializeSwizzler(dstInfo, NULL, dstInfo.minRowBytes(), opts, NUL L) != kSuccess) {
635 SkCodecPrintf("failed to initialize the swizzler.\n"); 675 SkCodecPrintf("failed to initialize the swizzler.\n");
636 return NULL; 676 return NULL;
637 } 677 }
638 678
639 SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES); 679 SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES);
640 if (fNumberPasses > 1) { 680 if (fNumberPasses > 1) {
641 // We cannot efficiently do scanline decoding. 681 // We cannot efficiently do scanline decoding.
642 return NULL; 682 return NULL;
643 } 683 }
644 684
645 return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, this)); 685 return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, this));
646 } 686 }
647 687
OLDNEW
« no previous file with comments | « src/codec/SkCodec_libpng.h ('k') | src/codec/SkMaskSwizzler.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698