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 "SkMSAN.h" | 9 #include "SkMSAN.h" |
10 #include "SkJpegCodec.h" | 10 #include "SkJpegCodec.h" |
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 return count; | 528 return count; |
529 } | 529 } |
530 | 530 |
531 /* | 531 /* |
532 * Performs the jpeg decode | 532 * Performs the jpeg decode |
533 */ | 533 */ |
534 SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo, | 534 SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo, |
535 void* dst, size_t dstRowBytes, | 535 void* dst, size_t dstRowBytes, |
536 const Options& options, SkPMColor*, int
*, | 536 const Options& options, SkPMColor*, int
*, |
537 int* rowsDecoded) { | 537 int* rowsDecoded) { |
538 if (options.fSubset) { | 538 /* if (options.fSubset) { |
539 // Subsets are not supported. | 539 // Subsets are not supported. |
540 return kUnimplemented; | 540 return kUnimplemented; |
541 } | 541 } |
542 | 542 |
543 // Get a pointer to the decompress info since we will use it quite frequentl
y | 543 // Get a pointer to the decompress info since we will use it quite frequentl
y |
544 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo(); | 544 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo(); |
545 | 545 |
546 // Set the jump location for libjpeg errors | 546 // Set the jump location for libjpeg errors |
547 if (setjmp(fDecoderMgr->getJmpBuf())) { | 547 if (setjmp(fDecoderMgr->getJmpBuf())) { |
548 return fDecoderMgr->returnFailure("setjmp", kInvalidInput); | 548 return fDecoderMgr->returnFailure("setjmp", kInvalidInput); |
(...skipping 21 matching lines...) Expand all Loading... |
570 | 570 |
571 this->allocateStorage(dstInfo); | 571 this->allocateStorage(dstInfo); |
572 | 572 |
573 int rows = this->readRows(dstInfo, dst, dstRowBytes, dstInfo.height()); | 573 int rows = this->readRows(dstInfo, dst, dstRowBytes, dstInfo.height()); |
574 if (rows < dstInfo.height()) { | 574 if (rows < dstInfo.height()) { |
575 *rowsDecoded = rows; | 575 *rowsDecoded = rows; |
576 return fDecoderMgr->returnFailure("Incomplete image data", kIncompleteIn
put); | 576 return fDecoderMgr->returnFailure("Incomplete image data", kIncompleteIn
put); |
577 } | 577 } |
578 | 578 |
579 return kSuccess; | 579 return kSuccess; |
| 580 */ |
| 581 |
| 582 this->initializeColorXform(dstInfo); |
| 583 |
| 584 // This will check is_yuv_supported(), so we don't need to here. |
| 585 SkYUVSizeInfo yuvInfo; |
| 586 if (!this->onQueryYUV8(&yuvInfo, nullptr)) { |
| 587 return fDecoderMgr->returnFailure("onQueryYUV8", kInvalidInput); |
| 588 } |
| 589 |
| 590 // Set the jump location for libjpeg errors |
| 591 if (setjmp(fDecoderMgr->getJmpBuf())) { |
| 592 return fDecoderMgr->returnFailure("setjmp", kInvalidInput); |
| 593 } |
| 594 |
| 595 // Get a pointer to the decompress info since we will use it quite frequentl
y |
| 596 jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo(); |
| 597 |
| 598 dinfo->raw_data_out = TRUE; |
| 599 if (!jpeg_start_decompress(dinfo)) { |
| 600 return fDecoderMgr->returnFailure("startDecompress", kInvalidInput); |
| 601 } |
| 602 |
| 603 // Currently, we require that the Y plane dimensions match the image dimensi
ons |
| 604 // and that the U and V planes are the same dimensions. |
| 605 SkASSERT(yuvInfo.fSizes[SkYUVSizeInfo::kU] == yuvInfo.fSizes[SkYUVSizeInfo::
kV]); |
| 606 SkASSERT((uint32_t) yuvInfo.fSizes[SkYUVSizeInfo::kY].width() == dinfo->outp
ut_width && |
| 607 (uint32_t) yuvInfo.fSizes[SkYUVSizeInfo::kY].height() == dinfo->outp
ut_height); |
| 608 |
| 609 // Build a JSAMPIMAGE to handle output from libjpeg-turbo. A JSAMPIMAGE has |
| 610 // a 2-D array of pixels for each of the components (Y, U, V) in the image. |
| 611 // Cheat Sheet: |
| 612 // JSAMPIMAGE == JSAMPLEARRAY* == JSAMPROW** == JSAMPLE*** |
| 613 JSAMPARRAY yuv[3]; |
| 614 |
| 615 // Set aside enough space for pointers to rows of Y, U, and V. |
| 616 JSAMPROW rowptrs[2 * DCTSIZE + DCTSIZE + DCTSIZE]; |
| 617 yuv[0] = &rowptrs[0]; // Y rows (DCTSIZE or 2 * DCTSIZE) |
| 618 yuv[1] = &rowptrs[1 /******/* DCTSIZE]; // U rows (DCTSIZE) |
| 619 yuv[2] = &rowptrs[2 /*******/* DCTSIZE]; // V rows (DCTSIZE) |
| 620 |
| 621 // Initialize rowptrs. |
| 622 SkASSERT(yuvInfo.fWidthBytes[0] == yuvInfo.fWidthBytes[1] && yuvInfo.fWidthB
ytes[0] == yuvInfo.fWidthBytes[2]); |
| 623 SkAutoTMalloc<uint8_t> storage(3 * DCTSIZE * yuvInfo.fWidthBytes[0]); |
| 624 int numYRowsPerBlock = DCTSIZE * dinfo->comp_info[0].v_samp_factor; |
| 625 SkASSERT(DCTSIZE == numYRowsPerBlock); |
| 626 JSAMPLE* storagePtr = (JSAMPLE*) storage.get(); |
| 627 for (int i = 0; i < numYRowsPerBlock; i++) { |
| 628 rowptrs[i] = storagePtr; |
| 629 storagePtr += yuvInfo.fWidthBytes[0]; |
| 630 } |
| 631 for (int i = 0; i < numYRowsPerBlock; i++) { |
| 632 rowptrs[DCTSIZE + i] = storagePtr; |
| 633 storagePtr += yuvInfo.fWidthBytes[0]; |
| 634 } |
| 635 for (int i = 0; i < numYRowsPerBlock; i++) { |
| 636 rowptrs[DCTSIZE + DCTSIZE + i] = storagePtr; |
| 637 storagePtr += yuvInfo.fWidthBytes[0]; |
| 638 } |
| 639 |
| 640 uint32_t numRowsPerBlock = numYRowsPerBlock; |
| 641 |
| 642 // We intentionally round down here, as this first loop will only handle |
| 643 // full block rows. As a special case at the end, we will handle any |
| 644 // remaining rows that do not make up a full block. |
| 645 const int numIters = dinfo->output_height / numRowsPerBlock; |
| 646 for (int i = 0; i < numIters; i++) { |
| 647 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock); |
| 648 if (linesRead < numRowsPerBlock) { |
| 649 // FIXME: Handle incomplete YUV decodes without signalling an error. |
| 650 return kInvalidInput; |
| 651 } |
| 652 |
| 653 for (uint32_t j = 0; j < DCTSIZE; j++) { |
| 654 fColorXform->applyYUV(dst, yuv[0][j], yuv[1][j], yuv[2][j], dstInfo.
width()); |
| 655 dst = SkTAddOffset<void>(dst, dstRowBytes); |
| 656 } |
| 657 } |
| 658 |
| 659 uint32_t remainingRows = dinfo->output_height - dinfo->output_scanline; |
| 660 SkASSERT(remainingRows == dinfo->output_height % numRowsPerBlock); |
| 661 SkASSERT(dinfo->output_scanline == numIters * numRowsPerBlock); |
| 662 if (remainingRows > 0) { |
| 663 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock); |
| 664 if (linesRead < remainingRows) { |
| 665 // FIXME: Handle incomplete YUV decodes without signalling an error. |
| 666 return kInvalidInput; |
| 667 } |
| 668 |
| 669 for (uint32_t j = 0; j < remainingRows; j++) { |
| 670 fColorXform->applyYUV(dst, yuv[0][j], yuv[1][j], yuv[2][j], dstInfo.
width()); |
| 671 dst = SkTAddOffset<void>(dst, dstRowBytes); |
| 672 } |
| 673 } |
| 674 |
| 675 return kSuccess; |
580 } | 676 } |
581 | 677 |
582 void SkJpegCodec::allocateStorage(const SkImageInfo& dstInfo) { | 678 void SkJpegCodec::allocateStorage(const SkImageInfo& dstInfo) { |
583 int dstWidth = dstInfo.width(); | 679 int dstWidth = dstInfo.width(); |
584 | 680 |
585 size_t swizzleBytes = 0; | 681 size_t swizzleBytes = 0; |
586 if (fSwizzler) { | 682 if (fSwizzler) { |
587 swizzleBytes = get_row_bytes(fDecoderMgr->dinfo()); | 683 swizzleBytes = get_row_bytes(fDecoderMgr->dinfo()); |
588 dstWidth = fSwizzler->swizzleWidth(); | 684 dstWidth = fSwizzler->swizzleWidth(); |
589 SkASSERT(!fColorXform || SkIsAlign4(swizzleBytes)); | 685 SkASSERT(!fColorXform || SkIsAlign4(swizzleBytes)); |
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
925 | 1021 |
926 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock); | 1022 JDIMENSION linesRead = jpeg_read_raw_data(dinfo, yuv, numRowsPerBlock); |
927 if (linesRead < remainingRows) { | 1023 if (linesRead < remainingRows) { |
928 // FIXME: Handle incomplete YUV decodes without signalling an error. | 1024 // FIXME: Handle incomplete YUV decodes without signalling an error. |
929 return kInvalidInput; | 1025 return kInvalidInput; |
930 } | 1026 } |
931 } | 1027 } |
932 | 1028 |
933 return kSuccess; | 1029 return kSuccess; |
934 } | 1030 } |
OLD | NEW |