 Chromium Code Reviews
 Chromium Code Reviews Issue 1820073002:
  Add SkEncodedInfo to report properties of encoded image data  (Closed) 
  Base URL: https://skia.googlesource.com/skia.git@master
    
  
    Issue 1820073002:
  Add SkEncodedInfo to report properties of encoded image data  (Closed) 
  Base URL: https://skia.googlesource.com/skia.git@master| 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 |