OLD | NEW |
---|---|
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 "SkBitmap.h" | 8 #include "SkBitmap.h" |
9 #include "SkCodecPriv.h" | 9 #include "SkCodecPriv.h" |
10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
265 // | 265 // |
266 // @param stream Input data. Will be read to get enough information to properly | 266 // @param stream Input data. Will be read to get enough information to properly |
267 // setup the codec. | 267 // setup the codec. |
268 // @param chunkReader SkPngChunkReader, for reading unknown chunks. May be NULL. | 268 // @param chunkReader SkPngChunkReader, for reading unknown chunks. May be NULL. |
269 // If not NULL, png_ptr will hold an *unowned* pointer to it. The caller is | 269 // If not NULL, png_ptr will hold an *unowned* pointer to it. The caller is |
270 // expected to continue to own it for the lifetime of the png_ptr. | 270 // expected to continue to own it for the lifetime of the png_ptr. |
271 // @param png_ptrp Optional output variable. If non-NULL, will be set to a new | 271 // @param png_ptrp Optional output variable. If non-NULL, will be set to a new |
272 // png_structp on success. | 272 // png_structp on success. |
273 // @param info_ptrp Optional output variable. If non-NULL, will be set to a new | 273 // @param info_ptrp Optional output variable. If non-NULL, will be set to a new |
274 // png_infop on success; | 274 // png_infop on success; |
275 // @param imageInfo Optional output variable. If non-NULL, will be set to | 275 // @param info Optional output variable. If non-NULL, will be set to |
276 // reflect the properties of the encoded image on success. | 276 // reflect the properties of the encoded image on success. |
277 // @param bitDepthPtr Optional output variable. If non-NULL, will be set to the | 277 // @param bitDepthPtr Optional output variable. If non-NULL, will be set to the |
278 // bit depth of the encoded image on success. | 278 // bit depth of the encoded image on success. |
279 // @param numberPassesPtr Optional output variable. If non-NULL, will be set to | 279 // @param numberPassesPtr Optional output variable. If non-NULL, will be set to |
280 // the number_passes of the encoded image on success. | 280 // the number_passes of the encoded image on success. |
281 // @return true on success, in which case the caller is responsible for calling | 281 // @return true on success, in which case the caller is responsible for calling |
282 // png_destroy_read_struct(png_ptrp, info_ptrp). | 282 // png_destroy_read_struct(png_ptrp, info_ptrp). |
283 // If it returns false, the passed in fields (except stream) are unchanged. | 283 // If it returns false, the passed in fields (except stream) are unchanged. |
284 static bool read_header(SkStream* stream, SkPngChunkReader* chunkReader, | 284 static bool read_header(SkStream* stream, SkPngChunkReader* chunkReader, |
285 png_structp* png_ptrp, png_infop* info_ptrp, | 285 png_structp* png_ptrp, png_infop* info_ptrp, |
286 SkImageInfo* imageInfo, int* bitDepthPtr, int* numberPas sesPtr) { | 286 SkEncodedInfo* info, int* bitDepthPtr, int* numberPasses Ptr) { |
287 // The image is known to be a PNG. Decode enough to know the SkImageInfo. | 287 // The image is known to be a PNG. Decode enough to know the SkImageInfo. |
288 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, | 288 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, |
289 sk_error_fn, sk_warning_fn); | 289 sk_error_fn, sk_warning_fn); |
290 if (!png_ptr) { | 290 if (!png_ptr) { |
291 return false; | 291 return false; |
292 } | 292 } |
293 | 293 |
294 AutoCleanPng autoClean(png_ptr); | 294 AutoCleanPng autoClean(png_ptr); |
295 | 295 |
296 png_infop info_ptr = png_create_info_struct(png_ptr); | 296 png_infop info_ptr = png_create_info_struct(png_ptr); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
334 // TODO: Should we handle this in SkSwizzler? Could this also benefit | 334 // TODO: Should we handle this in SkSwizzler? Could this also benefit |
335 // RAW decodes? | 335 // RAW decodes? |
336 if (bitDepth == 16) { | 336 if (bitDepth == 16) { |
337 SkASSERT(PNG_COLOR_TYPE_PALETTE != encodedColorType); | 337 SkASSERT(PNG_COLOR_TYPE_PALETTE != encodedColorType); |
338 png_set_strip_16(png_ptr); | 338 png_set_strip_16(png_ptr); |
339 } | 339 } |
340 | 340 |
341 // Now determine the default colorType and alphaType and set the required tr ansforms. | 341 // Now determine the default colorType and alphaType and set the required tr ansforms. |
342 // Often, we depend on SkSwizzler to perform any transforms that we need. H owever, we | 342 // Often, we depend on SkSwizzler to perform any transforms that we need. H owever, we |
343 // still depend on libpng for many of the rare and PNG-specific cases. | 343 // still depend on libpng for many of the rare and PNG-specific cases. |
344 SkColorType colorType = kUnknown_SkColorType; | 344 SkEncodedInfo::Color color; |
345 SkAlphaType alphaType = kUnknown_SkAlphaType; | 345 SkEncodedInfo::Alpha alpha; |
346 switch (encodedColorType) { | 346 switch (encodedColorType) { |
347 case PNG_COLOR_TYPE_PALETTE: | 347 case PNG_COLOR_TYPE_PALETTE: |
348 // Extract multiple pixels with bit depths of 1, 2, and 4 from a sin gle | 348 // Extract multiple pixels with bit depths of 1, 2, and 4 from a sin gle |
349 // byte into separate bytes (useful for paletted and grayscale image s). | 349 // byte into separate bytes (useful for paletted and grayscale image s). |
350 if (bitDepth < 8) { | 350 if (bitDepth < 8) { |
scroggo
2016/03/23 14:48:50
I think eventually we'll want to just use the raw
msarett
2016/03/24 16:20:44
Thanks I completely missed this...
Yes, let's rep
| |
351 // TODO: Should we use SkSwizzler here? | 351 // TODO: Should we use SkSwizzler here? |
352 png_set_packing(png_ptr); | 352 png_set_packing(png_ptr); |
353 } | 353 } |
354 | 354 |
355 colorType = kIndex_8_SkColorType; | 355 color = SkEncodedInfo::kPalette_Color; |
356 // Set the alpha type depending on if a transparency chunk exists. | 356 // Set the alpha depending on if a transparency chunk exists. |
357 alphaType = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ? | 357 alpha = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ? |
358 kUnpremul_SkAlphaType : kOpaque_SkAlphaType; | 358 SkEncodedInfo::kUnpremul_Alpha : SkEncodedInfo::kOpaque_Alph a; |
359 break; | 359 break; |
360 case PNG_COLOR_TYPE_RGB: | 360 case PNG_COLOR_TYPE_RGB: |
361 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { | 361 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { |
362 // Convert to RGBA if transparency chunk exists. | 362 // Convert to RGBA if transparency chunk exists. |
363 png_set_tRNS_to_alpha(png_ptr); | 363 png_set_tRNS_to_alpha(png_ptr); |
364 alphaType = kUnpremul_SkAlphaType; | 364 color = SkEncodedInfo::kRGBA_Color; |
365 alpha = SkEncodedInfo::kBinary_Alpha; | |
365 } else { | 366 } else { |
366 alphaType = kOpaque_SkAlphaType; | 367 color = SkEncodedInfo::kRGB_Color; |
368 alpha = SkEncodedInfo::kOpaque_Alpha; | |
367 } | 369 } |
368 colorType = kN32_SkColorType; | |
369 break; | 370 break; |
370 case PNG_COLOR_TYPE_GRAY: | 371 case PNG_COLOR_TYPE_GRAY: |
371 // Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/p ixel. | 372 // Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/p ixel. |
372 if (bitDepth < 8) { | 373 if (bitDepth < 8) { |
373 // TODO: Should we use SkSwizzler here? | 374 // TODO: Should we use SkSwizzler here? |
374 png_set_expand_gray_1_2_4_to_8(png_ptr); | 375 png_set_expand_gray_1_2_4_to_8(png_ptr); |
375 } | 376 } |
376 | 377 |
377 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { | 378 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { |
378 png_set_tRNS_to_alpha(png_ptr); | 379 png_set_tRNS_to_alpha(png_ptr); |
379 | 380 color = SkEncodedInfo::kGrayAlpha_Color; |
380 // We will recommend kN32 here since we do not support kGray | 381 alpha = SkEncodedInfo::kBinary_Alpha; |
381 // with alpha. | |
382 colorType = kN32_SkColorType; | |
383 alphaType = kUnpremul_SkAlphaType; | |
384 } else { | 382 } else { |
385 colorType = kGray_8_SkColorType; | 383 color = SkEncodedInfo::kGray_Color; |
386 alphaType = kOpaque_SkAlphaType; | 384 alpha = SkEncodedInfo::kOpaque_Alpha; |
387 } | 385 } |
388 break; | 386 break; |
389 case PNG_COLOR_TYPE_GRAY_ALPHA: | 387 case PNG_COLOR_TYPE_GRAY_ALPHA: |
390 // We will recommend kN32 here since we do not support anything | 388 color = SkEncodedInfo::kGrayAlpha_Color; |
391 // similar to GRAY_ALPHA. | 389 alpha = SkEncodedInfo::kUnpremul_Alpha; |
392 colorType = kN32_SkColorType; | |
393 alphaType = kUnpremul_SkAlphaType; | |
394 break; | 390 break; |
395 case PNG_COLOR_TYPE_RGBA: | 391 case PNG_COLOR_TYPE_RGBA: |
396 colorType = kN32_SkColorType; | 392 color = SkEncodedInfo::kRGBA_Color; |
397 alphaType = kUnpremul_SkAlphaType; | 393 alpha = SkEncodedInfo::kUnpremul_Alpha; |
398 break; | 394 break; |
399 default: | 395 default: |
400 // All the color types have been covered above. | 396 // All the color types have been covered above. |
401 SkASSERT(false); | 397 SkASSERT(false); |
398 color = SkEncodedInfo::kRGBA_Color; | |
399 alpha = SkEncodedInfo::kUnpremul_Alpha; | |
402 } | 400 } |
403 | 401 |
404 int numberPasses = png_set_interlace_handling(png_ptr); | 402 int numberPasses = png_set_interlace_handling(png_ptr); |
405 if (numberPassesPtr) { | 403 if (numberPassesPtr) { |
406 *numberPassesPtr = numberPasses; | 404 *numberPassesPtr = numberPasses; |
407 } | 405 } |
408 | 406 |
409 SkColorProfileType profileType = kLinear_SkColorProfileType; | 407 if (info) { |
410 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sRGB)) { | 408 *info = SkEncodedInfo::Make(origWidth, origHeight, color, alpha, bitDept h); |
411 profileType = kSRGB_SkColorProfileType; | |
412 } | |
413 | |
414 if (imageInfo) { | |
415 *imageInfo = SkImageInfo::Make(origWidth, origHeight, colorType, alphaTy pe, profileType); | |
416 } | 409 } |
417 autoClean.release(); | 410 autoClean.release(); |
418 if (png_ptrp) { | 411 if (png_ptrp) { |
419 *png_ptrp = png_ptr; | 412 *png_ptrp = png_ptr; |
420 } | 413 } |
421 if (info_ptrp) { | 414 if (info_ptrp) { |
422 *info_ptrp = info_ptr; | 415 *info_ptrp = info_ptr; |
423 } | 416 } |
424 | 417 |
425 return true; | 418 return true; |
426 } | 419 } |
427 | 420 |
428 SkPngCodec::SkPngCodec(const SkImageInfo& info, SkStream* stream, SkPngChunkRead er* chunkReader, | 421 SkPngCodec::SkPngCodec(const SkEncodedInfo& info, SkStream* stream, SkPngChunkRe ader* chunkReader, |
429 png_structp png_ptr, png_infop info_ptr, int bitDepth, in t numberPasses, | 422 png_structp png_ptr, png_infop info_ptr, int bitDepth, in t numberPasses, |
430 sk_sp<SkColorSpace> colorSpace) | 423 sk_sp<SkColorSpace> colorSpace) |
431 : INHERITED(info, stream, colorSpace) | 424 : INHERITED(info, stream, colorSpace) |
432 , fPngChunkReader(SkSafeRef(chunkReader)) | 425 , fPngChunkReader(SkSafeRef(chunkReader)) |
433 , fPng_ptr(png_ptr) | 426 , fPng_ptr(png_ptr) |
434 , fInfo_ptr(info_ptr) | 427 , fInfo_ptr(info_ptr) |
435 , fSrcConfig(SkSwizzler::kUnknown) | 428 , fSrcConfig(SkSwizzler::kUnknown) |
436 , fNumberPasses(numberPasses) | 429 , fNumberPasses(numberPasses) |
437 , fBitDepth(bitDepth) | 430 , fBitDepth(bitDepth) |
438 {} | 431 {} |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
630 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); | 623 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); |
631 if (colorPtr) { | 624 if (colorPtr) { |
632 return get_color_table_fill_value(colorType, colorPtr, 0); | 625 return get_color_table_fill_value(colorType, colorPtr, 0); |
633 } | 626 } |
634 return INHERITED::onGetFillValue(colorType); | 627 return INHERITED::onGetFillValue(colorType); |
635 } | 628 } |
636 | 629 |
637 // Subclass of SkPngCodec which supports scanline decoding | 630 // Subclass of SkPngCodec which supports scanline decoding |
638 class SkPngScanlineDecoder : public SkPngCodec { | 631 class SkPngScanlineDecoder : public SkPngCodec { |
639 public: | 632 public: |
640 SkPngScanlineDecoder(const SkImageInfo& srcInfo, SkStream* stream, | 633 SkPngScanlineDecoder(const SkEncodedInfo& info, SkStream* stream, |
641 SkPngChunkReader* chunkReader, png_structp png_ptr, png_infop info_p tr, int bitDepth, | 634 SkPngChunkReader* chunkReader, png_structp png_ptr, png_infop info_p tr, int bitDepth, |
642 sk_sp<SkColorSpace> colorSpace) | 635 sk_sp<SkColorSpace> colorSpace) |
643 : INHERITED(srcInfo, stream, chunkReader, png_ptr, info_ptr, bitDepth, 1 , colorSpace) | 636 : INHERITED(info, stream, chunkReader, png_ptr, info_ptr, bitDepth, 1, c olorSpace) |
644 , fSrcRow(nullptr) | 637 , fSrcRow(nullptr) |
645 {} | 638 {} |
646 | 639 |
647 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti ons, | 640 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti ons, |
648 SkPMColor ctable[], int* ctableCount) override { | 641 SkPMColor ctable[], int* ctableCount) override { |
649 if (!conversion_possible(dstInfo, this->getInfo())) { | 642 if (!conversion_possible(dstInfo, this->getInfo())) { |
650 return kInvalidConversion; | 643 return kInvalidConversion; |
651 } | 644 } |
652 | 645 |
653 const Result result = this->initializeSwizzler(dstInfo, options, ctable, | 646 const Result result = this->initializeSwizzler(dstInfo, options, ctable, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
696 private: | 689 private: |
697 SkAutoTMalloc<uint8_t> fStorage; | 690 SkAutoTMalloc<uint8_t> fStorage; |
698 uint8_t* fSrcRow; | 691 uint8_t* fSrcRow; |
699 | 692 |
700 typedef SkPngCodec INHERITED; | 693 typedef SkPngCodec INHERITED; |
701 }; | 694 }; |
702 | 695 |
703 | 696 |
704 class SkPngInterlacedScanlineDecoder : public SkPngCodec { | 697 class SkPngInterlacedScanlineDecoder : public SkPngCodec { |
705 public: | 698 public: |
706 SkPngInterlacedScanlineDecoder(const SkImageInfo& srcInfo, SkStream* stream, | 699 SkPngInterlacedScanlineDecoder(const SkEncodedInfo& info, SkStream* stream, |
707 SkPngChunkReader* chunkReader, png_structp png_ptr, png_infop info_p tr, | 700 SkPngChunkReader* chunkReader, png_structp png_ptr, png_infop info_p tr, |
708 int bitDepth, int numberPasses, sk_sp<SkColorSpace> colorSpace) | 701 int bitDepth, int numberPasses, sk_sp<SkColorSpace> colorSpace) |
709 : INHERITED(srcInfo, stream, chunkReader, png_ptr, info_ptr, bitDepth, n umberPasses, | 702 : INHERITED(info, stream, chunkReader, png_ptr, info_ptr, bitDepth, numb erPasses, |
710 colorSpace) | 703 colorSpace) |
711 , fHeight(-1) | 704 , fHeight(-1) |
712 , fCanSkipRewind(false) | 705 , fCanSkipRewind(false) |
713 { | 706 { |
714 SkASSERT(numberPasses != 1); | 707 SkASSERT(numberPasses != 1); |
715 } | 708 } |
716 | 709 |
717 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti ons, | 710 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti ons, |
718 SkPMColor ctable[], int* ctableCount) override { | 711 SkPMColor ctable[], int* ctableCount) override { |
719 if (!conversion_possible(dstInfo, this->getInfo())) { | 712 if (!conversion_possible(dstInfo, this->getInfo())) { |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
822 // add another layer. | 815 // add another layer. |
823 bool fCanSkipRewind; | 816 bool fCanSkipRewind; |
824 | 817 |
825 typedef SkPngCodec INHERITED; | 818 typedef SkPngCodec INHERITED; |
826 }; | 819 }; |
827 | 820 |
828 SkCodec* SkPngCodec::NewFromStream(SkStream* stream, SkPngChunkReader* chunkRead er) { | 821 SkCodec* SkPngCodec::NewFromStream(SkStream* stream, SkPngChunkReader* chunkRead er) { |
829 SkAutoTDelete<SkStream> streamDeleter(stream); | 822 SkAutoTDelete<SkStream> streamDeleter(stream); |
830 png_structp png_ptr; | 823 png_structp png_ptr; |
831 png_infop info_ptr; | 824 png_infop info_ptr; |
832 SkImageInfo imageInfo; | 825 SkEncodedInfo imageInfo; |
833 int bitDepth; | 826 int bitDepth; |
834 int numberPasses; | 827 int numberPasses; |
835 | 828 |
836 if (!read_header(stream, chunkReader, &png_ptr, &info_ptr, &imageInfo, &bitD epth, | 829 if (!read_header(stream, chunkReader, &png_ptr, &info_ptr, &imageInfo, &bitD epth, |
837 &numberPasses)) { | 830 &numberPasses)) { |
838 return nullptr; | 831 return nullptr; |
839 } | 832 } |
840 | 833 |
841 auto colorSpace = read_color_space(png_ptr, info_ptr); | 834 auto colorSpace = read_color_space(png_ptr, info_ptr); |
842 | 835 |
843 if (1 == numberPasses) { | 836 if (1 == numberPasses) { |
844 return new SkPngScanlineDecoder(imageInfo, streamDeleter.release(), chun kReader, | 837 return new SkPngScanlineDecoder(imageInfo, streamDeleter.release(), chun kReader, |
845 png_ptr, info_ptr, bitDepth, colorSpace) ; | 838 png_ptr, info_ptr, bitDepth, colorSpace) ; |
846 } | 839 } |
847 | 840 |
848 return new SkPngInterlacedScanlineDecoder(imageInfo, streamDeleter.release() , chunkReader, | 841 return new SkPngInterlacedScanlineDecoder(imageInfo, streamDeleter.release() , chunkReader, |
849 png_ptr, info_ptr, bitDepth, numbe rPasses, | 842 png_ptr, info_ptr, bitDepth, numbe rPasses, |
850 colorSpace); | 843 colorSpace); |
851 } | 844 } |
OLD | NEW |