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

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

Issue 1213743004: Revert of Fixing libpng transform use (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 5 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/SkCodec_libpng.h ('k') | no next file » | 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 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 } 207 }
208 return true; 208 return true;
209 } 209 }
210 210
211 // Reads the header, and initializes the passed in fields, if not NULL (except 211 // Reads the header, and initializes the passed in fields, if not NULL (except
212 // stream, which is passed to the read function). 212 // stream, which is passed to the read function).
213 // Returns true on success, in which case the caller is responsible for calling 213 // Returns true on success, in which case the caller is responsible for calling
214 // png_destroy_read_struct. If it returns false, the passed in fields (except 214 // png_destroy_read_struct. If it returns false, the passed in fields (except
215 // stream) are unchanged. 215 // stream) are unchanged.
216 static bool read_header(SkStream* stream, png_structp* png_ptrp, 216 static bool read_header(SkStream* stream, png_structp* png_ptrp,
217 png_infop* info_ptrp, SkImageInfo* imageInfo, int* bitDe pthPtr) { 217 png_infop* info_ptrp, SkImageInfo* imageInfo) {
218 // The image is known to be a PNG. Decode enough to know the SkImageInfo. 218 // The image is known to be a PNG. Decode enough to know the SkImageInfo.
219 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, 219 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
220 sk_error_fn, sk_warning_fn); 220 sk_error_fn, sk_warning_fn);
221 if (!png_ptr) { 221 if (!png_ptr) {
222 return false; 222 return false;
223 } 223 }
224 224
225 AutoCleanPng autoClean(png_ptr); 225 AutoCleanPng autoClean(png_ptr);
226 226
227 png_infop info_ptr = png_create_info_struct(png_ptr); 227 png_infop info_ptr = png_create_info_struct(png_ptr);
(...skipping 17 matching lines...) Expand all
245 // If it does, we need to figure out a way to set it here. 245 // If it does, we need to figure out a way to set it here.
246 246
247 // The call to png_read_info() gives us all of the information from the 247 // The call to png_read_info() gives us all of the information from the
248 // PNG file before the first IDAT (image data chunk). 248 // PNG file before the first IDAT (image data chunk).
249 png_read_info(png_ptr, info_ptr); 249 png_read_info(png_ptr, info_ptr);
250 png_uint_32 origWidth, origHeight; 250 png_uint_32 origWidth, origHeight;
251 int bitDepth, colorType; 251 int bitDepth, colorType;
252 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, 252 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
253 &colorType, int_p_NULL, int_p_NULL, int_p_NULL); 253 &colorType, int_p_NULL, int_p_NULL, int_p_NULL);
254 254
255 if (bitDepthPtr) {
256 *bitDepthPtr = bitDepth;
257 }
258
259 // sanity check for size 255 // sanity check for size
260 { 256 {
261 int64_t size = sk_64_mul(origWidth, origHeight); 257 int64_t size = sk_64_mul(origWidth, origHeight);
262 // now check that if we are 4-bytes per pixel, we also don't overflow 258 // now check that if we are 4-bytes per pixel, we also don't overflow
263 if (size < 0 || size > (0x7FFFFFFF >> 2)) { 259 if (size < 0 || size > (0x7FFFFFFF >> 2)) {
264 return false; 260 return false;
265 } 261 }
266 } 262 }
267 263
268 // Tell libpng to strip 16 bit/color files down to 8 bits/color 264 // Tell libpng to strip 16 bit/color files down to 8 bits/color
269 if (bitDepth == 16) { 265 if (bitDepth == 16) {
270 png_set_strip_16(png_ptr); 266 png_set_strip_16(png_ptr);
271 } 267 }
272 #ifdef PNG_READ_PACK_SUPPORTED 268 #ifdef PNG_READ_PACK_SUPPORTED
273 // Extract multiple pixels with bit depths of 1, 2, and 4 from a single 269 // Extract multiple pixels with bit depths of 1, 2, and 4 from a single
274 // byte into separate bytes (useful for paletted and grayscale images). 270 // byte into separate bytes (useful for paletted and grayscale images).
275 if (bitDepth < 8) { 271 if (bitDepth < 8) {
276 png_set_packing(png_ptr); 272 png_set_packing(png_ptr);
277 } 273 }
278 #endif 274 #endif
279 // Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel. 275 // Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel.
280 if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) { 276 if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) {
281 png_set_expand_gray_1_2_4_to_8(png_ptr); 277 png_set_expand_gray_1_2_4_to_8(png_ptr);
282 } 278 }
283 279
284 // Now determine the default SkColorType and SkAlphaType and set required tr ansforms 280
281 // Now determine the default SkColorType and SkAlphaType.
285 SkColorType skColorType; 282 SkColorType skColorType;
286 SkAlphaType skAlphaType; 283 SkAlphaType skAlphaType;
287 switch (colorType) { 284 switch (colorType) {
288 case PNG_COLOR_TYPE_PALETTE: 285 case PNG_COLOR_TYPE_PALETTE:
289 skColorType = kIndex_8_SkColorType; 286 skColorType = kIndex_8_SkColorType;
290 skAlphaType = has_transparency_in_palette(png_ptr, info_ptr) ? 287 skAlphaType = has_transparency_in_palette(png_ptr, info_ptr) ?
291 kUnpremul_SkAlphaType : kOpaque_SkAlphaType; 288 kUnpremul_SkAlphaType : kOpaque_SkAlphaType;
292 break; 289 break;
293 case PNG_COLOR_TYPE_RGB: 290 case PNG_COLOR_TYPE_GRAY:
294 if (has_transparency_in_palette(png_ptr, info_ptr)) { 291 if (false) {
295 //convert to RGBA with tranparency information in tRNS chunk if it exists 292 // FIXME: Is this the wrong default behavior? This means if the
296 png_set_tRNS_to_alpha(png_ptr); 293 // caller supplies the info we gave them, they'll get Alpha 8.
294 skColorType = kAlpha_8_SkColorType;
295 // FIXME: Strangely, the canonical type for Alpha 8 is Premul.
296 skAlphaType = kPremul_SkAlphaType;
297 } else {
298 skColorType = kN32_SkColorType;
299 skAlphaType = kOpaque_SkAlphaType;
300 }
301 break;
302 default:
303 // Note: This *almost* mimics the code in SkImageDecoder_libpng.
304 // has_transparency_in_palette makes an additional check - whether
305 // numTrans is greater than 0. Why does the other code not make that
306 // check?
307 if (has_transparency_in_palette(png_ptr, info_ptr)
308 || PNG_COLOR_TYPE_RGB_ALPHA == colorType
309 || PNG_COLOR_TYPE_GRAY_ALPHA == colorType)
310 {
297 skAlphaType = kUnpremul_SkAlphaType; 311 skAlphaType = kUnpremul_SkAlphaType;
298 } else { 312 } else {
299 //convert to RGBA with Opaque Alpha
300 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
301 skAlphaType = kOpaque_SkAlphaType; 313 skAlphaType = kOpaque_SkAlphaType;
302 } 314 }
303 skColorType = kN32_SkColorType; 315 skColorType = kN32_SkColorType;
304 break; 316 break;
305 case PNG_COLOR_TYPE_GRAY: 317 }
306 if (has_transparency_in_palette(png_ptr, info_ptr)) { 318
307 //FIXME: support gray with alpha as a color type 319 {
308 //convert to RGBA if there is transparentcy info in the tRNS chu nk 320 // FIXME: Again, this block needs to go into onGetPixels.
309 png_set_tRNS_to_alpha(png_ptr); 321 bool convertGrayToRGB = PNG_COLOR_TYPE_GRAY == colorType && skColorType != kAlpha_8_SkColorType;
310 png_set_gray_to_rgb(png_ptr); 322
311 skColorType = kN32_SkColorType; 323 // Unless the user is requesting A8, convert a grayscale image into RGB.
312 skAlphaType = kUnpremul_SkAlphaType; 324 // GRAY_ALPHA will always be converted to RGB
313 } else { 325 if (convertGrayToRGB || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) {
314 skColorType = kGray_8_SkColorType;
315 skAlphaType = kOpaque_SkAlphaType;
316 }
317 break;
318 case PNG_COLOR_TYPE_GRAY_ALPHA:
319 //FIXME: support gray with alpha as a color type
320 //convert to RGBA
321 png_set_gray_to_rgb(png_ptr); 326 png_set_gray_to_rgb(png_ptr);
322 skColorType = kN32_SkColorType; 327 }
323 skAlphaType = kUnpremul_SkAlphaType; 328
324 break; 329 // Add filler (or alpha) byte (after each RGB triplet) if necessary.
325 case PNG_COLOR_TYPE_RGBA: 330 // FIXME: It seems like we could just use RGB as the SrcConfig here.
326 skColorType = kN32_SkColorType; 331 if (colorType == PNG_COLOR_TYPE_RGB || convertGrayToRGB) {
327 skAlphaType = kUnpremul_SkAlphaType; 332 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
328 break; 333 }
329 default:
330 //all the color types have been covered above
331 SkASSERT(false);
332 } 334 }
333 335
334 // FIXME: Also need to check for sRGB (skbug.com/3471). 336 // FIXME: Also need to check for sRGB (skbug.com/3471).
335 337
336 if (imageInfo) { 338 if (imageInfo) {
337 *imageInfo = SkImageInfo::Make(origWidth, origHeight, skColorType, skAlp haType); 339 *imageInfo = SkImageInfo::Make(origWidth, origHeight, skColorType,
340 skAlphaType);
338 } 341 }
339 autoClean.detach(); 342 autoClean.detach();
340 if (png_ptrp) { 343 if (png_ptrp) {
341 *png_ptrp = png_ptr; 344 *png_ptrp = png_ptr;
342 } 345 }
343 if (info_ptrp) { 346 if (info_ptrp) {
344 *info_ptrp = info_ptr; 347 *info_ptrp = info_ptr;
345 } 348 }
346
347 return true; 349 return true;
348 } 350 }
349 351
350 SkCodec* SkPngCodec::NewFromStream(SkStream* stream) { 352 SkCodec* SkPngCodec::NewFromStream(SkStream* stream) {
351 SkAutoTDelete<SkStream> streamDeleter(stream); 353 SkAutoTDelete<SkStream> streamDeleter(stream);
352 png_structp png_ptr; 354 png_structp png_ptr;
353 png_infop info_ptr; 355 png_infop info_ptr;
354 SkImageInfo imageInfo; 356 SkImageInfo imageInfo;
355 int bitDepth; 357 if (read_header(stream, &png_ptr, &info_ptr, &imageInfo)) {
356 if (read_header(stream, &png_ptr, &info_ptr, &imageInfo, &bitDepth)) { 358 return SkNEW_ARGS(SkPngCodec, (imageInfo, streamDeleter.detach(), png_pt r, info_ptr));
357 return SkNEW_ARGS(SkPngCodec, (imageInfo, streamDeleter.detach(),
358 png_ptr, info_ptr, bitDepth));
359 } 359 }
360 return NULL; 360 return NULL;
361 } 361 }
362 362
363 #define INVALID_NUMBER_PASSES -1 363 #define INVALID_NUMBER_PASSES -1
364 SkPngCodec::SkPngCodec(const SkImageInfo& info, SkStream* stream, 364 SkPngCodec::SkPngCodec(const SkImageInfo& info, SkStream* stream,
365 png_structp png_ptr, png_infop info_ptr, int bitDepth) 365 png_structp png_ptr, png_infop info_ptr)
366 : INHERITED(info, stream) 366 : INHERITED(info, stream)
367 , fPng_ptr(png_ptr) 367 , fPng_ptr(png_ptr)
368 , fInfo_ptr(info_ptr) 368 , fInfo_ptr(info_ptr)
369 , fSrcConfig(SkSwizzler::kUnknown) 369 , fSrcConfig(SkSwizzler::kUnknown)
370 , fNumberPasses(INVALID_NUMBER_PASSES) 370 , fNumberPasses(INVALID_NUMBER_PASSES)
371 , fReallyHasAlpha(false) 371 , fReallyHasAlpha(false)
372 , fBitDepth(bitDepth)
373 {} 372 {}
374 373
375 SkPngCodec::~SkPngCodec() { 374 SkPngCodec::~SkPngCodec() {
376 // First, ensure that the scanline decoder is left in a finished state. 375 // First, ensure that the scanline decoder is left in a finished state.
377 SkAutoTDelete<SkScanlineDecoder> decoder(this->detachScanlineDecoder()); 376 SkAutoTDelete<SkScanlineDecoder> decoder(this->detachScanlineDecoder());
378 if (NULL != decoder) { 377 if (NULL != decoder) {
379 this->finish(); 378 this->finish();
380 } 379 }
381 380
382 this->destroyReadStruct(); 381 this->destroyReadStruct();
(...skipping 30 matching lines...) Expand all
413 switch (dst.alphaType()) { 412 switch (dst.alphaType()) {
414 case kPremul_SkAlphaType: 413 case kPremul_SkAlphaType:
415 case kUnpremul_SkAlphaType: 414 case kUnpremul_SkAlphaType:
416 // The source is not opaque, so either of these is okay 415 // The source is not opaque, so either of these is okay
417 break; 416 break;
418 default: 417 default:
419 // We cannot decode a non-opaque image to opaque (or unknown) 418 // We cannot decode a non-opaque image to opaque (or unknown)
420 return false; 419 return false;
421 } 420 }
422 } 421 }
422
423 // Check for supported color types 423 // Check for supported color types
424 switch (dst.colorType()) { 424 switch (dst.colorType()) {
425 // Allow output to kN32 from any type of input
425 case kN32_SkColorType: 426 case kN32_SkColorType:
426 return true; 427 return true;
427 default: 428 default:
428 return dst.colorType() == src.colorType(); 429 return dst.colorType() == src.colorType();
429 } 430 }
430 } 431 }
431 432
432 SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo, 433 SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo,
433 void* dst, size_t rowBytes, 434 void* dst, size_t rowBytes,
434 const Options& options, 435 const Options& options,
435 SkPMColor ctable[], 436 SkPMColor ctable[],
436 int* ctableCount) { 437 int* ctableCount) {
437 // FIXME: Could we use the return value of setjmp to specify the type of 438 // FIXME: Could we use the return value of setjmp to specify the type of
438 // error? 439 // error?
439 if (setjmp(png_jmpbuf(fPng_ptr))) { 440 if (setjmp(png_jmpbuf(fPng_ptr))) {
440 SkCodecPrintf("setjmp long jump!\n"); 441 SkCodecPrintf("setjmp long jump!\n");
441 return kInvalidInput; 442 return kInvalidInput;
442 } 443 }
443 fNumberPasses = png_set_interlace_handling(fPng_ptr); 444
444 png_read_update_info(fPng_ptr, fInfo_ptr); 445 // FIXME: We already retrieved this information. Store it in SkPngCodec?
446 png_uint_32 origWidth, origHeight;
447 int bitDepth, pngColorType, interlaceType;
448 png_get_IHDR(fPng_ptr, fInfo_ptr, &origWidth, &origHeight, &bitDepth,
449 &pngColorType, &interlaceType, int_p_NULL, int_p_NULL);
450
451 fNumberPasses = (interlaceType != PNG_INTERLACE_NONE) ?
452 png_set_interlace_handling(fPng_ptr) : 1;
445 453
446 // Set to the default before calling decodePalette, which may change it. 454 // Set to the default before calling decodePalette, which may change it.
447 fReallyHasAlpha = false; 455 fReallyHasAlpha = false;
448 456 if (PNG_COLOR_TYPE_PALETTE == pngColorType) {
449 //srcColorType was determined in readHeader() which determined png color typ e 457 fSrcConfig = SkSwizzler::kIndex;
450 const SkColorType srcColorType = this->getInfo().colorType(); 458 if (!this->decodePalette(kPremul_SkAlphaType == requestedInfo.alphaType( ), bitDepth,
451 459 ctableCount)) {
452 switch (srcColorType) { 460 return kInvalidInput;
453 case kIndex_8_SkColorType: 461 }
454 //decode palette to Skia format 462 } else if (kAlpha_8_SkColorType == requestedInfo.colorType()) {
455 fSrcConfig = SkSwizzler::kIndex; 463 // Note: we check the destination, since otherwise we would have
456 if (!this->decodePalette(kPremul_SkAlphaType == requestedInfo.alphaT ype(), fBitDepth, 464 // told png to upscale.
457 ctableCount)) { 465 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType);
458 return kInvalidInput; 466 fSrcConfig = SkSwizzler::kGray;
459 } 467 } else if (this->getInfo().alphaType() == kOpaque_SkAlphaType) {
460 break; 468 fSrcConfig = SkSwizzler::kRGBX;
461 case kGray_8_SkColorType: 469 } else {
462 fSrcConfig = SkSwizzler::kGray; 470 fSrcConfig = SkSwizzler::kRGBA;
463 break; 471 }
464 case kN32_SkColorType:
465 if (this->getInfo().alphaType() == kOpaque_SkAlphaType) {
466 fSrcConfig = SkSwizzler::kRGBX;
467 } else {
468 fSrcConfig = SkSwizzler::kRGBA;
469 }
470 break;
471 default:
472 //would have exited before now if the colorType was supported by png
473 SkASSERT(false);
474 }
475 472
476 // Copy the color table to the client if they request kIndex8 mode 473 // Copy the color table to the client if they request kIndex8 mode
477 copy_color_table(requestedInfo, fColorTable, ctable, ctableCount); 474 copy_color_table(requestedInfo, fColorTable, ctable, ctableCount);
478 475
479 // Create the swizzler. SkPngCodec retains ownership of the color table. 476 // Create the swizzler. SkPngCodec retains ownership of the color table.
480 const SkPMColor* colors = fColorTable ? fColorTable->readColors() : NULL; 477 const SkPMColor* colors = fColorTable ? fColorTable->readColors() : NULL;
481 fSwizzler.reset(SkSwizzler::CreateSwizzler(fSrcConfig, colors, requestedInfo , 478 fSwizzler.reset(SkSwizzler::CreateSwizzler(fSrcConfig, colors, requestedInfo ,
482 dst, rowBytes, options.fZeroInitialized)); 479 dst, rowBytes, options.fZeroInitialized));
483 if (!fSwizzler) { 480 if (!fSwizzler) {
484 // FIXME: CreateSwizzler could fail for another reason. 481 // FIXME: CreateSwizzler could fail for another reason.
485 return kUnimplemented; 482 return kUnimplemented;
486 } 483 }
484
485 // FIXME: Here is where we should likely insert some of the modifications
486 // made in the factory.
487 png_read_update_info(fPng_ptr, fInfo_ptr);
488
487 return kSuccess; 489 return kSuccess;
488 } 490 }
489 491
490
491 bool SkPngCodec::handleRewind() { 492 bool SkPngCodec::handleRewind() {
492 switch (this->rewindIfNeeded()) { 493 switch (this->rewindIfNeeded()) {
493 case kNoRewindNecessary_RewindState: 494 case kNoRewindNecessary_RewindState:
494 return true; 495 return true;
495 case kCouldNotRewind_RewindState: 496 case kCouldNotRewind_RewindState:
496 return false; 497 return false;
497 case kRewound_RewindState: { 498 case kRewound_RewindState: {
498 // This sets fPng_ptr and fInfo_ptr to NULL. If read_header 499 // This sets fPng_ptr and fInfo_ptr to NULL. If read_header
499 // succeeds, they will be repopulated, and if it fails, they will 500 // succeeds, they will be repopulated, and if it fails, they will
500 // remain NULL. Any future accesses to fPng_ptr and fInfo_ptr will 501 // remain NULL. Any future accesses to fPng_ptr and fInfo_ptr will
501 // come through this function which will rewind and again attempt 502 // come through this function which will rewind and again attempt
502 // to reinitialize them. 503 // to reinitialize them.
503 this->destroyReadStruct(); 504 this->destroyReadStruct();
504 png_structp png_ptr; 505 png_structp png_ptr;
505 png_infop info_ptr; 506 png_infop info_ptr;
506 if (read_header(this->stream(), &png_ptr, &info_ptr, NULL, NULL)) { 507 if (read_header(this->stream(), &png_ptr, &info_ptr, NULL)) {
507 fPng_ptr = png_ptr; 508 fPng_ptr = png_ptr;
508 fInfo_ptr = info_ptr; 509 fInfo_ptr = info_ptr;
509 return true; 510 return true;
510 } 511 }
511 return false; 512 return false;
512 } 513 }
513 default: 514 default:
514 SkASSERT(false); 515 SkASSERT(false);
515 return false; 516 return false;
516 } 517 }
517 } 518 }
518 519
519 SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void* dst, 520 SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void* dst,
520 size_t rowBytes, const Options& options, 521 size_t rowBytes, const Options& options,
521 SkPMColor ctable[], int* ctableCount) { 522 SkPMColor ctable[], int* ctableCount) {
522 if (!conversion_possible(requestedInfo, this->getInfo())) {
523 return kInvalidConversion;
524 }
525 // Do not allow a regular decode if the caller has asked for a scanline deco der 523 // Do not allow a regular decode if the caller has asked for a scanline deco der
526 if (NULL != this->scanlineDecoder()) { 524 if (NULL != this->scanlineDecoder()) {
527 SkCodecPrintf("cannot getPixels() if a scanline decoder has been created \n"); 525 SkCodecPrintf("cannot getPixels() if a scanline decoder has been created \n");
528 return kInvalidParameters; 526 return kInvalidParameters;
529 } 527 }
528
529 if (!this->handleRewind()) {
530 return kCouldNotRewind;
531 }
530 if (requestedInfo.dimensions() != this->getInfo().dimensions()) { 532 if (requestedInfo.dimensions() != this->getInfo().dimensions()) {
531 return kInvalidScale; 533 return kInvalidScale;
532 } 534 }
533 if (!this->handleRewind()) { 535 if (!conversion_possible(requestedInfo, this->getInfo())) {
534 return kCouldNotRewind; 536 return kInvalidConversion;
535 } 537 }
536 538
537 // Note that ctable and ctableCount may be modified if there is a color tabl e 539 // Note that ctable and ctableCount may be modified if there is a color tabl e
538 const Result result = this->initializeSwizzler(requestedInfo, dst, rowBytes, 540 const Result result = this->initializeSwizzler(requestedInfo, dst, rowBytes,
539 options, ctable, ctableCount) ; 541 options, ctable, ctableCount) ;
542
540 if (result != kSuccess) { 543 if (result != kSuccess) {
541 return result; 544 return result;
542 } 545 }
546
543 // FIXME: Could we use the return value of setjmp to specify the type of 547 // FIXME: Could we use the return value of setjmp to specify the type of
544 // error? 548 // error?
545 if (setjmp(png_jmpbuf(fPng_ptr))) { 549 if (setjmp(png_jmpbuf(fPng_ptr))) {
546 SkCodecPrintf("setjmp long jump!\n"); 550 SkCodecPrintf("setjmp long jump!\n");
547 return kInvalidInput; 551 return kInvalidInput;
548 } 552 }
549 553
550 SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES); 554 SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES);
551 SkAutoMalloc storage; 555 SkAutoMalloc storage;
552 if (fNumberPasses > 1) { 556 if (fNumberPasses > 1) {
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
654 658
655 659
656 class SkPngInterlacedScanlineDecoder : public SkScanlineDecoder { 660 class SkPngInterlacedScanlineDecoder : public SkScanlineDecoder {
657 public: 661 public:
658 SkPngInterlacedScanlineDecoder(const SkImageInfo& dstInfo, SkPngCodec* codec ) 662 SkPngInterlacedScanlineDecoder(const SkImageInfo& dstInfo, SkPngCodec* codec )
659 : INHERITED(dstInfo) 663 : INHERITED(dstInfo)
660 , fCodec(codec) 664 , fCodec(codec)
661 , fHasAlpha(false) 665 , fHasAlpha(false)
662 , fCurrentRow(0) 666 , fCurrentRow(0)
663 , fHeight(dstInfo.height()) 667 , fHeight(dstInfo.height())
668 , fSrcRowBytes(dstInfo.minRowBytes())
664 , fRewindNeeded(false) 669 , fRewindNeeded(false)
665 { 670 {
666 fSrcRowBytes = dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcC onfig);
667 fGarbageRow.reset(fSrcRowBytes); 671 fGarbageRow.reset(fSrcRowBytes);
668 fGarbageRowPtr = static_cast<uint8_t*>(fGarbageRow.get()); 672 fGarbageRowPtr = static_cast<uint8_t*>(fGarbageRow.get());
669 } 673 }
670 674
671 SkImageGenerator::Result onGetScanlines(void* dst, int count, size_t dstRowB ytes) override { 675 SkImageGenerator::Result onGetScanlines(void* dst, int count, size_t dstRowB ytes) override {
672 //rewind stream if have previously called onGetScanlines, 676 //rewind stream if have previously called onGetScanlines,
673 //since we need entire progressive image to get scanlines 677 //since we need entire progressive image to get scanlines
674 if (fRewindNeeded) { 678 if (fRewindNeeded) {
675 if(false == fCodec->handleRewind()) { 679 if(false == fCodec->handleRewind()) {
676 return SkImageGenerator::kCouldNotRewind; 680 return SkImageGenerator::kCouldNotRewind;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 728
725 private: 729 private:
726 SkPngCodec* fCodec; // Unowned. 730 SkPngCodec* fCodec; // Unowned.
727 bool fHasAlpha; 731 bool fHasAlpha;
728 int fCurrentRow; 732 int fCurrentRow;
729 int fHeight; 733 int fHeight;
730 size_t fSrcRowBytes; 734 size_t fSrcRowBytes;
731 bool fRewindNeeded; 735 bool fRewindNeeded;
732 SkAutoMalloc fGarbageRow; 736 SkAutoMalloc fGarbageRow;
733 uint8_t* fGarbageRowPtr; 737 uint8_t* fGarbageRowPtr;
738
739
740
741
734 742
735 typedef SkScanlineDecoder INHERITED; 743 typedef SkScanlineDecoder INHERITED;
736 }; 744 };
737 745
738 746
739 SkScanlineDecoder* SkPngCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo, 747 SkScanlineDecoder* SkPngCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo,
740 const Options& options, SkPMColor ctable[], int* ctableCount) { 748 const Options& options, SkPMColor ctable[], int* ctableCount) {
749 if (!this->handleRewind()) {
750 return NULL;
751 }
752
753 // Check to see if scaling was requested.
754 if (dstInfo.dimensions() != this->getInfo().dimensions()) {
755 return NULL;
756 }
757
741 if (!conversion_possible(dstInfo, this->getInfo())) { 758 if (!conversion_possible(dstInfo, this->getInfo())) {
742 SkCodecPrintf("no conversion possible\n"); 759 SkCodecPrintf("no conversion possible\n");
743 return NULL; 760 return NULL;
744 } 761 }
745 // Check to see if scaling was requested.
746 if (dstInfo.dimensions() != this->getInfo().dimensions()) {
747 return NULL;
748 }
749 if (!this->handleRewind()) {
750 return NULL;
751 }
752 762
753 // Note: We set dst to NULL since we do not know it yet. rowBytes is not nee ded, 763 // Note: We set dst to NULL since we do not know it yet. rowBytes is not nee ded,
754 // since we'll be manually updating the dstRow, but the SkSwizzler requires it to 764 // since we'll be manually updating the dstRow, but the SkSwizzler requires it to
755 // be at least dstInfo.minRowBytes. 765 // be at least dstInfo.minRowBytes.
756 if (this->initializeSwizzler(dstInfo, NULL, dstInfo.minRowBytes(), options, ctable, 766 if (this->initializeSwizzler(dstInfo, NULL, dstInfo.minRowBytes(), options, ctable,
757 ctableCount) != kSuccess) { 767 ctableCount) != kSuccess) {
758 SkCodecPrintf("failed to initialize the swizzler.\n"); 768 SkCodecPrintf("failed to initialize the swizzler.\n");
759 return NULL; 769 return NULL;
760 } 770 }
761 771
762 SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES); 772 SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES);
763 if (fNumberPasses > 1) { 773 if (fNumberPasses > 1) {
764 // interlaced image 774 // interlaced image
765 return SkNEW_ARGS(SkPngInterlacedScanlineDecoder, (dstInfo, this)); 775 return SkNEW_ARGS(SkPngInterlacedScanlineDecoder, (dstInfo, this));
766 } 776 }
767 777
768 return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, this)); 778 return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, this));
769 } 779 }
770 780
OLDNEW
« no previous file with comments | « src/codec/SkCodec_libpng.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698