OLD | NEW |
---|---|
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 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
347 // Read rows of the image | 347 // Read rows of the image |
348 uint32_t rowsDecoded = turbo_jpeg_read_scanlines(dinfo, &dstRow, 1); | 348 uint32_t rowsDecoded = turbo_jpeg_read_scanlines(dinfo, &dstRow, 1); |
349 | 349 |
350 // If we cannot read enough rows, assume the input is incomplete | 350 // If we cannot read enough rows, assume the input is incomplete |
351 if (rowsDecoded != 1) { | 351 if (rowsDecoded != 1) { |
352 // Fill the remainder of the image with black. This error handling | 352 // Fill the remainder of the image with black. This error handling |
353 // behavior is unspecified but SkCodec consistently uses black as | 353 // behavior is unspecified but SkCodec consistently uses black as |
354 // the fill color for opaque images. If the destination is kGray, | 354 // the fill color for opaque images. If the destination is kGray, |
355 // the low 8 bits of SK_ColorBLACK will be used. Conveniently, | 355 // the low 8 bits of SK_ColorBLACK will be used. Conveniently, |
356 // these are zeros, which is the representation for black in kGray. | 356 // these are zeros, which is the representation for black in kGray. |
357 SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes, dstHeight - y, SK_Col orBLACK, NULL); | 357 // If the destination is kRGB_565, the low 16 bits of SK_ColorBLACK |
358 // will be used. Conveniently, these are zeros, which is the | |
359 // representation for black in kRGB_565. | |
360 if (kNo_ZeroInitialized == options.fZeroInitialized || | |
361 kN32_SkColorType == dstInfo.colorType()) { | |
362 SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes, dstHeight - y, | |
363 SK_ColorBLACK, NULL); | |
364 } | |
358 | 365 |
359 // Prevent libjpeg from failing on incomplete decode | 366 // Prevent libjpeg from failing on incomplete decode |
360 dinfo->output_scanline = dstHeight; | 367 dinfo->output_scanline = dstHeight; |
361 | 368 |
362 // Finish the decode and indicate that the input was incomplete. | 369 // Finish the decode and indicate that the input was incomplete. |
363 turbo_jpeg_finish_decompress(dinfo); | 370 turbo_jpeg_finish_decompress(dinfo); |
364 return fDecoderMgr->returnFailure("Incomplete image data", kIncomple teInput); | 371 return fDecoderMgr->returnFailure("Incomplete image data", kIncomple teInput); |
365 } | 372 } |
366 | 373 |
367 // Convert to RGBA if necessary | 374 // Convert to RGBA if necessary |
368 if (JCS_CMYK == dinfo->out_color_space) { | 375 if (JCS_CMYK == dinfo->out_color_space) { |
369 convert_CMYK_to_RGBA(dstRow, dstInfo.width()); | 376 convert_CMYK_to_RGBA(dstRow, dstInfo.width()); |
370 } | 377 } |
371 | 378 |
372 // Move to the next row | 379 // Move to the next row |
373 dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes); | 380 dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes); |
374 } | 381 } |
375 turbo_jpeg_finish_decompress(dinfo); | 382 turbo_jpeg_finish_decompress(dinfo); |
376 | 383 |
377 return kSuccess; | 384 return kSuccess; |
378 } | 385 } |
379 | 386 |
380 /* | 387 /* |
381 * Enable scanline decoding for jpegs | 388 * Enable scanline decoding for jpegs |
382 */ | 389 */ |
383 class SkJpegScanlineDecoder : public SkScanlineDecoder { | 390 class SkJpegScanlineDecoder : public SkScanlineDecoder { |
384 public: | 391 public: |
385 SkJpegScanlineDecoder(const SkImageInfo& dstInfo, SkJpegCodec* codec) | 392 SkJpegScanlineDecoder(const SkImageInfo& dstInfo, SkJpegCodec* codec, |
393 const SkCodec::Options& opts) | |
386 : INHERITED(dstInfo) | 394 : INHERITED(dstInfo) |
387 , fCodec(codec) | 395 , fCodec(codec) |
396 , fOpts(opts) | |
388 {} | 397 {} |
389 | 398 |
390 virtual ~SkJpegScanlineDecoder() { | 399 virtual ~SkJpegScanlineDecoder() { |
391 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) { | 400 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) { |
392 SkCodecPrintf("setjmp: Error in libjpeg finish_decompress\n"); | 401 SkCodecPrintf("setjmp: Error in libjpeg finish_decompress\n"); |
393 return; | 402 return; |
394 } | 403 } |
395 | 404 |
396 // We may not have decoded the entire image. Prevent libjpeg-turbo from failing on a | 405 // We may not have decoded the entire image. Prevent libjpeg-turbo from failing on a |
397 // partial decode. | 406 // partial decode. |
398 fCodec->fDecoderMgr->dinfo()->output_scanline = fCodec->getInfo().height (); | 407 fCodec->fDecoderMgr->dinfo()->output_scanline = fCodec->getInfo().height (); |
399 turbo_jpeg_finish_decompress(fCodec->fDecoderMgr->dinfo()); | 408 turbo_jpeg_finish_decompress(fCodec->fDecoderMgr->dinfo()); |
400 } | 409 } |
401 | 410 |
402 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri de { | 411 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri de { |
403 // Set the jump location for libjpeg errors | 412 // Set the jump location for libjpeg errors |
404 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) { | 413 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) { |
405 return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvali dInput); | 414 return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvali dInput); |
406 } | 415 } |
407 | 416 |
408 // Read rows one at a time | 417 // Read rows one at a time |
409 JSAMPLE* dstRow = (JSAMPLE*) dst; | 418 JSAMPLE* dstRow = (JSAMPLE*) dst; |
410 for (int y = 0; y < count; y++) { | 419 for (int y = 0; y < count; y++) { |
411 // Read row of the image | 420 // Read row of the image |
412 uint32_t rowsDecoded = | 421 uint32_t rowsDecoded = |
413 turbo_jpeg_read_scanlines(fCodec->fDecoderMgr->dinfo(), &dst Row, 1); | 422 turbo_jpeg_read_scanlines(fCodec->fDecoderMgr->dinfo(), &dst Row, 1); |
414 if (rowsDecoded != 1) { | 423 if (rowsDecoded != 1) { |
415 SkSwizzler::Fill( | 424 if (SkCodec::kNo_ZeroInitialized == fOpts.fZeroInitialized || |
416 dstRow, this->dstInfo(), rowBytes, count - y, SK_ColorBL ACK, NULL); | 425 kN32_SkColorType == this->dstInfo().colorType()) { |
426 SkSwizzler::Fill(dstRow, this->dstInfo(), rowBytes, | |
427 count - y, SK_ColorBLACK, NULL); | |
428 } | |
417 fCodec->fDecoderMgr->dinfo()->output_scanline = this->dstInfo(). height(); | 429 fCodec->fDecoderMgr->dinfo()->output_scanline = this->dstInfo(). height(); |
418 return SkCodec::kIncompleteInput; | 430 return SkCodec::kIncompleteInput; |
419 } | 431 } |
420 | 432 |
421 // Convert to RGBA if necessary | 433 // Convert to RGBA if necessary |
422 if (JCS_CMYK == fCodec->fDecoderMgr->dinfo()->out_color_space) { | 434 if (JCS_CMYK == fCodec->fDecoderMgr->dinfo()->out_color_space) { |
423 convert_CMYK_to_RGBA(dstRow, this->dstInfo().width()); | 435 convert_CMYK_to_RGBA(dstRow, this->dstInfo().width()); |
424 } | 436 } |
425 | 437 |
426 // Move to the next row | 438 // Move to the next row |
(...skipping 18 matching lines...) Expand all Loading... | |
445 return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvali dInput); | 457 return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvali dInput); |
446 } | 458 } |
447 | 459 |
448 turbo_jpeg_skip_scanlines(fCodec->fDecoderMgr->dinfo(), count); | 460 turbo_jpeg_skip_scanlines(fCodec->fDecoderMgr->dinfo(), count); |
449 | 461 |
450 return SkCodec::kSuccess; | 462 return SkCodec::kSuccess; |
451 } | 463 } |
452 | 464 |
453 private: | 465 private: |
454 SkAutoTDelete<SkJpegCodec> fCodec; | 466 SkAutoTDelete<SkJpegCodec> fCodec; |
467 const SkCodec::Options& fOpts; | |
scroggo
2015/08/03 18:41:24
I missed this when I first reviewed, but mention i
| |
455 | 468 |
456 typedef SkScanlineDecoder INHERITED; | 469 typedef SkScanlineDecoder INHERITED; |
457 }; | 470 }; |
458 | 471 |
459 SkScanlineDecoder* SkJpegCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo, | 472 SkScanlineDecoder* SkJpegCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo, |
460 const Options& options, SkPMColor ctable[], int* ctableCount) { | 473 const Options& options, SkPMColor ctable[], int* ctableCount) { |
461 | 474 |
462 // Rewind the stream if needed | 475 // Rewind the stream if needed |
463 if (!this->handleRewind()) { | 476 if (!this->handleRewind()) { |
464 SkCodecPrintf("Could not rewind\n"); | 477 SkCodecPrintf("Could not rewind\n"); |
(...skipping 27 matching lines...) Expand all Loading... | |
492 return NULL; | 505 return NULL; |
493 } | 506 } |
494 | 507 |
495 // Now, given valid output dimensions, we can start the decompress | 508 // Now, given valid output dimensions, we can start the decompress |
496 if (!turbo_jpeg_start_decompress(codec->fDecoderMgr->dinfo())) { | 509 if (!turbo_jpeg_start_decompress(codec->fDecoderMgr->dinfo())) { |
497 SkCodecPrintf("start decompress failed\n"); | 510 SkCodecPrintf("start decompress failed\n"); |
498 return NULL; | 511 return NULL; |
499 } | 512 } |
500 | 513 |
501 // Return the new scanline decoder | 514 // Return the new scanline decoder |
502 return SkNEW_ARGS(SkJpegScanlineDecoder, (dstInfo, codec.detach())); | 515 return SkNEW_ARGS(SkJpegScanlineDecoder, (dstInfo, codec.detach(), options)) ; |
503 } | 516 } |
OLD | NEW |