• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2007 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 
9 #include "SkImageDecoder.h"
10 #include "SkImageEncoder.h"
11 #include "SkJpegUtility.h"
12 #include "SkColorPriv.h"
13 #include "SkDither.h"
14 #include "SkScaledBitmapSampler.h"
15 #include "SkStream.h"
16 #include "SkTemplates.h"
17 #include "SkTime.h"
18 #include "SkUtils.h"
19 #include "SkRTConf.h"
20 #include "SkRect.h"
21 #include "SkCanvas.h"
22 
23 
24 #include <stdio.h>
25 extern "C" {
26     #include "jpeglib.h"
27     #include "jerror.h"
28 }
29 
30 // These enable timing code that report milliseconds for an encoding/decoding
31 //#define TIME_ENCODE
32 //#define TIME_DECODE
33 
34 // this enables our rgb->yuv code, which is faster than libjpeg on ARM
35 #define WE_CONVERT_TO_YUV
36 
37 // If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offers
38 // support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565.
39 
40 #if defined(SK_DEBUG)
41 #define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS false
42 #define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS false
43 #else  // !defined(SK_DEBUG)
44 #define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS true
45 #define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS true
46 #endif  // defined(SK_DEBUG)
47 SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderWarnings,
48                 "images.jpeg.suppressDecoderWarnings",
49                 DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS,
50                 "Suppress most JPG warnings when calling decode functions.");
51 SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderErrors,
52                 "images.jpeg.suppressDecoderErrors",
53                 DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS,
54                 "Suppress most JPG error messages when decode "
55                 "function fails.");
56 
57 //////////////////////////////////////////////////////////////////////////
58 //////////////////////////////////////////////////////////////////////////
59 
overwrite_mem_buffer_size(jpeg_decompress_struct * cinfo)60 static void overwrite_mem_buffer_size(jpeg_decompress_struct* cinfo) {
61 #ifdef SK_BUILD_FOR_ANDROID
62     /* 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.
64      */
65 #ifdef ANDROID_LARGE_MEMORY_DEVICE
66     cinfo->mem->max_memory_to_use = 30 * 1024 * 1024;
67 #else
68     cinfo->mem->max_memory_to_use = 5 * 1024 * 1024;
69 #endif
70 #endif // SK_BUILD_FOR_ANDROID
71 }
72 
73 //////////////////////////////////////////////////////////////////////////
74 //////////////////////////////////////////////////////////////////////////
75 
do_nothing_emit_message(jpeg_common_struct *,int)76 static void do_nothing_emit_message(jpeg_common_struct*, int) {
77     /* do nothing */
78 }
do_nothing_output_message(j_common_ptr)79 static void do_nothing_output_message(j_common_ptr) {
80     /* do nothing */
81 }
82 
initialize_info(jpeg_decompress_struct * cinfo,skjpeg_source_mgr * src_mgr)83 static void initialize_info(jpeg_decompress_struct* cinfo, skjpeg_source_mgr* src_mgr) {
84     SkASSERT(cinfo != NULL);
85     SkASSERT(src_mgr != NULL);
86     jpeg_create_decompress(cinfo);
87     overwrite_mem_buffer_size(cinfo);
88     cinfo->src = src_mgr;
89     /* To suppress warnings with a SK_DEBUG binary, set the
90      * environment variable "skia_images_jpeg_suppressDecoderWarnings"
91      * to "true".  Inside a program that links to skia:
92      * SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true); */
93     if (c_suppressJPEGImageDecoderWarnings) {
94         cinfo->err->emit_message = &do_nothing_emit_message;
95     }
96     /* To suppress error messages with a SK_DEBUG binary, set the
97      * environment variable "skia_images_jpeg_suppressDecoderErrors"
98      * to "true".  Inside a program that links to skia:
99      * SK_CONF_SET("images.jpeg.suppressDecoderErrors", true); */
100     if (c_suppressJPEGImageDecoderErrors) {
101         cinfo->err->output_message = &do_nothing_output_message;
102     }
103 }
104 
105 #ifdef SK_BUILD_FOR_ANDROID
106 class SkJPEGImageIndex {
107 public:
108     // Takes ownership of stream.
SkJPEGImageIndex(SkStreamRewindable * stream,SkImageDecoder * decoder)109     SkJPEGImageIndex(SkStreamRewindable* stream, SkImageDecoder* decoder)
110         : fSrcMgr(stream, decoder)
111         , fStream(stream)
112         , fInfoInitialized(false)
113         , fHuffmanCreated(false)
114         , fDecompressStarted(false)
115         {
116             SkDEBUGCODE(fReadHeaderSucceeded = false;)
117         }
118 
~SkJPEGImageIndex()119     ~SkJPEGImageIndex() {
120         if (fHuffmanCreated) {
121             // Set to false before calling the libjpeg function, in case
122             // the libjpeg function calls longjmp. Our setjmp handler may
123             // attempt to delete this SkJPEGImageIndex, thus entering this
124             // destructor again. Setting fHuffmanCreated to false first
125             // prevents an infinite loop.
126             fHuffmanCreated = false;
127             jpeg_destroy_huffman_index(&fHuffmanIndex);
128         }
129         if (fDecompressStarted) {
130             // Like fHuffmanCreated, set to false before calling libjpeg
131             // function to prevent potential infinite loop.
132             fDecompressStarted = false;
133             jpeg_finish_decompress(&fCInfo);
134         }
135         if (fInfoInitialized) {
136             this->destroyInfo();
137         }
138     }
139 
140     /**
141      *  Destroy the cinfo struct.
142      *  After this call, if a huffman index was already built, it
143      *  can be used after calling initializeInfoAndReadHeader
144      *  again. Must not be called after startTileDecompress except
145      *  in the destructor.
146      */
destroyInfo()147     void destroyInfo() {
148         SkASSERT(fInfoInitialized);
149         SkASSERT(!fDecompressStarted);
150         // Like fHuffmanCreated, set to false before calling libjpeg
151         // function to prevent potential infinite loop.
152         fInfoInitialized = false;
153         jpeg_destroy_decompress(&fCInfo);
154         SkDEBUGCODE(fReadHeaderSucceeded = false;)
155     }
156 
157     /**
158      *  Initialize the cinfo struct.
159      *  Calls jpeg_create_decompress, makes customizations, and
160      *  finally calls jpeg_read_header. Returns true if jpeg_read_header
161      *  returns JPEG_HEADER_OK.
162      *  If cinfo was already initialized, destroyInfo must be called to
163      *  destroy the old one. Must not be called after startTileDecompress.
164      */
initializeInfoAndReadHeader()165     bool initializeInfoAndReadHeader() {
166         SkASSERT(!fInfoInitialized && !fDecompressStarted);
167         initialize_info(&fCInfo, &fSrcMgr);
168         fInfoInitialized = true;
169         const bool success = (JPEG_HEADER_OK == jpeg_read_header(&fCInfo, true));
170         SkDEBUGCODE(fReadHeaderSucceeded = success;)
171         return success;
172     }
173 
cinfo()174     jpeg_decompress_struct* cinfo() { return &fCInfo; }
175 
huffmanIndex()176     huffman_index* huffmanIndex() { return &fHuffmanIndex; }
177 
178     /**
179      *  Build the index to be used for tile based decoding.
180      *  Must only be called after a successful call to
181      *  initializeInfoAndReadHeader and must not be called more
182      *  than once.
183      */
buildHuffmanIndex()184     bool buildHuffmanIndex() {
185         SkASSERT(fReadHeaderSucceeded);
186         SkASSERT(!fHuffmanCreated);
187         jpeg_create_huffman_index(&fCInfo, &fHuffmanIndex);
188         SkASSERT(1 == fCInfo.scale_num && 1 == fCInfo.scale_denom);
189         fHuffmanCreated = jpeg_build_huffman_index(&fCInfo, &fHuffmanIndex);
190         return fHuffmanCreated;
191     }
192 
193     /**
194      *  Start tile based decoding. Must only be called after a
195      *  successful call to buildHuffmanIndex, and must only be
196      *  called once.
197      */
startTileDecompress()198     bool startTileDecompress() {
199         SkASSERT(fHuffmanCreated);
200         SkASSERT(fReadHeaderSucceeded);
201         SkASSERT(!fDecompressStarted);
202         if (jpeg_start_tile_decompress(&fCInfo)) {
203             fDecompressStarted = true;
204             return true;
205         }
206         return false;
207     }
208 
209 private:
210     skjpeg_source_mgr  fSrcMgr;
211     SkAutoTDelete<SkStream> fStream;
212     jpeg_decompress_struct fCInfo;
213     huffman_index fHuffmanIndex;
214     bool fInfoInitialized;
215     bool fHuffmanCreated;
216     bool fDecompressStarted;
217     SkDEBUGCODE(bool fReadHeaderSucceeded;)
218 };
219 #endif
220 
221 class SkJPEGImageDecoder : public SkImageDecoder {
222 public:
223 #ifdef SK_BUILD_FOR_ANDROID
SkJPEGImageDecoder()224     SkJPEGImageDecoder() {
225         fImageIndex = NULL;
226         fImageWidth = 0;
227         fImageHeight = 0;
228     }
229 
~SkJPEGImageDecoder()230     virtual ~SkJPEGImageDecoder() {
231         SkDELETE(fImageIndex);
232     }
233 #endif
234 
getFormat() const235     Format getFormat() const override {
236         return kJPEG_Format;
237     }
238 
239 protected:
240 #ifdef SK_BUILD_FOR_ANDROID
241     bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *height) override;
242     bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) override;
243 #endif
244     Result onDecode(SkStream* stream, SkBitmap* bm, Mode) override;
245     bool onDecodeYUV8Planes(SkStream* stream, SkISize componentSizes[3],
246                             void* planes[3], size_t rowBytes[3],
247                             SkYUVColorSpace* colorSpace) override;
248 
249 private:
250 #ifdef SK_BUILD_FOR_ANDROID
251     SkJPEGImageIndex* fImageIndex;
252     int fImageWidth;
253     int fImageHeight;
254 #endif
255 
256     /**
257      *  Determine the appropriate bitmap colortype and out_color_space based on
258      *  both the preference of the caller and the jpeg_color_space on the
259      *  jpeg_decompress_struct passed in.
260      *  Must be called after jpeg_read_header.
261      */
262     SkColorType getBitmapColorType(jpeg_decompress_struct*);
263 
264     typedef SkImageDecoder INHERITED;
265 };
266 
267 //////////////////////////////////////////////////////////////////////////
268 
269 /* Automatically clean up after throwing an exception */
270 class JPEGAutoClean {
271 public:
JPEGAutoClean()272     JPEGAutoClean(): cinfo_ptr(NULL) {}
~JPEGAutoClean()273     ~JPEGAutoClean() {
274         if (cinfo_ptr) {
275             jpeg_destroy_decompress(cinfo_ptr);
276         }
277     }
set(jpeg_decompress_struct * info)278     void set(jpeg_decompress_struct* info) {
279         cinfo_ptr = info;
280     }
281 private:
282     jpeg_decompress_struct* cinfo_ptr;
283 };
284 
285 ///////////////////////////////////////////////////////////////////////////////
286 
287 /*  If we need to better match the request, we might examine the image and
288      output dimensions, and determine if the downsampling jpeg provided is
289      not sufficient. If so, we can recompute a modified sampleSize value to
290      make up the difference.
291 
292      To skip this additional scaling, just set sampleSize = 1; below.
293  */
recompute_sampleSize(int sampleSize,const jpeg_decompress_struct & cinfo)294 static int recompute_sampleSize(int sampleSize,
295                                 const jpeg_decompress_struct& cinfo) {
296     return sampleSize * cinfo.output_width / cinfo.image_width;
297 }
298 
valid_output_dimensions(const jpeg_decompress_struct & cinfo)299 static bool valid_output_dimensions(const jpeg_decompress_struct& cinfo) {
300     /* These are initialized to 0, so if they have non-zero values, we assume
301        they are "valid" (i.e. have been computed by libjpeg)
302      */
303     return 0 != cinfo.output_width && 0 != cinfo.output_height;
304 }
305 
skip_src_rows(jpeg_decompress_struct * cinfo,void * buffer,int count)306 static bool skip_src_rows(jpeg_decompress_struct* cinfo, void* buffer, int count) {
307     for (int i = 0; i < count; i++) {
308         JSAMPLE* rowptr = (JSAMPLE*)buffer;
309         int row_count = jpeg_read_scanlines(cinfo, &rowptr, 1);
310         if (1 != row_count) {
311             return false;
312         }
313     }
314     return true;
315 }
316 
317 #ifdef SK_BUILD_FOR_ANDROID
skip_src_rows_tile(jpeg_decompress_struct * cinfo,huffman_index * index,void * buffer,int count)318 static bool skip_src_rows_tile(jpeg_decompress_struct* cinfo,
319                                huffman_index *index, void* buffer, int count) {
320     for (int i = 0; i < count; i++) {
321         JSAMPLE* rowptr = (JSAMPLE*)buffer;
322         int row_count = jpeg_read_tile_scanline(cinfo, index, &rowptr);
323         if (1 != row_count) {
324             return false;
325         }
326     }
327     return true;
328 }
329 #endif
330 
331 ///////////////////////////////////////////////////////////////////////////////
332 
333 // This guy exists just to aid in debugging, as it allows debuggers to just
334 // set a break-point in one place to see all error exists.
print_jpeg_decoder_errors(const jpeg_decompress_struct & cinfo,int width,int height,const char caller[])335 static void print_jpeg_decoder_errors(const jpeg_decompress_struct& cinfo,
336                          int width, int height, const char caller[]) {
337     if (!(c_suppressJPEGImageDecoderErrors)) {
338         char buffer[JMSG_LENGTH_MAX];
339         cinfo.err->format_message((const j_common_ptr)&cinfo, buffer);
340         SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n",
341                  cinfo.err->msg_code, buffer, caller, width, height);
342     }
343 }
344 
return_false(const jpeg_decompress_struct & cinfo,const char caller[])345 static bool return_false(const jpeg_decompress_struct& cinfo,
346                          const char caller[]) {
347     print_jpeg_decoder_errors(cinfo, 0, 0, caller);
348     return false;
349 }
350 
351 #ifdef SK_BUILD_FOR_ANDROID
return_false(const jpeg_decompress_struct & cinfo,const SkBitmap & bm,const char caller[])352 static bool return_false(const jpeg_decompress_struct& cinfo,
353                          const SkBitmap& bm, const char caller[]) {
354     print_jpeg_decoder_errors(cinfo, bm.width(), bm.height(), caller);
355     return false;
356 }
357 #endif
358 
return_failure(const jpeg_decompress_struct & cinfo,const SkBitmap & bm,const char caller[])359 static SkImageDecoder::Result return_failure(const jpeg_decompress_struct& cinfo,
360                                              const SkBitmap& bm, const char caller[]) {
361     print_jpeg_decoder_errors(cinfo, bm.width(), bm.height(), caller);
362     return SkImageDecoder::kFailure;
363 }
364 
365 ///////////////////////////////////////////////////////////////////////////////
366 
367 // Convert a scanline of CMYK samples to RGBX in place. Note that this
368 // method moves the "scanline" pointer in its processing
convert_CMYK_to_RGB(uint8_t * scanline,unsigned int width)369 static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) {
370     // At this point we've received CMYK pixels from libjpeg. We
371     // perform a crude conversion to RGB (based on the formulae
372     // from easyrgb.com):
373     //  CMYK -> CMY
374     //    C = ( C * (1 - K) + K )      // for each CMY component
375     //  CMY -> RGB
376     //    R = ( 1 - C ) * 255          // for each RGB component
377     // Unfortunately we are seeing inverted CMYK so all the original terms
378     // are 1-. This yields:
379     //  CMYK -> CMY
380     //    C = ( (1-C) * (1 - (1-K) + (1-K) ) -> C = 1 - C*K
381     // The conversion from CMY->RGB remains the same
382     for (unsigned int x = 0; x < width; ++x, scanline += 4) {
383         scanline[0] = SkMulDiv255Round(scanline[0], scanline[3]);
384         scanline[1] = SkMulDiv255Round(scanline[1], scanline[3]);
385         scanline[2] = SkMulDiv255Round(scanline[2], scanline[3]);
386         scanline[3] = 255;
387     }
388 }
389 
390 /**
391  *  Common code for setting the error manager.
392  */
set_error_mgr(jpeg_decompress_struct * cinfo,skjpeg_error_mgr * errorManager)393 static void set_error_mgr(jpeg_decompress_struct* cinfo, skjpeg_error_mgr* errorManager) {
394     SkASSERT(cinfo != NULL);
395     SkASSERT(errorManager != NULL);
396     cinfo->err = jpeg_std_error(errorManager);
397     errorManager->error_exit = skjpeg_error_exit;
398 }
399 
400 /**
401  *  Common code for turning off upsampling and smoothing. Turning these
402  *  off helps performance without showing noticable differences in the
403  *  resulting bitmap.
404  */
turn_off_visual_optimizations(jpeg_decompress_struct * cinfo)405 static void turn_off_visual_optimizations(jpeg_decompress_struct* cinfo) {
406     SkASSERT(cinfo != NULL);
407     /* this gives about 30% performance improvement. In theory it may
408        reduce the visual quality, in practice I'm not seeing a difference
409      */
410     cinfo->do_fancy_upsampling = 0;
411 
412     /* this gives another few percents */
413     cinfo->do_block_smoothing = 0;
414 }
415 
416 /**
417  * Common code for setting the dct method.
418  */
set_dct_method(const SkImageDecoder & decoder,jpeg_decompress_struct * cinfo)419 static void set_dct_method(const SkImageDecoder& decoder, jpeg_decompress_struct* cinfo) {
420     SkASSERT(cinfo != NULL);
421 #ifdef DCT_IFAST_SUPPORTED
422     if (decoder.getPreferQualityOverSpeed()) {
423         cinfo->dct_method = JDCT_ISLOW;
424     } else {
425         cinfo->dct_method = JDCT_IFAST;
426     }
427 #else
428     cinfo->dct_method = JDCT_ISLOW;
429 #endif
430 }
431 
getBitmapColorType(jpeg_decompress_struct * cinfo)432 SkColorType SkJPEGImageDecoder::getBitmapColorType(jpeg_decompress_struct* cinfo) {
433     SkASSERT(cinfo != NULL);
434 
435     SrcDepth srcDepth = k32Bit_SrcDepth;
436     if (JCS_GRAYSCALE == cinfo->jpeg_color_space) {
437         srcDepth = k8BitGray_SrcDepth;
438     }
439 
440     SkColorType colorType = this->getPrefColorType(srcDepth, /*hasAlpha*/ false);
441     switch (colorType) {
442         case kAlpha_8_SkColorType:
443             // Only respect A8 colortype if the original is grayscale,
444             // in which case we will treat the grayscale as alpha
445             // values.
446             if (cinfo->jpeg_color_space != JCS_GRAYSCALE) {
447                 colorType = kN32_SkColorType;
448             }
449             break;
450         case kN32_SkColorType:
451             // Fall through.
452         case kARGB_4444_SkColorType:
453             // Fall through.
454         case kRGB_565_SkColorType:
455             // These are acceptable destination colortypes.
456             break;
457         default:
458             // Force all other colortypes to 8888.
459             colorType = kN32_SkColorType;
460             break;
461     }
462 
463     switch (cinfo->jpeg_color_space) {
464         case JCS_CMYK:
465             // Fall through.
466         case JCS_YCCK:
467             // libjpeg cannot convert from CMYK or YCCK to RGB - here we set up
468             // so libjpeg will give us CMYK samples back and we will later
469             // manually convert them to RGB
470             cinfo->out_color_space = JCS_CMYK;
471             break;
472         case JCS_GRAYSCALE:
473             if (kAlpha_8_SkColorType == colorType) {
474                 cinfo->out_color_space = JCS_GRAYSCALE;
475                 break;
476             }
477             // The data is JCS_GRAYSCALE, but the caller wants some sort of RGB
478             // colortype. Fall through to set to the default.
479         default:
480             cinfo->out_color_space = JCS_RGB;
481             break;
482     }
483     return colorType;
484 }
485 
486 /**
487  *  Based on the colortype and dither mode, adjust out_color_space and
488  *  dither_mode of cinfo. Only does work in ANDROID_RGB
489  */
adjust_out_color_space_and_dither(jpeg_decompress_struct * cinfo,SkColorType colorType,const SkImageDecoder & decoder)490 static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo,
491                                               SkColorType colorType,
492                                               const SkImageDecoder& decoder) {
493     SkASSERT(cinfo != NULL);
494 #ifdef ANDROID_RGB
495     cinfo->dither_mode = JDITHER_NONE;
496     if (JCS_CMYK == cinfo->out_color_space) {
497         return;
498     }
499     switch (colorType) {
500         case kN32_SkColorType:
501             cinfo->out_color_space = JCS_RGBA_8888;
502             break;
503         case kRGB_565_SkColorType:
504             cinfo->out_color_space = JCS_RGB_565;
505             if (decoder.getDitherImage()) {
506                 cinfo->dither_mode = JDITHER_ORDERED;
507             }
508             break;
509         default:
510             break;
511     }
512 #endif
513 }
514 
515 /**
516    Sets all pixels in given bitmap to SK_ColorWHITE for all rows >= y.
517    Used when decoding fails partway through reading scanlines to fill
518    remaining lines. */
fill_below_level(int y,SkBitmap * bitmap)519 static void fill_below_level(int y, SkBitmap* bitmap) {
520     SkIRect rect = SkIRect::MakeLTRB(0, y, bitmap->width(), bitmap->height());
521     SkCanvas canvas(*bitmap);
522     canvas.clipRect(SkRect::Make(rect));
523     canvas.drawColor(SK_ColorWHITE);
524 }
525 
526 /**
527  *  Get the config and bytes per pixel of the source data. Return
528  *  whether the data is supported.
529  */
get_src_config(const jpeg_decompress_struct & cinfo,SkScaledBitmapSampler::SrcConfig * sc,int * srcBytesPerPixel)530 static bool get_src_config(const jpeg_decompress_struct& cinfo,
531                            SkScaledBitmapSampler::SrcConfig* sc,
532                            int* srcBytesPerPixel) {
533     SkASSERT(sc != NULL && srcBytesPerPixel != NULL);
534     if (JCS_CMYK == cinfo.out_color_space) {
535         // In this case we will manually convert the CMYK values to RGB
536         *sc = SkScaledBitmapSampler::kRGBX;
537         // The CMYK work-around relies on 4 components per pixel here
538         *srcBytesPerPixel = 4;
539     } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_space) {
540         *sc = SkScaledBitmapSampler::kRGB;
541         *srcBytesPerPixel = 3;
542 #ifdef ANDROID_RGB
543     } else if (JCS_RGBA_8888 == cinfo.out_color_space) {
544         *sc = SkScaledBitmapSampler::kRGBX;
545         *srcBytesPerPixel = 4;
546     } else if (JCS_RGB_565 == cinfo.out_color_space) {
547         *sc = SkScaledBitmapSampler::kRGB_565;
548         *srcBytesPerPixel = 2;
549 #endif
550     } else if (1 == cinfo.out_color_components &&
551                JCS_GRAYSCALE == cinfo.out_color_space) {
552         *sc = SkScaledBitmapSampler::kGray;
553         *srcBytesPerPixel = 1;
554     } else {
555         return false;
556     }
557     return true;
558 }
559 
onDecode(SkStream * stream,SkBitmap * bm,Mode mode)560 SkImageDecoder::Result SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
561 #ifdef TIME_DECODE
562     SkAutoTime atm("JPEG Decode");
563 #endif
564 
565     JPEGAutoClean autoClean;
566 
567     jpeg_decompress_struct  cinfo;
568     skjpeg_source_mgr       srcManager(stream, this);
569 
570     skjpeg_error_mgr errorManager;
571     set_error_mgr(&cinfo, &errorManager);
572 
573     // All objects need to be instantiated before this setjmp call so that
574     // they will be cleaned up properly if an error occurs.
575     if (setjmp(errorManager.fJmpBuf)) {
576         return return_failure(cinfo, *bm, "setjmp");
577     }
578 
579     initialize_info(&cinfo, &srcManager);
580     autoClean.set(&cinfo);
581 
582     int status = jpeg_read_header(&cinfo, true);
583     if (status != JPEG_HEADER_OK) {
584         return return_failure(cinfo, *bm, "read_header");
585     }
586 
587     /*  Try to fulfill the requested sampleSize. Since jpeg can do it (when it
588         can) much faster that we, just use their num/denom api to approximate
589         the size.
590     */
591     int sampleSize = this->getSampleSize();
592 
593     set_dct_method(*this, &cinfo);
594 
595     SkASSERT(1 == cinfo.scale_num);
596     cinfo.scale_denom = sampleSize;
597 
598     turn_off_visual_optimizations(&cinfo);
599 
600     const SkColorType colorType = this->getBitmapColorType(&cinfo);
601     const SkAlphaType alphaType = kAlpha_8_SkColorType == colorType ?
602                                       kPremul_SkAlphaType : kOpaque_SkAlphaType;
603 
604     adjust_out_color_space_and_dither(&cinfo, colorType, *this);
605 
606     if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) {
607         // Assume an A8 bitmap is not opaque to avoid the check of each
608         // individual pixel. It is very unlikely to be opaque, since
609         // an opaque A8 bitmap would not be very interesting.
610         // Otherwise, a jpeg image is opaque.
611         bool success = bm->setInfo(SkImageInfo::Make(cinfo.image_width, cinfo.image_height,
612                                                      colorType, alphaType));
613         return success ? kSuccess : kFailure;
614     }
615 
616     /*  image_width and image_height are the original dimensions, available
617         after jpeg_read_header(). To see the scaled dimensions, we have to call
618         jpeg_start_decompress(), and then read output_width and output_height.
619     */
620     if (!jpeg_start_decompress(&cinfo)) {
621         /*  If we failed here, we may still have enough information to return
622             to the caller if they just wanted (subsampled bounds). If sampleSize
623             was 1, then we would have already returned. Thus we just check if
624             we're in kDecodeBounds_Mode, and that we have valid output sizes.
625 
626             One reason to fail here is that we have insufficient stream data
627             to complete the setup. However, output dimensions seem to get
628             computed very early, which is why this special check can pay off.
629          */
630         if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimensions(cinfo)) {
631             SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height,
632                                        recompute_sampleSize(sampleSize, cinfo));
633             // Assume an A8 bitmap is not opaque to avoid the check of each
634             // individual pixel. It is very unlikely to be opaque, since
635             // an opaque A8 bitmap would not be very interesting.
636             // Otherwise, a jpeg image is opaque.
637             bool success = bm->setInfo(SkImageInfo::Make(smpl.scaledWidth(), smpl.scaledHeight(),
638                                                          colorType, alphaType));
639             return success ? kSuccess : kFailure;
640         } else {
641             return return_failure(cinfo, *bm, "start_decompress");
642         }
643     }
644     sampleSize = recompute_sampleSize(sampleSize, cinfo);
645 
646     SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampleSize);
647     // Assume an A8 bitmap is not opaque to avoid the check of each
648     // individual pixel. It is very unlikely to be opaque, since
649     // an opaque A8 bitmap would not be very interesting.
650     // Otherwise, a jpeg image is opaque.
651     bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(),
652                                   colorType, alphaType));
653     if (SkImageDecoder::kDecodeBounds_Mode == mode) {
654         return kSuccess;
655     }
656     if (!this->allocPixelRef(bm, NULL)) {
657         return return_failure(cinfo, *bm, "allocPixelRef");
658     }
659 
660     SkAutoLockPixels alp(*bm);
661 
662 #ifdef ANDROID_RGB
663     /* short-circuit the SkScaledBitmapSampler when possible, as this gives
664        a significant performance boost.
665     */
666     if (sampleSize == 1 &&
667         ((kN32_SkColorType == colorType && cinfo.out_color_space == JCS_RGBA_8888) ||
668          (kRGB_565_SkColorType == colorType && cinfo.out_color_space == JCS_RGB_565)))
669     {
670         JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
671         INT32 const bpr =  bm->rowBytes();
672 
673         while (cinfo.output_scanline < cinfo.output_height) {
674             int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
675             if (0 == row_count) {
676                 // if row_count == 0, then we didn't get a scanline,
677                 // so return early.  We will return a partial image.
678                 fill_below_level(cinfo.output_scanline, bm);
679                 cinfo.output_scanline = cinfo.output_height;
680                 jpeg_finish_decompress(&cinfo);
681                 return kPartialSuccess;
682             }
683             if (this->shouldCancelDecode()) {
684                 return return_failure(cinfo, *bm, "shouldCancelDecode");
685             }
686             rowptr += bpr;
687         }
688         jpeg_finish_decompress(&cinfo);
689         return kSuccess;
690     }
691 #endif
692 
693     // check for supported formats
694     SkScaledBitmapSampler::SrcConfig sc;
695     int srcBytesPerPixel;
696 
697     if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) {
698         return return_failure(cinfo, *bm, "jpeg colorspace");
699     }
700 
701     if (!sampler.begin(bm, sc, *this)) {
702         return return_failure(cinfo, *bm, "sampler.begin");
703     }
704 
705     SkAutoMalloc srcStorage(cinfo.output_width * srcBytesPerPixel);
706     uint8_t* srcRow = (uint8_t*)srcStorage.get();
707 
708     //  Possibly skip initial rows [sampler.srcY0]
709     if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) {
710         return return_failure(cinfo, *bm, "skip rows");
711     }
712 
713     // now loop through scanlines until y == bm->height() - 1
714     for (int y = 0;; y++) {
715         JSAMPLE* rowptr = (JSAMPLE*)srcRow;
716         int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
717         if (0 == row_count) {
718             // if row_count == 0, then we didn't get a scanline,
719             // so return early.  We will return a partial image.
720             fill_below_level(y, bm);
721             cinfo.output_scanline = cinfo.output_height;
722             jpeg_finish_decompress(&cinfo);
723             return kPartialSuccess;
724         }
725         if (this->shouldCancelDecode()) {
726             return return_failure(cinfo, *bm, "shouldCancelDecode");
727         }
728 
729         if (JCS_CMYK == cinfo.out_color_space) {
730             convert_CMYK_to_RGB(srcRow, cinfo.output_width);
731         }
732 
733         sampler.next(srcRow);
734         if (bm->height() - 1 == y) {
735             // we're done
736             break;
737         }
738 
739         if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) {
740             return return_failure(cinfo, *bm, "skip rows");
741         }
742     }
743 
744     // we formally skip the rest, so we don't get a complaint from libjpeg
745     if (!skip_src_rows(&cinfo, srcRow,
746                        cinfo.output_height - cinfo.output_scanline)) {
747         return return_failure(cinfo, *bm, "skip rows");
748     }
749     jpeg_finish_decompress(&cinfo);
750 
751     return kSuccess;
752 }
753 
754 ///////////////////////////////////////////////////////////////////////////////
755 
756 enum SizeType {
757     kSizeForMemoryAllocation_SizeType,
758     kActualSize_SizeType
759 };
760 
compute_yuv_size(const jpeg_decompress_struct & info,int component,SizeType sizeType)761 static SkISize compute_yuv_size(const jpeg_decompress_struct& info, int component,
762                                 SizeType sizeType) {
763     if (sizeType == kSizeForMemoryAllocation_SizeType) {
764         return SkISize::Make(info.cur_comp_info[component]->width_in_blocks * DCTSIZE,
765                              info.cur_comp_info[component]->height_in_blocks * DCTSIZE);
766     }
767     return SkISize::Make(info.cur_comp_info[component]->downsampled_width,
768                          info.cur_comp_info[component]->downsampled_height);
769 }
770 
appears_to_be_yuv(const jpeg_decompress_struct & info)771 static bool appears_to_be_yuv(const jpeg_decompress_struct& info) {
772     return (info.jpeg_color_space == JCS_YCbCr)
773         && (DCTSIZE == 8)
774         && (info.num_components == 3)
775         && (info.comps_in_scan >= info.num_components)
776         && (info.scale_denom <= 8)
777         && (info.cur_comp_info[0])
778         && (info.cur_comp_info[1])
779         && (info.cur_comp_info[2])
780         && (info.cur_comp_info[1]->h_samp_factor == 1)
781         && (info.cur_comp_info[1]->v_samp_factor == 1)
782         && (info.cur_comp_info[2]->h_samp_factor == 1)
783         && (info.cur_comp_info[2]->v_samp_factor == 1);
784 }
785 
update_components_sizes(const jpeg_decompress_struct & cinfo,SkISize componentSizes[3],SizeType sizeType)786 static void update_components_sizes(const jpeg_decompress_struct& cinfo, SkISize componentSizes[3],
787                                     SizeType sizeType) {
788     SkASSERT(appears_to_be_yuv(cinfo));
789     for (int i = 0; i < 3; ++i) {
790         componentSizes[i] = compute_yuv_size(cinfo, i, sizeType);
791     }
792 }
793 
output_raw_data(jpeg_decompress_struct & cinfo,void * planes[3],size_t rowBytes[3])794 static bool output_raw_data(jpeg_decompress_struct& cinfo, void* planes[3], size_t rowBytes[3]) {
795     SkASSERT(appears_to_be_yuv(cinfo));
796     // U size and V size have to be the same if we're calling output_raw_data()
797     SkISize uvSize = compute_yuv_size(cinfo, 1, kSizeForMemoryAllocation_SizeType);
798     SkASSERT(uvSize == compute_yuv_size(cinfo, 2, kSizeForMemoryAllocation_SizeType));
799 
800     JSAMPARRAY bufferraw[3];
801     JSAMPROW bufferraw2[32];
802     bufferraw[0] = &bufferraw2[0]; // Y channel rows (8 or 16)
803     bufferraw[1] = &bufferraw2[16]; // U channel rows (8)
804     bufferraw[2] = &bufferraw2[24]; // V channel rows (8)
805     int yWidth = cinfo.output_width;
806     int yHeight = cinfo.output_height;
807     int yMaxH = yHeight - 1;
808     int v = cinfo.cur_comp_info[0]->v_samp_factor;
809     int uvMaxH = uvSize.height() - 1;
810     JSAMPROW outputY = static_cast<JSAMPROW>(planes[0]);
811     JSAMPROW outputU = static_cast<JSAMPROW>(planes[1]);
812     JSAMPROW outputV = static_cast<JSAMPROW>(planes[2]);
813     size_t rowBytesY = rowBytes[0];
814     size_t rowBytesU = rowBytes[1];
815     size_t rowBytesV = rowBytes[2];
816 
817     int yScanlinesToRead = DCTSIZE * v;
818     SkAutoMalloc lastRowStorage(rowBytesY * 4);
819     JSAMPROW yLastRow = (JSAMPROW)lastRowStorage.get();
820     JSAMPROW uLastRow = yLastRow + rowBytesY;
821     JSAMPROW vLastRow = uLastRow + rowBytesY;
822     JSAMPROW dummyRow = vLastRow + rowBytesY;
823 
824     while (cinfo.output_scanline < cinfo.output_height) {
825         // Request 8 or 16 scanlines: returns 0 or more scanlines.
826         bool hasYLastRow(false), hasUVLastRow(false);
827         // Assign 8 or 16 rows of memory to read the Y channel.
828         for (int i = 0; i < yScanlinesToRead; ++i) {
829             int scanline = (cinfo.output_scanline + i);
830             if (scanline < yMaxH) {
831                 bufferraw2[i] = &outputY[scanline * rowBytesY];
832             } else if (scanline == yMaxH) {
833                 bufferraw2[i] = yLastRow;
834                 hasYLastRow = true;
835             } else {
836                 bufferraw2[i] = dummyRow;
837             }
838         }
839         int scaledScanline = cinfo.output_scanline / v;
840         // Assign 8 rows of memory to read the U and V channels.
841         for (int i = 0; i < 8; ++i) {
842             int scanline = (scaledScanline + i);
843             if (scanline < uvMaxH) {
844                 bufferraw2[16 + i] = &outputU[scanline * rowBytesU];
845                 bufferraw2[24 + i] = &outputV[scanline * rowBytesV];
846             } else if (scanline == uvMaxH) {
847                 bufferraw2[16 + i] = uLastRow;
848                 bufferraw2[24 + i] = vLastRow;
849                 hasUVLastRow = true;
850             } else {
851                 bufferraw2[16 + i] = dummyRow;
852                 bufferraw2[24 + i] = dummyRow;
853             }
854         }
855         JDIMENSION scanlinesRead = jpeg_read_raw_data(&cinfo, bufferraw, yScanlinesToRead);
856 
857         if (scanlinesRead == 0) {
858             return false;
859         }
860 
861         if (hasYLastRow) {
862             memcpy(&outputY[yMaxH * rowBytesY], yLastRow, yWidth);
863         }
864         if (hasUVLastRow) {
865             memcpy(&outputU[uvMaxH * rowBytesU], uLastRow, uvSize.width());
866             memcpy(&outputV[uvMaxH * rowBytesV], vLastRow, uvSize.width());
867         }
868     }
869 
870     cinfo.output_scanline = SkMin32(cinfo.output_scanline, cinfo.output_height);
871 
872     return true;
873 }
874 
onDecodeYUV8Planes(SkStream * stream,SkISize componentSizes[3],void * planes[3],size_t rowBytes[3],SkYUVColorSpace * colorSpace)875 bool SkJPEGImageDecoder::onDecodeYUV8Planes(SkStream* stream, SkISize componentSizes[3],
876                                             void* planes[3], size_t rowBytes[3],
877                                             SkYUVColorSpace* colorSpace) {
878 #ifdef TIME_DECODE
879     SkAutoTime atm("JPEG YUV8 Decode");
880 #endif
881     if (this->getSampleSize() != 1) {
882         return false; // Resizing not supported
883     }
884 
885     JPEGAutoClean autoClean;
886 
887     jpeg_decompress_struct  cinfo;
888     skjpeg_source_mgr       srcManager(stream, this);
889 
890     skjpeg_error_mgr errorManager;
891     set_error_mgr(&cinfo, &errorManager);
892 
893     // All objects need to be instantiated before this setjmp call so that
894     // they will be cleaned up properly if an error occurs.
895     if (setjmp(errorManager.fJmpBuf)) {
896         return return_false(cinfo, "setjmp YUV8");
897     }
898 
899     initialize_info(&cinfo, &srcManager);
900     autoClean.set(&cinfo);
901 
902     int status = jpeg_read_header(&cinfo, true);
903     if (status != JPEG_HEADER_OK) {
904         return return_false(cinfo, "read_header YUV8");
905     }
906 
907     if (!appears_to_be_yuv(cinfo)) {
908         // It's not an error to not be encoded in YUV, so no need to use return_false()
909         return false;
910     }
911 
912     cinfo.out_color_space = JCS_YCbCr;
913     cinfo.raw_data_out = TRUE;
914 
915     if (!planes || !planes[0] || !rowBytes || !rowBytes[0]) { // Compute size only
916         update_components_sizes(cinfo, componentSizes, kSizeForMemoryAllocation_SizeType);
917         return true;
918     }
919 
920     set_dct_method(*this, &cinfo);
921 
922     SkASSERT(1 == cinfo.scale_num);
923     cinfo.scale_denom = 1;
924 
925     turn_off_visual_optimizations(&cinfo);
926 
927 #ifdef ANDROID_RGB
928     cinfo.dither_mode = JDITHER_NONE;
929 #endif
930 
931     /*  image_width and image_height are the original dimensions, available
932         after jpeg_read_header(). To see the scaled dimensions, we have to call
933         jpeg_start_decompress(), and then read output_width and output_height.
934     */
935     if (!jpeg_start_decompress(&cinfo)) {
936         return return_false(cinfo, "start_decompress YUV8");
937     }
938 
939     // Seems like jpeg_start_decompress is updating our opinion of whether cinfo represents YUV.
940     // Again, not really an error.
941     if (!appears_to_be_yuv(cinfo)) {
942         return false;
943     }
944 
945     if (!output_raw_data(cinfo, planes, rowBytes)) {
946         return return_false(cinfo, "output_raw_data");
947     }
948 
949     update_components_sizes(cinfo, componentSizes, kActualSize_SizeType);
950     jpeg_finish_decompress(&cinfo);
951 
952     if (NULL != colorSpace) {
953         *colorSpace = kJPEG_SkYUVColorSpace;
954     }
955 
956     return true;
957 }
958 
959 ///////////////////////////////////////////////////////////////////////////////
960 
961 #ifdef SK_BUILD_FOR_ANDROID
onBuildTileIndex(SkStreamRewindable * stream,int * width,int * height)962 bool SkJPEGImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, int *width, int *height) {
963 
964     SkAutoTDelete<SkJPEGImageIndex> imageIndex(SkNEW_ARGS(SkJPEGImageIndex, (stream, this)));
965 
966     skjpeg_error_mgr sk_err;
967     set_error_mgr(imageIndex->cinfo(), &sk_err);
968 
969     // All objects need to be instantiated before this setjmp call so that
970     // they will be cleaned up properly if an error occurs.
971     if (setjmp(sk_err.fJmpBuf)) {
972         return false;
973     }
974 
975     // create the cinfo used to create/build the huffmanIndex
976     if (!imageIndex->initializeInfoAndReadHeader()) {
977         return false;
978     }
979 
980     if (!imageIndex->buildHuffmanIndex()) {
981         return false;
982     }
983 
984     // destroy the cinfo used to create/build the huffman index
985     imageIndex->destroyInfo();
986 
987     // Init decoder to image decode mode
988     if (!imageIndex->initializeInfoAndReadHeader()) {
989         return false;
990     }
991 
992     jpeg_decompress_struct* cinfo = imageIndex->cinfo();
993     // We have a new cinfo, so set the error mgr again.
994     set_error_mgr(cinfo, &sk_err);
995 
996     // FIXME: This sets cinfo->out_color_space, which we may change later
997     // based on the config in onDecodeSubset. This should be fine, since
998     // jpeg_init_read_tile_scanline will check out_color_space again after
999     // that change (when it calls jinit_color_deconverter).
1000     (void) this->getBitmapColorType(cinfo);
1001 
1002     turn_off_visual_optimizations(cinfo);
1003 
1004     // instead of jpeg_start_decompress() we start a tiled decompress
1005     if (!imageIndex->startTileDecompress()) {
1006         return false;
1007     }
1008 
1009     SkASSERT(1 == cinfo->scale_num);
1010     fImageWidth = cinfo->output_width;
1011     fImageHeight = cinfo->output_height;
1012 
1013     if (width) {
1014         *width = fImageWidth;
1015     }
1016     if (height) {
1017         *height = fImageHeight;
1018     }
1019 
1020     SkDELETE(fImageIndex);
1021     fImageIndex = imageIndex.detach();
1022 
1023     return true;
1024 }
1025 
onDecodeSubset(SkBitmap * bm,const SkIRect & region)1026 bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
1027     if (NULL == fImageIndex) {
1028         return false;
1029     }
1030     jpeg_decompress_struct* cinfo = fImageIndex->cinfo();
1031 
1032     SkIRect rect = SkIRect::MakeWH(fImageWidth, fImageHeight);
1033     if (!rect.intersect(region)) {
1034         // If the requested region is entirely outside the image return false
1035         return false;
1036     }
1037 
1038 
1039     skjpeg_error_mgr errorManager;
1040     set_error_mgr(cinfo, &errorManager);
1041 
1042     if (setjmp(errorManager.fJmpBuf)) {
1043         return false;
1044     }
1045 
1046     int requestedSampleSize = this->getSampleSize();
1047     cinfo->scale_denom = requestedSampleSize;
1048 
1049     set_dct_method(*this, cinfo);
1050 
1051     const SkColorType colorType = this->getBitmapColorType(cinfo);
1052     adjust_out_color_space_and_dither(cinfo, colorType, *this);
1053 
1054     int startX = rect.fLeft;
1055     int startY = rect.fTop;
1056     int width = rect.width();
1057     int height = rect.height();
1058 
1059     jpeg_init_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(),
1060                                  &startX, &startY, &width, &height);
1061     int skiaSampleSize = recompute_sampleSize(requestedSampleSize, *cinfo);
1062     int actualSampleSize = skiaSampleSize * (DCTSIZE / cinfo->min_DCT_scaled_size);
1063 
1064     SkScaledBitmapSampler sampler(width, height, skiaSampleSize);
1065 
1066     SkBitmap bitmap;
1067     // Assume an A8 bitmap is not opaque to avoid the check of each
1068     // individual pixel. It is very unlikely to be opaque, since
1069     // an opaque A8 bitmap would not be very interesting.
1070     // Otherwise, a jpeg image is opaque.
1071     bitmap.setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(), colorType,
1072                                      kAlpha_8_SkColorType == colorType ?
1073                                          kPremul_SkAlphaType : kOpaque_SkAlphaType));
1074 
1075     // Check ahead of time if the swap(dest, src) is possible or not.
1076     // If yes, then we will stick to AllocPixelRef since it's cheaper with the
1077     // swap happening. If no, then we will use alloc to allocate pixels to
1078     // prevent garbage collection.
1079     int w = rect.width() / actualSampleSize;
1080     int h = rect.height() / actualSampleSize;
1081     bool swapOnly = (rect == region) && bm->isNull() &&
1082                     (w == bitmap.width()) && (h == bitmap.height()) &&
1083                     ((startX - rect.x()) / actualSampleSize == 0) &&
1084                     ((startY - rect.y()) / actualSampleSize == 0);
1085     if (swapOnly) {
1086         if (!this->allocPixelRef(&bitmap, NULL)) {
1087             return return_false(*cinfo, bitmap, "allocPixelRef");
1088         }
1089     } else {
1090         if (!bitmap.tryAllocPixels()) {
1091             return return_false(*cinfo, bitmap, "allocPixels");
1092         }
1093     }
1094 
1095     SkAutoLockPixels alp(bitmap);
1096 
1097 #ifdef ANDROID_RGB
1098     /* short-circuit the SkScaledBitmapSampler when possible, as this gives
1099        a significant performance boost.
1100     */
1101     if (skiaSampleSize == 1 &&
1102         ((kN32_SkColorType == colorType && cinfo->out_color_space == JCS_RGBA_8888) ||
1103          (kRGB_565_SkColorType == colorType && cinfo->out_color_space == JCS_RGB_565)))
1104     {
1105         JSAMPLE* rowptr = (JSAMPLE*)bitmap.getPixels();
1106         INT32 const bpr = bitmap.rowBytes();
1107         int rowTotalCount = 0;
1108 
1109         while (rowTotalCount < height) {
1110             int rowCount = jpeg_read_tile_scanline(cinfo,
1111                                                    fImageIndex->huffmanIndex(),
1112                                                    &rowptr);
1113             // if rowCount == 0, then we didn't get a scanline, so abort.
1114             // onDecodeSubset() relies on onBuildTileIndex(), which
1115             // needs a complete image to succeed.
1116             if (0 == rowCount) {
1117                 return return_false(*cinfo, bitmap, "read_scanlines");
1118             }
1119             if (this->shouldCancelDecode()) {
1120                 return return_false(*cinfo, bitmap, "shouldCancelDecode");
1121             }
1122             rowTotalCount += rowCount;
1123             rowptr += bpr;
1124         }
1125 
1126         if (swapOnly) {
1127             bm->swap(bitmap);
1128             return true;
1129         }
1130 
1131         return cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(),
1132                           region.width(), region.height(), startX, startY);
1133     }
1134 #endif
1135 
1136     // check for supported formats
1137     SkScaledBitmapSampler::SrcConfig sc;
1138     int srcBytesPerPixel;
1139 
1140     if (!get_src_config(*cinfo, &sc, &srcBytesPerPixel)) {
1141         return return_false(*cinfo, *bm, "jpeg colorspace");
1142     }
1143 
1144     if (!sampler.begin(&bitmap, sc, *this)) {
1145         return return_false(*cinfo, bitmap, "sampler.begin");
1146     }
1147 
1148     SkAutoMalloc  srcStorage(width * srcBytesPerPixel);
1149     uint8_t* srcRow = (uint8_t*)srcStorage.get();
1150 
1151     //  Possibly skip initial rows [sampler.srcY0]
1152     if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler.srcY0())) {
1153         return return_false(*cinfo, bitmap, "skip rows");
1154     }
1155 
1156     // now loop through scanlines until y == bitmap->height() - 1
1157     for (int y = 0;; y++) {
1158         JSAMPLE* rowptr = (JSAMPLE*)srcRow;
1159         int row_count = jpeg_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(), &rowptr);
1160         // if row_count == 0, then we didn't get a scanline, so abort.
1161         // onDecodeSubset() relies on onBuildTileIndex(), which
1162         // needs a complete image to succeed.
1163         if (0 == row_count) {
1164             return return_false(*cinfo, bitmap, "read_scanlines");
1165         }
1166         if (this->shouldCancelDecode()) {
1167             return return_false(*cinfo, bitmap, "shouldCancelDecode");
1168         }
1169 
1170         if (JCS_CMYK == cinfo->out_color_space) {
1171             convert_CMYK_to_RGB(srcRow, width);
1172         }
1173 
1174         sampler.next(srcRow);
1175         if (bitmap.height() - 1 == y) {
1176             // we're done
1177             break;
1178         }
1179 
1180         if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow,
1181                                 sampler.srcDY() - 1)) {
1182             return return_false(*cinfo, bitmap, "skip rows");
1183         }
1184     }
1185     if (swapOnly) {
1186         bm->swap(bitmap);
1187         return true;
1188     }
1189     return cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(),
1190                       region.width(), region.height(), startX, startY);
1191 }
1192 #endif
1193 
1194 ///////////////////////////////////////////////////////////////////////////////
1195 
1196 #include "SkColorPriv.h"
1197 
1198 // taken from jcolor.c in libjpeg
1199 #if 0   // 16bit - precise but slow
1200     #define CYR     19595   // 0.299
1201     #define CYG     38470   // 0.587
1202     #define CYB      7471   // 0.114
1203 
1204     #define CUR    -11059   // -0.16874
1205     #define CUG    -21709   // -0.33126
1206     #define CUB     32768   // 0.5
1207 
1208     #define CVR     32768   // 0.5
1209     #define CVG    -27439   // -0.41869
1210     #define CVB     -5329   // -0.08131
1211 
1212     #define CSHIFT  16
1213 #else      // 8bit - fast, slightly less precise
1214     #define CYR     77    // 0.299
1215     #define CYG     150    // 0.587
1216     #define CYB      29    // 0.114
1217 
1218     #define CUR     -43    // -0.16874
1219     #define CUG    -85    // -0.33126
1220     #define CUB     128    // 0.5
1221 
1222     #define CVR      128   // 0.5
1223     #define CVG     -107   // -0.41869
1224     #define CVB      -21   // -0.08131
1225 
1226     #define CSHIFT  8
1227 #endif
1228 
rgb2yuv_32(uint8_t dst[],SkPMColor c)1229 static void rgb2yuv_32(uint8_t dst[], SkPMColor c) {
1230     int r = SkGetPackedR32(c);
1231     int g = SkGetPackedG32(c);
1232     int b = SkGetPackedB32(c);
1233 
1234     int  y = ( CYR*r + CYG*g + CYB*b ) >> CSHIFT;
1235     int  u = ( CUR*r + CUG*g + CUB*b ) >> CSHIFT;
1236     int  v = ( CVR*r + CVG*g + CVB*b ) >> CSHIFT;
1237 
1238     dst[0] = SkToU8(y);
1239     dst[1] = SkToU8(u + 128);
1240     dst[2] = SkToU8(v + 128);
1241 }
1242 
rgb2yuv_4444(uint8_t dst[],U16CPU c)1243 static void rgb2yuv_4444(uint8_t dst[], U16CPU c) {
1244     int r = SkGetPackedR4444(c);
1245     int g = SkGetPackedG4444(c);
1246     int b = SkGetPackedB4444(c);
1247 
1248     int  y = ( CYR*r + CYG*g + CYB*b ) >> (CSHIFT - 4);
1249     int  u = ( CUR*r + CUG*g + CUB*b ) >> (CSHIFT - 4);
1250     int  v = ( CVR*r + CVG*g + CVB*b ) >> (CSHIFT - 4);
1251 
1252     dst[0] = SkToU8(y);
1253     dst[1] = SkToU8(u + 128);
1254     dst[2] = SkToU8(v + 128);
1255 }
1256 
rgb2yuv_16(uint8_t dst[],U16CPU c)1257 static void rgb2yuv_16(uint8_t dst[], U16CPU c) {
1258     int r = SkGetPackedR16(c);
1259     int g = SkGetPackedG16(c);
1260     int b = SkGetPackedB16(c);
1261 
1262     int  y = ( 2*CYR*r + CYG*g + 2*CYB*b ) >> (CSHIFT - 2);
1263     int  u = ( 2*CUR*r + CUG*g + 2*CUB*b ) >> (CSHIFT - 2);
1264     int  v = ( 2*CVR*r + CVG*g + 2*CVB*b ) >> (CSHIFT - 2);
1265 
1266     dst[0] = SkToU8(y);
1267     dst[1] = SkToU8(u + 128);
1268     dst[2] = SkToU8(v + 128);
1269 }
1270 
1271 ///////////////////////////////////////////////////////////////////////////////
1272 
1273 typedef void (*WriteScanline)(uint8_t* SK_RESTRICT dst,
1274                               const void* SK_RESTRICT src, int width,
1275                               const SkPMColor* SK_RESTRICT ctable);
1276 
Write_32_YUV(uint8_t * SK_RESTRICT dst,const void * SK_RESTRICT srcRow,int width,const SkPMColor *)1277 static void Write_32_YUV(uint8_t* SK_RESTRICT dst,
1278                          const void* SK_RESTRICT srcRow, int width,
1279                          const SkPMColor*) {
1280     const uint32_t* SK_RESTRICT src = (const uint32_t*)srcRow;
1281     while (--width >= 0) {
1282 #ifdef WE_CONVERT_TO_YUV
1283         rgb2yuv_32(dst, *src++);
1284 #else
1285         uint32_t c = *src++;
1286         dst[0] = SkGetPackedR32(c);
1287         dst[1] = SkGetPackedG32(c);
1288         dst[2] = SkGetPackedB32(c);
1289 #endif
1290         dst += 3;
1291     }
1292 }
1293 
Write_4444_YUV(uint8_t * SK_RESTRICT dst,const void * SK_RESTRICT srcRow,int width,const SkPMColor *)1294 static void Write_4444_YUV(uint8_t* SK_RESTRICT dst,
1295                            const void* SK_RESTRICT srcRow, int width,
1296                            const SkPMColor*) {
1297     const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)srcRow;
1298     while (--width >= 0) {
1299 #ifdef WE_CONVERT_TO_YUV
1300         rgb2yuv_4444(dst, *src++);
1301 #else
1302         SkPMColor16 c = *src++;
1303         dst[0] = SkPacked4444ToR32(c);
1304         dst[1] = SkPacked4444ToG32(c);
1305         dst[2] = SkPacked4444ToB32(c);
1306 #endif
1307         dst += 3;
1308     }
1309 }
1310 
Write_16_YUV(uint8_t * SK_RESTRICT dst,const void * SK_RESTRICT srcRow,int width,const SkPMColor *)1311 static void Write_16_YUV(uint8_t* SK_RESTRICT dst,
1312                          const void* SK_RESTRICT srcRow, int width,
1313                          const SkPMColor*) {
1314     const uint16_t* SK_RESTRICT src = (const uint16_t*)srcRow;
1315     while (--width >= 0) {
1316 #ifdef WE_CONVERT_TO_YUV
1317         rgb2yuv_16(dst, *src++);
1318 #else
1319         uint16_t c = *src++;
1320         dst[0] = SkPacked16ToR32(c);
1321         dst[1] = SkPacked16ToG32(c);
1322         dst[2] = SkPacked16ToB32(c);
1323 #endif
1324         dst += 3;
1325     }
1326 }
1327 
Write_Index_YUV(uint8_t * SK_RESTRICT dst,const void * SK_RESTRICT srcRow,int width,const SkPMColor * SK_RESTRICT ctable)1328 static void Write_Index_YUV(uint8_t* SK_RESTRICT dst,
1329                             const void* SK_RESTRICT srcRow, int width,
1330                             const SkPMColor* SK_RESTRICT ctable) {
1331     const uint8_t* SK_RESTRICT src = (const uint8_t*)srcRow;
1332     while (--width >= 0) {
1333 #ifdef WE_CONVERT_TO_YUV
1334         rgb2yuv_32(dst, ctable[*src++]);
1335 #else
1336         uint32_t c = ctable[*src++];
1337         dst[0] = SkGetPackedR32(c);
1338         dst[1] = SkGetPackedG32(c);
1339         dst[2] = SkGetPackedB32(c);
1340 #endif
1341         dst += 3;
1342     }
1343 }
1344 
ChooseWriter(const SkBitmap & bm)1345 static WriteScanline ChooseWriter(const SkBitmap& bm) {
1346     switch (bm.colorType()) {
1347         case kN32_SkColorType:
1348             return Write_32_YUV;
1349         case kRGB_565_SkColorType:
1350             return Write_16_YUV;
1351         case kARGB_4444_SkColorType:
1352             return Write_4444_YUV;
1353         case kIndex_8_SkColorType:
1354             return Write_Index_YUV;
1355         default:
1356             return NULL;
1357     }
1358 }
1359 
1360 class SkJPEGImageEncoder : public SkImageEncoder {
1361 protected:
onEncode(SkWStream * stream,const SkBitmap & bm,int quality)1362     virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) {
1363 #ifdef TIME_ENCODE
1364         SkAutoTime atm("JPEG Encode");
1365 #endif
1366 
1367         SkAutoLockPixels alp(bm);
1368         if (NULL == bm.getPixels()) {
1369             return false;
1370         }
1371 
1372         jpeg_compress_struct    cinfo;
1373         skjpeg_error_mgr        sk_err;
1374         skjpeg_destination_mgr  sk_wstream(stream);
1375 
1376         // allocate these before set call setjmp
1377         SkAutoMalloc    oneRow;
1378 
1379         cinfo.err = jpeg_std_error(&sk_err);
1380         sk_err.error_exit = skjpeg_error_exit;
1381         if (setjmp(sk_err.fJmpBuf)) {
1382             return false;
1383         }
1384 
1385         // Keep after setjmp or mark volatile.
1386         const WriteScanline writer = ChooseWriter(bm);
1387         if (NULL == writer) {
1388             return false;
1389         }
1390 
1391         jpeg_create_compress(&cinfo);
1392         cinfo.dest = &sk_wstream;
1393         cinfo.image_width = bm.width();
1394         cinfo.image_height = bm.height();
1395         cinfo.input_components = 3;
1396 #ifdef WE_CONVERT_TO_YUV
1397         cinfo.in_color_space = JCS_YCbCr;
1398 #else
1399         cinfo.in_color_space = JCS_RGB;
1400 #endif
1401         cinfo.input_gamma = 1;
1402 
1403         jpeg_set_defaults(&cinfo);
1404         jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
1405 #ifdef DCT_IFAST_SUPPORTED
1406         cinfo.dct_method = JDCT_IFAST;
1407 #endif
1408 
1409         jpeg_start_compress(&cinfo, TRUE);
1410 
1411         const int       width = bm.width();
1412         uint8_t*        oneRowP = (uint8_t*)oneRow.reset(width * 3);
1413 
1414         const SkPMColor* colors = bm.getColorTable() ? bm.getColorTable()->readColors() : NULL;
1415         const void*      srcRow = bm.getPixels();
1416 
1417         while (cinfo.next_scanline < cinfo.image_height) {
1418             JSAMPROW row_pointer[1];    /* pointer to JSAMPLE row[s] */
1419 
1420             writer(oneRowP, srcRow, width, colors);
1421             row_pointer[0] = oneRowP;
1422             (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
1423             srcRow = (const void*)((const char*)srcRow + bm.rowBytes());
1424         }
1425 
1426         jpeg_finish_compress(&cinfo);
1427         jpeg_destroy_compress(&cinfo);
1428 
1429         return true;
1430     }
1431 };
1432 
1433 ///////////////////////////////////////////////////////////////////////////////
1434 DEFINE_DECODER_CREATOR(JPEGImageDecoder);
1435 DEFINE_ENCODER_CREATOR(JPEGImageEncoder);
1436 ///////////////////////////////////////////////////////////////////////////////
1437 
is_jpeg(SkStreamRewindable * stream)1438 static bool is_jpeg(SkStreamRewindable* stream) {
1439     static const unsigned char gHeader[] = { 0xFF, 0xD8, 0xFF };
1440     static const size_t HEADER_SIZE = sizeof(gHeader);
1441 
1442     char buffer[HEADER_SIZE];
1443     size_t len = stream->read(buffer, HEADER_SIZE);
1444 
1445     if (len != HEADER_SIZE) {
1446         return false;   // can't read enough
1447     }
1448     if (memcmp(buffer, gHeader, HEADER_SIZE)) {
1449         return false;
1450     }
1451     return true;
1452 }
1453 
1454 
sk_libjpeg_dfactory(SkStreamRewindable * stream)1455 static SkImageDecoder* sk_libjpeg_dfactory(SkStreamRewindable* stream) {
1456     if (is_jpeg(stream)) {
1457         return SkNEW(SkJPEGImageDecoder);
1458     }
1459     return NULL;
1460 }
1461 
get_format_jpeg(SkStreamRewindable * stream)1462 static SkImageDecoder::Format get_format_jpeg(SkStreamRewindable* stream) {
1463     if (is_jpeg(stream)) {
1464         return SkImageDecoder::kJPEG_Format;
1465     }
1466     return SkImageDecoder::kUnknown_Format;
1467 }
1468 
sk_libjpeg_efactory(SkImageEncoder::Type t)1469 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) {
1470     return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL;
1471 }
1472 
1473 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory);
1474 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg);
1475 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory);
1476