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

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

Issue 1040453002: Add SkPngChunkReader. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Peeker -> SkChunkReader, passed to constructor. Created 5 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 "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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 SkStream* stream = static_cast<SkStream*>(png_get_io_ptr(png_ptr)); 59 SkStream* stream = static_cast<SkStream*>(png_get_io_ptr(png_ptr));
60 const size_t bytes = stream->read(data, length); 60 const size_t bytes = stream->read(data, length);
61 if (bytes != length) { 61 if (bytes != length) {
62 // FIXME: We want to report the fact that the stream was truncated. 62 // FIXME: We want to report the fact that the stream was truncated.
63 // One way to do that might be to pass a enum to longjmp so setjmp can 63 // One way to do that might be to pass a enum to longjmp so setjmp can
64 // specify the failure. 64 // specify the failure.
65 png_error(png_ptr, "Read Error!"); 65 png_error(png_ptr, "Read Error!");
66 } 66 }
67 } 67 }
68 68
69 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
70 static int sk_read_user_chunk(png_structp png_ptr, png_unknown_chunkp chunk) {
71 SkChunkReader* chunkReader = (SkChunkReader*)png_get_user_chunk_ptr(png_ptr) ;
72 // peek() returning true means continue decoding
73 return chunkReader->readChunk((const char*)chunk->name, chunk->data, chunk-> size) ? 1 : -1;
74 }
75 #endif
76
69 /////////////////////////////////////////////////////////////////////////////// 77 ///////////////////////////////////////////////////////////////////////////////
70 // Helpers 78 // Helpers
71 /////////////////////////////////////////////////////////////////////////////// 79 ///////////////////////////////////////////////////////////////////////////////
72 80
73 class AutoCleanPng : public SkNoncopyable { 81 class AutoCleanPng : public SkNoncopyable {
74 public: 82 public:
75 AutoCleanPng(png_structp png_ptr) 83 AutoCleanPng(png_structp png_ptr)
76 : fPng_ptr(png_ptr) 84 : fPng_ptr(png_ptr)
77 , fInfo_ptr(NULL) {} 85 , fInfo_ptr(NULL) {}
78 86
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 char buf[PNG_BYTES_TO_CHECK]; 202 char buf[PNG_BYTES_TO_CHECK];
195 if (stream->read(buf, PNG_BYTES_TO_CHECK) != PNG_BYTES_TO_CHECK) { 203 if (stream->read(buf, PNG_BYTES_TO_CHECK) != PNG_BYTES_TO_CHECK) {
196 return false; 204 return false;
197 } 205 }
198 if (png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) { 206 if (png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) {
199 return false; 207 return false;
200 } 208 }
201 return true; 209 return true;
202 } 210 }
203 211
204 SkCodec* SkPngCodec::NewFromStream(SkStream* stream) { 212 SkCodec* SkPngCodec::NewFromStream(SkStream* stream, SkChunkReader* chunkReader) {
205 // The image is known to be a PNG. Decode enough to know the SkImageInfo. 213 // The image is known to be a PNG. Decode enough to know the SkImageInfo.
206 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, 214 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
207 sk_error_fn, sk_warning_fn); 215 sk_error_fn, sk_warning_fn);
208 if (!png_ptr) { 216 if (!png_ptr) {
209 return NULL; 217 return NULL;
210 } 218 }
211 219
212 AutoCleanPng autoClean(png_ptr); 220 AutoCleanPng autoClean(png_ptr);
213 221
214 png_infop info_ptr = png_create_info_struct(png_ptr); 222 png_infop info_ptr = png_create_info_struct(png_ptr);
215 if (info_ptr == NULL) { 223 if (info_ptr == NULL) {
216 return NULL; 224 return NULL;
217 } 225 }
218 226
219 autoClean.setInfoPtr(info_ptr); 227 autoClean.setInfoPtr(info_ptr);
220 228
221 // FIXME: Could we use the return value of setjmp to specify the type of 229 // FIXME: Could we use the return value of setjmp to specify the type of
222 // error? 230 // error?
223 if (setjmp(png_jmpbuf(png_ptr))) { 231 if (setjmp(png_jmpbuf(png_ptr))) {
224 return NULL; 232 return NULL;
225 } 233 }
226 234
227 png_set_read_fn(png_ptr, static_cast<void*>(stream), sk_read_fn); 235 png_set_read_fn(png_ptr, static_cast<void*>(stream), sk_read_fn);
228 236
229 // FIXME: This is where the old code hooks up the Peeker. Does it need to 237 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
230 // be set this early? (i.e. where are the user chunks? early in the stream, 238 // hookup our chunkReader so we can see any user-chunks the caller may be in terested in
231 // potentially?) 239 if (chunkReader) {
232 // If it does, we need to figure out a way to set it here. 240 png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, (png_byte* )"", 0);
241 png_set_read_user_chunk_fn(png_ptr, (png_voidp) chunkReader, sk_read_use r_chunk);
242 }
243 #endif
233 244
234 // The call to png_read_info() gives us all of the information from the 245 // The call to png_read_info() gives us all of the information from the
235 // PNG file before the first IDAT (image data chunk). 246 // PNG file before the first IDAT (image data chunk).
236 png_read_info(png_ptr, info_ptr); 247 png_read_info(png_ptr, info_ptr);
237 png_uint_32 origWidth, origHeight; 248 png_uint_32 origWidth, origHeight;
238 int bitDepth, colorType; 249 int bitDepth, colorType;
239 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, 250 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
240 &colorType, int_p_NULL, int_p_NULL, int_p_NULL); 251 &colorType, int_p_NULL, int_p_NULL, int_p_NULL);
241 252
242 // sanity check for size 253 // sanity check for size
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 // FIXME: It seems like we could just use RGB as the SrcConfig here. 331 // FIXME: It seems like we could just use RGB as the SrcConfig here.
321 if (colorType == PNG_COLOR_TYPE_RGB || convertGrayToRGB) { 332 if (colorType == PNG_COLOR_TYPE_RGB || convertGrayToRGB) {
322 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); 333 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
323 } 334 }
324 } 335 }
325 336
326 // FIXME: Also need to check for sRGB (skbug.com/3471). 337 // FIXME: Also need to check for sRGB (skbug.com/3471).
327 338
328 SkImageInfo info = SkImageInfo::Make(origWidth, origHeight, skColorType, 339 SkImageInfo info = SkImageInfo::Make(origWidth, origHeight, skColorType,
329 skAlphaType); 340 skAlphaType);
330 SkCodec* codec = SkNEW_ARGS(SkPngCodec, (info, stream, png_ptr, info_ptr)); 341 SkCodec* codec = SkNEW_ARGS(SkPngCodec, (info, stream, chunkReader, png_ptr, info_ptr));
331 autoClean.detach(); 342 autoClean.detach();
332 return codec; 343 return codec;
333 } 344 }
334 345
335 #define INVALID_NUMBER_PASSES -1 346 #define INVALID_NUMBER_PASSES -1
336 SkPngCodec::SkPngCodec(const SkImageInfo& info, SkStream* stream, 347 SkPngCodec::SkPngCodec(const SkImageInfo& info, SkStream* stream, SkChunkReader* chunkReader,
337 png_structp png_ptr, png_infop info_ptr) 348 png_structp png_ptr, png_infop info_ptr)
338 : INHERITED(info, stream) 349 : INHERITED(info, stream)
350 , fChunkReader(SkSafeRef(chunkReader))
339 , fPng_ptr(png_ptr) 351 , fPng_ptr(png_ptr)
340 , fInfo_ptr(info_ptr) 352 , fInfo_ptr(info_ptr)
341 , fSrcConfig(SkSwizzler::kUnknown) 353 , fSrcConfig(SkSwizzler::kUnknown)
342 , fNumberPasses(INVALID_NUMBER_PASSES) 354 , fNumberPasses(INVALID_NUMBER_PASSES)
343 , fReallyHasAlpha(false) 355 , fReallyHasAlpha(false)
344 {} 356 {}
345 357
346 SkPngCodec::~SkPngCodec() { 358 SkPngCodec::~SkPngCodec() {
347 png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, png_infopp_NULL); 359 png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, png_infopp_NULL);
348 } 360 }
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
572 584
573 SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES); 585 SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES);
574 if (fNumberPasses > 1) { 586 if (fNumberPasses > 1) {
575 // We cannot efficiently do scanline decoding. 587 // We cannot efficiently do scanline decoding.
576 return NULL; 588 return NULL;
577 } 589 }
578 590
579 return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, this)); 591 return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, this));
580 } 592 }
581 593
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698