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 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 virtual Format getFormat() const { | 232 virtual Format getFormat() const { |
233 return kJPEG_Format; | 233 return kJPEG_Format; |
234 } | 234 } |
235 | 235 |
236 protected: | 236 protected: |
237 #ifdef SK_BUILD_FOR_ANDROID | 237 #ifdef SK_BUILD_FOR_ANDROID |
238 virtual bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *h
eight) SK_OVERRIDE; | 238 virtual bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *h
eight) SK_OVERRIDE; |
239 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRI
DE; | 239 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRI
DE; |
240 #endif | 240 #endif |
241 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; | 241 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; |
242 virtual bool onDecodeYUV8Planes(SkStream* stream, SkISize componentSizes[3], | |
243 void* planes[3], size_t rowBytes[3], | |
244 SkYUVColorSpace* colorSpace) SK_OVERRIDE; | |
245 | 242 |
246 private: | 243 private: |
247 #ifdef SK_BUILD_FOR_ANDROID | 244 #ifdef SK_BUILD_FOR_ANDROID |
248 SkJPEGImageIndex* fImageIndex; | 245 SkJPEGImageIndex* fImageIndex; |
249 int fImageWidth; | 246 int fImageWidth; |
250 int fImageHeight; | 247 int fImageHeight; |
251 #endif | 248 #endif |
252 | 249 |
253 /** | 250 /** |
254 * Determine the appropriate bitmap colortype and out_color_space based on | 251 * Determine the appropriate bitmap colortype and out_color_space based on |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 return false; | 318 return false; |
322 } | 319 } |
323 } | 320 } |
324 return true; | 321 return true; |
325 } | 322 } |
326 #endif | 323 #endif |
327 | 324 |
328 // This guy exists just to aid in debugging, as it allows debuggers to just | 325 // This guy exists just to aid in debugging, as it allows debuggers to just |
329 // set a break-point in one place to see all error exists. | 326 // set a break-point in one place to see all error exists. |
330 static bool return_false(const jpeg_decompress_struct& cinfo, | 327 static bool return_false(const jpeg_decompress_struct& cinfo, |
331 int width, int height, const char caller[]) { | 328 const SkBitmap& bm, const char caller[]) { |
332 if (!(c_suppressJPEGImageDecoderErrors)) { | 329 if (!(c_suppressJPEGImageDecoderErrors)) { |
333 char buffer[JMSG_LENGTH_MAX]; | 330 char buffer[JMSG_LENGTH_MAX]; |
334 cinfo.err->format_message((const j_common_ptr)&cinfo, buffer); | 331 cinfo.err->format_message((const j_common_ptr)&cinfo, buffer); |
335 SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n", | 332 SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n", |
336 cinfo.err->msg_code, buffer, caller, width, height); | 333 cinfo.err->msg_code, buffer, caller, bm.width(), bm.height()); |
337 } | 334 } |
338 return false; // must always return false | 335 return false; // must always return false |
339 } | 336 } |
340 | 337 |
341 static bool return_false(const jpeg_decompress_struct& cinfo, | |
342 const SkBitmap& bm, const char caller[]) { | |
343 return return_false(cinfo, bm.width(), bm.height(), caller); | |
344 } | |
345 | |
346 // Convert a scanline of CMYK samples to RGBX in place. Note that this | 338 // Convert a scanline of CMYK samples to RGBX in place. Note that this |
347 // method moves the "scanline" pointer in its processing | 339 // method moves the "scanline" pointer in its processing |
348 static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) { | 340 static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) { |
349 // At this point we've received CMYK pixels from libjpeg. We | 341 // At this point we've received CMYK pixels from libjpeg. We |
350 // perform a crude conversion to RGB (based on the formulae | 342 // perform a crude conversion to RGB (based on the formulae |
351 // from easyrgb.com): | 343 // from easyrgb.com): |
352 // CMYK -> CMY | 344 // CMYK -> CMY |
353 // C = ( C * (1 - K) + K ) // for each CMY component | 345 // C = ( C * (1 - K) + K ) // for each CMY component |
354 // CMY -> RGB | 346 // CMY -> RGB |
355 // R = ( 1 - C ) * 255 // for each RGB component | 347 // R = ( 1 - C ) * 255 // for each RGB component |
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
727 // we formally skip the rest, so we don't get a complaint from libjpeg | 719 // we formally skip the rest, so we don't get a complaint from libjpeg |
728 if (!skip_src_rows(&cinfo, srcRow, | 720 if (!skip_src_rows(&cinfo, srcRow, |
729 cinfo.output_height - cinfo.output_scanline)) { | 721 cinfo.output_height - cinfo.output_scanline)) { |
730 return return_false(cinfo, *bm, "skip rows"); | 722 return return_false(cinfo, *bm, "skip rows"); |
731 } | 723 } |
732 jpeg_finish_decompress(&cinfo); | 724 jpeg_finish_decompress(&cinfo); |
733 | 725 |
734 return true; | 726 return true; |
735 } | 727 } |
736 | 728 |
737 enum SizeType { | |
738 kSizeForMemoryAllocation_SizeType, | |
739 kActualSize_SizeType | |
740 }; | |
741 | |
742 static SkISize compute_yuv_size(const jpeg_decompress_struct& info, int componen
t, | |
743 SizeType sizeType) { | |
744 if (sizeType == kSizeForMemoryAllocation_SizeType) { | |
745 return SkISize::Make(info.cur_comp_info[component]->width_in_blocks * DC
TSIZE, | |
746 info.cur_comp_info[component]->height_in_blocks * D
CTSIZE); | |
747 } | |
748 return SkISize::Make(info.cur_comp_info[component]->downsampled_width, | |
749 info.cur_comp_info[component]->downsampled_height); | |
750 } | |
751 | |
752 // Enum for YUV decoding | |
753 enum YUVSubsampling { | |
754 kUNKNOWN_YUVSubsampling, | |
755 k410_YUVSubsampling, | |
756 k411_YUVSubsampling, | |
757 k420_YUVSubsampling, | |
758 k422_YUVSubsampling, | |
759 k440_YUVSubsampling, | |
760 k444_YUVSubsampling | |
761 }; | |
762 | |
763 static YUVSubsampling yuv_subsampling(const jpeg_decompress_struct& info) { | |
764 if ((DCTSIZE == 8) | |
765 && (info.num_components == 3) | |
766 && (info.comps_in_scan >= info.num_components) | |
767 && (info.scale_denom <= 8) | |
768 && (info.cur_comp_info[0]) | |
769 && (info.cur_comp_info[1]) | |
770 && (info.cur_comp_info[2]) | |
771 && (info.cur_comp_info[1]->h_samp_factor == 1) | |
772 && (info.cur_comp_info[1]->v_samp_factor == 1) | |
773 && (info.cur_comp_info[2]->h_samp_factor == 1) | |
774 && (info.cur_comp_info[2]->v_samp_factor == 1)) | |
775 { | |
776 int h = info.cur_comp_info[0]->h_samp_factor; | |
777 int v = info.cur_comp_info[0]->v_samp_factor; | |
778 // 4:4:4 : (h == 1) && (v == 1) | |
779 // 4:4:0 : (h == 1) && (v == 2) | |
780 // 4:2:2 : (h == 2) && (v == 1) | |
781 // 4:2:0 : (h == 2) && (v == 2) | |
782 // 4:1:1 : (h == 4) && (v == 1) | |
783 // 4:1:0 : (h == 4) && (v == 2) | |
784 if (v == 1) { | |
785 switch (h) { | |
786 case 1: | |
787 return k444_YUVSubsampling; | |
788 case 2: | |
789 return k422_YUVSubsampling; | |
790 case 4: | |
791 return k411_YUVSubsampling; | |
792 default: | |
793 break; | |
794 } | |
795 } else if (v == 2) { | |
796 switch (h) { | |
797 case 1: | |
798 return k440_YUVSubsampling; | |
799 case 2: | |
800 return k420_YUVSubsampling; | |
801 case 4: | |
802 return k410_YUVSubsampling; | |
803 default: | |
804 break; | |
805 } | |
806 } | |
807 } | |
808 | |
809 return kUNKNOWN_YUVSubsampling; | |
810 } | |
811 | |
812 static void update_components_sizes(const jpeg_decompress_struct& cinfo, SkISize
componentSizes[3], | |
813 SizeType sizeType) { | |
814 for (int i = 0; i < 3; ++i) { | |
815 componentSizes[i] = compute_yuv_size(cinfo, i, sizeType); | |
816 } | |
817 } | |
818 | |
819 static bool output_raw_data(jpeg_decompress_struct& cinfo, void* planes[3], size
_t rowBytes[3]) { | |
820 // U size and V size have to be the same if we're calling output_raw_data() | |
821 SkISize uvSize = compute_yuv_size(cinfo, 1, kSizeForMemoryAllocation_SizeTyp
e); | |
822 SkASSERT(uvSize == compute_yuv_size(cinfo, 2, kSizeForMemoryAllocation_SizeT
ype)); | |
823 | |
824 JSAMPARRAY bufferraw[3]; | |
825 JSAMPROW bufferraw2[32]; | |
826 bufferraw[0] = &bufferraw2[0]; // Y channel rows (8 or 16) | |
827 bufferraw[1] = &bufferraw2[16]; // U channel rows (8) | |
828 bufferraw[2] = &bufferraw2[24]; // V channel rows (8) | |
829 int yWidth = cinfo.output_width; | |
830 int yHeight = cinfo.output_height; | |
831 int yMaxH = yHeight - 1; | |
832 int v = cinfo.cur_comp_info[0]->v_samp_factor; | |
833 int uvMaxH = uvSize.height() - 1; | |
834 JSAMPROW outputY = static_cast<JSAMPROW>(planes[0]); | |
835 JSAMPROW outputU = static_cast<JSAMPROW>(planes[1]); | |
836 JSAMPROW outputV = static_cast<JSAMPROW>(planes[2]); | |
837 size_t rowBytesY = rowBytes[0]; | |
838 size_t rowBytesU = rowBytes[1]; | |
839 size_t rowBytesV = rowBytes[2]; | |
840 | |
841 int yScanlinesToRead = DCTSIZE * v; | |
842 SkAutoMalloc lastRowStorage(yWidth * 8); | |
843 JSAMPROW yLastRow = (JSAMPROW)lastRowStorage.get(); | |
844 JSAMPROW uLastRow = yLastRow + 2 * yWidth; | |
845 JSAMPROW vLastRow = uLastRow + 2 * yWidth; | |
846 JSAMPROW dummyRow = vLastRow + 2 * yWidth; | |
847 | |
848 while (cinfo.output_scanline < cinfo.output_height) { | |
849 // Request 8 or 16 scanlines: returns 0 or more scanlines. | |
850 bool hasYLastRow(false), hasUVLastRow(false); | |
851 // Assign 8 or 16 rows of memory to read the Y channel. | |
852 for (int i = 0; i < yScanlinesToRead; ++i) { | |
853 int scanline = (cinfo.output_scanline + i); | |
854 if (scanline < yMaxH) { | |
855 bufferraw2[i] = &outputY[scanline * rowBytesY]; | |
856 } else if (scanline == yMaxH) { | |
857 bufferraw2[i] = yLastRow; | |
858 hasYLastRow = true; | |
859 } else { | |
860 bufferraw2[i] = dummyRow; | |
861 } | |
862 } | |
863 int scaledScanline = cinfo.output_scanline / v; | |
864 // Assign 8 rows of memory to read the U and V channels. | |
865 for (int i = 0; i < 8; ++i) { | |
866 int scanline = (scaledScanline + i); | |
867 if (scanline < uvMaxH) { | |
868 bufferraw2[16 + i] = &outputU[scanline * rowBytesU]; | |
869 bufferraw2[24 + i] = &outputV[scanline * rowBytesV]; | |
870 } else if (scanline == uvMaxH) { | |
871 bufferraw2[16 + i] = uLastRow; | |
872 bufferraw2[24 + i] = vLastRow; | |
873 hasUVLastRow = true; | |
874 } else { | |
875 bufferraw2[16 + i] = dummyRow; | |
876 bufferraw2[24 + i] = dummyRow; | |
877 } | |
878 } | |
879 JDIMENSION scanlinesRead = jpeg_read_raw_data(&cinfo, bufferraw, yScanli
nesToRead); | |
880 | |
881 if (scanlinesRead == 0) | |
882 return false; | |
883 | |
884 if (hasYLastRow) { | |
885 memcpy(&outputY[yMaxH * rowBytesY], yLastRow, yWidth); | |
886 } | |
887 if (hasUVLastRow) { | |
888 memcpy(&outputU[uvMaxH * rowBytesU], uLastRow, uvSize.width()); | |
889 memcpy(&outputV[uvMaxH * rowBytesV], vLastRow, uvSize.width()); | |
890 } | |
891 } | |
892 | |
893 cinfo.output_scanline = SkMin32(cinfo.output_scanline, cinfo.output_height); | |
894 | |
895 return true; | |
896 } | |
897 | |
898 bool SkJPEGImageDecoder::onDecodeYUV8Planes(SkStream* stream, SkISize componentS
izes[3], | |
899 void* planes[3], size_t rowBytes[3], | |
900 SkYUVColorSpace* colorSpace) { | |
901 #ifdef TIME_DECODE | |
902 SkAutoTime atm("JPEG YUV8 Decode"); | |
903 #endif | |
904 | |
905 if (this->getSampleSize() != 1) { | |
906 return false; // Resizing not supported | |
907 } | |
908 | |
909 JPEGAutoClean autoClean; | |
910 | |
911 jpeg_decompress_struct cinfo; | |
912 skjpeg_source_mgr srcManager(stream, this); | |
913 | |
914 skjpeg_error_mgr errorManager; | |
915 set_error_mgr(&cinfo, &errorManager); | |
916 | |
917 // All objects need to be instantiated before this setjmp call so that | |
918 // they will be cleaned up properly if an error occurs. | |
919 if (setjmp(errorManager.fJmpBuf)) { | |
920 return return_false(cinfo, 0, 0, "setjmp"); | |
921 } | |
922 | |
923 initialize_info(&cinfo, &srcManager); | |
924 autoClean.set(&cinfo); | |
925 | |
926 int status = jpeg_read_header(&cinfo, true); | |
927 if (status != JPEG_HEADER_OK) { | |
928 return return_false(cinfo, 0, 0, "read_header"); | |
929 } | |
930 | |
931 if (cinfo.jpeg_color_space != JCS_YCbCr) { | |
932 // It's not an error to not be encoded in YUV, so no need to use return_
false() | |
933 return false; | |
934 } | |
935 | |
936 cinfo.out_color_space = JCS_YCbCr; | |
937 cinfo.raw_data_out = TRUE; | |
938 | |
939 if (!planes || !planes[0] || !rowBytes || !rowBytes[0]) { // Compute size on
ly | |
940 update_components_sizes(cinfo, componentSizes, kSizeForMemoryAllocation_
SizeType); | |
941 return true; | |
942 } | |
943 | |
944 set_dct_method(*this, &cinfo); | |
945 | |
946 SkASSERT(1 == cinfo.scale_num); | |
947 cinfo.scale_denom = 1; | |
948 | |
949 turn_off_visual_optimizations(&cinfo); | |
950 | |
951 #ifdef ANDROID_RGB | |
952 cinfo.dither_mode = JDITHER_NONE; | |
953 #endif | |
954 | |
955 /* image_width and image_height are the original dimensions, available | |
956 after jpeg_read_header(). To see the scaled dimensions, we have to call | |
957 jpeg_start_decompress(), and then read output_width and output_height. | |
958 */ | |
959 if (!jpeg_start_decompress(&cinfo)) { | |
960 return return_false(cinfo, 0, 0, "start_decompress"); | |
961 } | |
962 | |
963 if (!output_raw_data(cinfo, planes, rowBytes)) { | |
964 return return_false(cinfo, 0, 0, "output_raw_data"); | |
965 } | |
966 | |
967 update_components_sizes(cinfo, componentSizes, kActualSize_SizeType); | |
968 jpeg_finish_decompress(&cinfo); | |
969 | |
970 if (NULL != colorSpace) { | |
971 *colorSpace = kJPEG_SkYUVColorSpace; | |
972 } | |
973 | |
974 return true; | |
975 } | |
976 | |
977 #ifdef SK_BUILD_FOR_ANDROID | 729 #ifdef SK_BUILD_FOR_ANDROID |
978 bool SkJPEGImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, int *width
, int *height) { | 730 bool SkJPEGImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, int *width
, int *height) { |
979 | 731 |
980 SkAutoTDelete<SkJPEGImageIndex> imageIndex(SkNEW_ARGS(SkJPEGImageIndex, (str
eam, this))); | 732 SkAutoTDelete<SkJPEGImageIndex> imageIndex(SkNEW_ARGS(SkJPEGImageIndex, (str
eam, this))); |
981 jpeg_decompress_struct* cinfo = imageIndex->cinfo(); | 733 jpeg_decompress_struct* cinfo = imageIndex->cinfo(); |
982 | 734 |
983 skjpeg_error_mgr sk_err; | 735 skjpeg_error_mgr sk_err; |
984 set_error_mgr(cinfo, &sk_err); | 736 set_error_mgr(cinfo, &sk_err); |
985 | 737 |
986 // All objects need to be instantiated before this setjmp call so that | 738 // All objects need to be instantiated before this setjmp call so that |
(...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1481 return SkImageDecoder::kUnknown_Format; | 1233 return SkImageDecoder::kUnknown_Format; |
1482 } | 1234 } |
1483 | 1235 |
1484 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { | 1236 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { |
1485 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL; | 1237 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL; |
1486 } | 1238 } |
1487 | 1239 |
1488 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory); | 1240 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory); |
1489 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg); | 1241 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg); |
1490 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory); | 1242 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory); |
OLD | NEW |