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

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: Created 4 years, 9 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
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 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698