| 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 |