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

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

Issue 1180983002: Switch SkJpegCode to libjpeg-turbo (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Adding turbo to DEPS Created 5 years, 6 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"
11 #include "SkJpegUtility.h" 11 #include "SkJpegUtility.h"
12 #include "SkColorPriv.h" 12 #include "SkColorPriv.h"
13 #include "SkDither.h" 13 #include "SkDither.h"
14 #include "SkScaledBitmapSampler.h" 14 #include "SkScaledBitmapSampler.h"
15 #include "SkStream.h" 15 #include "SkStream.h"
16 #include "SkTemplates.h" 16 #include "SkTemplates.h"
17 #include "SkTime.h" 17 #include "SkTime.h"
18 #include "SkUtils.h" 18 #include "SkUtils.h"
19 #include "SkRTConf.h" 19 #include "SkRTConf.h"
20 #include "SkRect.h" 20 #include "SkRect.h"
21 #include "SkCanvas.h" 21 #include "SkCanvas.h"
22 22
23 23
24 #include <stdio.h> 24 #include <stdio.h>
25 extern "C" { 25 extern "C" {
26 #ifdef SK_BUILD_FOR_ANDROID
27 #include "manglejpeglib.h"
28 #else
26 #include "jpeglib.h" 29 #include "jpeglib.h"
30 #endif
27 #include "jerror.h" 31 #include "jerror.h"
28 } 32 }
29 33
30 // These enable timing code that report milliseconds for an encoding/decoding 34 // These enable timing code that report milliseconds for an encoding/decoding
31 //#define TIME_ENCODE 35 //#define TIME_ENCODE
32 //#define TIME_DECODE 36 //#define TIME_DECODE
33 37
34 // this enables our rgb->yuv code, which is faster than libjpeg on ARM 38 // this enables our rgb->yuv code, which is faster than libjpeg on ARM
35 #define WE_CONVERT_TO_YUV 39 #define WE_CONVERT_TO_YUV
36 40
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 // attempt to delete this SkJPEGImageIndex, thus entering this 110 // attempt to delete this SkJPEGImageIndex, thus entering this
107 // destructor again. Setting fHuffmanCreated to false first 111 // destructor again. Setting fHuffmanCreated to false first
108 // prevents an infinite loop. 112 // prevents an infinite loop.
109 fHuffmanCreated = false; 113 fHuffmanCreated = false;
110 jpeg_destroy_huffman_index(&fHuffmanIndex); 114 jpeg_destroy_huffman_index(&fHuffmanIndex);
111 } 115 }
112 if (fDecompressStarted) { 116 if (fDecompressStarted) {
113 // Like fHuffmanCreated, set to false before calling libjpeg 117 // Like fHuffmanCreated, set to false before calling libjpeg
114 // function to prevent potential infinite loop. 118 // function to prevent potential infinite loop.
115 fDecompressStarted = false; 119 fDecompressStarted = false;
116 jpeg_finish_decompress(&fCInfo); 120 jFinDecompress(&fCInfo);
117 } 121 }
118 if (fInfoInitialized) { 122 if (fInfoInitialized) {
119 this->destroyInfo(); 123 this->destroyInfo();
120 } 124 }
121 } 125 }
122 126
123 /** 127 /**
124 * Destroy the cinfo struct. 128 * Destroy the cinfo struct.
125 * After this call, if a huffman index was already built, it 129 * After this call, if a huffman index was already built, it
126 * can be used after calling initializeInfoAndReadHeader 130 * can be used after calling initializeInfoAndReadHeader
127 * again. Must not be called after startTileDecompress except 131 * again. Must not be called after startTileDecompress except
128 * in the destructor. 132 * in the destructor.
129 */ 133 */
130 void destroyInfo() { 134 void destroyInfo() {
131 SkASSERT(fInfoInitialized); 135 SkASSERT(fInfoInitialized);
132 SkASSERT(!fDecompressStarted); 136 SkASSERT(!fDecompressStarted);
133 // Like fHuffmanCreated, set to false before calling libjpeg 137 // Like fHuffmanCreated, set to false before calling libjpeg
134 // function to prevent potential infinite loop. 138 // function to prevent potential infinite loop.
135 fInfoInitialized = false; 139 fInfoInitialized = false;
136 jpeg_destroy_decompress(&fCInfo); 140 jDestDecompress(&fCInfo);
137 SkDEBUGCODE(fReadHeaderSucceeded = false;) 141 SkDEBUGCODE(fReadHeaderSucceeded = false;)
138 } 142 }
139 143
140 /** 144 /**
141 * Initialize the cinfo struct. 145 * Initialize the cinfo struct.
142 * Calls jpeg_create_decompress, makes customizations, and 146 * Calls jpeg_create_decompress, makes customizations, and
143 * finally calls jpeg_read_header. Returns true if jpeg_read_header 147 * finally calls jReadHeader. Returns true if jReadHeader
144 * returns JPEG_HEADER_OK. 148 * returns JPEG_HEADER_OK.
145 * If cinfo was already initialized, destroyInfo must be called to 149 * If cinfo was already initialized, destroyInfo must be called to
146 * destroy the old one. Must not be called after startTileDecompress. 150 * destroy the old one. Must not be called after startTileDecompress.
147 */ 151 */
148 bool initializeInfoAndReadHeader() { 152 bool initializeInfoAndReadHeader() {
149 SkASSERT(!fInfoInitialized && !fDecompressStarted); 153 SkASSERT(!fInfoInitialized && !fDecompressStarted);
150 initialize_info(&fCInfo, &fSrcMgr); 154 initialize_info(&fCInfo, &fSrcMgr);
151 fInfoInitialized = true; 155 fInfoInitialized = true;
152 const bool success = (JPEG_HEADER_OK == jpeg_read_header(&fCInfo, true)) ; 156 const bool success = (JPEG_HEADER_OK == jReadHeader(&fCInfo, true));
153 SkDEBUGCODE(fReadHeaderSucceeded = success;) 157 SkDEBUGCODE(fReadHeaderSucceeded = success;)
154 return success; 158 return success;
155 } 159 }
156 160
157 jpeg_decompress_struct* cinfo() { return &fCInfo; } 161 jpeg_decompress_struct* cinfo() { return &fCInfo; }
158 162
159 huffman_index* huffmanIndex() { return &fHuffmanIndex; } 163 huffman_index* huffmanIndex() { return &fHuffmanIndex; }
160 164
161 /** 165 /**
162 * Build the index to be used for tile based decoding. 166 * Build the index to be used for tile based decoding.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 #ifdef SK_BUILD_FOR_ANDROID 237 #ifdef SK_BUILD_FOR_ANDROID
234 SkJPEGImageIndex* fImageIndex; 238 SkJPEGImageIndex* fImageIndex;
235 int fImageWidth; 239 int fImageWidth;
236 int fImageHeight; 240 int fImageHeight;
237 #endif 241 #endif
238 242
239 /** 243 /**
240 * Determine the appropriate bitmap colortype and out_color_space based on 244 * Determine the appropriate bitmap colortype and out_color_space based on
241 * both the preference of the caller and the jpeg_color_space on the 245 * both the preference of the caller and the jpeg_color_space on the
242 * jpeg_decompress_struct passed in. 246 * jpeg_decompress_struct passed in.
243 * Must be called after jpeg_read_header. 247 * Must be called after jReadHeader.
244 */ 248 */
245 SkColorType getBitmapColorType(jpeg_decompress_struct*); 249 SkColorType getBitmapColorType(jpeg_decompress_struct*);
246 250
247 typedef SkImageDecoder INHERITED; 251 typedef SkImageDecoder INHERITED;
248 }; 252 };
249 253
250 ////////////////////////////////////////////////////////////////////////// 254 //////////////////////////////////////////////////////////////////////////
251 255
252 /* Automatically clean up after throwing an exception */ 256 /* Automatically clean up after throwing an exception */
253 class JPEGAutoClean { 257 class JPEGAutoClean {
254 public: 258 public:
255 JPEGAutoClean(): cinfo_ptr(NULL) {} 259 JPEGAutoClean(): cinfo_ptr(NULL) {}
256 ~JPEGAutoClean() { 260 ~JPEGAutoClean() {
257 if (cinfo_ptr) { 261 if (cinfo_ptr) {
258 jpeg_destroy_decompress(cinfo_ptr); 262 jDestDecompress(cinfo_ptr);
259 } 263 }
260 } 264 }
261 void set(jpeg_decompress_struct* info) { 265 void set(jpeg_decompress_struct* info) {
262 cinfo_ptr = info; 266 cinfo_ptr = info;
263 } 267 }
264 private: 268 private:
265 jpeg_decompress_struct* cinfo_ptr; 269 jpeg_decompress_struct* cinfo_ptr;
266 }; 270 };
267 271
268 /////////////////////////////////////////////////////////////////////////////// 272 ///////////////////////////////////////////////////////////////////////////////
(...skipping 13 matching lines...) Expand all
282 static bool valid_output_dimensions(const jpeg_decompress_struct& cinfo) { 286 static bool valid_output_dimensions(const jpeg_decompress_struct& cinfo) {
283 /* These are initialized to 0, so if they have non-zero values, we assume 287 /* These are initialized to 0, so if they have non-zero values, we assume
284 they are "valid" (i.e. have been computed by libjpeg) 288 they are "valid" (i.e. have been computed by libjpeg)
285 */ 289 */
286 return 0 != cinfo.output_width && 0 != cinfo.output_height; 290 return 0 != cinfo.output_width && 0 != cinfo.output_height;
287 } 291 }
288 292
289 static bool skip_src_rows(jpeg_decompress_struct* cinfo, void* buffer, int count ) { 293 static bool skip_src_rows(jpeg_decompress_struct* cinfo, void* buffer, int count ) {
290 for (int i = 0; i < count; i++) { 294 for (int i = 0; i < count; i++) {
291 JSAMPLE* rowptr = (JSAMPLE*)buffer; 295 JSAMPLE* rowptr = (JSAMPLE*)buffer;
292 int row_count = jpeg_read_scanlines(cinfo, &rowptr, 1); 296 int row_count = jReadScanlines(cinfo, &rowptr, 1);
293 if (1 != row_count) { 297 if (1 != row_count) {
294 return false; 298 return false;
295 } 299 }
296 } 300 }
297 return true; 301 return true;
298 } 302 }
299 303
300 #ifdef SK_BUILD_FOR_ANDROID 304 #ifdef SK_BUILD_FOR_ANDROID
301 static bool skip_src_rows_tile(jpeg_decompress_struct* cinfo, 305 static bool skip_src_rows_tile(jpeg_decompress_struct* cinfo,
302 huffman_index *index, void* buffer, int count) { 306 huffman_index *index, void* buffer, int count) {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 scanline[3] = 255; 373 scanline[3] = 255;
370 } 374 }
371 } 375 }
372 376
373 /** 377 /**
374 * Common code for setting the error manager. 378 * Common code for setting the error manager.
375 */ 379 */
376 static void set_error_mgr(jpeg_decompress_struct* cinfo, skjpeg_error_mgr* error Manager) { 380 static void set_error_mgr(jpeg_decompress_struct* cinfo, skjpeg_error_mgr* error Manager) {
377 SkASSERT(cinfo != NULL); 381 SkASSERT(cinfo != NULL);
378 SkASSERT(errorManager != NULL); 382 SkASSERT(errorManager != NULL);
379 cinfo->err = jpeg_std_error(errorManager); 383 cinfo->err = jStdError(errorManager);
380 errorManager->error_exit = skjpeg_error_exit; 384 errorManager->error_exit = skjpeg_error_exit;
381 } 385 }
382 386
383 /** 387 /**
384 * Common code for turning off upsampling and smoothing. Turning these 388 * Common code for turning off upsampling and smoothing. Turning these
385 * off helps performance without showing noticable differences in the 389 * off helps performance without showing noticable differences in the
386 * resulting bitmap. 390 * resulting bitmap.
387 */ 391 */
388 static void turn_off_visual_optimizations(jpeg_decompress_struct* cinfo) { 392 static void turn_off_visual_optimizations(jpeg_decompress_struct* cinfo) {
389 SkASSERT(cinfo != NULL); 393 SkASSERT(cinfo != NULL);
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
555 559
556 // All objects need to be instantiated before this setjmp call so that 560 // All objects need to be instantiated before this setjmp call so that
557 // they will be cleaned up properly if an error occurs. 561 // they will be cleaned up properly if an error occurs.
558 if (setjmp(errorManager.fJmpBuf)) { 562 if (setjmp(errorManager.fJmpBuf)) {
559 return return_failure(cinfo, *bm, "setjmp"); 563 return return_failure(cinfo, *bm, "setjmp");
560 } 564 }
561 565
562 initialize_info(&cinfo, &srcManager); 566 initialize_info(&cinfo, &srcManager);
563 autoClean.set(&cinfo); 567 autoClean.set(&cinfo);
564 568
565 int status = jpeg_read_header(&cinfo, true); 569 int status = jReadHeader(&cinfo, true);
566 if (status != JPEG_HEADER_OK) { 570 if (status != JPEG_HEADER_OK) {
567 return return_failure(cinfo, *bm, "read_header"); 571 return return_failure(cinfo, *bm, "read_header");
568 } 572 }
569 573
570 /* Try to fulfill the requested sampleSize. Since jpeg can do it (when it 574 /* Try to fulfill the requested sampleSize. Since jpeg can do it (when it
571 can) much faster that we, just use their num/denom api to approximate 575 can) much faster that we, just use their num/denom api to approximate
572 the size. 576 the size.
573 */ 577 */
574 int sampleSize = this->getSampleSize(); 578 int sampleSize = this->getSampleSize();
575 579
(...skipping 14 matching lines...) Expand all
590 // Assume an A8 bitmap is not opaque to avoid the check of each 594 // Assume an A8 bitmap is not opaque to avoid the check of each
591 // individual pixel. It is very unlikely to be opaque, since 595 // individual pixel. It is very unlikely to be opaque, since
592 // an opaque A8 bitmap would not be very interesting. 596 // an opaque A8 bitmap would not be very interesting.
593 // Otherwise, a jpeg image is opaque. 597 // Otherwise, a jpeg image is opaque.
594 bool success = bm->setInfo(SkImageInfo::Make(cinfo.image_width, cinfo.im age_height, 598 bool success = bm->setInfo(SkImageInfo::Make(cinfo.image_width, cinfo.im age_height,
595 colorType, alphaType)); 599 colorType, alphaType));
596 return success ? kSuccess : kFailure; 600 return success ? kSuccess : kFailure;
597 } 601 }
598 602
599 /* image_width and image_height are the original dimensions, available 603 /* image_width and image_height are the original dimensions, available
600 after jpeg_read_header(). To see the scaled dimensions, we have to call 604 after jReadHeader(). To see the scaled dimensions, we have to call
601 jpeg_start_decompress(), and then read output_width and output_height. 605 jStrtDecompress(), and then read output_width and output_height.
602 */ 606 */
603 if (!jpeg_start_decompress(&cinfo)) { 607 if (!jStrtDecompress(&cinfo)) {
604 /* If we failed here, we may still have enough information to return 608 /* If we failed here, we may still have enough information to return
605 to the caller if they just wanted (subsampled bounds). If sampleSize 609 to the caller if they just wanted (subsampled bounds). If sampleSize
606 was 1, then we would have already returned. Thus we just check if 610 was 1, then we would have already returned. Thus we just check if
607 we're in kDecodeBounds_Mode, and that we have valid output sizes. 611 we're in kDecodeBounds_Mode, and that we have valid output sizes.
608 612
609 One reason to fail here is that we have insufficient stream data 613 One reason to fail here is that we have insufficient stream data
610 to complete the setup. However, output dimensions seem to get 614 to complete the setup. However, output dimensions seem to get
611 computed very early, which is why this special check can pay off. 615 computed very early, which is why this special check can pay off.
612 */ 616 */
613 if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimension s(cinfo)) { 617 if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimension s(cinfo)) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
647 a significant performance boost. 651 a significant performance boost.
648 */ 652 */
649 if (sampleSize == 1 && 653 if (sampleSize == 1 &&
650 ((kN32_SkColorType == colorType && cinfo.out_color_space == JCS_RGBA_888 8) || 654 ((kN32_SkColorType == colorType && cinfo.out_color_space == JCS_RGBA_888 8) ||
651 (kRGB_565_SkColorType == colorType && cinfo.out_color_space == JCS_RGB_ 565))) 655 (kRGB_565_SkColorType == colorType && cinfo.out_color_space == JCS_RGB_ 565)))
652 { 656 {
653 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels(); 657 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
654 INT32 const bpr = bm->rowBytes(); 658 INT32 const bpr = bm->rowBytes();
655 659
656 while (cinfo.output_scanline < cinfo.output_height) { 660 while (cinfo.output_scanline < cinfo.output_height) {
657 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); 661 int row_count = jReadScanlines(&cinfo, &rowptr, 1);
658 if (0 == row_count) { 662 if (0 == row_count) {
659 // if row_count == 0, then we didn't get a scanline, 663 // if row_count == 0, then we didn't get a scanline,
660 // so return early. We will return a partial image. 664 // so return early. We will return a partial image.
661 fill_below_level(cinfo.output_scanline, bm); 665 fill_below_level(cinfo.output_scanline, bm);
662 cinfo.output_scanline = cinfo.output_height; 666 cinfo.output_scanline = cinfo.output_height;
663 jpeg_finish_decompress(&cinfo); 667 jFinDecompress(&cinfo);
664 return kPartialSuccess; 668 return kPartialSuccess;
665 } 669 }
666 if (this->shouldCancelDecode()) { 670 if (this->shouldCancelDecode()) {
667 return return_failure(cinfo, *bm, "shouldCancelDecode"); 671 return return_failure(cinfo, *bm, "shouldCancelDecode");
668 } 672 }
669 rowptr += bpr; 673 rowptr += bpr;
670 } 674 }
671 jpeg_finish_decompress(&cinfo); 675 jFinDecompress(&cinfo);
672 return kSuccess; 676 return kSuccess;
673 } 677 }
674 #endif 678 #endif
675 679
676 // check for supported formats 680 // check for supported formats
677 SkScaledBitmapSampler::SrcConfig sc; 681 SkScaledBitmapSampler::SrcConfig sc;
678 int srcBytesPerPixel; 682 int srcBytesPerPixel;
679 683
680 if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) { 684 if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) {
681 return return_failure(cinfo, *bm, "jpeg colorspace"); 685 return return_failure(cinfo, *bm, "jpeg colorspace");
682 } 686 }
683 687
684 if (!sampler.begin(bm, sc, *this)) { 688 if (!sampler.begin(bm, sc, *this)) {
685 return return_failure(cinfo, *bm, "sampler.begin"); 689 return return_failure(cinfo, *bm, "sampler.begin");
686 } 690 }
687 691
688 SkAutoMalloc srcStorage(cinfo.output_width * srcBytesPerPixel); 692 SkAutoMalloc srcStorage(cinfo.output_width * srcBytesPerPixel);
689 uint8_t* srcRow = (uint8_t*)srcStorage.get(); 693 uint8_t* srcRow = (uint8_t*)srcStorage.get();
690 694
691 // Possibly skip initial rows [sampler.srcY0] 695 // Possibly skip initial rows [sampler.srcY0]
692 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) { 696 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) {
693 return return_failure(cinfo, *bm, "skip rows"); 697 return return_failure(cinfo, *bm, "skip rows");
694 } 698 }
695 699
696 // now loop through scanlines until y == bm->height() - 1 700 // now loop through scanlines until y == bm->height() - 1
697 for (int y = 0;; y++) { 701 for (int y = 0;; y++) {
698 JSAMPLE* rowptr = (JSAMPLE*)srcRow; 702 JSAMPLE* rowptr = (JSAMPLE*)srcRow;
699 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); 703 int row_count = jReadScanlines(&cinfo, &rowptr, 1);
700 if (0 == row_count) { 704 if (0 == row_count) {
701 // if row_count == 0, then we didn't get a scanline, 705 // if row_count == 0, then we didn't get a scanline,
702 // so return early. We will return a partial image. 706 // so return early. We will return a partial image.
703 fill_below_level(y, bm); 707 fill_below_level(y, bm);
704 cinfo.output_scanline = cinfo.output_height; 708 cinfo.output_scanline = cinfo.output_height;
705 jpeg_finish_decompress(&cinfo); 709 jFinDecompress(&cinfo);
706 return kPartialSuccess; 710 return kPartialSuccess;
707 } 711 }
708 if (this->shouldCancelDecode()) { 712 if (this->shouldCancelDecode()) {
709 return return_failure(cinfo, *bm, "shouldCancelDecode"); 713 return return_failure(cinfo, *bm, "shouldCancelDecode");
710 } 714 }
711 715
712 if (JCS_CMYK == cinfo.out_color_space) { 716 if (JCS_CMYK == cinfo.out_color_space) {
713 convert_CMYK_to_RGB(srcRow, cinfo.output_width); 717 convert_CMYK_to_RGB(srcRow, cinfo.output_width);
714 } 718 }
715 719
716 sampler.next(srcRow); 720 sampler.next(srcRow);
717 if (bm->height() - 1 == y) { 721 if (bm->height() - 1 == y) {
718 // we're done 722 // we're done
719 break; 723 break;
720 } 724 }
721 725
722 if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) { 726 if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) {
723 return return_failure(cinfo, *bm, "skip rows"); 727 return return_failure(cinfo, *bm, "skip rows");
724 } 728 }
725 } 729 }
726 730
727 // we formally skip the rest, so we don't get a complaint from libjpeg 731 // we formally skip the rest, so we don't get a complaint from libjpeg
728 if (!skip_src_rows(&cinfo, srcRow, 732 if (!skip_src_rows(&cinfo, srcRow,
729 cinfo.output_height - cinfo.output_scanline)) { 733 cinfo.output_height - cinfo.output_scanline)) {
730 return return_failure(cinfo, *bm, "skip rows"); 734 return return_failure(cinfo, *bm, "skip rows");
731 } 735 }
732 jpeg_finish_decompress(&cinfo); 736 jFinDecompress(&cinfo);
733 737
734 return kSuccess; 738 return kSuccess;
735 } 739 }
736 740
737 /////////////////////////////////////////////////////////////////////////////// 741 ///////////////////////////////////////////////////////////////////////////////
738 742
739 enum SizeType { 743 enum SizeType {
740 kSizeForMemoryAllocation_SizeType, 744 kSizeForMemoryAllocation_SizeType,
741 kActualSize_SizeType 745 kActualSize_SizeType
742 }; 746 };
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
828 bufferraw2[24 + i] = &outputV[scanline * rowBytesV]; 832 bufferraw2[24 + i] = &outputV[scanline * rowBytesV];
829 } else if (scanline == uvMaxH) { 833 } else if (scanline == uvMaxH) {
830 bufferraw2[16 + i] = uLastRow; 834 bufferraw2[16 + i] = uLastRow;
831 bufferraw2[24 + i] = vLastRow; 835 bufferraw2[24 + i] = vLastRow;
832 hasUVLastRow = true; 836 hasUVLastRow = true;
833 } else { 837 } else {
834 bufferraw2[16 + i] = dummyRow; 838 bufferraw2[16 + i] = dummyRow;
835 bufferraw2[24 + i] = dummyRow; 839 bufferraw2[24 + i] = dummyRow;
836 } 840 }
837 } 841 }
838 JDIMENSION scanlinesRead = jpeg_read_raw_data(&cinfo, bufferraw, yScanli nesToRead); 842 JDIMENSION scanlinesRead = jReadRawData(&cinfo, bufferraw, yScanlinesToR ead);
839 843
840 if (scanlinesRead == 0) { 844 if (scanlinesRead == 0) {
841 return false; 845 return false;
842 } 846 }
843 847
844 if (hasYLastRow) { 848 if (hasYLastRow) {
845 memcpy(&outputY[yMaxH * rowBytesY], yLastRow, yWidth); 849 memcpy(&outputY[yMaxH * rowBytesY], yLastRow, yWidth);
846 } 850 }
847 if (hasUVLastRow) { 851 if (hasUVLastRow) {
848 memcpy(&outputU[uvMaxH * rowBytesU], uLastRow, uvSize.width()); 852 memcpy(&outputU[uvMaxH * rowBytesU], uLastRow, uvSize.width());
(...skipping 26 matching lines...) Expand all
875 879
876 // All objects need to be instantiated before this setjmp call so that 880 // All objects need to be instantiated before this setjmp call so that
877 // they will be cleaned up properly if an error occurs. 881 // they will be cleaned up properly if an error occurs.
878 if (setjmp(errorManager.fJmpBuf)) { 882 if (setjmp(errorManager.fJmpBuf)) {
879 return return_false(cinfo, "setjmp YUV8"); 883 return return_false(cinfo, "setjmp YUV8");
880 } 884 }
881 885
882 initialize_info(&cinfo, &srcManager); 886 initialize_info(&cinfo, &srcManager);
883 autoClean.set(&cinfo); 887 autoClean.set(&cinfo);
884 888
885 int status = jpeg_read_header(&cinfo, true); 889 int status = jReadHeader(&cinfo, true);
886 if (status != JPEG_HEADER_OK) { 890 if (status != JPEG_HEADER_OK) {
887 return return_false(cinfo, "read_header YUV8"); 891 return return_false(cinfo, "read_header YUV8");
888 } 892 }
889 893
890 if (!appears_to_be_yuv(cinfo)) { 894 if (!appears_to_be_yuv(cinfo)) {
891 // It's not an error to not be encoded in YUV, so no need to use return_ false() 895 // It's not an error to not be encoded in YUV, so no need to use return_ false()
892 return false; 896 return false;
893 } 897 }
894 898
895 cinfo.out_color_space = JCS_YCbCr; 899 cinfo.out_color_space = JCS_YCbCr;
896 cinfo.raw_data_out = TRUE; 900 cinfo.raw_data_out = TRUE;
897 901
898 if (!planes || !planes[0] || !rowBytes || !rowBytes[0]) { // Compute size on ly 902 if (!planes || !planes[0] || !rowBytes || !rowBytes[0]) { // Compute size on ly
899 update_components_sizes(cinfo, componentSizes, kSizeForMemoryAllocation_ SizeType); 903 update_components_sizes(cinfo, componentSizes, kSizeForMemoryAllocation_ SizeType);
900 return true; 904 return true;
901 } 905 }
902 906
903 set_dct_method(*this, &cinfo); 907 set_dct_method(*this, &cinfo);
904 908
905 SkASSERT(1 == cinfo.scale_num); 909 SkASSERT(1 == cinfo.scale_num);
906 cinfo.scale_denom = 1; 910 cinfo.scale_denom = 1;
907 911
908 turn_off_visual_optimizations(&cinfo); 912 turn_off_visual_optimizations(&cinfo);
909 913
910 #ifdef ANDROID_RGB 914 #ifdef ANDROID_RGB
911 cinfo.dither_mode = JDITHER_NONE; 915 cinfo.dither_mode = JDITHER_NONE;
912 #endif 916 #endif
913 917
914 /* image_width and image_height are the original dimensions, available 918 /* image_width and image_height are the original dimensions, available
915 after jpeg_read_header(). To see the scaled dimensions, we have to call 919 after jReadHeader(). To see the scaled dimensions, we have to call
916 jpeg_start_decompress(), and then read output_width and output_height. 920 jStrtDecompress(), and then read output_width and output_height.
917 */ 921 */
918 if (!jpeg_start_decompress(&cinfo)) { 922 if (!jStrtDecompress(&cinfo)) {
919 return return_false(cinfo, "start_decompress YUV8"); 923 return return_false(cinfo, "start_decompress YUV8");
920 } 924 }
921 925
922 // Seems like jpeg_start_decompress is updating our opinion of whether cinfo represents YUV. 926 // Seems like jStrtDecompress is updating our opinion of whether cinfo repre sents YUV.
923 // Again, not really an error. 927 // Again, not really an error.
924 if (!appears_to_be_yuv(cinfo)) { 928 if (!appears_to_be_yuv(cinfo)) {
925 return false; 929 return false;
926 } 930 }
927 931
928 if (!output_raw_data(cinfo, planes, rowBytes)) { 932 if (!output_raw_data(cinfo, planes, rowBytes)) {
929 return return_false(cinfo, "output_raw_data"); 933 return return_false(cinfo, "output_raw_data");
930 } 934 }
931 935
932 update_components_sizes(cinfo, componentSizes, kActualSize_SizeType); 936 update_components_sizes(cinfo, componentSizes, kActualSize_SizeType);
933 jpeg_finish_decompress(&cinfo); 937 jFinDecompress(&cinfo);
934 938
935 if (NULL != colorSpace) { 939 if (NULL != colorSpace) {
936 *colorSpace = kJPEG_SkYUVColorSpace; 940 *colorSpace = kJPEG_SkYUVColorSpace;
937 } 941 }
938 942
939 return true; 943 return true;
940 } 944 }
941 945
942 /////////////////////////////////////////////////////////////////////////////// 946 ///////////////////////////////////////////////////////////////////////////////
943 947
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
977 set_error_mgr(cinfo, &sk_err); 981 set_error_mgr(cinfo, &sk_err);
978 982
979 // FIXME: This sets cinfo->out_color_space, which we may change later 983 // FIXME: This sets cinfo->out_color_space, which we may change later
980 // based on the config in onDecodeSubset. This should be fine, since 984 // based on the config in onDecodeSubset. This should be fine, since
981 // jpeg_init_read_tile_scanline will check out_color_space again after 985 // jpeg_init_read_tile_scanline will check out_color_space again after
982 // that change (when it calls jinit_color_deconverter). 986 // that change (when it calls jinit_color_deconverter).
983 (void) this->getBitmapColorType(cinfo); 987 (void) this->getBitmapColorType(cinfo);
984 988
985 turn_off_visual_optimizations(cinfo); 989 turn_off_visual_optimizations(cinfo);
986 990
987 // instead of jpeg_start_decompress() we start a tiled decompress 991 // instead of jStrtDecompress() we start a tiled decompress
988 if (!imageIndex->startTileDecompress()) { 992 if (!imageIndex->startTileDecompress()) {
989 return false; 993 return false;
990 } 994 }
991 995
992 SkASSERT(1 == cinfo->scale_num); 996 SkASSERT(1 == cinfo->scale_num);
993 fImageWidth = cinfo->output_width; 997 fImageWidth = cinfo->output_width;
994 fImageHeight = cinfo->output_height; 998 fImageHeight = cinfo->output_height;
995 999
996 if (width) { 1000 if (width) {
997 *width = fImageWidth; 1001 *width = fImageWidth;
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after
1352 return false; 1356 return false;
1353 } 1357 }
1354 1358
1355 jpeg_compress_struct cinfo; 1359 jpeg_compress_struct cinfo;
1356 skjpeg_error_mgr sk_err; 1360 skjpeg_error_mgr sk_err;
1357 skjpeg_destination_mgr sk_wstream(stream); 1361 skjpeg_destination_mgr sk_wstream(stream);
1358 1362
1359 // allocate these before set call setjmp 1363 // allocate these before set call setjmp
1360 SkAutoMalloc oneRow; 1364 SkAutoMalloc oneRow;
1361 1365
1362 cinfo.err = jpeg_std_error(&sk_err); 1366 cinfo.err = jStdError(&sk_err);
1363 sk_err.error_exit = skjpeg_error_exit; 1367 sk_err.error_exit = skjpeg_error_exit;
1364 if (setjmp(sk_err.fJmpBuf)) { 1368 if (setjmp(sk_err.fJmpBuf)) {
1365 return false; 1369 return false;
1366 } 1370 }
1367 1371
1368 // Keep after setjmp or mark volatile. 1372 // Keep after setjmp or mark volatile.
1369 const WriteScanline writer = ChooseWriter(bm); 1373 const WriteScanline writer = ChooseWriter(bm);
1370 if (NULL == writer) { 1374 if (NULL == writer) {
1371 return false; 1375 return false;
1372 } 1376 }
1373 1377
1374 jpeg_create_compress(&cinfo); 1378 jpeg_create_compress(&cinfo);
1375 cinfo.dest = &sk_wstream; 1379 cinfo.dest = &sk_wstream;
1376 cinfo.image_width = bm.width(); 1380 cinfo.image_width = bm.width();
1377 cinfo.image_height = bm.height(); 1381 cinfo.image_height = bm.height();
1378 cinfo.input_components = 3; 1382 cinfo.input_components = 3;
1379 #ifdef WE_CONVERT_TO_YUV 1383 #ifdef WE_CONVERT_TO_YUV
1380 cinfo.in_color_space = JCS_YCbCr; 1384 cinfo.in_color_space = JCS_YCbCr;
1381 #else 1385 #else
1382 cinfo.in_color_space = JCS_RGB; 1386 cinfo.in_color_space = JCS_RGB;
1383 #endif 1387 #endif
1384 cinfo.input_gamma = 1; 1388 cinfo.input_gamma = 1;
1385 1389
1386 jpeg_set_defaults(&cinfo); 1390 jSetDefaults(&cinfo);
1387 jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); 1391 jSetQuality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
1388 #ifdef DCT_IFAST_SUPPORTED 1392 #ifdef DCT_IFAST_SUPPORTED
1389 cinfo.dct_method = JDCT_IFAST; 1393 cinfo.dct_method = JDCT_IFAST;
1390 #endif 1394 #endif
1391 1395
1392 jpeg_start_compress(&cinfo, TRUE); 1396 jStrtCompress(&cinfo, TRUE);
1393 1397
1394 const int width = bm.width(); 1398 const int width = bm.width();
1395 uint8_t* oneRowP = (uint8_t*)oneRow.reset(width * 3); 1399 uint8_t* oneRowP = (uint8_t*)oneRow.reset(width * 3);
1396 1400
1397 const SkPMColor* colors = bm.getColorTable() ? bm.getColorTable()->readC olors() : NULL; 1401 const SkPMColor* colors = bm.getColorTable() ? bm.getColorTable()->readC olors() : NULL;
1398 const void* srcRow = bm.getPixels(); 1402 const void* srcRow = bm.getPixels();
1399 1403
1400 while (cinfo.next_scanline < cinfo.image_height) { 1404 while (cinfo.next_scanline < cinfo.image_height) {
1401 JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ 1405 JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
1402 1406
1403 writer(oneRowP, srcRow, width, colors); 1407 writer(oneRowP, srcRow, width, colors);
1404 row_pointer[0] = oneRowP; 1408 row_pointer[0] = oneRowP;
1405 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); 1409 (void) jWrtScanlines(&cinfo, row_pointer, 1);
1406 srcRow = (const void*)((const char*)srcRow + bm.rowBytes()); 1410 srcRow = (const void*)((const char*)srcRow + bm.rowBytes());
1407 } 1411 }
1408 1412
1409 jpeg_finish_compress(&cinfo); 1413 jFinCompress(&cinfo);
1410 jpeg_destroy_compress(&cinfo); 1414 jDestCompress(&cinfo);
1411 1415
1412 return true; 1416 return true;
1413 } 1417 }
1414 }; 1418 };
1415 1419
1416 /////////////////////////////////////////////////////////////////////////////// 1420 ///////////////////////////////////////////////////////////////////////////////
1417 DEFINE_DECODER_CREATOR(JPEGImageDecoder); 1421 DEFINE_DECODER_CREATOR(JPEGImageDecoder);
1418 DEFINE_ENCODER_CREATOR(JPEGImageEncoder); 1422 DEFINE_ENCODER_CREATOR(JPEGImageEncoder);
1419 /////////////////////////////////////////////////////////////////////////////// 1423 ///////////////////////////////////////////////////////////////////////////////
1420 1424
(...skipping 28 matching lines...) Expand all
1449 return SkImageDecoder::kUnknown_Format; 1453 return SkImageDecoder::kUnknown_Format;
1450 } 1454 }
1451 1455
1452 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { 1456 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) {
1453 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL; 1457 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL;
1454 } 1458 }
1455 1459
1456 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory); 1460 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory);
1457 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg); 1461 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg);
1458 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory); 1462 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698