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

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

Issue 656163002: Revert of JPEG YUV Decoding (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 2 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
« no previous file with comments | « src/images/SkImageDecoder.cpp ('k') | tests/JpegTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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);
OLDNEW
« no previous file with comments | « src/images/SkImageDecoder.cpp ('k') | tests/JpegTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698