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

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

Issue 1332053002: Fill incomplete images in SkCodec parent class (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Rebase on merged SkCodec and SkScanlineDecoder Created 5 years, 2 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.h" 8 #include "SkCodec.h"
9 #include "SkJpegCodec.h" 9 #include "SkJpegCodec.h"
10 #include "SkJpegDecoderMgr.h" 10 #include "SkJpegDecoderMgr.h"
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 jpeg_calc_output_dimensions(fDecoderMgr->dinfo()); 295 jpeg_calc_output_dimensions(fDecoderMgr->dinfo());
296 } 296 }
297 return true; 297 return true;
298 } 298 }
299 299
300 /* 300 /*
301 * Performs the jpeg decode 301 * Performs the jpeg decode
302 */ 302 */
303 SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo, 303 SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo,
304 void* dst, size_t dstRowBytes, 304 void* dst, size_t dstRowBytes,
305 const Options& options, SkPMColor*, int *) { 305 const Options& options, SkPMColor*, int *,
306 int* rowsDecoded) {
306 if (options.fSubset) { 307 if (options.fSubset) {
307 // Subsets are not supported. 308 // Subsets are not supported.
308 return kUnimplemented; 309 return kUnimplemented;
309 } 310 }
310 311
311 // Get a pointer to the decompress info since we will use it quite frequentl y 312 // Get a pointer to the decompress info since we will use it quite frequentl y
312 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo(); 313 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();
313 314
314 // Set the jump location for libjpeg errors 315 // Set the jump location for libjpeg errors
315 if (setjmp(fDecoderMgr->getJmpBuf())) { 316 if (setjmp(fDecoderMgr->getJmpBuf())) {
(...skipping 17 matching lines...) Expand all
333 334
334 // The recommended output buffer height should always be 1 in high quality m odes. 335 // The recommended output buffer height should always be 1 in high quality m odes.
335 // If it's not, we want to know because it means our strategy is not optimal . 336 // If it's not, we want to know because it means our strategy is not optimal .
336 SkASSERT(1 == dinfo->rec_outbuf_height); 337 SkASSERT(1 == dinfo->rec_outbuf_height);
337 338
338 // Perform the decode a single row at a time 339 // Perform the decode a single row at a time
339 uint32_t dstHeight = dstInfo.height(); 340 uint32_t dstHeight = dstInfo.height();
340 JSAMPLE* dstRow = (JSAMPLE*) dst; 341 JSAMPLE* dstRow = (JSAMPLE*) dst;
341 for (uint32_t y = 0; y < dstHeight; y++) { 342 for (uint32_t y = 0; y < dstHeight; y++) {
342 // Read rows of the image 343 // Read rows of the image
343 uint32_t rowsDecoded = jpeg_read_scanlines(dinfo, &dstRow, 1); 344 uint32_t lines = jpeg_read_scanlines(dinfo, &dstRow, 1);
344 345
345 // If we cannot read enough rows, assume the input is incomplete 346 // If we cannot read enough rows, assume the input is incomplete
346 if (rowsDecoded != 1) { 347 if (lines != 1) {
347 // Fill the remainder of the image with black. This error handling 348 *rowsDecoded = y;
348 // behavior is unspecified but SkCodec consistently uses black as
349 // the fill color for opaque images. If the destination is kGray,
350 // the low 8 bits of SK_ColorBLACK will be used. Conveniently,
351 // these are zeros, which is the representation for black in kGray.
352 // If the destination is kRGB_565, the low 16 bits of SK_ColorBLACK
353 // will be used. Conveniently, these are zeros, which is the
354 // representation for black in kRGB_565.
355 SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes, dstHeight - y,
356 SK_ColorBLACK, nullptr, options.fZeroInitialized);
357 349
358 // Prevent libjpeg from failing on incomplete decode 350 // Prevent libjpeg from failing on incomplete decode
359 dinfo->output_scanline = dstHeight; 351 dinfo->output_scanline = dstHeight;
360 352
361 // Finish the decode and indicate that the input was incomplete. 353 // Finish the decode and indicate that the input was incomplete.
362 jpeg_finish_decompress(dinfo); 354 jpeg_finish_decompress(dinfo);
363 return fDecoderMgr->returnFailure("Incomplete image data", kIncomple teInput); 355 return fDecoderMgr->returnFailure("Incomplete image data", kIncomple teInput);
364 } 356 }
365 357
366 // Convert to RGBA if necessary 358 // Convert to RGBA if necessary
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 SkCodecPrintf("setjmp: Error in libjpeg finish_decompress\n"); 446 SkCodecPrintf("setjmp: Error in libjpeg finish_decompress\n");
455 return; 447 return;
456 } 448 }
457 449
458 // We may not have decoded the entire image. Prevent libjpeg-turbo from fai ling on a 450 // We may not have decoded the entire image. Prevent libjpeg-turbo from fai ling on a
459 // partial decode. 451 // partial decode.
460 fDecoderMgr->dinfo()->output_scanline = this->getInfo().height(); 452 fDecoderMgr->dinfo()->output_scanline = this->getInfo().height();
461 jpeg_finish_decompress(fDecoderMgr->dinfo()); 453 jpeg_finish_decompress(fDecoderMgr->dinfo());
462 } 454 }
463 455
464 SkCodec::Result SkJpegCodec::onGetScanlines(void* dst, int count, size_t rowByte s) { 456 uint32_t SkJpegCodec::onGetScanlines(void* dst, int count, size_t rowBytes) {
465 // Set the jump location for libjpeg errors 457 // Set the jump location for libjpeg errors
466 if (setjmp(fDecoderMgr->getJmpBuf())) { 458 if (setjmp(fDecoderMgr->getJmpBuf())) {
467 return fDecoderMgr->returnFailure("setjmp", kInvalidInput); 459 return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
468 } 460 }
469 // Read rows one at a time 461 // Read rows one at a time
470 JSAMPLE* dstRow; 462 JSAMPLE* dstRow;
471 if (fSwizzler) { 463 if (fSwizzler) {
472 // write data to storage row, then sample using swizzler 464 // write data to storage row, then sample using swizzler
473 dstRow = fSrcRow; 465 dstRow = fSrcRow;
474 } else { 466 } else {
475 // write data directly to dst 467 // write data directly to dst
476 dstRow = (JSAMPLE*) dst; 468 dstRow = (JSAMPLE*) dst;
477 } 469 }
478 470
479 for (int y = 0; y < count; y++) { 471 for (int y = 0; y < count; y++) {
480 // Read row of the image 472 // Read row of the image
481 uint32_t rowsDecoded = jpeg_read_scanlines(fDecoderMgr->dinfo(), &dstRow , 1); 473 uint32_t rowsDecoded = jpeg_read_scanlines(fDecoderMgr->dinfo(), &dstRow , 1);
482 if (rowsDecoded != 1) { 474 if (rowsDecoded != 1) {
483 SkSwizzler::Fill(dstRow, this->dstInfo(), rowBytes, count - y,
484 SK_ColorBLACK, nullptr, this->options().fZeroInitialized );
485 fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height(); 475 fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height();
486 return kIncompleteInput; 476 return y;
487 } 477 }
488 478
489 // Convert to RGBA if necessary 479 // Convert to RGBA if necessary
490 if (JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) { 480 if (JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) {
491 convert_CMYK_to_RGBA(dstRow, fDecoderMgr->dinfo()->output_width); 481 convert_CMYK_to_RGBA(dstRow, fDecoderMgr->dinfo()->output_width);
492 } 482 }
493 483
494 if(fSwizzler) { 484 if(fSwizzler) {
495 // use swizzler to sample row 485 // use swizzler to sample row
496 fSwizzler->swizzle(dst, dstRow); 486 fSwizzler->swizzle(dst, dstRow);
497 dst = SkTAddOffset<JSAMPLE>(dst, rowBytes); 487 dst = SkTAddOffset<JSAMPLE>(dst, rowBytes);
498 } else { 488 } else {
499 dstRow = SkTAddOffset<JSAMPLE>(dstRow, rowBytes); 489 dstRow = SkTAddOffset<JSAMPLE>(dstRow, rowBytes);
500 } 490 }
501 } 491 }
502 return kSuccess; 492 return count;
503 } 493 }
504 494
505 #ifndef TURBO_HAS_SKIP 495 #ifndef TURBO_HAS_SKIP
506 // TODO (msarett): Make this a member function and avoid reallocating the 496 // TODO (msarett): Make this a member function and avoid reallocating the
507 // memory buffer on each call to skip. 497 // memory buffer on each call to skip.
508 #define jpeg_skip_scanlines(dinfo, count) \ 498 #define jpeg_skip_scanlines(dinfo, count) \
509 SkAutoMalloc storage(get_row_bytes(dinfo)); \ 499 SkAutoMalloc storage(get_row_bytes(dinfo)); \
510 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); \ 500 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); \
511 for (int y = 0; y < count; y++) { \ 501 for (int y = 0; y < count; y++) { \
512 jpeg_read_scanlines(dinfo, &storagePtr, 1); \ 502 jpeg_read_scanlines(dinfo, &storagePtr, 1); \
513 } 503 }
514 #endif 504 #endif
515 505
516 SkCodec::Result SkJpegCodec::onSkipScanlines(int count) { 506 bool SkJpegCodec::onSkipScanlines(int count) {
517 // Set the jump location for libjpeg errors 507 // Set the jump location for libjpeg errors
518 if (setjmp(fDecoderMgr->getJmpBuf())) { 508 if (setjmp(fDecoderMgr->getJmpBuf())) {
519 return fDecoderMgr->returnFailure("setjmp", kInvalidInput); 509 return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
520 } 510 }
521 511
522 jpeg_skip_scanlines(fDecoderMgr->dinfo(), count); 512 return count == jpeg_skip_scanlines(fDecoderMgr->dinfo(), count);
523
524 return kSuccess;
525 } 513 }
526
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698