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