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

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

Issue 374743003: Skia side RGB to YUV gpu conversion (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Ported a minimal set of blink side changes for YUV decoding tests 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
248 virtual bool getImageFormat(SkStream* stream, SkISize sizes[3]) SK_OVERRIDE;
249 virtual void setYUVBuffers(void* yuv[3], size_t rowBytes[3]) SK_OVERRIDE;
250
236 protected: 251 protected:
237 #ifdef SK_BUILD_FOR_ANDROID 252 #ifdef SK_BUILD_FOR_ANDROID
238 virtual bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *h eight) SK_OVERRIDE; 253 virtual bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *h eight) SK_OVERRIDE;
239 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRI DE; 254 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRI DE;
240 #endif 255 #endif
241 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; 256 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE;
242 257
243 private: 258 private:
244 #ifdef SK_BUILD_FOR_ANDROID 259 #ifdef SK_BUILD_FOR_ANDROID
245 SkJPEGImageIndex* fImageIndex; 260 SkJPEGImageIndex* fImageIndex;
246 int fImageWidth; 261 int fImageWidth;
247 int fImageHeight; 262 int fImageHeight;
248 #endif 263 #endif
264 uint8_t* fYUVBuffers[3];
265 size_t fRowBytes[3];
266
267 bool isSupportedYUVFormat(jpeg_decompress_struct& cinfo) const {
268 if ((cinfo.jpeg_color_space == JCS_YCbCr) &&
269 (cinfo.num_components == 3) &&
270 (cinfo.scale_denom <= 8) &&
271 (cinfo.cur_comp_info[1]->h_samp_factor == 1) &&
272 (cinfo.cur_comp_info[1]->v_samp_factor == 1) &&
273 (cinfo.cur_comp_info[2]->h_samp_factor == 1) &&
274 (cinfo.cur_comp_info[2]->v_samp_factor == 1)) {
275 int h = cinfo.cur_comp_info[0]->h_samp_factor;
276 int v = cinfo.cur_comp_info[0]->v_samp_factor;
277 if (((h == 1) || (h == 2) || (h == 4)) &&
278 ((v == 1) || (v == 2))) {
279 cinfo.out_color_space = JCS_YCbCr;
280 cinfo.raw_data_out = TRUE;
281
282 #ifdef SK_PRINT_YUV_FORMAT
283 printf("YUV 4:%d:%d\n", 4 / h, (v == 1) ? 4 / h : 0);
scroggo 2014/07/18 21:52:41 SkDebugf?
284 #endif
285 return true;
286 }
287 }
288 return false;
289 }
290
291 bool canDecodeToYUV(jpeg_decompress_struct& cinfo) const {
292 return ((NULL != fYUVBuffers[0]) &&
293 (NULL != fYUVBuffers[1]) &&
294 (NULL != fYUVBuffers[2]) &&
295 (fRowBytes[0] > 0) &&
296 (fRowBytes[1] > 0) &&
297 (fRowBytes[2] > 0) &&
298 isSupportedYUVFormat(cinfo));
299 }
249 300
250 /** 301 /**
251 * Determine the appropriate bitmap colortype and out_color_space based on 302 * 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 303 * both the preference of the caller and the jpeg_color_space on the
253 * jpeg_decompress_struct passed in. 304 * jpeg_decompress_struct passed in.
254 * Must be called after jpeg_read_header. 305 * Must be called after jpeg_read_header.
255 */ 306 */
256 SkColorType getBitmapColorType(jpeg_decompress_struct*); 307 SkColorType getBitmapColorType(jpeg_decompress_struct*);
257 308
309 bool decodeToBitmap(SkBitmap* bm,
310 jpeg_decompress_struct& cinfo,
311 SkScaledBitmapSampler& sampler);
312 bool decodeToYUV(jpeg_decompress_struct& cinfo);
313
258 typedef SkImageDecoder INHERITED; 314 typedef SkImageDecoder INHERITED;
259 }; 315 };
260 316
261 ////////////////////////////////////////////////////////////////////////// 317 //////////////////////////////////////////////////////////////////////////
262 318
263 /* Automatically clean up after throwing an exception */ 319 /* Automatically clean up after throwing an exception */
264 class JPEGAutoClean { 320 class JPEGAutoClean {
265 public: 321 public:
266 JPEGAutoClean(): cinfo_ptr(NULL) {} 322 JPEGAutoClean(): cinfo_ptr(NULL) {}
267 ~JPEGAutoClean() { 323 ~JPEGAutoClean() {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 return false; 374 return false;
319 } 375 }
320 } 376 }
321 return true; 377 return true;
322 } 378 }
323 #endif 379 #endif
324 380
325 // This guy exists just to aid in debugging, as it allows debuggers to just 381 // 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. 382 // set a break-point in one place to see all error exists.
327 static bool return_false(const jpeg_decompress_struct& cinfo, 383 static bool return_false(const jpeg_decompress_struct& cinfo,
328 const SkBitmap& bm, const char caller[]) { 384 const SkBitmap* bm, const char caller[]) {
329 if (!(c_suppressJPEGImageDecoderErrors)) { 385 if (!(c_suppressJPEGImageDecoderErrors)) {
330 char buffer[JMSG_LENGTH_MAX]; 386 char buffer[JMSG_LENGTH_MAX];
331 cinfo.err->format_message((const j_common_ptr)&cinfo, buffer); 387 cinfo.err->format_message((const j_common_ptr)&cinfo, buffer);
332 SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n", 388 SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n",
333 cinfo.err->msg_code, buffer, caller, bm.width(), bm.height()); 389 cinfo.err->msg_code, buffer, caller,
390 (NULL == bm) ? bm->width() : 0,
scroggo 2014/07/18 21:52:41 This is backwards. If NULL == bm, you want to retu
391 (NULL == bm) ? bm->height() : 0);
334 } 392 }
335 return false; // must always return false 393 return false; // must always return false
336 } 394 }
337 395
338 // Convert a scanline of CMYK samples to RGBX in place. Note that this 396 // Convert a scanline of CMYK samples to RGBX in place. Note that this
339 // method moves the "scanline" pointer in its processing 397 // method moves the "scanline" pointer in its processing
340 static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) { 398 static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) {
341 // At this point we've received CMYK pixels from libjpeg. We 399 // At this point we've received CMYK pixels from libjpeg. We
342 // perform a crude conversion to RGB (based on the formulae 400 // perform a crude conversion to RGB (based on the formulae
343 // from easyrgb.com): 401 // from easyrgb.com):
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 596
539 jpeg_decompress_struct cinfo; 597 jpeg_decompress_struct cinfo;
540 skjpeg_source_mgr srcManager(stream, this); 598 skjpeg_source_mgr srcManager(stream, this);
541 599
542 skjpeg_error_mgr errorManager; 600 skjpeg_error_mgr errorManager;
543 set_error_mgr(&cinfo, &errorManager); 601 set_error_mgr(&cinfo, &errorManager);
544 602
545 // All objects need to be instantiated before this setjmp call so that 603 // All objects need to be instantiated before this setjmp call so that
546 // they will be cleaned up properly if an error occurs. 604 // they will be cleaned up properly if an error occurs.
547 if (setjmp(errorManager.fJmpBuf)) { 605 if (setjmp(errorManager.fJmpBuf)) {
548 return return_false(cinfo, *bm, "setjmp"); 606 return return_false(cinfo, bm, "setjmp");
549 } 607 }
550 608
551 initialize_info(&cinfo, &srcManager); 609 initialize_info(&cinfo, &srcManager);
552 autoClean.set(&cinfo); 610 autoClean.set(&cinfo);
553 611
554 int status = jpeg_read_header(&cinfo, true); 612 int status = jpeg_read_header(&cinfo, true);
555 if (status != JPEG_HEADER_OK) { 613 if (status != JPEG_HEADER_OK) {
556 return return_false(cinfo, *bm, "read_header"); 614 return return_false(cinfo, bm, "read_header");
557 } 615 }
558 616
559 /* Try to fulfill the requested sampleSize. Since jpeg can do it (when it 617 /* 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 618 can) much faster that we, just use their num/denom api to approximate
561 the size. 619 the size.
562 */ 620 */
563 int sampleSize = this->getSampleSize(); 621 int sampleSize = this->getSampleSize();
564 622
565 set_dct_method(*this, &cinfo); 623 set_dct_method(*this, &cinfo);
566 624
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimension s(cinfo)) { 659 if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimension s(cinfo)) {
602 SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height, 660 SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height,
603 recompute_sampleSize(sampleSize, cinfo)); 661 recompute_sampleSize(sampleSize, cinfo));
604 // Assume an A8 bitmap is not opaque to avoid the check of each 662 // Assume an A8 bitmap is not opaque to avoid the check of each
605 // individual pixel. It is very unlikely to be opaque, since 663 // individual pixel. It is very unlikely to be opaque, since
606 // an opaque A8 bitmap would not be very interesting. 664 // an opaque A8 bitmap would not be very interesting.
607 // Otherwise, a jpeg image is opaque. 665 // Otherwise, a jpeg image is opaque.
608 return bm->setInfo(SkImageInfo::Make(smpl.scaledWidth(), smpl.scaled Height(), 666 return bm->setInfo(SkImageInfo::Make(smpl.scaledWidth(), smpl.scaled Height(),
609 colorType, alphaType)); 667 colorType, alphaType));
610 } else { 668 } else {
611 return return_false(cinfo, *bm, "start_decompress"); 669 return return_false(cinfo, bm, "start_decompress");
612 } 670 }
613 } 671 }
614 sampleSize = recompute_sampleSize(sampleSize, cinfo); 672 sampleSize = recompute_sampleSize(sampleSize, cinfo);
615 673
616 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER 674 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
617 // should we allow the Chooser (if present) to pick a colortype for us??? 675 // 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)) { 676 if (!this->chooseFromOneChoice(colorType, cinfo.output_width, cinfo.output_h eight)) {
619 return return_false(cinfo, *bm, "chooseFromOneChoice"); 677 return return_false(cinfo, bm, "chooseFromOneChoice");
620 } 678 }
621 #endif 679 #endif
622 680
623 SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampl eSize); 681 SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampl eSize);
624 // Assume an A8 bitmap is not opaque to avoid the check of each 682 // Assume an A8 bitmap is not opaque to avoid the check of each
625 // individual pixel. It is very unlikely to be opaque, since 683 // individual pixel. It is very unlikely to be opaque, since
626 // an opaque A8 bitmap would not be very interesting. 684 // an opaque A8 bitmap would not be very interesting.
627 // Otherwise, a jpeg image is opaque. 685 // Otherwise, a jpeg image is opaque.
628 bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(), 686 bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(),
629 colorType, alphaType)); 687 colorType, alphaType));
630 if (SkImageDecoder::kDecodeBounds_Mode == mode) { 688 if (SkImageDecoder::kDecodeBounds_Mode == mode) {
631 return true; 689 return true;
632 } 690 }
691
692 return canDecodeToYUV(cinfo) ? decodeToYUV(cinfo) : decodeToBitmap(bm, cinfo , sampler);
scroggo 2014/07/18 21:52:41 It seems awkward that if canDecodeToYUV is true we
693 }
694
695 bool SkJPEGImageDecoder::decodeToBitmap(SkBitmap* bm,
696 jpeg_decompress_struct& cinfo,
697 SkScaledBitmapSampler& sampler) {
633 if (!this->allocPixelRef(bm, NULL)) { 698 if (!this->allocPixelRef(bm, NULL)) {
634 return return_false(cinfo, *bm, "allocPixelRef"); 699 return return_false(cinfo, bm, "allocPixelRef");
635 } 700 }
636 701
637 SkAutoLockPixels alp(*bm); 702 SkAutoLockPixels alp(*bm);
638 703
639 #ifdef ANDROID_RGB 704 #ifdef ANDROID_RGB
640 /* short-circuit the SkScaledBitmapSampler when possible, as this gives 705 /* short-circuit the SkScaledBitmapSampler when possible, as this gives
641 a significant performance boost. 706 a significant performance boost.
642 */ 707 */
643 if (sampleSize == 1 && 708 if (sampleSize == 1 &&
644 ((kN32_SkColorType == colorType && cinfo.out_color_space == JCS_RGBA_888 8) || 709 ((kN32_SkColorType == colorType && cinfo.out_color_space == JCS_RGBA_888 8) ||
645 (kRGB_565_SkColorType == colorType && cinfo.out_color_space == JCS_RGB_ 565))) 710 (kRGB_565_SkColorType == colorType && cinfo.out_color_space == JCS_RGB_ 565)))
646 { 711 {
647 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels(); 712 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
648 INT32 const bpr = bm->rowBytes(); 713 INT32 const bpr = bm->rowBytes();
649 714
650 while (cinfo.output_scanline < cinfo.output_height) { 715 while (cinfo.output_scanline < cinfo.output_height) {
651 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); 716 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
652 if (0 == row_count) { 717 if (0 == row_count) {
653 // if row_count == 0, then we didn't get a scanline, 718 // if row_count == 0, then we didn't get a scanline,
654 // so return early. We will return a partial image. 719 // so return early. We will return a partial image.
655 fill_below_level(cinfo.output_scanline, bm); 720 fill_below_level(cinfo.output_scanline, bm);
656 cinfo.output_scanline = cinfo.output_height; 721 cinfo.output_scanline = cinfo.output_height;
657 break; // Skip to jpeg_finish_decompress() 722 break; // Skip to jpeg_finish_decompress()
658 } 723 }
659 if (this->shouldCancelDecode()) { 724 if (this->shouldCancelDecode()) {
660 return return_false(cinfo, *bm, "shouldCancelDecode"); 725 return return_false(cinfo, bm, "shouldCancelDecode");
661 } 726 }
662 rowptr += bpr; 727 rowptr += bpr;
663 } 728 }
664 jpeg_finish_decompress(&cinfo); 729 jpeg_finish_decompress(&cinfo);
665 return true; 730 return true;
666 } 731 }
667 #endif 732 #endif
668 733
669 // check for supported formats 734 // check for supported formats
670 SkScaledBitmapSampler::SrcConfig sc; 735 SkScaledBitmapSampler::SrcConfig sc;
671 int srcBytesPerPixel; 736 int srcBytesPerPixel;
672 737
673 if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) { 738 if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) {
674 return return_false(cinfo, *bm, "jpeg colorspace"); 739 return return_false(cinfo, bm, "jpeg colorspace");
675 } 740 }
676 741
677 if (!sampler.begin(bm, sc, *this)) { 742 if (!sampler.begin(bm, sc, *this)) {
678 return return_false(cinfo, *bm, "sampler.begin"); 743 return return_false(cinfo, bm, "sampler.begin");
679 } 744 }
680 745
681 SkAutoMalloc srcStorage(cinfo.output_width * srcBytesPerPixel); 746 SkAutoMalloc srcStorage(cinfo.output_width * srcBytesPerPixel);
682 uint8_t* srcRow = (uint8_t*)srcStorage.get(); 747 uint8_t* srcRow = (uint8_t*)srcStorage.get();
683 748
684 // Possibly skip initial rows [sampler.srcY0] 749 // Possibly skip initial rows [sampler.srcY0]
685 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) { 750 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) {
686 return return_false(cinfo, *bm, "skip rows"); 751 return return_false(cinfo, bm, "skip rows");
687 } 752 }
688 753
689 // now loop through scanlines until y == bm->height() - 1 754 // now loop through scanlines until y == bm->height() - 1
690 for (int y = 0;; y++) { 755 for (int y = 0;; y++) {
691 JSAMPLE* rowptr = (JSAMPLE*)srcRow; 756 JSAMPLE* rowptr = (JSAMPLE*)srcRow;
692 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); 757 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
693 if (0 == row_count) { 758 if (0 == row_count) {
694 // if row_count == 0, then we didn't get a scanline, 759 // if row_count == 0, then we didn't get a scanline,
695 // so return early. We will return a partial image. 760 // so return early. We will return a partial image.
696 fill_below_level(y, bm); 761 fill_below_level(y, bm);
697 cinfo.output_scanline = cinfo.output_height; 762 cinfo.output_scanline = cinfo.output_height;
698 break; // Skip to jpeg_finish_decompress() 763 break; // Skip to jpeg_finish_decompress()
699 } 764 }
700 if (this->shouldCancelDecode()) { 765 if (this->shouldCancelDecode()) {
701 return return_false(cinfo, *bm, "shouldCancelDecode"); 766 return return_false(cinfo, bm, "shouldCancelDecode");
702 } 767 }
703 768
704 if (JCS_CMYK == cinfo.out_color_space) { 769 if (JCS_CMYK == cinfo.out_color_space) {
705 convert_CMYK_to_RGB(srcRow, cinfo.output_width); 770 convert_CMYK_to_RGB(srcRow, cinfo.output_width);
706 } 771 }
707 772
708 sampler.next(srcRow); 773 sampler.next(srcRow);
709 if (bm->height() - 1 == y) { 774 if (bm->height() - 1 == y) {
710 // we're done 775 // we're done
711 break; 776 break;
712 } 777 }
713 778
714 if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) { 779 if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) {
715 return return_false(cinfo, *bm, "skip rows"); 780 return return_false(cinfo, bm, "skip rows");
716 } 781 }
717 } 782 }
718 783
719 // we formally skip the rest, so we don't get a complaint from libjpeg 784 // we formally skip the rest, so we don't get a complaint from libjpeg
720 if (!skip_src_rows(&cinfo, srcRow, 785 if (!skip_src_rows(&cinfo, srcRow,
721 cinfo.output_height - cinfo.output_scanline)) { 786 cinfo.output_height - cinfo.output_scanline)) {
722 return return_false(cinfo, *bm, "skip rows"); 787 return return_false(cinfo, bm, "skip rows");
723 } 788 }
724 jpeg_finish_decompress(&cinfo); 789 jpeg_finish_decompress(&cinfo);
725 790
726 return true; 791 return true;
727 } 792 }
728 793
794 bool SkJPEGImageDecoder::decodeToYUV(jpeg_decompress_struct& cinfo) {
795 uint8_t* bufferraw[3];
796 uint8_t* bufferraw2[32];
797 bufferraw[0] = (uint8_t*)&bufferraw2[0];
798 bufferraw[1] = (uint8_t*)&bufferraw2[16];
799 bufferraw[2] = (uint8_t*)&bufferraw2[24];
800 int yWidth = cinfo.output_width;
801 int yHeight = cinfo.output_height;
802 int yMaxH = yHeight - 1;
803 int v = cinfo.cur_comp_info[0]->v_samp_factor;
804 int uvWidth(0), uvHeight(0);
805 compute_uv_size(cinfo, uvWidth, uvHeight);
806 int uvMaxH = uvHeight - 1;
807
808 SkAutoMalloc lastRowStorage(yWidth * 8);
809 uint8_t* yLastRow = (uint8_t*)lastRowStorage.get();
810 uint8_t* uLastRow = yLastRow + 2 * yWidth;
811 uint8_t* vLastRow = uLastRow + 2 * yWidth;
812 uint8_t* dummyRow = vLastRow + 2 * yWidth;
813
814 int scanlinesToRead = DCTSIZE * v;
815 while (cinfo.output_scanline < cinfo.output_height) {
816 // Request 8 or 16 scanlines: returns 0 or more scanlines.
817 bool hasYLastRow(false), hasUVLastRow(false);
818 for (int i = 0; i < scanlinesToRead; ++i) {
819 int scanline = (cinfo.output_scanline + i);
820 if (scanline < yMaxH) {
821 bufferraw2[i] = &fYUVBuffers[0][scanline * fRowBytes[0]];
822 } else if (scanline == yMaxH) {
823 bufferraw2[i] = yLastRow;
824 hasYLastRow = true;
825 } else {
826 bufferraw2[i] = dummyRow;
827 }
828 }
829 int scaledScanline = cinfo.output_scanline / v;
830 for (int i = 0; i < 8; ++i) {
831 int scanline = (scaledScanline + i);
832 if (scanline < uvMaxH) {
833 bufferraw2[16+i] = &fYUVBuffers[1][scanline * fRowBytes[1]];
834 bufferraw2[24+i] = &fYUVBuffers[2][scanline * fRowBytes[2]];
835 } else if (scanline == uvMaxH) {
836 bufferraw2[16+i] = uLastRow;
837 bufferraw2[24+i] = vLastRow;
838 hasUVLastRow = true;
839 } else {
840 bufferraw2[16+i] = dummyRow;
841 bufferraw2[24+i] = dummyRow;
842 }
843 }
844 JDIMENSION scanlinesRead = jpeg_read_raw_data(&cinfo, (JSAMPIMAGE)buffer raw, scanlinesToRead);
scroggo 2014/07/18 21:52:41 100 chars
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::setYUVBuffers(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::getImageFormat(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