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

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

Issue 399683007: JPEG YUV Decoding (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: API changes 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderWarnings, 47 SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderWarnings,
48 "images.jpeg.suppressDecoderWarnings", 48 "images.jpeg.suppressDecoderWarnings",
49 DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS, 49 DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS,
50 "Suppress most JPG warnings when calling decode functions."); 50 "Suppress most JPG warnings when calling decode functions.");
51 SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderErrors, 51 SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderErrors,
52 "images.jpeg.suppressDecoderErrors", 52 "images.jpeg.suppressDecoderErrors",
53 DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS, 53 DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS,
54 "Suppress most JPG error messages when decode " 54 "Suppress most JPG error messages when decode "
55 "function fails."); 55 "function fails.");
56 56
57 // Enum for YUV decoding
scroggo 2014/10/15 15:16:06 Could these enums be moved closer to where they ar
sugoi1 2014/10/15 17:47:43 Done.
58 enum YUVSubsampling {
59 kUNKNOWN_YUVSubsampling,
60 k410_YUVSubsampling,
61 k411_YUVSubsampling,
62 k420_YUVSubsampling,
63 k422_YUVSubsampling,
64 k440_YUVSubsampling,
65 k444_YUVSubsampling
66 };
67
68 enum SizeType {
69 kSizeForMemoryAllocation_SizeType,
70 kActualSize_SizeType
71 };
72
57 ////////////////////////////////////////////////////////////////////////// 73 //////////////////////////////////////////////////////////////////////////
58 ////////////////////////////////////////////////////////////////////////// 74 //////////////////////////////////////////////////////////////////////////
59 75
60 static void overwrite_mem_buffer_size(jpeg_decompress_struct* cinfo) { 76 static void overwrite_mem_buffer_size(jpeg_decompress_struct* cinfo) {
61 #ifdef SK_BUILD_FOR_ANDROID 77 #ifdef SK_BUILD_FOR_ANDROID
62 /* Check if the device indicates that it has a large amount of system memory 78 /* Check if the device indicates that it has a large amount of system memory
63 * if so, increase the memory allocation to 30MB instead of the default 5MB. 79 * if so, increase the memory allocation to 30MB instead of the default 5MB.
64 */ 80 */
65 #ifdef ANDROID_LARGE_MEMORY_DEVICE 81 #ifdef ANDROID_LARGE_MEMORY_DEVICE
66 cinfo->mem->max_memory_to_use = 30 * 1024 * 1024; 82 cinfo->mem->max_memory_to_use = 30 * 1024 * 1024;
(...skipping 28 matching lines...) Expand all
95 } 111 }
96 /* To suppress error messages with a SK_DEBUG binary, set the 112 /* To suppress error messages with a SK_DEBUG binary, set the
97 * environment variable "skia_images_jpeg_suppressDecoderErrors" 113 * environment variable "skia_images_jpeg_suppressDecoderErrors"
98 * to "true". Inside a program that links to skia: 114 * to "true". Inside a program that links to skia:
99 * SK_CONF_SET("images.jpeg.suppressDecoderErrors", true); */ 115 * SK_CONF_SET("images.jpeg.suppressDecoderErrors", true); */
100 if (c_suppressJPEGImageDecoderErrors) { 116 if (c_suppressJPEGImageDecoderErrors) {
101 cinfo->err->output_message = &do_nothing_output_message; 117 cinfo->err->output_message = &do_nothing_output_message;
102 } 118 }
103 } 119 }
104 120
121 static SkISize compute_yuv_size(const jpeg_decompress_struct& info, int componen t,
scroggo 2014/10/15 15:16:05 Again, these functions appear to be defined well b
sugoi1 2014/10/15 17:47:43 Moved them lower.
122 SizeType sizeType)
123 {
scroggo 2014/10/15 15:16:05 style nit: open brace does not get its own line.
sugoi1 2014/10/15 17:47:44 Done.
124 if (sizeType == kSizeForMemoryAllocation_SizeType) {
125 return SkISize::Make(info.cur_comp_info[component]->width_in_blocks * DC TSIZE,
126 info.cur_comp_info[component]->height_in_blocks * D CTSIZE);
127 }
128 return SkISize::Make(info.cur_comp_info[component]->downsampled_width,
129 info.cur_comp_info[component]->downsampled_height);
130 }
131
132 static YUVSubsampling yuv_subsampling(const jpeg_decompress_struct& info)
133 {
134 if ((DCTSIZE == 8)
135 && (info.num_components == 3)
136 && (info.comps_in_scan >= info.num_components)
137 && (info.scale_denom <= 8)
138 && (info.cur_comp_info[0])
139 && (info.cur_comp_info[1])
140 && (info.cur_comp_info[2])
141 && (info.cur_comp_info[1]->h_samp_factor == 1)
142 && (info.cur_comp_info[1]->v_samp_factor == 1)
143 && (info.cur_comp_info[2]->h_samp_factor == 1)
144 && (info.cur_comp_info[2]->v_samp_factor == 1)) {
scroggo 2014/10/15 15:16:06 In this case, I think the open brace should go on
sugoi1 2014/10/15 17:47:43 Done.
145 int h = info.cur_comp_info[0]->h_samp_factor;
146 int v = info.cur_comp_info[0]->v_samp_factor;
147 // 4:4:4 : (h == 1) && (v == 1)
148 // 4:4:0 : (h == 1) && (v == 2)
149 // 4:2:2 : (h == 2) && (v == 1)
150 // 4:2:0 : (h == 2) && (v == 2)
151 // 4:1:1 : (h == 4) && (v == 1)
152 // 4:1:0 : (h == 4) && (v == 2)
153 if (v == 1) {
154 switch (h) {
155 case 1:
scroggo 2014/10/15 15:16:06 I think we don't match blink and/or chrome, but we
sugoi1 2014/10/15 17:47:43 Done.
156 return k444_YUVSubsampling;
157 case 2:
158 return k422_YUVSubsampling;
159 case 4:
160 return k411_YUVSubsampling;
161 default:
162 break;
163 }
164 } else if (v == 2) {
165 switch (h) {
166 case 1:
167 return k440_YUVSubsampling;
168 case 2:
169 return k420_YUVSubsampling;
170 case 4:
171 return k410_YUVSubsampling;
172 default:
173 break;
174 }
175 }
176 }
177
178 return kUNKNOWN_YUVSubsampling;
179 }
180
105 #ifdef SK_BUILD_FOR_ANDROID 181 #ifdef SK_BUILD_FOR_ANDROID
106 class SkJPEGImageIndex { 182 class SkJPEGImageIndex {
107 public: 183 public:
108 SkJPEGImageIndex(SkStreamRewindable* stream, SkImageDecoder* decoder) 184 SkJPEGImageIndex(SkStreamRewindable* stream, SkImageDecoder* decoder)
109 : fSrcMgr(stream, decoder) 185 : fSrcMgr(stream, decoder)
110 , fInfoInitialized(false) 186 , fInfoInitialized(false)
111 , fHuffmanCreated(false) 187 , fHuffmanCreated(false)
112 , fDecompressStarted(false) 188 , fDecompressStarted(false)
113 { 189 {
114 SkDEBUGCODE(fReadHeaderSucceeded = false;) 190 SkDEBUGCODE(fReadHeaderSucceeded = false;)
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 virtual Format getFormat() const { 308 virtual Format getFormat() const {
233 return kJPEG_Format; 309 return kJPEG_Format;
234 } 310 }
235 311
236 protected: 312 protected:
237 #ifdef SK_BUILD_FOR_ANDROID 313 #ifdef SK_BUILD_FOR_ANDROID
238 virtual bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *h eight) SK_OVERRIDE; 314 virtual bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *h eight) SK_OVERRIDE;
239 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRI DE; 315 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRI DE;
240 #endif 316 #endif
241 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; 317 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE;
318 virtual bool onDecodeYUV8Planes(SkStream* stream, SkISize componentSizes[3],
319 void* planes[3], size_t rowBytes[3],
320 SkYUVColorSpace* colorSpace) SK_OVERRIDE;
242 321
243 private: 322 private:
244 #ifdef SK_BUILD_FOR_ANDROID 323 #ifdef SK_BUILD_FOR_ANDROID
245 SkJPEGImageIndex* fImageIndex; 324 SkJPEGImageIndex* fImageIndex;
246 int fImageWidth; 325 int fImageWidth;
247 int fImageHeight; 326 int fImageHeight;
248 #endif 327 #endif
249 328
250 /** 329 /**
251 * Determine the appropriate bitmap colortype and out_color_space based on 330 * Determine the appropriate bitmap colortype and out_color_space based on
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 return false; 397 return false;
319 } 398 }
320 } 399 }
321 return true; 400 return true;
322 } 401 }
323 #endif 402 #endif
324 403
325 // This guy exists just to aid in debugging, as it allows debuggers to just 404 // This guy exists just to aid in debugging, as it allows debuggers to just
326 // set a break-point in one place to see all error exists. 405 // set a break-point in one place to see all error exists.
327 static bool return_false(const jpeg_decompress_struct& cinfo, 406 static bool return_false(const jpeg_decompress_struct& cinfo,
328 const SkBitmap& bm, const char caller[]) { 407 int width, int height, const char caller[]) {
329 if (!(c_suppressJPEGImageDecoderErrors)) { 408 if (!(c_suppressJPEGImageDecoderErrors)) {
330 char buffer[JMSG_LENGTH_MAX]; 409 char buffer[JMSG_LENGTH_MAX];
331 cinfo.err->format_message((const j_common_ptr)&cinfo, buffer); 410 cinfo.err->format_message((const j_common_ptr)&cinfo, buffer);
332 SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n", 411 SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n",
333 cinfo.err->msg_code, buffer, caller, bm.width(), bm.height()); 412 cinfo.err->msg_code, buffer, caller, width, height);
334 } 413 }
335 return false; // must always return false 414 return false; // must always return false
336 } 415 }
337 416
417 static bool return_false(const jpeg_decompress_struct& cinfo,
418 const SkBitmap& bm, const char caller[]) {
419 return return_false(cinfo, bm.width(), bm.height(), caller);
420 }
421
338 // Convert a scanline of CMYK samples to RGBX in place. Note that this 422 // Convert a scanline of CMYK samples to RGBX in place. Note that this
339 // method moves the "scanline" pointer in its processing 423 // method moves the "scanline" pointer in its processing
340 static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) { 424 static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) {
341 // At this point we've received CMYK pixels from libjpeg. We 425 // At this point we've received CMYK pixels from libjpeg. We
342 // perform a crude conversion to RGB (based on the formulae 426 // perform a crude conversion to RGB (based on the formulae
343 // from easyrgb.com): 427 // from easyrgb.com):
344 // CMYK -> CMY 428 // CMYK -> CMY
345 // C = ( C * (1 - K) + K ) // for each CMY component 429 // C = ( C * (1 - K) + K ) // for each CMY component
346 // CMY -> RGB 430 // CMY -> RGB
347 // R = ( 1 - C ) * 255 // for each RGB component 431 // R = ( 1 - C ) * 255 // for each RGB component
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after
719 // we formally skip the rest, so we don't get a complaint from libjpeg 803 // we formally skip the rest, so we don't get a complaint from libjpeg
720 if (!skip_src_rows(&cinfo, srcRow, 804 if (!skip_src_rows(&cinfo, srcRow,
721 cinfo.output_height - cinfo.output_scanline)) { 805 cinfo.output_height - cinfo.output_scanline)) {
722 return return_false(cinfo, *bm, "skip rows"); 806 return return_false(cinfo, *bm, "skip rows");
723 } 807 }
724 jpeg_finish_decompress(&cinfo); 808 jpeg_finish_decompress(&cinfo);
725 809
726 return true; 810 return true;
727 } 811 }
728 812
813 static void update_components_sizes(const jpeg_decompress_struct& cinfo, SkISize componentSizes[3],
814 SizeType sizeType) {
815 for (int i = 0; i < 3; ++i) {
816 componentSizes[i] = compute_yuv_size(cinfo, i, sizeType);
817 }
818 }
819
820 static bool output_raw_data(jpeg_decompress_struct& cinfo, void* planes[3], size _t rowBytes[3]) {
821 // U size and V size have to be the same if we're calling output_raw_dat a()
822 SkISize uvSize = compute_yuv_size(cinfo, 1, kSizeForMemoryAllocation_Siz eType);
scroggo 2014/10/15 15:16:05 nit: indentation (first two lines)
sugoi1 2014/10/15 17:47:43 Oops, there were tabs in there. Removed.
823 SkASSERT(uvSize == compute_yuv_size(cinfo, 2, kSizeForMemoryAllocation_SizeT ype));
824
825 JSAMPARRAY bufferraw[3];
826 JSAMPROW bufferraw2[32];
827 bufferraw[0] = &bufferraw2[0]; // Y channel rows (8 or 16)
828 bufferraw[1] = &bufferraw2[16]; // U channel rows (8)
829 bufferraw[2] = &bufferraw2[24]; // V channel rows (8)
830 int yWidth = cinfo.output_width;
831 int yHeight = cinfo.output_height;
832 int yMaxH = yHeight - 1;
833 int v = cinfo.cur_comp_info[0]->v_samp_factor;
834 int uvMaxH = uvSize.height() - 1;
835 JSAMPROW outputY = static_cast<JSAMPROW>(planes[0]);
836 JSAMPROW outputU = static_cast<JSAMPROW>(planes[1]);
837 JSAMPROW outputV = static_cast<JSAMPROW>(planes[2]);
838 size_t rowBytesY = rowBytes[0];
839 size_t rowBytesU = rowBytes[1];
840 size_t rowBytesV = rowBytes[2];
841
842 int yScanlinesToRead = DCTSIZE * v;
843 SkAutoMalloc lastRowStorage(yWidth * 8);
844 JSAMPROW yLastRow = (JSAMPROW)lastRowStorage.get();
845 JSAMPROW uLastRow = yLastRow + 2 * yWidth;
846 JSAMPROW vLastRow = uLastRow + 2 * yWidth;
847 JSAMPROW dummyRow = vLastRow + 2 * yWidth;
848
849 while (cinfo.output_scanline < cinfo.output_height) {
850 // Request 8 or 16 scanlines: returns 0 or more scanlines.
851 bool hasYLastRow(false), hasUVLastRow(false);
852 // Assign 8 or 16 rows of memory to read the Y channel.
853 for (int i = 0; i < yScanlinesToRead; ++i) {
854 int scanline = (cinfo.output_scanline + i);
855 if (scanline < yMaxH) {
856 bufferraw2[i] = &outputY[scanline * rowBytesY];
857 } else if (scanline == yMaxH) {
858 bufferraw2[i] = yLastRow;
859 hasYLastRow = true;
860 } else {
861 bufferraw2[i] = dummyRow;
862 }
863 }
864 int scaledScanline = cinfo.output_scanline / v;
865 // Assign 8 rows of memory to read the U and V channels.
866 for (int i = 0; i < 8; ++i) {
867 int scanline = (scaledScanline + i);
868 if (scanline < uvMaxH) {
869 bufferraw2[16 + i] = &outputU[scanline * rowBytesU];
870 bufferraw2[24 + i] = &outputV[scanline * rowBytesV];
871 } else if (scanline == uvMaxH) {
872 bufferraw2[16 + i] = uLastRow;
873 bufferraw2[24 + i] = vLastRow;
874 hasUVLastRow = true;
875 } else {
876 bufferraw2[16 + i] = dummyRow;
877 bufferraw2[24 + i] = dummyRow;
878 }
879 }
880 JDIMENSION scanlinesRead = jpeg_read_raw_data(&cinfo, bufferraw, yScanli nesToRead);
881
882 if (scanlinesRead == 0)
883 return false;
884
885 if (hasYLastRow) {
886 memcpy(&outputY[yMaxH * rowBytesY], yLastRow, yWidth);
887 }
888 if (hasUVLastRow) {
889 memcpy(&outputU[uvMaxH * rowBytesU], uLastRow, uvSize.width());
890 memcpy(&outputV[uvMaxH * rowBytesV], vLastRow, uvSize.width());
891 }
892 }
893
894 cinfo.output_scanline = SkMin32(cinfo.output_scanline, cinfo.output_height);
895
896 return true;
897 }
898
899 bool SkJPEGImageDecoder::onDecodeYUV8Planes(SkStream* stream, SkISize componentS izes[3],
900 void* planes[3], size_t rowBytes[3],
901 SkYUVColorSpace* colorSpace) {
902 #ifdef TIME_DECODE
903 SkAutoTime atm("JPEG Decode");
scroggo 2014/10/15 15:16:06 Not sure if anyone uses TIME_DECODE, but shouldn't
sugoi1 2014/10/15 17:47:43 Done.
904 #endif
905
906 if (this->getSampleSize() != 1) {
907 return false; // Resizing not supported
scroggo 2014/10/15 15:16:05 Is there a way we could let the client know this?
sugoi1 2014/10/15 17:47:43 Well, it's not that it's impossible, it's just not
908 }
909
910 JPEGAutoClean autoClean;
911
912 jpeg_decompress_struct cinfo;
913 skjpeg_source_mgr srcManager(stream, this);
914
915 skjpeg_error_mgr errorManager;
916 set_error_mgr(&cinfo, &errorManager);
917
918 // All objects need to be instantiated before this setjmp call so that
919 // they will be cleaned up properly if an error occurs.
920 if (setjmp(errorManager.fJmpBuf)) {
921 return return_false(cinfo, 0, 0, "setjmp");
922 }
923
924 initialize_info(&cinfo, &srcManager);
925 autoClean.set(&cinfo);
926
927 int status = jpeg_read_header(&cinfo, true);
928 if (status != JPEG_HEADER_OK) {
929 return return_false(cinfo, 0, 0, "read_header");
930 }
931
932 if (cinfo.jpeg_color_space != JCS_YCbCr) {
933 // It's not an error to not be encoded in YUV, so no need to use return_ false()
934 return false;
935 }
936
937 cinfo.out_color_space = JCS_YCbCr;
938 cinfo.raw_data_out = TRUE;
939
940 if (!planes || !planes[0] || !rowBytes || !rowBytes[0]) { // Compute size on ly
941 update_components_sizes(cinfo, componentSizes, kSizeForMemoryAllocation_ SizeType);
942 return true;
943 }
944
945 set_dct_method(*this, &cinfo);
946
947 SkASSERT(1 == cinfo.scale_num);
948 cinfo.scale_denom = 1;
949
950 turn_off_visual_optimizations(&cinfo);
951
952 #ifdef ANDROID_RGB
953 cinfo.dither_mode = JDITHER_NONE;
954 #endif
955
956 /* image_width and image_height are the original dimensions, available
scroggo 2014/10/15 15:16:06 This comment appears to have been copied word for
sugoi1 2014/10/15 17:47:43 Actually, it does apply, output_width and output_h
957 after jpeg_read_header(). To see the scaled dimensions, we have to call
958 jpeg_start_decompress(), and then read output_width and output_height.
959 */
960 if (!jpeg_start_decompress(&cinfo)) {
961 return return_false(cinfo, 0, 0, "start_decompress");
962 }
963
964 if (!output_raw_data(cinfo, planes, rowBytes)) {
965 return return_false(cinfo, 0, 0, "output_raw_data");
966 }
967
968 update_components_sizes(cinfo, componentSizes, kActualSize_SizeType);
969 jpeg_finish_decompress(&cinfo);
970
971 if (NULL != colorSpace) {
reed1 2014/10/15 15:08:08 Does libjpeg actually support different spaces? If
sugoi1 2014/10/15 17:47:44 Not that I know of. AFAIK, JPEG always uses the sa
972 *colorSpace = kJPEG_SkYUVColorSpace;
973 }
974
975 return true;
976 }
977
729 #ifdef SK_BUILD_FOR_ANDROID 978 #ifdef SK_BUILD_FOR_ANDROID
730 bool SkJPEGImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, int *width , int *height) { 979 bool SkJPEGImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, int *width , int *height) {
731 980
732 SkAutoTDelete<SkJPEGImageIndex> imageIndex(SkNEW_ARGS(SkJPEGImageIndex, (str eam, this))); 981 SkAutoTDelete<SkJPEGImageIndex> imageIndex(SkNEW_ARGS(SkJPEGImageIndex, (str eam, this)));
733 jpeg_decompress_struct* cinfo = imageIndex->cinfo(); 982 jpeg_decompress_struct* cinfo = imageIndex->cinfo();
734 983
735 skjpeg_error_mgr sk_err; 984 skjpeg_error_mgr sk_err;
736 set_error_mgr(cinfo, &sk_err); 985 set_error_mgr(cinfo, &sk_err);
737 986
738 // All objects need to be instantiated before this setjmp call so that 987 // All objects need to be instantiated before this setjmp call so that
(...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after
1233 return SkImageDecoder::kUnknown_Format; 1482 return SkImageDecoder::kUnknown_Format;
1234 } 1483 }
1235 1484
1236 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { 1485 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) {
1237 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL; 1486 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL;
1238 } 1487 }
1239 1488
1240 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory); 1489 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory);
1241 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg); 1490 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg);
1242 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory); 1491 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