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

Side by Side Diff: src/images/SkImageDecoder_libjpeg.cpp

Issue 399683007: JPEG YUV Decoding (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 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
OLDNEW
1 /* 1 /*
2 * Copyright 2007 The Android Open Source Project 2 * Copyright 2007 The Android Open Source Project
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 8
9 #include "SkImageDecoder.h" 9 #include "SkImageDecoder.h"
10 #include "SkImageEncoder.h" 10 #include "SkImageEncoder.h"
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 } 95 }
96 /* To suppress error messages with a SK_DEBUG binary, set the 96 /* To suppress error messages with a SK_DEBUG binary, set the
97 * environment variable "skia_images_jpeg_suppressDecoderErrors" 97 * environment variable "skia_images_jpeg_suppressDecoderErrors"
98 * to "true". Inside a program that links to skia: 98 * to "true". Inside a program that links to skia:
99 * SK_CONF_SET("images.jpeg.suppressDecoderErrors", true); */ 99 * SK_CONF_SET("images.jpeg.suppressDecoderErrors", true); */
100 if (c_suppressJPEGImageDecoderErrors) { 100 if (c_suppressJPEGImageDecoderErrors) {
101 cinfo->err->output_message = &do_nothing_output_message; 101 cinfo->err->output_message = &do_nothing_output_message;
102 } 102 }
103 } 103 }
104 104
105 static void compute_uv_size(const jpeg_decompress_struct& info, int& width, int& height)
106 {
107 int h = info.cur_comp_info[0]->h_samp_factor;
108 int v = info.cur_comp_info[0]->v_samp_factor;
109 width = (info.output_width + h - 1) / h;
110 height = (info.output_height + v - 1) / v;
111 }
112
105 #ifdef SK_BUILD_FOR_ANDROID 113 #ifdef SK_BUILD_FOR_ANDROID
106 class SkJPEGImageIndex { 114 class SkJPEGImageIndex {
107 public: 115 public:
108 SkJPEGImageIndex(SkStreamRewindable* stream, SkImageDecoder* decoder) 116 SkJPEGImageIndex(SkStreamRewindable* stream, SkImageDecoder* decoder)
109 : fSrcMgr(stream, decoder) 117 : fSrcMgr(stream, decoder)
110 , fInfoInitialized(false) 118 , fInfoInitialized(false)
111 , fHuffmanCreated(false) 119 , fHuffmanCreated(false)
112 , fDecompressStarted(false) 120 , fDecompressStarted(false)
113 { 121 {
114 SkDEBUGCODE(fReadHeaderSucceeded = false;) 122 SkDEBUGCODE(fReadHeaderSucceeded = false;)
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 huffman_index fHuffmanIndex; 218 huffman_index fHuffmanIndex;
211 bool fInfoInitialized; 219 bool fInfoInitialized;
212 bool fHuffmanCreated; 220 bool fHuffmanCreated;
213 bool fDecompressStarted; 221 bool fDecompressStarted;
214 SkDEBUGCODE(bool fReadHeaderSucceeded;) 222 SkDEBUGCODE(bool fReadHeaderSucceeded;)
215 }; 223 };
216 #endif 224 #endif
217 225
218 class SkJPEGImageDecoder : public SkImageDecoder { 226 class SkJPEGImageDecoder : public SkImageDecoder {
219 public: 227 public:
228 SkJPEGImageDecoder() {
220 #ifdef SK_BUILD_FOR_ANDROID 229 #ifdef SK_BUILD_FOR_ANDROID
221 SkJPEGImageDecoder() {
222 fImageIndex = NULL; 230 fImageIndex = NULL;
223 fImageWidth = 0; 231 fImageWidth = 0;
224 fImageHeight = 0; 232 fImageHeight = 0;
233 #endif
234 fYUVBuffers[0] = fYUVBuffers[1] = fYUVBuffers[2] = NULL;
235 fRowBytes[0] = fRowBytes[1] = fRowBytes[2] = 0;
225 } 236 }
226 237
238 #ifdef SK_BUILD_FOR_ANDROID
227 virtual ~SkJPEGImageDecoder() { 239 virtual ~SkJPEGImageDecoder() {
228 SkDELETE(fImageIndex); 240 SkDELETE(fImageIndex);
229 } 241 }
230 #endif 242 #endif
231 243
232 virtual Format getFormat() const { 244 virtual Format getFormat() const {
233 return kJPEG_Format; 245 return kJPEG_Format;
234 } 246 }
235 247
236 protected: 248 protected:
237 #ifdef SK_BUILD_FOR_ANDROID 249 #ifdef SK_BUILD_FOR_ANDROID
238 virtual bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *h eight) SK_OVERRIDE; 250 virtual bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *h eight) SK_OVERRIDE;
239 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRI DE; 251 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRI DE;
240 #endif 252 #endif
241 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; 253 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE;
254 virtual void onSetYUVBuffers(void* yuv[3], size_t rowBytes[3]) SK_OVERRIDE;
255 virtual bool onGetComponentSizes(SkStream* stream, SkISize sizes[3]) SK_OVER RIDE;
242 256
243 private: 257 private:
244 #ifdef SK_BUILD_FOR_ANDROID 258 #ifdef SK_BUILD_FOR_ANDROID
245 SkJPEGImageIndex* fImageIndex; 259 SkJPEGImageIndex* fImageIndex;
246 int fImageWidth; 260 int fImageWidth;
247 int fImageHeight; 261 int fImageHeight;
248 #endif 262 #endif
263 uint8_t* fYUVBuffers[3];
264 size_t fRowBytes[3];
265
266 bool isSupportedYUVFormat(jpeg_decompress_struct& cinfo) const {
267 if ((cinfo.jpeg_color_space == JCS_YCbCr) &&
268 (cinfo.num_components == 3) &&
269 (cinfo.scale_denom <= 8) &&
270 (cinfo.cur_comp_info[1]->h_samp_factor == 1) &&
271 (cinfo.cur_comp_info[1]->v_samp_factor == 1) &&
272 (cinfo.cur_comp_info[2]->h_samp_factor == 1) &&
273 (cinfo.cur_comp_info[2]->v_samp_factor == 1)) {
274 int h = cinfo.cur_comp_info[0]->h_samp_factor;
275 int v = cinfo.cur_comp_info[0]->v_samp_factor;
276 if (((h == 1) || (h == 2) || (h == 4)) &&
277 ((v == 1) || (v == 2))) {
278 cinfo.out_color_space = JCS_YCbCr;
279 cinfo.raw_data_out = TRUE;
280
281 #ifdef SK_PRINT_YUV_FORMAT
282 SkDebugf("YUV 4:%d:%d\n", 4 / h, (v == 1) ? 4 / h : 0);
283 #endif
284 return true;
285 }
286 }
287 return false;
288 }
289
290 bool canDecodeToYUV(jpeg_decompress_struct& cinfo) const {
291 return ((NULL != fYUVBuffers[0]) &&
292 (NULL != fYUVBuffers[1]) &&
293 (NULL != fYUVBuffers[2]) &&
294 (fRowBytes[0] > 0) &&
295 (fRowBytes[1] > 0) &&
296 (fRowBytes[2] > 0) &&
297 isSupportedYUVFormat(cinfo));
298 }
249 299
250 /** 300 /**
251 * Determine the appropriate bitmap colortype and out_color_space based on 301 * Determine the appropriate bitmap colortype and out_color_space based on
252 * both the preference of the caller and the jpeg_color_space on the 302 * both the preference of the caller and the jpeg_color_space on the
253 * jpeg_decompress_struct passed in. 303 * jpeg_decompress_struct passed in.
254 * Must be called after jpeg_read_header. 304 * Must be called after jpeg_read_header.
255 */ 305 */
256 SkColorType getBitmapColorType(jpeg_decompress_struct*); 306 SkColorType getBitmapColorType(jpeg_decompress_struct*);
257 307
308 bool decodeToBitmap(SkBitmap* bm,
309 jpeg_decompress_struct& cinfo,
310 SkScaledBitmapSampler& sampler);
311 bool decodeToYUV(jpeg_decompress_struct& cinfo);
312
258 typedef SkImageDecoder INHERITED; 313 typedef SkImageDecoder INHERITED;
259 }; 314 };
260 315
261 ////////////////////////////////////////////////////////////////////////// 316 //////////////////////////////////////////////////////////////////////////
262 317
263 /* Automatically clean up after throwing an exception */ 318 /* Automatically clean up after throwing an exception */
264 class JPEGAutoClean { 319 class JPEGAutoClean {
265 public: 320 public:
266 JPEGAutoClean(): cinfo_ptr(NULL) {} 321 JPEGAutoClean(): cinfo_ptr(NULL) {}
267 ~JPEGAutoClean() { 322 ~JPEGAutoClean() {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 return false; 373 return false;
319 } 374 }
320 } 375 }
321 return true; 376 return true;
322 } 377 }
323 #endif 378 #endif
324 379
325 // This guy exists just to aid in debugging, as it allows debuggers to just 380 // This guy exists just to aid in debugging, as it allows debuggers to just
326 // set a break-point in one place to see all error exists. 381 // set a break-point in one place to see all error exists.
327 static bool return_false(const jpeg_decompress_struct& cinfo, 382 static bool return_false(const jpeg_decompress_struct& cinfo,
328 const SkBitmap& bm, const char caller[]) { 383 const SkBitmap* bm, const char caller[]) {
329 if (!(c_suppressJPEGImageDecoderErrors)) { 384 if (!(c_suppressJPEGImageDecoderErrors)) {
330 char buffer[JMSG_LENGTH_MAX]; 385 char buffer[JMSG_LENGTH_MAX];
331 cinfo.err->format_message((const j_common_ptr)&cinfo, buffer); 386 cinfo.err->format_message((const j_common_ptr)&cinfo, buffer);
332 SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n", 387 SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n",
333 cinfo.err->msg_code, buffer, caller, bm.width(), bm.height()); 388 cinfo.err->msg_code, buffer, caller,
389 (NULL != bm) ? bm->width() : 0,
390 (NULL != bm) ? bm->height() : 0);
334 } 391 }
335 return false; // must always return false 392 return false; // must always return false
336 } 393 }
337 394
338 // Convert a scanline of CMYK samples to RGBX in place. Note that this 395 // Convert a scanline of CMYK samples to RGBX in place. Note that this
339 // method moves the "scanline" pointer in its processing 396 // method moves the "scanline" pointer in its processing
340 static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) { 397 static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) {
341 // At this point we've received CMYK pixels from libjpeg. We 398 // At this point we've received CMYK pixels from libjpeg. We
342 // perform a crude conversion to RGB (based on the formulae 399 // perform a crude conversion to RGB (based on the formulae
343 // from easyrgb.com): 400 // from easyrgb.com):
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 595
539 jpeg_decompress_struct cinfo; 596 jpeg_decompress_struct cinfo;
540 skjpeg_source_mgr srcManager(stream, this); 597 skjpeg_source_mgr srcManager(stream, this);
541 598
542 skjpeg_error_mgr errorManager; 599 skjpeg_error_mgr errorManager;
543 set_error_mgr(&cinfo, &errorManager); 600 set_error_mgr(&cinfo, &errorManager);
544 601
545 // All objects need to be instantiated before this setjmp call so that 602 // All objects need to be instantiated before this setjmp call so that
546 // they will be cleaned up properly if an error occurs. 603 // they will be cleaned up properly if an error occurs.
547 if (setjmp(errorManager.fJmpBuf)) { 604 if (setjmp(errorManager.fJmpBuf)) {
548 return return_false(cinfo, *bm, "setjmp"); 605 return return_false(cinfo, bm, "setjmp");
549 } 606 }
550 607
551 initialize_info(&cinfo, &srcManager); 608 initialize_info(&cinfo, &srcManager);
552 autoClean.set(&cinfo); 609 autoClean.set(&cinfo);
553 610
554 int status = jpeg_read_header(&cinfo, true); 611 int status = jpeg_read_header(&cinfo, true);
555 if (status != JPEG_HEADER_OK) { 612 if (status != JPEG_HEADER_OK) {
556 return return_false(cinfo, *bm, "read_header"); 613 return return_false(cinfo, bm, "read_header");
557 } 614 }
558 615
559 /* Try to fulfill the requested sampleSize. Since jpeg can do it (when it 616 /* Try to fulfill the requested sampleSize. Since jpeg can do it (when it
560 can) much faster that we, just use their num/denom api to approximate 617 can) much faster that we, just use their num/denom api to approximate
561 the size. 618 the size.
562 */ 619 */
563 int sampleSize = this->getSampleSize(); 620 int sampleSize = this->getSampleSize();
564 621
565 set_dct_method(*this, &cinfo); 622 set_dct_method(*this, &cinfo);
566 623
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimension s(cinfo)) { 658 if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimension s(cinfo)) {
602 SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height, 659 SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height,
603 recompute_sampleSize(sampleSize, cinfo)); 660 recompute_sampleSize(sampleSize, cinfo));
604 // Assume an A8 bitmap is not opaque to avoid the check of each 661 // Assume an A8 bitmap is not opaque to avoid the check of each
605 // individual pixel. It is very unlikely to be opaque, since 662 // individual pixel. It is very unlikely to be opaque, since
606 // an opaque A8 bitmap would not be very interesting. 663 // an opaque A8 bitmap would not be very interesting.
607 // Otherwise, a jpeg image is opaque. 664 // Otherwise, a jpeg image is opaque.
608 return bm->setInfo(SkImageInfo::Make(smpl.scaledWidth(), smpl.scaled Height(), 665 return bm->setInfo(SkImageInfo::Make(smpl.scaledWidth(), smpl.scaled Height(),
609 colorType, alphaType)); 666 colorType, alphaType));
610 } else { 667 } else {
611 return return_false(cinfo, *bm, "start_decompress"); 668 return return_false(cinfo, bm, "start_decompress");
612 } 669 }
613 } 670 }
614 sampleSize = recompute_sampleSize(sampleSize, cinfo); 671 sampleSize = recompute_sampleSize(sampleSize, cinfo);
615 672
616 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER 673 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
617 // should we allow the Chooser (if present) to pick a colortype for us??? 674 // should we allow the Chooser (if present) to pick a colortype for us???
618 if (!this->chooseFromOneChoice(colorType, cinfo.output_width, cinfo.output_h eight)) { 675 if (!this->chooseFromOneChoice(colorType, cinfo.output_width, cinfo.output_h eight)) {
619 return return_false(cinfo, *bm, "chooseFromOneChoice"); 676 return return_false(cinfo, bm, "chooseFromOneChoice");
620 } 677 }
621 #endif 678 #endif
622 679
623 SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampl eSize); 680 SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampl eSize);
624 // Assume an A8 bitmap is not opaque to avoid the check of each 681 // Assume an A8 bitmap is not opaque to avoid the check of each
625 // individual pixel. It is very unlikely to be opaque, since 682 // individual pixel. It is very unlikely to be opaque, since
626 // an opaque A8 bitmap would not be very interesting. 683 // an opaque A8 bitmap would not be very interesting.
627 // Otherwise, a jpeg image is opaque. 684 // Otherwise, a jpeg image is opaque.
628 bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(), 685 bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(),
629 colorType, alphaType)); 686 colorType, alphaType));
630 if (SkImageDecoder::kDecodeBounds_Mode == mode) { 687 if (SkImageDecoder::kDecodeBounds_Mode == mode) {
631 return true; 688 return true;
632 } 689 }
690
691 return canDecodeToYUV(cinfo) ? decodeToYUV(cinfo) : decodeToBitmap(bm, cinfo , sampler);
692 }
693
694 bool SkJPEGImageDecoder::decodeToBitmap(SkBitmap* bm,
695 jpeg_decompress_struct& cinfo,
696 SkScaledBitmapSampler& sampler) {
633 if (!this->allocPixelRef(bm, NULL)) { 697 if (!this->allocPixelRef(bm, NULL)) {
634 return return_false(cinfo, *bm, "allocPixelRef"); 698 return return_false(cinfo, bm, "allocPixelRef");
635 } 699 }
636 700
637 SkAutoLockPixels alp(*bm); 701 SkAutoLockPixels alp(*bm);
638 702
639 #ifdef ANDROID_RGB 703 #ifdef ANDROID_RGB
640 /* short-circuit the SkScaledBitmapSampler when possible, as this gives 704 /* short-circuit the SkScaledBitmapSampler when possible, as this gives
641 a significant performance boost. 705 a significant performance boost.
642 */ 706 */
643 if (sampleSize == 1 && 707 if (sampleSize == 1 &&
644 ((kN32_SkColorType == colorType && cinfo.out_color_space == JCS_RGBA_888 8) || 708 ((kN32_SkColorType == colorType && cinfo.out_color_space == JCS_RGBA_888 8) ||
645 (kRGB_565_SkColorType == colorType && cinfo.out_color_space == JCS_RGB_ 565))) 709 (kRGB_565_SkColorType == colorType && cinfo.out_color_space == JCS_RGB_ 565)))
646 { 710 {
647 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels(); 711 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
648 INT32 const bpr = bm->rowBytes(); 712 INT32 const bpr = bm->rowBytes();
649 713
650 while (cinfo.output_scanline < cinfo.output_height) { 714 while (cinfo.output_scanline < cinfo.output_height) {
651 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); 715 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
652 if (0 == row_count) { 716 if (0 == row_count) {
653 // if row_count == 0, then we didn't get a scanline, 717 // if row_count == 0, then we didn't get a scanline,
654 // so return early. We will return a partial image. 718 // so return early. We will return a partial image.
655 fill_below_level(cinfo.output_scanline, bm); 719 fill_below_level(cinfo.output_scanline, bm);
656 cinfo.output_scanline = cinfo.output_height; 720 cinfo.output_scanline = cinfo.output_height;
657 break; // Skip to jpeg_finish_decompress() 721 break; // Skip to jpeg_finish_decompress()
658 } 722 }
659 if (this->shouldCancelDecode()) { 723 if (this->shouldCancelDecode()) {
660 return return_false(cinfo, *bm, "shouldCancelDecode"); 724 return return_false(cinfo, bm, "shouldCancelDecode");
661 } 725 }
662 rowptr += bpr; 726 rowptr += bpr;
663 } 727 }
664 jpeg_finish_decompress(&cinfo); 728 jpeg_finish_decompress(&cinfo);
665 return true; 729 return true;
666 } 730 }
667 #endif 731 #endif
668 732
669 // check for supported formats 733 // check for supported formats
670 SkScaledBitmapSampler::SrcConfig sc; 734 SkScaledBitmapSampler::SrcConfig sc;
671 int srcBytesPerPixel; 735 int srcBytesPerPixel;
672 736
673 if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) { 737 if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) {
674 return return_false(cinfo, *bm, "jpeg colorspace"); 738 return return_false(cinfo, bm, "jpeg colorspace");
675 } 739 }
676 740
677 if (!sampler.begin(bm, sc, *this)) { 741 if (!sampler.begin(bm, sc, *this)) {
678 return return_false(cinfo, *bm, "sampler.begin"); 742 return return_false(cinfo, bm, "sampler.begin");
679 } 743 }
680 744
681 SkAutoMalloc srcStorage(cinfo.output_width * srcBytesPerPixel); 745 SkAutoMalloc srcStorage(cinfo.output_width * srcBytesPerPixel);
682 uint8_t* srcRow = (uint8_t*)srcStorage.get(); 746 uint8_t* srcRow = (uint8_t*)srcStorage.get();
683 747
684 // Possibly skip initial rows [sampler.srcY0] 748 // Possibly skip initial rows [sampler.srcY0]
685 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) { 749 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) {
686 return return_false(cinfo, *bm, "skip rows"); 750 return return_false(cinfo, bm, "skip rows");
687 } 751 }
688 752
689 // now loop through scanlines until y == bm->height() - 1 753 // now loop through scanlines until y == bm->height() - 1
690 for (int y = 0;; y++) { 754 for (int y = 0;; y++) {
691 JSAMPLE* rowptr = (JSAMPLE*)srcRow; 755 JSAMPLE* rowptr = (JSAMPLE*)srcRow;
692 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); 756 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
693 if (0 == row_count) { 757 if (0 == row_count) {
694 // if row_count == 0, then we didn't get a scanline, 758 // if row_count == 0, then we didn't get a scanline,
695 // so return early. We will return a partial image. 759 // so return early. We will return a partial image.
696 fill_below_level(y, bm); 760 fill_below_level(y, bm);
697 cinfo.output_scanline = cinfo.output_height; 761 cinfo.output_scanline = cinfo.output_height;
698 break; // Skip to jpeg_finish_decompress() 762 break; // Skip to jpeg_finish_decompress()
699 } 763 }
700 if (this->shouldCancelDecode()) { 764 if (this->shouldCancelDecode()) {
701 return return_false(cinfo, *bm, "shouldCancelDecode"); 765 return return_false(cinfo, bm, "shouldCancelDecode");
702 } 766 }
703 767
704 if (JCS_CMYK == cinfo.out_color_space) { 768 if (JCS_CMYK == cinfo.out_color_space) {
705 convert_CMYK_to_RGB(srcRow, cinfo.output_width); 769 convert_CMYK_to_RGB(srcRow, cinfo.output_width);
706 } 770 }
707 771
708 sampler.next(srcRow); 772 sampler.next(srcRow);
709 if (bm->height() - 1 == y) { 773 if (bm->height() - 1 == y) {
710 // we're done 774 // we're done
711 break; 775 break;
712 } 776 }
713 777
714 if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) { 778 if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) {
715 return return_false(cinfo, *bm, "skip rows"); 779 return return_false(cinfo, bm, "skip rows");
716 } 780 }
717 } 781 }
718 782
719 // we formally skip the rest, so we don't get a complaint from libjpeg 783 // we formally skip the rest, so we don't get a complaint from libjpeg
720 if (!skip_src_rows(&cinfo, srcRow, 784 if (!skip_src_rows(&cinfo, srcRow,
721 cinfo.output_height - cinfo.output_scanline)) { 785 cinfo.output_height - cinfo.output_scanline)) {
722 return return_false(cinfo, *bm, "skip rows"); 786 return return_false(cinfo, bm, "skip rows");
723 } 787 }
724 jpeg_finish_decompress(&cinfo); 788 jpeg_finish_decompress(&cinfo);
725 789
726 return true; 790 return true;
727 } 791 }
728 792
793 bool SkJPEGImageDecoder::decodeToYUV(jpeg_decompress_struct& cinfo) {
794 uint8_t* bufferraw[3];
795 uint8_t* bufferraw2[32];
796 bufferraw[0] = (uint8_t*)&bufferraw2[0];
797 bufferraw[1] = (uint8_t*)&bufferraw2[16];
798 bufferraw[2] = (uint8_t*)&bufferraw2[24];
799 int yWidth = cinfo.output_width;
800 int yHeight = cinfo.output_height;
801 int yMaxH = yHeight - 1;
802 int v = cinfo.cur_comp_info[0]->v_samp_factor;
803 int uvWidth(0), uvHeight(0);
804 compute_uv_size(cinfo, uvWidth, uvHeight);
805 int uvMaxH = uvHeight - 1;
806
807 SkAutoMalloc lastRowStorage(yWidth * 8);
808 uint8_t* yLastRow = (uint8_t*)lastRowStorage.get();
809 uint8_t* uLastRow = yLastRow + 2 * yWidth;
810 uint8_t* vLastRow = uLastRow + 2 * yWidth;
811 uint8_t* dummyRow = vLastRow + 2 * yWidth;
812
813 int scanlinesToRead = DCTSIZE * v;
814 while (cinfo.output_scanline < cinfo.output_height) {
815 // Request 8 or 16 scanlines: returns 0 or more scanlines.
816 bool hasYLastRow(false), hasUVLastRow(false);
817 for (int i = 0; i < scanlinesToRead; ++i) {
818 int scanline = (cinfo.output_scanline + i);
819 if (scanline < yMaxH) {
820 bufferraw2[i] = &fYUVBuffers[0][scanline * fRowBytes[0]];
821 } else if (scanline == yMaxH) {
822 bufferraw2[i] = yLastRow;
823 hasYLastRow = true;
824 } else {
825 bufferraw2[i] = dummyRow;
826 }
827 }
828 int scaledScanline = cinfo.output_scanline / v;
829 for (int i = 0; i < 8; ++i) {
830 int scanline = (scaledScanline + i);
831 if (scanline < uvMaxH) {
832 bufferraw2[16+i] = &fYUVBuffers[1][scanline * fRowBytes[1]];
833 bufferraw2[24+i] = &fYUVBuffers[2][scanline * fRowBytes[2]];
834 } else if (scanline == uvMaxH) {
835 bufferraw2[16+i] = uLastRow;
836 bufferraw2[24+i] = vLastRow;
837 hasUVLastRow = true;
838 } else {
839 bufferraw2[16+i] = dummyRow;
840 bufferraw2[24+i] = dummyRow;
841 }
842 }
843 JDIMENSION scanlinesRead =
844 jpeg_read_raw_data(&cinfo, (JSAMPIMAGE)bufferraw, scanlinesToRead);
845 if (scanlinesRead == 0) {
846 return false;
847 }
848 if (hasYLastRow) {
849 memcpy(&fYUVBuffers[0][ yMaxH * yWidth], yLastRow, yWidth);
850 }
851 if (hasUVLastRow) {
852 memcpy(&fYUVBuffers[1][uvMaxH * uvWidth], uLastRow, uvWidth);
853 memcpy(&fYUVBuffers[2][uvMaxH * uvWidth], vLastRow, uvWidth);
854 }
855 }
856
857 if (cinfo.output_scanline > cinfo.output_height) {
858 cinfo.output_scanline = cinfo.output_height;
859 }
860
861 jpeg_finish_decompress(&cinfo);
862
863 return true;
864 }
865
866 void SkJPEGImageDecoder::onSetYUVBuffers(void* yuv[3], size_t rowBytes[3]) {
867 for (int i = 0; i < 3; ++i) {
868 fYUVBuffers[i] = (uint8_t*)yuv[i];
869 fRowBytes[i] = rowBytes[i];
870 }
871 }
872
873 bool SkJPEGImageDecoder::onGetComponentSizes(SkStream* stream, SkISize sizes[3]) {
874 JPEGAutoClean autoClean;
875
876 jpeg_decompress_struct cinfo;
877 skjpeg_source_mgr srcManager(stream, this);
878
879 skjpeg_error_mgr errorManager;
880 set_error_mgr(&cinfo, &errorManager);
881
882 // All objects need to be instantiated before this setjmp call so that
883 // they will be cleaned up properly if an error occurs.
884 if (setjmp(errorManager.fJmpBuf)) {
885 return return_false(cinfo, NULL, "setjmp");
886 }
887
888 initialize_info(&cinfo, &srcManager);
889 autoClean.set(&cinfo);
890
891 int status = jpeg_read_header(&cinfo, true);
892 if (status != JPEG_HEADER_OK) {
893 return return_false(cinfo, NULL, "read_header");
894 }
895
896 if (isSupportedYUVFormat(cinfo)) {
897 jpeg_start_decompress(&cinfo); // Compute output width
898 sizes[0].set(cinfo.output_width, cinfo.output_height);
899 int w(0), h(0);
900 compute_uv_size(cinfo, w, h);
901 sizes[1].set(w, h);
902 sizes[2].set(w, h);
903 jpeg_abort_decompress(&cinfo);
904 return true;
905 }
906 return false;
907 }
908
729 #ifdef SK_BUILD_FOR_ANDROID 909 #ifdef SK_BUILD_FOR_ANDROID
730 bool SkJPEGImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, int *width , int *height) { 910 bool SkJPEGImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, int *width , int *height) {
731 911
732 SkAutoTDelete<SkJPEGImageIndex> imageIndex(SkNEW_ARGS(SkJPEGImageIndex, (str eam, this))); 912 SkAutoTDelete<SkJPEGImageIndex> imageIndex(SkNEW_ARGS(SkJPEGImageIndex, (str eam, this)));
733 jpeg_decompress_struct* cinfo = imageIndex->cinfo(); 913 jpeg_decompress_struct* cinfo = imageIndex->cinfo();
734 914
735 skjpeg_error_mgr sk_err; 915 skjpeg_error_mgr sk_err;
736 set_error_mgr(cinfo, &sk_err); 916 set_error_mgr(cinfo, &sk_err);
737 917
738 // All objects need to be instantiated before this setjmp call so that 918 // All objects need to be instantiated before this setjmp call so that
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
842 // swap happening. If no, then we will use alloc to allocate pixels to 1022 // swap happening. If no, then we will use alloc to allocate pixels to
843 // prevent garbage collection. 1023 // prevent garbage collection.
844 int w = rect.width() / actualSampleSize; 1024 int w = rect.width() / actualSampleSize;
845 int h = rect.height() / actualSampleSize; 1025 int h = rect.height() / actualSampleSize;
846 bool swapOnly = (rect == region) && bm->isNull() && 1026 bool swapOnly = (rect == region) && bm->isNull() &&
847 (w == bitmap.width()) && (h == bitmap.height()) && 1027 (w == bitmap.width()) && (h == bitmap.height()) &&
848 ((startX - rect.x()) / actualSampleSize == 0) && 1028 ((startX - rect.x()) / actualSampleSize == 0) &&
849 ((startY - rect.y()) / actualSampleSize == 0); 1029 ((startY - rect.y()) / actualSampleSize == 0);
850 if (swapOnly) { 1030 if (swapOnly) {
851 if (!this->allocPixelRef(&bitmap, NULL)) { 1031 if (!this->allocPixelRef(&bitmap, NULL)) {
852 return return_false(*cinfo, bitmap, "allocPixelRef"); 1032 return return_false(*cinfo, &bitmap, "allocPixelRef");
853 } 1033 }
854 } else { 1034 } else {
855 if (!bitmap.allocPixels()) { 1035 if (!bitmap.allocPixels()) {
856 return return_false(*cinfo, bitmap, "allocPixels"); 1036 return return_false(*cinfo, &bitmap, "allocPixels");
857 } 1037 }
858 } 1038 }
859 1039
860 SkAutoLockPixels alp(bitmap); 1040 SkAutoLockPixels alp(bitmap);
861 1041
862 #ifdef ANDROID_RGB 1042 #ifdef ANDROID_RGB
863 /* short-circuit the SkScaledBitmapSampler when possible, as this gives 1043 /* short-circuit the SkScaledBitmapSampler when possible, as this gives
864 a significant performance boost. 1044 a significant performance boost.
865 */ 1045 */
866 if (skiaSampleSize == 1 && 1046 if (skiaSampleSize == 1 &&
867 ((kN32_SkColorType == colorType && cinfo->out_color_space == JCS_RGBA_88 88) || 1047 ((kN32_SkColorType == colorType && cinfo->out_color_space == JCS_RGBA_88 88) ||
868 (kRGB_565_SkColorType == colorType && cinfo->out_color_space == JCS_RGB _565))) 1048 (kRGB_565_SkColorType == colorType && cinfo->out_color_space == JCS_RGB _565)))
869 { 1049 {
870 JSAMPLE* rowptr = (JSAMPLE*)bitmap.getPixels(); 1050 JSAMPLE* rowptr = (JSAMPLE*)bitmap.getPixels();
871 INT32 const bpr = bitmap.rowBytes(); 1051 INT32 const bpr = bitmap.rowBytes();
872 int rowTotalCount = 0; 1052 int rowTotalCount = 0;
873 1053
874 while (rowTotalCount < height) { 1054 while (rowTotalCount < height) {
875 int rowCount = jpeg_read_tile_scanline(cinfo, 1055 int rowCount = jpeg_read_tile_scanline(cinfo,
876 fImageIndex->huffmanIndex(), 1056 fImageIndex->huffmanIndex(),
877 &rowptr); 1057 &rowptr);
878 // if rowCount == 0, then we didn't get a scanline, so abort. 1058 // if rowCount == 0, then we didn't get a scanline, so abort.
879 // onDecodeSubset() relies on onBuildTileIndex(), which 1059 // onDecodeSubset() relies on onBuildTileIndex(), which
880 // needs a complete image to succeed. 1060 // needs a complete image to succeed.
881 if (0 == rowCount) { 1061 if (0 == rowCount) {
882 return return_false(*cinfo, bitmap, "read_scanlines"); 1062 return return_false(*cinfo, &bitmap, "read_scanlines");
883 } 1063 }
884 if (this->shouldCancelDecode()) { 1064 if (this->shouldCancelDecode()) {
885 return return_false(*cinfo, bitmap, "shouldCancelDecode"); 1065 return return_false(*cinfo, &bitmap, "shouldCancelDecode");
886 } 1066 }
887 rowTotalCount += rowCount; 1067 rowTotalCount += rowCount;
888 rowptr += bpr; 1068 rowptr += bpr;
889 } 1069 }
890 1070
891 if (swapOnly) { 1071 if (swapOnly) {
892 bm->swap(bitmap); 1072 bm->swap(bitmap);
893 } else { 1073 } else {
894 cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(), 1074 cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(),
895 region.width(), region.height(), startX, startY); 1075 region.width(), region.height(), startX, startY);
896 } 1076 }
897 return true; 1077 return true;
898 } 1078 }
899 #endif 1079 #endif
900 1080
901 // check for supported formats 1081 // check for supported formats
902 SkScaledBitmapSampler::SrcConfig sc; 1082 SkScaledBitmapSampler::SrcConfig sc;
903 int srcBytesPerPixel; 1083 int srcBytesPerPixel;
904 1084
905 if (!get_src_config(*cinfo, &sc, &srcBytesPerPixel)) { 1085 if (!get_src_config(*cinfo, &sc, &srcBytesPerPixel)) {
906 return return_false(*cinfo, *bm, "jpeg colorspace"); 1086 return return_false(*cinfo, bm, "jpeg colorspace");
907 } 1087 }
908 1088
909 if (!sampler.begin(&bitmap, sc, *this)) { 1089 if (!sampler.begin(&bitmap, sc, *this)) {
910 return return_false(*cinfo, bitmap, "sampler.begin"); 1090 return return_false(*cinfo, &bitmap, "sampler.begin");
911 } 1091 }
912 1092
913 SkAutoMalloc srcStorage(width * srcBytesPerPixel); 1093 SkAutoMalloc srcStorage(width * srcBytesPerPixel);
914 uint8_t* srcRow = (uint8_t*)srcStorage.get(); 1094 uint8_t* srcRow = (uint8_t*)srcStorage.get();
915 1095
916 // Possibly skip initial rows [sampler.srcY0] 1096 // Possibly skip initial rows [sampler.srcY0]
917 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler. srcY0())) { 1097 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler. srcY0())) {
918 return return_false(*cinfo, bitmap, "skip rows"); 1098 return return_false(*cinfo, &bitmap, "skip rows");
919 } 1099 }
920 1100
921 // now loop through scanlines until y == bitmap->height() - 1 1101 // now loop through scanlines until y == bitmap->height() - 1
922 for (int y = 0;; y++) { 1102 for (int y = 0;; y++) {
923 JSAMPLE* rowptr = (JSAMPLE*)srcRow; 1103 JSAMPLE* rowptr = (JSAMPLE*)srcRow;
924 int row_count = jpeg_read_tile_scanline(cinfo, fImageIndex->huffmanIndex (), &rowptr); 1104 int row_count = jpeg_read_tile_scanline(cinfo, fImageIndex->huffmanIndex (), &rowptr);
925 // if row_count == 0, then we didn't get a scanline, so abort. 1105 // if row_count == 0, then we didn't get a scanline, so abort.
926 // onDecodeSubset() relies on onBuildTileIndex(), which 1106 // onDecodeSubset() relies on onBuildTileIndex(), which
927 // needs a complete image to succeed. 1107 // needs a complete image to succeed.
928 if (0 == row_count) { 1108 if (0 == row_count) {
929 return return_false(*cinfo, bitmap, "read_scanlines"); 1109 return return_false(*cinfo, &bitmap, "read_scanlines");
930 } 1110 }
931 if (this->shouldCancelDecode()) { 1111 if (this->shouldCancelDecode()) {
932 return return_false(*cinfo, bitmap, "shouldCancelDecode"); 1112 return return_false(*cinfo, &bitmap, "shouldCancelDecode");
933 } 1113 }
934 1114
935 if (JCS_CMYK == cinfo->out_color_space) { 1115 if (JCS_CMYK == cinfo->out_color_space) {
936 convert_CMYK_to_RGB(srcRow, width); 1116 convert_CMYK_to_RGB(srcRow, width);
937 } 1117 }
938 1118
939 sampler.next(srcRow); 1119 sampler.next(srcRow);
940 if (bitmap.height() - 1 == y) { 1120 if (bitmap.height() - 1 == y) {
941 // we're done 1121 // we're done
942 break; 1122 break;
943 } 1123 }
944 1124
945 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, 1125 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow,
946 sampler.srcDY() - 1)) { 1126 sampler.srcDY() - 1)) {
947 return return_false(*cinfo, bitmap, "skip rows"); 1127 return return_false(*cinfo, &bitmap, "skip rows");
948 } 1128 }
949 } 1129 }
950 if (swapOnly) { 1130 if (swapOnly) {
951 bm->swap(bitmap); 1131 bm->swap(bitmap);
952 } else { 1132 } else {
953 cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(), 1133 cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(),
954 region.width(), region.height(), startX, startY); 1134 region.width(), region.height(), startX, startY);
955 } 1135 }
956 return true; 1136 return true;
957 } 1137 }
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
1233 return SkImageDecoder::kUnknown_Format; 1413 return SkImageDecoder::kUnknown_Format;
1234 } 1414 }
1235 1415
1236 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { 1416 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) {
1237 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL; 1417 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL;
1238 } 1418 }
1239 1419
1240 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory); 1420 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory);
1241 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg); 1421 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg);
1242 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory); 1422 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698