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

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

Issue 1820073002: Add SkEncodedInfo to report properties of encoded image data (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Order of param eval bug Created 4 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/SkPngCodec.h ('k') | src/codec/SkRawCodec.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 "SkBitmap.h" 8 #include "SkBitmap.h"
9 #include "SkCodecPriv.h" 9 #include "SkCodecPriv.h"
10 #include "SkColorPriv.h" 10 #include "SkColorPriv.h"
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 // 272 //
273 // @param stream Input data. Will be read to get enough information to properly 273 // @param stream Input data. Will be read to get enough information to properly
274 // setup the codec. 274 // setup the codec.
275 // @param chunkReader SkPngChunkReader, for reading unknown chunks. May be NULL. 275 // @param chunkReader SkPngChunkReader, for reading unknown chunks. May be NULL.
276 // If not NULL, png_ptr will hold an *unowned* pointer to it. The caller is 276 // If not NULL, png_ptr will hold an *unowned* pointer to it. The caller is
277 // expected to continue to own it for the lifetime of the png_ptr. 277 // expected to continue to own it for the lifetime of the png_ptr.
278 // @param png_ptrp Optional output variable. If non-NULL, will be set to a new 278 // @param png_ptrp Optional output variable. If non-NULL, will be set to a new
279 // png_structp on success. 279 // png_structp on success.
280 // @param info_ptrp Optional output variable. If non-NULL, will be set to a new 280 // @param info_ptrp Optional output variable. If non-NULL, will be set to a new
281 // png_infop on success; 281 // png_infop on success;
282 // @param imageInfo Optional output variable. If non-NULL, will be set to 282 // @param info Optional output variable. If non-NULL, will be set to
283 // reflect the properties of the encoded image on success. 283 // reflect the properties of the encoded image on success.
284 // @param bitDepthPtr Optional output variable. If non-NULL, will be set to the 284 // @param bitDepthPtr Optional output variable. If non-NULL, will be set to the
285 // bit depth of the encoded image on success. 285 // bit depth of the encoded image on success.
286 // @param numberPassesPtr Optional output variable. If non-NULL, will be set to 286 // @param numberPassesPtr Optional output variable. If non-NULL, will be set to
287 // the number_passes of the encoded image on success. 287 // the number_passes of the encoded image on success.
288 // @return true on success, in which case the caller is responsible for calling 288 // @return true on success, in which case the caller is responsible for calling
289 // png_destroy_read_struct(png_ptrp, info_ptrp). 289 // png_destroy_read_struct(png_ptrp, info_ptrp).
290 // If it returns false, the passed in fields (except stream) are unchanged. 290 // If it returns false, the passed in fields (except stream) are unchanged.
291 static bool read_header(SkStream* stream, SkPngChunkReader* chunkReader, 291 static bool read_header(SkStream* stream, SkPngChunkReader* chunkReader,
292 png_structp* png_ptrp, png_infop* info_ptrp, 292 png_structp* png_ptrp, png_infop* info_ptrp,
293 SkImageInfo* imageInfo, int* bitDepthPtr, int* numberPas sesPtr) { 293 int* width, int* height, SkEncodedInfo* info, int* bitDe pthPtr,
294 int* numberPassesPtr) {
294 // The image is known to be a PNG. Decode enough to know the SkImageInfo. 295 // The image is known to be a PNG. Decode enough to know the SkImageInfo.
295 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, 296 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr,
296 sk_error_fn, sk_warning_fn); 297 sk_error_fn, sk_warning_fn);
297 if (!png_ptr) { 298 if (!png_ptr) {
298 return false; 299 return false;
299 } 300 }
300 301
301 AutoCleanPng autoClean(png_ptr); 302 AutoCleanPng autoClean(png_ptr);
302 303
303 png_infop info_ptr = png_create_info_struct(png_ptr); 304 png_infop info_ptr = png_create_info_struct(png_ptr);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 // TODO: Should we handle this in SkSwizzler? Could this also benefit 342 // TODO: Should we handle this in SkSwizzler? Could this also benefit
342 // RAW decodes? 343 // RAW decodes?
343 if (bitDepth == 16) { 344 if (bitDepth == 16) {
344 SkASSERT(PNG_COLOR_TYPE_PALETTE != encodedColorType); 345 SkASSERT(PNG_COLOR_TYPE_PALETTE != encodedColorType);
345 png_set_strip_16(png_ptr); 346 png_set_strip_16(png_ptr);
346 } 347 }
347 348
348 // Now determine the default colorType and alphaType and set the required tr ansforms. 349 // Now determine the default colorType and alphaType and set the required tr ansforms.
349 // Often, we depend on SkSwizzler to perform any transforms that we need. H owever, we 350 // Often, we depend on SkSwizzler to perform any transforms that we need. H owever, we
350 // still depend on libpng for many of the rare and PNG-specific cases. 351 // still depend on libpng for many of the rare and PNG-specific cases.
351 SkColorType colorType = kUnknown_SkColorType; 352 SkEncodedInfo::Color color;
352 SkAlphaType alphaType = kUnknown_SkAlphaType; 353 SkEncodedInfo::Alpha alpha;
353 switch (encodedColorType) { 354 switch (encodedColorType) {
354 case PNG_COLOR_TYPE_PALETTE: 355 case PNG_COLOR_TYPE_PALETTE:
355 // Extract multiple pixels with bit depths of 1, 2, and 4 from a sin gle 356 // Extract multiple pixels with bit depths of 1, 2, and 4 from a sin gle
356 // byte into separate bytes (useful for paletted and grayscale image s). 357 // byte into separate bytes (useful for paletted and grayscale image s).
357 if (bitDepth < 8) { 358 if (bitDepth < 8) {
358 // TODO: Should we use SkSwizzler here? 359 // TODO: Should we use SkSwizzler here?
359 png_set_packing(png_ptr); 360 png_set_packing(png_ptr);
360 } 361 }
361 362
362 colorType = kIndex_8_SkColorType; 363 color = SkEncodedInfo::kPalette_Color;
363 // Set the alpha type depending on if a transparency chunk exists. 364 // Set the alpha depending on if a transparency chunk exists.
364 alphaType = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ? 365 alpha = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ?
365 kUnpremul_SkAlphaType : kOpaque_SkAlphaType; 366 SkEncodedInfo::kUnpremul_Alpha : SkEncodedInfo::kOpaque_Alph a;
366 break; 367 break;
367 case PNG_COLOR_TYPE_RGB: 368 case PNG_COLOR_TYPE_RGB:
368 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { 369 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
369 // Convert to RGBA if transparency chunk exists. 370 // Convert to RGBA if transparency chunk exists.
370 png_set_tRNS_to_alpha(png_ptr); 371 png_set_tRNS_to_alpha(png_ptr);
371 alphaType = kUnpremul_SkAlphaType; 372 color = SkEncodedInfo::kRGBA_Color;
373 alpha = SkEncodedInfo::kBinary_Alpha;
372 } else { 374 } else {
373 alphaType = kOpaque_SkAlphaType; 375 color = SkEncodedInfo::kRGB_Color;
376 alpha = SkEncodedInfo::kOpaque_Alpha;
374 } 377 }
375 colorType = kN32_SkColorType;
376 break; 378 break;
377 case PNG_COLOR_TYPE_GRAY: 379 case PNG_COLOR_TYPE_GRAY:
378 // Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/p ixel. 380 // Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/p ixel.
379 if (bitDepth < 8) { 381 if (bitDepth < 8) {
380 // TODO: Should we use SkSwizzler here? 382 // TODO: Should we use SkSwizzler here?
381 png_set_expand_gray_1_2_4_to_8(png_ptr); 383 png_set_expand_gray_1_2_4_to_8(png_ptr);
382 } 384 }
383 385
384 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { 386 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
385 png_set_tRNS_to_alpha(png_ptr); 387 png_set_tRNS_to_alpha(png_ptr);
386 388 color = SkEncodedInfo::kGrayAlpha_Color;
387 // We will recommend kN32 here since we do not support kGray 389 alpha = SkEncodedInfo::kBinary_Alpha;
388 // with alpha.
389 colorType = kN32_SkColorType;
390 alphaType = kUnpremul_SkAlphaType;
391 } else { 390 } else {
392 colorType = kGray_8_SkColorType; 391 color = SkEncodedInfo::kGray_Color;
393 alphaType = kOpaque_SkAlphaType; 392 alpha = SkEncodedInfo::kOpaque_Alpha;
394 } 393 }
395 break; 394 break;
396 case PNG_COLOR_TYPE_GRAY_ALPHA: 395 case PNG_COLOR_TYPE_GRAY_ALPHA:
397 // We will recommend kN32 here since we do not support anything 396 color = SkEncodedInfo::kGrayAlpha_Color;
398 // similar to GRAY_ALPHA. 397 alpha = SkEncodedInfo::kUnpremul_Alpha;
399 colorType = kN32_SkColorType;
400 alphaType = kUnpremul_SkAlphaType;
401 break; 398 break;
402 case PNG_COLOR_TYPE_RGBA: 399 case PNG_COLOR_TYPE_RGBA:
403 colorType = kN32_SkColorType; 400 color = SkEncodedInfo::kRGBA_Color;
404 alphaType = kUnpremul_SkAlphaType; 401 alpha = SkEncodedInfo::kUnpremul_Alpha;
405 break; 402 break;
406 default: 403 default:
407 // All the color types have been covered above. 404 // All the color types have been covered above.
408 SkASSERT(false); 405 SkASSERT(false);
406 color = SkEncodedInfo::kRGBA_Color;
407 alpha = SkEncodedInfo::kUnpremul_Alpha;
409 } 408 }
410 409
411 int numberPasses = png_set_interlace_handling(png_ptr); 410 int numberPasses = png_set_interlace_handling(png_ptr);
412 if (numberPassesPtr) { 411 if (numberPassesPtr) {
413 *numberPassesPtr = numberPasses; 412 *numberPassesPtr = numberPasses;
414 } 413 }
415 414
416 SkColorProfileType profileType = kLinear_SkColorProfileType; 415 if (info) {
417 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sRGB)) { 416 *info = SkEncodedInfo::Make(color, alpha, 8);
418 profileType = kSRGB_SkColorProfileType;
419 } 417 }
420 418 if (width) {
421 if (imageInfo) { 419 *width = origWidth;
422 *imageInfo = SkImageInfo::Make(origWidth, origHeight, colorType, alphaTy pe, profileType); 420 }
421 if (height) {
422 *height = origHeight;
423 } 423 }
424 autoClean.release(); 424 autoClean.release();
425 if (png_ptrp) { 425 if (png_ptrp) {
426 *png_ptrp = png_ptr; 426 *png_ptrp = png_ptr;
427 } 427 }
428 if (info_ptrp) { 428 if (info_ptrp) {
429 *info_ptrp = info_ptr; 429 *info_ptrp = info_ptr;
430 } 430 }
431 431
432 return true; 432 return true;
433 } 433 }
434 434
435 SkPngCodec::SkPngCodec(const SkImageInfo& info, SkStream* stream, SkPngChunkRead er* chunkReader, 435 SkPngCodec::SkPngCodec(int width, int height, const SkEncodedInfo& info, SkStrea m* stream,
436 png_structp png_ptr, png_infop info_ptr, int bitDepth, in t numberPasses, 436 SkPngChunkReader* chunkReader, png_structp png_ptr, png_i nfop info_ptr,
437 sk_sp<SkColorSpace> colorSpace) 437 int bitDepth, int numberPasses, sk_sp<SkColorSpace> color Space)
438 : INHERITED(info, stream, colorSpace) 438 : INHERITED(width, height, info, stream, colorSpace)
439 , fPngChunkReader(SkSafeRef(chunkReader)) 439 , fPngChunkReader(SkSafeRef(chunkReader))
440 , fPng_ptr(png_ptr) 440 , fPng_ptr(png_ptr)
441 , fInfo_ptr(info_ptr) 441 , fInfo_ptr(info_ptr)
442 , fSrcConfig(SkSwizzler::kUnknown) 442 , fSrcConfig(SkSwizzler::kUnknown)
443 , fNumberPasses(numberPasses) 443 , fNumberPasses(numberPasses)
444 , fBitDepth(bitDepth) 444 , fBitDepth(bitDepth)
445 {} 445 {}
446 446
447 SkPngCodec::~SkPngCodec() { 447 SkPngCodec::~SkPngCodec() {
448 this->destroyReadStruct(); 448 this->destroyReadStruct();
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 // This sets fPng_ptr and fInfo_ptr to nullptr. If read_header 531 // This sets fPng_ptr and fInfo_ptr to nullptr. If read_header
532 // succeeds, they will be repopulated, and if it fails, they will 532 // succeeds, they will be repopulated, and if it fails, they will
533 // remain nullptr. Any future accesses to fPng_ptr and fInfo_ptr will 533 // remain nullptr. Any future accesses to fPng_ptr and fInfo_ptr will
534 // come through this function which will rewind and again attempt 534 // come through this function which will rewind and again attempt
535 // to reinitialize them. 535 // to reinitialize them.
536 this->destroyReadStruct(); 536 this->destroyReadStruct();
537 537
538 png_structp png_ptr; 538 png_structp png_ptr;
539 png_infop info_ptr; 539 png_infop info_ptr;
540 if (!read_header(this->stream(), fPngChunkReader.get(), &png_ptr, &info_ptr, 540 if (!read_header(this->stream(), fPngChunkReader.get(), &png_ptr, &info_ptr,
541 nullptr, nullptr, nullptr)) { 541 nullptr, nullptr, nullptr, nullptr, nullptr)) {
542 return false; 542 return false;
543 } 543 }
544 544
545 fPng_ptr = png_ptr; 545 fPng_ptr = png_ptr;
546 fInfo_ptr = info_ptr; 546 fInfo_ptr = info_ptr;
547 return true; 547 return true;
548 } 548 }
549 549
550 SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void* dst, 550 SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void* dst,
551 size_t dstRowBytes, const Options& optio ns, 551 size_t dstRowBytes, const Options& optio ns,
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
637 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 637 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
638 if (colorPtr) { 638 if (colorPtr) {
639 return get_color_table_fill_value(colorType, colorPtr, 0); 639 return get_color_table_fill_value(colorType, colorPtr, 0);
640 } 640 }
641 return INHERITED::onGetFillValue(colorType); 641 return INHERITED::onGetFillValue(colorType);
642 } 642 }
643 643
644 // Subclass of SkPngCodec which supports scanline decoding 644 // Subclass of SkPngCodec which supports scanline decoding
645 class SkPngScanlineDecoder : public SkPngCodec { 645 class SkPngScanlineDecoder : public SkPngCodec {
646 public: 646 public:
647 SkPngScanlineDecoder(const SkImageInfo& srcInfo, SkStream* stream, 647 SkPngScanlineDecoder(int width, int height, const SkEncodedInfo& info, SkStr eam* stream,
648 SkPngChunkReader* chunkReader, png_structp png_ptr, png_infop info_p tr, int bitDepth, 648 SkPngChunkReader* chunkReader, png_structp png_ptr, png_infop info_p tr, int bitDepth,
649 sk_sp<SkColorSpace> colorSpace) 649 sk_sp<SkColorSpace> colorSpace)
650 : INHERITED(srcInfo, stream, chunkReader, png_ptr, info_ptr, bitDepth, 1 , colorSpace) 650 : INHERITED(width, height, info, stream, chunkReader, png_ptr, info_ptr, bitDepth, 1,
651 colorSpace)
651 , fSrcRow(nullptr) 652 , fSrcRow(nullptr)
652 {} 653 {}
653 654
654 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti ons, 655 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti ons,
655 SkPMColor ctable[], int* ctableCount) override { 656 SkPMColor ctable[], int* ctableCount) override {
656 if (!conversion_possible(dstInfo, this->getInfo())) { 657 if (!conversion_possible(dstInfo, this->getInfo())) {
657 return kInvalidConversion; 658 return kInvalidConversion;
658 } 659 }
659 660
660 const Result result = this->initializeSwizzler(dstInfo, options, ctable, 661 const Result result = this->initializeSwizzler(dstInfo, options, ctable,
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
703 private: 704 private:
704 SkAutoTMalloc<uint8_t> fStorage; 705 SkAutoTMalloc<uint8_t> fStorage;
705 uint8_t* fSrcRow; 706 uint8_t* fSrcRow;
706 707
707 typedef SkPngCodec INHERITED; 708 typedef SkPngCodec INHERITED;
708 }; 709 };
709 710
710 711
711 class SkPngInterlacedScanlineDecoder : public SkPngCodec { 712 class SkPngInterlacedScanlineDecoder : public SkPngCodec {
712 public: 713 public:
713 SkPngInterlacedScanlineDecoder(const SkImageInfo& srcInfo, SkStream* stream, 714 SkPngInterlacedScanlineDecoder(int width, int height, const SkEncodedInfo& i nfo,
714 SkPngChunkReader* chunkReader, png_structp png_ptr, png_infop info_p tr, 715 SkStream* stream, SkPngChunkReader* chunkReader, png_structp png_ptr ,
715 int bitDepth, int numberPasses, sk_sp<SkColorSpace> colorSpace) 716 png_infop info_ptr, int bitDepth, int numberPasses, sk_sp<SkColorSpa ce> colorSpace)
716 : INHERITED(srcInfo, stream, chunkReader, png_ptr, info_ptr, bitDepth, n umberPasses, 717 : INHERITED(width, height, info, stream, chunkReader, png_ptr, info_ptr, bitDepth,
717 colorSpace) 718 numberPasses, colorSpace)
718 , fHeight(-1) 719 , fHeight(-1)
719 , fCanSkipRewind(false) 720 , fCanSkipRewind(false)
720 { 721 {
721 SkASSERT(numberPasses != 1); 722 SkASSERT(numberPasses != 1);
722 } 723 }
723 724
724 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti ons, 725 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti ons,
725 SkPMColor ctable[], int* ctableCount) override { 726 SkPMColor ctable[], int* ctableCount) override {
726 if (!conversion_possible(dstInfo, this->getInfo())) { 727 if (!conversion_possible(dstInfo, this->getInfo())) {
727 return kInvalidConversion; 728 return kInvalidConversion;
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
829 // add another layer. 830 // add another layer.
830 bool fCanSkipRewind; 831 bool fCanSkipRewind;
831 832
832 typedef SkPngCodec INHERITED; 833 typedef SkPngCodec INHERITED;
833 }; 834 };
834 835
835 SkCodec* SkPngCodec::NewFromStream(SkStream* stream, SkPngChunkReader* chunkRead er) { 836 SkCodec* SkPngCodec::NewFromStream(SkStream* stream, SkPngChunkReader* chunkRead er) {
836 SkAutoTDelete<SkStream> streamDeleter(stream); 837 SkAutoTDelete<SkStream> streamDeleter(stream);
837 png_structp png_ptr; 838 png_structp png_ptr;
838 png_infop info_ptr; 839 png_infop info_ptr;
839 SkImageInfo imageInfo; 840 int width, height;
841 SkEncodedInfo imageInfo;
840 int bitDepth; 842 int bitDepth;
841 int numberPasses; 843 int numberPasses;
842 844
843 if (!read_header(stream, chunkReader, &png_ptr, &info_ptr, &imageInfo, &bitD epth, 845 if (!read_header(stream, chunkReader, &png_ptr, &info_ptr, &width, &height, &imageInfo,
844 &numberPasses)) { 846 &bitDepth, &numberPasses)) {
845 return nullptr; 847 return nullptr;
846 } 848 }
847 849
848 auto colorSpace = read_color_space(png_ptr, info_ptr); 850 auto colorSpace = read_color_space(png_ptr, info_ptr);
849 851
850 if (1 == numberPasses) { 852 if (1 == numberPasses) {
851 return new SkPngScanlineDecoder(imageInfo, streamDeleter.release(), chun kReader, 853 return new SkPngScanlineDecoder(width, height, imageInfo, streamDeleter. release(),
852 png_ptr, info_ptr, bitDepth, colorSpace) ; 854 chunkReader, png_ptr, info_ptr, bitDepth , colorSpace);
853 } 855 }
854 856
855 return new SkPngInterlacedScanlineDecoder(imageInfo, streamDeleter.release() , chunkReader, 857 return new SkPngInterlacedScanlineDecoder(width, height, imageInfo, streamDe leter.release(),
856 png_ptr, info_ptr, bitDepth, numbe rPasses, 858 chunkReader, png_ptr, info_ptr, bi tDepth,
857 colorSpace); 859 numberPasses, colorSpace);
858 } 860 }
OLDNEW
« no previous file with comments | « src/codec/SkPngCodec.h ('k') | src/codec/SkRawCodec.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698