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

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

Issue 1472863003: Revert of Add SkPngChunkReader. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years 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/images/SkImageDecoder.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"
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 SkStream* stream = static_cast<SkStream*>(png_get_io_ptr(png_ptr)); 58 SkStream* stream = static_cast<SkStream*>(png_get_io_ptr(png_ptr));
59 const size_t bytes = stream->read(data, length); 59 const size_t bytes = stream->read(data, length);
60 if (bytes != length) { 60 if (bytes != length) {
61 // FIXME: We want to report the fact that the stream was truncated. 61 // FIXME: We want to report the fact that the stream was truncated.
62 // One way to do that might be to pass a enum to longjmp so setjmp can 62 // One way to do that might be to pass a enum to longjmp so setjmp can
63 // specify the failure. 63 // specify the failure.
64 png_error(png_ptr, "Read Error!"); 64 png_error(png_ptr, "Read Error!");
65 } 65 }
66 } 66 }
67 67
68 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
69 static int sk_read_user_chunk(png_structp png_ptr, png_unknown_chunkp chunk) {
70 SkPngChunkReader* chunkReader = (SkPngChunkReader*)png_get_user_chunk_ptr(pn g_ptr);
71 // readChunk() returning true means continue decoding
72 return chunkReader->readChunk((const char*)chunk->name, chunk->data, chunk-> size) ? 1 : -1;
73 }
74 #endif
75
76 /////////////////////////////////////////////////////////////////////////////// 68 ///////////////////////////////////////////////////////////////////////////////
77 // Helpers 69 // Helpers
78 /////////////////////////////////////////////////////////////////////////////// 70 ///////////////////////////////////////////////////////////////////////////////
79 71
80 class AutoCleanPng : public SkNoncopyable { 72 class AutoCleanPng : public SkNoncopyable {
81 public: 73 public:
82 AutoCleanPng(png_structp png_ptr) 74 AutoCleanPng(png_structp png_ptr)
83 : fPng_ptr(png_ptr) 75 : fPng_ptr(png_ptr)
84 , fInfo_ptr(nullptr) {} 76 , fInfo_ptr(nullptr) {}
85 77
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 char buf[PNG_BYTES_TO_CHECK]; 204 char buf[PNG_BYTES_TO_CHECK];
213 if (stream->read(buf, PNG_BYTES_TO_CHECK) != PNG_BYTES_TO_CHECK) { 205 if (stream->read(buf, PNG_BYTES_TO_CHECK) != PNG_BYTES_TO_CHECK) {
214 return false; 206 return false;
215 } 207 }
216 if (png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) { 208 if (png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) {
217 return false; 209 return false;
218 } 210 }
219 return true; 211 return true;
220 } 212 }
221 213
222 // Reads the header and initializes the output fields, if not NULL. 214 // Reads the header, and initializes the passed in fields, if not nullptr (excep t
223 // 215 // stream, which is passed to the read function).
224 // @param stream Input data. Will be read to get enough information to properly 216 // Returns true on success, in which case the caller is responsible for calling
225 // setup the codec. 217 // png_destroy_read_struct. If it returns false, the passed in fields (except
226 // @param chunkReader SkPngChunkReader, for reading unknown chunks. May be NULL. 218 // stream) are unchanged.
227 // If not NULL, png_ptr will hold an *unowned* pointer to it. The caller is 219 static bool read_header(SkStream* stream, png_structp* png_ptrp,
228 // expected to continue to own it for the lifetime of the png_ptr. 220 png_infop* info_ptrp, SkImageInfo* imageInfo,
229 // @param png_ptrp Optional output variable. If non-NULL, will be set to a new 221 int* bitDepthPtr, int* numberPassesPtr) {
230 // png_structp on success.
231 // @param info_ptrp Optional output variable. If non-NULL, will be set to a new
232 // png_infop on success;
233 // @param imageInfo Optional output variable. If non-NULL, will be set to
234 // reflect the properties of the encoded image on success.
235 // @param bitDepthPtr Optional output variable. If non-NULL, will be set to the
236 // bit depth of the encoded image on success.
237 // @param numberPassesPtr Optional output variable. If non-NULL, will be set to
238 // the number_passes of the encoded image on success.
239 // @return true on success, in which case the caller is responsible for calling
240 // png_destroy_read_struct(png_ptrp, info_ptrp).
241 // If it returns false, the passed in fields (except stream) are unchanged.
242 static bool read_header(SkStream* stream, SkPngChunkReader* chunkReader,
243 png_structp* png_ptrp, png_infop* info_ptrp,
244 SkImageInfo* imageInfo, int* bitDepthPtr, int* numberPas sesPtr) {
245 // The image is known to be a PNG. Decode enough to know the SkImageInfo. 222 // The image is known to be a PNG. Decode enough to know the SkImageInfo.
246 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, 223 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr,
247 sk_error_fn, sk_warning_fn); 224 sk_error_fn, sk_warning_fn);
248 if (!png_ptr) { 225 if (!png_ptr) {
249 return false; 226 return false;
250 } 227 }
251 228
252 AutoCleanPng autoClean(png_ptr); 229 AutoCleanPng autoClean(png_ptr);
253 230
254 png_infop info_ptr = png_create_info_struct(png_ptr); 231 png_infop info_ptr = png_create_info_struct(png_ptr);
255 if (info_ptr == nullptr) { 232 if (info_ptr == nullptr) {
256 return false; 233 return false;
257 } 234 }
258 235
259 autoClean.setInfoPtr(info_ptr); 236 autoClean.setInfoPtr(info_ptr);
260 237
261 // FIXME: Could we use the return value of setjmp to specify the type of 238 // FIXME: Could we use the return value of setjmp to specify the type of
262 // error? 239 // error?
263 if (setjmp(png_jmpbuf(png_ptr))) { 240 if (setjmp(png_jmpbuf(png_ptr))) {
264 return false; 241 return false;
265 } 242 }
266 243
267 png_set_read_fn(png_ptr, static_cast<void*>(stream), sk_read_fn); 244 png_set_read_fn(png_ptr, static_cast<void*>(stream), sk_read_fn);
268 245
269 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED 246 // FIXME: This is where the old code hooks up the Peeker. Does it need to
270 // FIXME: Does this need to be installed so early? 247 // be set this early? (i.e. where are the user chunks? early in the stream,
271 // hookup our chunkReader so we can see any user-chunks the caller may be in terested in 248 // potentially?)
272 if (chunkReader) { 249 // If it does, we need to figure out a way to set it here.
273 png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, (png_byte* )"", 0);
274 png_set_read_user_chunk_fn(png_ptr, (png_voidp) chunkReader, sk_read_use r_chunk);
275 }
276 #endif
277 250
278 // The call to png_read_info() gives us all of the information from the 251 // The call to png_read_info() gives us all of the information from the
279 // PNG file before the first IDAT (image data chunk). 252 // PNG file before the first IDAT (image data chunk).
280 png_read_info(png_ptr, info_ptr); 253 png_read_info(png_ptr, info_ptr);
281 png_uint_32 origWidth, origHeight; 254 png_uint_32 origWidth, origHeight;
282 int bitDepth, colorType; 255 int bitDepth, colorType;
283 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, 256 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
284 &colorType, int_p_NULL, int_p_NULL, int_p_NULL); 257 &colorType, int_p_NULL, int_p_NULL, int_p_NULL);
285 258
286 if (bitDepthPtr) { 259 if (bitDepthPtr) {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 if (png_ptrp) { 349 if (png_ptrp) {
377 *png_ptrp = png_ptr; 350 *png_ptrp = png_ptr;
378 } 351 }
379 if (info_ptrp) { 352 if (info_ptrp) {
380 *info_ptrp = info_ptr; 353 *info_ptrp = info_ptr;
381 } 354 }
382 355
383 return true; 356 return true;
384 } 357 }
385 358
386 SkPngCodec::SkPngCodec(const SkImageInfo& info, SkStream* stream, SkPngChunkRead er* chunkReader, 359 SkPngCodec::SkPngCodec(const SkImageInfo& info, SkStream* stream,
387 png_structp png_ptr, png_infop info_ptr, int bitDepth, in t numberPasses) 360 png_structp png_ptr, png_infop info_ptr, int bitDepth, in t numberPasses)
388 : INHERITED(info, stream) 361 : INHERITED(info, stream)
389 , fPngChunkReader(SkSafeRef(chunkReader))
390 , fPng_ptr(png_ptr) 362 , fPng_ptr(png_ptr)
391 , fInfo_ptr(info_ptr) 363 , fInfo_ptr(info_ptr)
392 , fSrcConfig(SkSwizzler::kUnknown) 364 , fSrcConfig(SkSwizzler::kUnknown)
393 , fNumberPasses(numberPasses) 365 , fNumberPasses(numberPasses)
394 , fBitDepth(bitDepth) 366 , fBitDepth(bitDepth)
395 { 367 {
396 if (info.alphaType() == kOpaque_SkAlphaType) { 368 if (info.alphaType() == kOpaque_SkAlphaType) {
397 fAlphaState = kOpaque_AlphaState; 369 fAlphaState = kOpaque_AlphaState;
398 } else { 370 } else {
399 fAlphaState = kUnknown_AlphaState; 371 fAlphaState = kUnknown_AlphaState;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 bool SkPngCodec::onRewind() { 446 bool SkPngCodec::onRewind() {
475 // This sets fPng_ptr and fInfo_ptr to nullptr. If read_header 447 // This sets fPng_ptr and fInfo_ptr to nullptr. If read_header
476 // succeeds, they will be repopulated, and if it fails, they will 448 // succeeds, they will be repopulated, and if it fails, they will
477 // remain nullptr. Any future accesses to fPng_ptr and fInfo_ptr will 449 // remain nullptr. Any future accesses to fPng_ptr and fInfo_ptr will
478 // come through this function which will rewind and again attempt 450 // come through this function which will rewind and again attempt
479 // to reinitialize them. 451 // to reinitialize them.
480 this->destroyReadStruct(); 452 this->destroyReadStruct();
481 453
482 png_structp png_ptr; 454 png_structp png_ptr;
483 png_infop info_ptr; 455 png_infop info_ptr;
484 if (!read_header(this->stream(), fPngChunkReader.get(), &png_ptr, &info_ptr, 456 if (!read_header(this->stream(), &png_ptr, &info_ptr, nullptr, nullptr, null ptr)) {
485 nullptr, nullptr, nullptr)) {
486 return false; 457 return false;
487 } 458 }
488 459
489 fPng_ptr = png_ptr; 460 fPng_ptr = png_ptr;
490 fInfo_ptr = info_ptr; 461 fInfo_ptr = info_ptr;
491 return true; 462 return true;
492 } 463 }
493 464
494 SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void* dst, 465 SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void* dst,
495 size_t dstRowBytes, const Options& optio ns, 466 size_t dstRowBytes, const Options& optio ns,
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 595
625 // All valid AlphaStates have been covered, so this should not be reached. 596 // All valid AlphaStates have been covered, so this should not be reached.
626 SkASSERT(false); 597 SkASSERT(false);
627 return true; 598 return true;
628 } 599 }
629 600
630 // Subclass of SkPngCodec which supports scanline decoding 601 // Subclass of SkPngCodec which supports scanline decoding
631 class SkPngScanlineDecoder : public SkPngCodec { 602 class SkPngScanlineDecoder : public SkPngCodec {
632 public: 603 public:
633 SkPngScanlineDecoder(const SkImageInfo& srcInfo, SkStream* stream, 604 SkPngScanlineDecoder(const SkImageInfo& srcInfo, SkStream* stream,
634 SkPngChunkReader* chunkReader, png_structp png_ptr, png_infop info_p tr, int bitDepth) 605 png_structp png_ptr, png_infop info_ptr, int bitDepth)
635 : INHERITED(srcInfo, stream, chunkReader, png_ptr, info_ptr, bitDepth, 1 ) 606 : INHERITED(srcInfo, stream, png_ptr, info_ptr, bitDepth, 1)
636 , fAlphaState(kUnknown_AlphaState) 607 , fAlphaState(kUnknown_AlphaState)
637 , fSrcRow(nullptr) 608 , fSrcRow(nullptr)
638 {} 609 {}
639 610
640 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti ons, 611 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti ons,
641 SkPMColor ctable[], int* ctableCount) override { 612 SkPMColor ctable[], int* ctableCount) override {
642 if (!conversion_possible(dstInfo, this->getInfo())) { 613 if (!conversion_possible(dstInfo, this->getInfo())) {
643 return kInvalidConversion; 614 return kInvalidConversion;
644 } 615 }
645 616
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
708 SkAutoMalloc fStorage; 679 SkAutoMalloc fStorage;
709 uint8_t* fSrcRow; 680 uint8_t* fSrcRow;
710 681
711 typedef SkPngCodec INHERITED; 682 typedef SkPngCodec INHERITED;
712 }; 683 };
713 684
714 685
715 class SkPngInterlacedScanlineDecoder : public SkPngCodec { 686 class SkPngInterlacedScanlineDecoder : public SkPngCodec {
716 public: 687 public:
717 SkPngInterlacedScanlineDecoder(const SkImageInfo& srcInfo, SkStream* stream, 688 SkPngInterlacedScanlineDecoder(const SkImageInfo& srcInfo, SkStream* stream,
718 SkPngChunkReader* chunkReader, png_structp png_ptr, png_infop info_p tr, 689 png_structp png_ptr, png_infop info_ptr, int bitDepth, int numberPas ses)
719 int bitDepth, int numberPasses) 690 : INHERITED(srcInfo, stream, png_ptr, info_ptr, bitDepth, numberPasses)
720 : INHERITED(srcInfo, stream, chunkReader, png_ptr, info_ptr, bitDepth, n umberPasses)
721 , fAlphaState(kUnknown_AlphaState) 691 , fAlphaState(kUnknown_AlphaState)
722 , fHeight(-1) 692 , fHeight(-1)
723 , fCanSkipRewind(false) 693 , fCanSkipRewind(false)
724 { 694 {
725 SkASSERT(numberPasses != 1); 695 SkASSERT(numberPasses != 1);
726 } 696 }
727 697
728 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti ons, 698 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti ons,
729 SkPMColor ctable[], int* ctableCount) override { 699 SkPMColor ctable[], int* ctableCount) override {
730 if (!conversion_possible(dstInfo, this->getInfo())) { 700 if (!conversion_possible(dstInfo, this->getInfo())) {
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
845 // to note that the *next* time it is called a rewind is needed. 815 // to note that the *next* time it is called a rewind is needed.
846 // SkPngInterlacedScanlineDecoder has an extra wrinkle - calling 816 // SkPngInterlacedScanlineDecoder has an extra wrinkle - calling
847 // onStartScanlineDecode followed by onGetScanlines does *not* require a 817 // onStartScanlineDecode followed by onGetScanlines does *not* require a
848 // rewind. Since rewindIfNeeded does not have this flexibility, we need to 818 // rewind. Since rewindIfNeeded does not have this flexibility, we need to
849 // add another layer. 819 // add another layer.
850 bool fCanSkipRewind; 820 bool fCanSkipRewind;
851 821
852 typedef SkPngCodec INHERITED; 822 typedef SkPngCodec INHERITED;
853 }; 823 };
854 824
855 SkCodec* SkPngCodec::NewFromStream(SkStream* stream, SkPngChunkReader* chunkRead er) { 825 SkCodec* SkPngCodec::NewFromStream(SkStream* stream) {
856 SkAutoTDelete<SkStream> streamDeleter(stream); 826 SkAutoTDelete<SkStream> streamDeleter(stream);
857 png_structp png_ptr; 827 png_structp png_ptr;
858 png_infop info_ptr; 828 png_infop info_ptr;
859 SkImageInfo imageInfo; 829 SkImageInfo imageInfo;
860 int bitDepth; 830 int bitDepth;
861 int numberPasses; 831 int numberPasses;
862 832
863 if (!read_header(stream, chunkReader, &png_ptr, &info_ptr, &imageInfo, &bitD epth, 833 if (!read_header(stream, &png_ptr, &info_ptr, &imageInfo, &bitDepth, &number Passes)) {
864 &numberPasses)) {
865 return nullptr; 834 return nullptr;
866 } 835 }
867 836
868 if (1 == numberPasses) { 837 if (1 == numberPasses) {
869 return new SkPngScanlineDecoder(imageInfo, streamDeleter.detach(), chunk Reader, 838 return new SkPngScanlineDecoder(imageInfo, streamDeleter.detach(), png_p tr, info_ptr,
870 png_ptr, info_ptr, bitDepth); 839 bitDepth);
871 } 840 }
872 841
873 return new SkPngInterlacedScanlineDecoder(imageInfo, streamDeleter.detach(), chunkReader, 842 return new SkPngInterlacedScanlineDecoder(imageInfo, streamDeleter.detach(), png_ptr,
874 png_ptr, info_ptr, bitDepth, numbe rPasses); 843 info_ptr, bitDepth, numberPasses);
875 } 844 }
OLDNEW
« no previous file with comments | « src/codec/SkCodec_libpng.h ('k') | src/images/SkImageDecoder.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698