Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / images / SkImageDecoder_libjpeg.cpp
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
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
76 static void do_nothing_emit_message(jpeg_common_struct*, int) {
77     /* do nothing */
78 }
79 static void do_nothing_output_message(j_common_ptr) {
80     /* do nothing */
81 }
82
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     SkJPEGImageIndex(SkStreamRewindable* stream, SkImageDecoder* decoder)
109         : fSrcMgr(stream, decoder)
110         , fInfoInitialized(false)
111         , fHuffmanCreated(false)
112         , fDecompressStarted(false)
113         {
114             SkDEBUGCODE(fReadHeaderSucceeded = false;)
115         }
116
117     ~SkJPEGImageIndex() {
118         if (fHuffmanCreated) {
119             // Set to false before calling the libjpeg function, in case
120             // the libjpeg function calls longjmp. Our setjmp handler may
121             // attempt to delete this SkJPEGImageIndex, thus entering this
122             // destructor again. Setting fHuffmanCreated to false first
123             // prevents an infinite loop.
124             fHuffmanCreated = false;
125             jpeg_destroy_huffman_index(&fHuffmanIndex);
126         }
127         if (fDecompressStarted) {
128             // Like fHuffmanCreated, set to false before calling libjpeg
129             // function to prevent potential infinite loop.
130             fDecompressStarted = false;
131             jpeg_finish_decompress(&fCInfo);
132         }
133         if (fInfoInitialized) {
134             this->destroyInfo();
135         }
136     }
137
138     /**
139      *  Destroy the cinfo struct.
140      *  After this call, if a huffman index was already built, it
141      *  can be used after calling initializeInfoAndReadHeader
142      *  again. Must not be called after startTileDecompress except
143      *  in the destructor.
144      */
145     void destroyInfo() {
146         SkASSERT(fInfoInitialized);
147         SkASSERT(!fDecompressStarted);
148         // Like fHuffmanCreated, set to false before calling libjpeg
149         // function to prevent potential infinite loop.
150         fInfoInitialized = false;
151         jpeg_destroy_decompress(&fCInfo);
152         SkDEBUGCODE(fReadHeaderSucceeded = false;)
153     }
154
155     /**
156      *  Initialize the cinfo struct.
157      *  Calls jpeg_create_decompress, makes customizations, and
158      *  finally calls jpeg_read_header. Returns true if jpeg_read_header
159      *  returns JPEG_HEADER_OK.
160      *  If cinfo was already initialized, destroyInfo must be called to
161      *  destroy the old one. Must not be called after startTileDecompress.
162      */
163     bool initializeInfoAndReadHeader() {
164         SkASSERT(!fInfoInitialized && !fDecompressStarted);
165         initialize_info(&fCInfo, &fSrcMgr);
166         fInfoInitialized = true;
167         const bool success = (JPEG_HEADER_OK == jpeg_read_header(&fCInfo, true));
168         SkDEBUGCODE(fReadHeaderSucceeded = success;)
169         return success;
170     }
171
172     jpeg_decompress_struct* cinfo() { return &fCInfo; }
173
174     huffman_index* huffmanIndex() { return &fHuffmanIndex; }
175
176     /**
177      *  Build the index to be used for tile based decoding.
178      *  Must only be called after a successful call to
179      *  initializeInfoAndReadHeader and must not be called more
180      *  than once.
181      */
182     bool buildHuffmanIndex() {
183         SkASSERT(fReadHeaderSucceeded);
184         SkASSERT(!fHuffmanCreated);
185         jpeg_create_huffman_index(&fCInfo, &fHuffmanIndex);
186         SkASSERT(1 == fCInfo.scale_num && 1 == fCInfo.scale_denom);
187         fHuffmanCreated = jpeg_build_huffman_index(&fCInfo, &fHuffmanIndex);
188         return fHuffmanCreated;
189     }
190
191     /**
192      *  Start tile based decoding. Must only be called after a
193      *  successful call to buildHuffmanIndex, and must only be
194      *  called once.
195      */
196     bool startTileDecompress() {
197         SkASSERT(fHuffmanCreated);
198         SkASSERT(fReadHeaderSucceeded);
199         SkASSERT(!fDecompressStarted);
200         if (jpeg_start_tile_decompress(&fCInfo)) {
201             fDecompressStarted = true;
202             return true;
203         }
204         return false;
205     }
206
207 private:
208     skjpeg_source_mgr  fSrcMgr;
209     jpeg_decompress_struct fCInfo;
210     huffman_index fHuffmanIndex;
211     bool fInfoInitialized;
212     bool fHuffmanCreated;
213     bool fDecompressStarted;
214     SkDEBUGCODE(bool fReadHeaderSucceeded;)
215 };
216 #endif
217
218 class SkJPEGImageDecoder : public SkImageDecoder {
219 public:
220 #ifdef SK_BUILD_FOR_ANDROID
221     SkJPEGImageDecoder() {
222         fImageIndex = NULL;
223         fImageWidth = 0;
224         fImageHeight = 0;
225     }
226
227     virtual ~SkJPEGImageDecoder() {
228         SkDELETE(fImageIndex);
229     }
230 #endif
231
232     virtual Format getFormat() const {
233         return kJPEG_Format;
234     }
235
236 protected:
237 #ifdef SK_BUILD_FOR_ANDROID
238     virtual bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *height) SK_OVERRIDE;
239     virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRIDE;
240 #endif
241     virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE;
242
243 private:
244 #ifdef SK_BUILD_FOR_ANDROID
245     SkJPEGImageIndex* fImageIndex;
246     int fImageWidth;
247     int fImageHeight;
248 #endif
249
250     /**
251      *  Determine the appropriate bitmap colortype and out_color_space based on
252      *  both the preference of the caller and the jpeg_color_space on the
253      *  jpeg_decompress_struct passed in.
254      *  Must be called after jpeg_read_header.
255      */
256     SkColorType getBitmapColorType(jpeg_decompress_struct*);
257
258     typedef SkImageDecoder INHERITED;
259 };
260
261 //////////////////////////////////////////////////////////////////////////
262
263 /* Automatically clean up after throwing an exception */
264 class JPEGAutoClean {
265 public:
266     JPEGAutoClean(): cinfo_ptr(NULL) {}
267     ~JPEGAutoClean() {
268         if (cinfo_ptr) {
269             jpeg_destroy_decompress(cinfo_ptr);
270         }
271     }
272     void set(jpeg_decompress_struct* info) {
273         cinfo_ptr = info;
274     }
275 private:
276     jpeg_decompress_struct* cinfo_ptr;
277 };
278
279 ///////////////////////////////////////////////////////////////////////////////
280
281 /*  If we need to better match the request, we might examine the image and
282      output dimensions, and determine if the downsampling jpeg provided is
283      not sufficient. If so, we can recompute a modified sampleSize value to
284      make up the difference.
285
286      To skip this additional scaling, just set sampleSize = 1; below.
287  */
288 static int recompute_sampleSize(int sampleSize,
289                                 const jpeg_decompress_struct& cinfo) {
290     return sampleSize * cinfo.output_width / cinfo.image_width;
291 }
292
293 static bool valid_output_dimensions(const jpeg_decompress_struct& cinfo) {
294     /* These are initialized to 0, so if they have non-zero values, we assume
295        they are "valid" (i.e. have been computed by libjpeg)
296      */
297     return 0 != cinfo.output_width && 0 != cinfo.output_height;
298 }
299
300 static bool skip_src_rows(jpeg_decompress_struct* cinfo, void* buffer, int count) {
301     for (int i = 0; i < count; i++) {
302         JSAMPLE* rowptr = (JSAMPLE*)buffer;
303         int row_count = jpeg_read_scanlines(cinfo, &rowptr, 1);
304         if (1 != row_count) {
305             return false;
306         }
307     }
308     return true;
309 }
310
311 #ifdef SK_BUILD_FOR_ANDROID
312 static bool skip_src_rows_tile(jpeg_decompress_struct* cinfo,
313                                huffman_index *index, void* buffer, int count) {
314     for (int i = 0; i < count; i++) {
315         JSAMPLE* rowptr = (JSAMPLE*)buffer;
316         int row_count = jpeg_read_tile_scanline(cinfo, index, &rowptr);
317         if (1 != row_count) {
318             return false;
319         }
320     }
321     return true;
322 }
323 #endif
324
325 // 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.
327 static bool return_false(const jpeg_decompress_struct& cinfo,
328                          const SkBitmap& bm, const char caller[]) {
329     if (!(c_suppressJPEGImageDecoderErrors)) {
330         char buffer[JMSG_LENGTH_MAX];
331         cinfo.err->format_message((const j_common_ptr)&cinfo, buffer);
332         SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n",
333                  cinfo.err->msg_code, buffer, caller, bm.width(), bm.height());
334     }
335     return false;   // must always return false
336 }
337
338 // Convert a scanline of CMYK samples to RGBX in place. Note that this
339 // method moves the "scanline" pointer in its processing
340 static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) {
341     // At this point we've received CMYK pixels from libjpeg. We
342     // perform a crude conversion to RGB (based on the formulae
343     // from easyrgb.com):
344     //  CMYK -> CMY
345     //    C = ( C * (1 - K) + K )      // for each CMY component
346     //  CMY -> RGB
347     //    R = ( 1 - C ) * 255          // for each RGB component
348     // Unfortunately we are seeing inverted CMYK so all the original terms
349     // are 1-. This yields:
350     //  CMYK -> CMY
351     //    C = ( (1-C) * (1 - (1-K) + (1-K) ) -> C = 1 - C*K
352     // The conversion from CMY->RGB remains the same
353     for (unsigned int x = 0; x < width; ++x, scanline += 4) {
354         scanline[0] = SkMulDiv255Round(scanline[0], scanline[3]);
355         scanline[1] = SkMulDiv255Round(scanline[1], scanline[3]);
356         scanline[2] = SkMulDiv255Round(scanline[2], scanline[3]);
357         scanline[3] = 255;
358     }
359 }
360
361 /**
362  *  Common code for setting the error manager.
363  */
364 static void set_error_mgr(jpeg_decompress_struct* cinfo, skjpeg_error_mgr* errorManager) {
365     SkASSERT(cinfo != NULL);
366     SkASSERT(errorManager != NULL);
367     cinfo->err = jpeg_std_error(errorManager);
368     errorManager->error_exit = skjpeg_error_exit;
369 }
370
371 /**
372  *  Common code for turning off upsampling and smoothing. Turning these
373  *  off helps performance without showing noticable differences in the
374  *  resulting bitmap.
375  */
376 static void turn_off_visual_optimizations(jpeg_decompress_struct* cinfo) {
377     SkASSERT(cinfo != NULL);
378     /* this gives about 30% performance improvement. In theory it may
379        reduce the visual quality, in practice I'm not seeing a difference
380      */
381     cinfo->do_fancy_upsampling = 0;
382
383     /* this gives another few percents */
384     cinfo->do_block_smoothing = 0;
385 }
386
387 /**
388  * Common code for setting the dct method.
389  */
390 static void set_dct_method(const SkImageDecoder& decoder, jpeg_decompress_struct* cinfo) {
391     SkASSERT(cinfo != NULL);
392 #ifdef DCT_IFAST_SUPPORTED
393     if (decoder.getPreferQualityOverSpeed()) {
394         cinfo->dct_method = JDCT_ISLOW;
395     } else {
396         cinfo->dct_method = JDCT_IFAST;
397     }
398 #else
399     cinfo->dct_method = JDCT_ISLOW;
400 #endif
401 }
402
403 SkColorType SkJPEGImageDecoder::getBitmapColorType(jpeg_decompress_struct* cinfo) {
404     SkASSERT(cinfo != NULL);
405
406     SrcDepth srcDepth = k32Bit_SrcDepth;
407     if (JCS_GRAYSCALE == cinfo->jpeg_color_space) {
408         srcDepth = k8BitGray_SrcDepth;
409     }
410
411     SkColorType colorType = this->getPrefColorType(srcDepth, /*hasAlpha*/ false);
412     switch (colorType) {
413         case kAlpha_8_SkColorType:
414             // Only respect A8 colortype if the original is grayscale,
415             // in which case we will treat the grayscale as alpha
416             // values.
417             if (cinfo->jpeg_color_space != JCS_GRAYSCALE) {
418                 colorType = kN32_SkColorType;
419             }
420             break;
421         case kN32_SkColorType:
422             // Fall through.
423         case kARGB_4444_SkColorType:
424             // Fall through.
425         case kRGB_565_SkColorType:
426             // These are acceptable destination colortypes.
427             break;
428         default:
429             // Force all other colortypes to 8888.
430             colorType = kN32_SkColorType;
431             break;
432     }
433
434     switch (cinfo->jpeg_color_space) {
435         case JCS_CMYK:
436             // Fall through.
437         case JCS_YCCK:
438             // libjpeg cannot convert from CMYK or YCCK to RGB - here we set up
439             // so libjpeg will give us CMYK samples back and we will later
440             // manually convert them to RGB
441             cinfo->out_color_space = JCS_CMYK;
442             break;
443         case JCS_GRAYSCALE:
444             if (kAlpha_8_SkColorType == colorType) {
445                 cinfo->out_color_space = JCS_GRAYSCALE;
446                 break;
447             }
448             // The data is JCS_GRAYSCALE, but the caller wants some sort of RGB
449             // colortype. Fall through to set to the default.
450         default:
451             cinfo->out_color_space = JCS_RGB;
452             break;
453     }
454     return colorType;
455 }
456
457 /**
458  *  Based on the colortype and dither mode, adjust out_color_space and
459  *  dither_mode of cinfo. Only does work in ANDROID_RGB
460  */
461 static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo,
462                                               SkColorType colorType,
463                                               const SkImageDecoder& decoder) {
464     SkASSERT(cinfo != NULL);
465 #ifdef ANDROID_RGB
466     cinfo->dither_mode = JDITHER_NONE;
467     if (JCS_CMYK == cinfo->out_color_space) {
468         return;
469     }
470     switch (colorType) {
471         case kN32_SkColorType:
472             cinfo->out_color_space = JCS_RGBA_8888;
473             break;
474         case kRGB_565_SkColorType:
475             cinfo->out_color_space = JCS_RGB_565;
476             if (decoder.getDitherImage()) {
477                 cinfo->dither_mode = JDITHER_ORDERED;
478             }
479             break;
480         default:
481             break;
482     }
483 #endif
484 }
485
486
487 /**
488    Sets all pixels in given bitmap to SK_ColorWHITE for all rows >= y.
489    Used when decoding fails partway through reading scanlines to fill
490    remaining lines. */
491 static void fill_below_level(int y, SkBitmap* bitmap) {
492     SkIRect rect = SkIRect::MakeLTRB(0, y, bitmap->width(), bitmap->height());
493     SkCanvas canvas(*bitmap);
494     canvas.clipRect(SkRect::Make(rect));
495     canvas.drawColor(SK_ColorWHITE);
496 }
497
498 /**
499  *  Get the config and bytes per pixel of the source data. Return
500  *  whether the data is supported.
501  */
502 static bool get_src_config(const jpeg_decompress_struct& cinfo,
503                            SkScaledBitmapSampler::SrcConfig* sc,
504                            int* srcBytesPerPixel) {
505     SkASSERT(sc != NULL && srcBytesPerPixel != NULL);
506     if (JCS_CMYK == cinfo.out_color_space) {
507         // In this case we will manually convert the CMYK values to RGB
508         *sc = SkScaledBitmapSampler::kRGBX;
509         // The CMYK work-around relies on 4 components per pixel here
510         *srcBytesPerPixel = 4;
511     } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_space) {
512         *sc = SkScaledBitmapSampler::kRGB;
513         *srcBytesPerPixel = 3;
514 #ifdef ANDROID_RGB
515     } else if (JCS_RGBA_8888 == cinfo.out_color_space) {
516         *sc = SkScaledBitmapSampler::kRGBX;
517         *srcBytesPerPixel = 4;
518     } else if (JCS_RGB_565 == cinfo.out_color_space) {
519         *sc = SkScaledBitmapSampler::kRGB_565;
520         *srcBytesPerPixel = 2;
521 #endif
522     } else if (1 == cinfo.out_color_components &&
523                JCS_GRAYSCALE == cinfo.out_color_space) {
524         *sc = SkScaledBitmapSampler::kGray;
525         *srcBytesPerPixel = 1;
526     } else {
527         return false;
528     }
529     return true;
530 }
531
532 bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
533 #ifdef TIME_DECODE
534     SkAutoTime atm("JPEG Decode");
535 #endif
536
537     JPEGAutoClean autoClean;
538
539     jpeg_decompress_struct  cinfo;
540     skjpeg_source_mgr       srcManager(stream, this);
541
542     skjpeg_error_mgr errorManager;
543     set_error_mgr(&cinfo, &errorManager);
544
545     // All objects need to be instantiated before this setjmp call so that
546     // they will be cleaned up properly if an error occurs.
547     if (setjmp(errorManager.fJmpBuf)) {
548         return return_false(cinfo, *bm, "setjmp");
549     }
550
551     initialize_info(&cinfo, &srcManager);
552     autoClean.set(&cinfo);
553
554     int status = jpeg_read_header(&cinfo, true);
555     if (status != JPEG_HEADER_OK) {
556         return return_false(cinfo, *bm, "read_header");
557     }
558
559     /*  Try to fulfill the requested sampleSize. Since jpeg can do it (when it
560         can) much faster that we, just use their num/denom api to approximate
561         the size.
562     */
563     int sampleSize = this->getSampleSize();
564
565     set_dct_method(*this, &cinfo);
566
567     SkASSERT(1 == cinfo.scale_num);
568     cinfo.scale_denom = sampleSize;
569
570     turn_off_visual_optimizations(&cinfo);
571
572     const SkColorType colorType = this->getBitmapColorType(&cinfo);
573     const SkAlphaType alphaType = kAlpha_8_SkColorType == colorType ?
574                                       kPremul_SkAlphaType : kOpaque_SkAlphaType;
575
576     adjust_out_color_space_and_dither(&cinfo, colorType, *this);
577
578     if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) {
579         // Assume an A8 bitmap is not opaque to avoid the check of each
580         // individual pixel. It is very unlikely to be opaque, since
581         // an opaque A8 bitmap would not be very interesting.
582         // Otherwise, a jpeg image is opaque.
583         return bm->setInfo(SkImageInfo::Make(cinfo.image_width, cinfo.image_height,
584                                              colorType, alphaType));
585     }
586
587     /*  image_width and image_height are the original dimensions, available
588         after jpeg_read_header(). To see the scaled dimensions, we have to call
589         jpeg_start_decompress(), and then read output_width and output_height.
590     */
591     if (!jpeg_start_decompress(&cinfo)) {
592         /*  If we failed here, we may still have enough information to return
593             to the caller if they just wanted (subsampled bounds). If sampleSize
594             was 1, then we would have already returned. Thus we just check if
595             we're in kDecodeBounds_Mode, and that we have valid output sizes.
596
597             One reason to fail here is that we have insufficient stream data
598             to complete the setup. However, output dimensions seem to get
599             computed very early, which is why this special check can pay off.
600          */
601         if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimensions(cinfo)) {
602             SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height,
603                                        recompute_sampleSize(sampleSize, cinfo));
604             // Assume an A8 bitmap is not opaque to avoid the check of each
605             // individual pixel. It is very unlikely to be opaque, since
606             // an opaque A8 bitmap would not be very interesting.
607             // Otherwise, a jpeg image is opaque.
608             return bm->setInfo(SkImageInfo::Make(smpl.scaledWidth(), smpl.scaledHeight(),
609                                                  colorType, alphaType));
610         } else {
611             return return_false(cinfo, *bm, "start_decompress");
612         }
613     }
614     sampleSize = recompute_sampleSize(sampleSize, cinfo);
615
616 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
617     // should we allow the Chooser (if present) to pick a colortype for us???
618     if (!this->chooseFromOneChoice(colorType, cinfo.output_width, cinfo.output_height)) {
619         return return_false(cinfo, *bm, "chooseFromOneChoice");
620     }
621 #endif
622
623     SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampleSize);
624     // Assume an A8 bitmap is not opaque to avoid the check of each
625     // individual pixel. It is very unlikely to be opaque, since
626     // an opaque A8 bitmap would not be very interesting.
627     // Otherwise, a jpeg image is opaque.
628     bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(),
629                                   colorType, alphaType));
630     if (SkImageDecoder::kDecodeBounds_Mode == mode) {
631         return true;
632     }
633     if (!this->allocPixelRef(bm, NULL)) {
634         return return_false(cinfo, *bm, "allocPixelRef");
635     }
636
637     SkAutoLockPixels alp(*bm);
638
639 #ifdef ANDROID_RGB
640     /* short-circuit the SkScaledBitmapSampler when possible, as this gives
641        a significant performance boost.
642     */
643     if (sampleSize == 1 &&
644         ((kN32_SkColorType == colorType && cinfo.out_color_space == JCS_RGBA_8888) ||
645          (kRGB_565_SkColorType == colorType && cinfo.out_color_space == JCS_RGB_565)))
646     {
647         JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
648         INT32 const bpr =  bm->rowBytes();
649
650         while (cinfo.output_scanline < cinfo.output_height) {
651             int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
652             if (0 == row_count) {
653                 // if row_count == 0, then we didn't get a scanline,
654                 // so return early.  We will return a partial image.
655                 fill_below_level(cinfo.output_scanline, bm);
656                 cinfo.output_scanline = cinfo.output_height;
657                 break;  // Skip to jpeg_finish_decompress()
658             }
659             if (this->shouldCancelDecode()) {
660                 return return_false(cinfo, *bm, "shouldCancelDecode");
661             }
662             rowptr += bpr;
663         }
664         jpeg_finish_decompress(&cinfo);
665         return true;
666     }
667 #endif
668
669     // check for supported formats
670     SkScaledBitmapSampler::SrcConfig sc;
671     int srcBytesPerPixel;
672
673     if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) {
674         return return_false(cinfo, *bm, "jpeg colorspace");
675     }
676
677     if (!sampler.begin(bm, sc, *this)) {
678         return return_false(cinfo, *bm, "sampler.begin");
679     }
680
681     SkAutoMalloc srcStorage(cinfo.output_width * srcBytesPerPixel);
682     uint8_t* srcRow = (uint8_t*)srcStorage.get();
683
684     //  Possibly skip initial rows [sampler.srcY0]
685     if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) {
686         return return_false(cinfo, *bm, "skip rows");
687     }
688
689     // now loop through scanlines until y == bm->height() - 1
690     for (int y = 0;; y++) {
691         JSAMPLE* rowptr = (JSAMPLE*)srcRow;
692         int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
693         if (0 == row_count) {
694             // if row_count == 0, then we didn't get a scanline,
695             // so return early.  We will return a partial image.
696             fill_below_level(y, bm);
697             cinfo.output_scanline = cinfo.output_height;
698             break;  // Skip to jpeg_finish_decompress()
699         }
700         if (this->shouldCancelDecode()) {
701             return return_false(cinfo, *bm, "shouldCancelDecode");
702         }
703
704         if (JCS_CMYK == cinfo.out_color_space) {
705             convert_CMYK_to_RGB(srcRow, cinfo.output_width);
706         }
707
708         sampler.next(srcRow);
709         if (bm->height() - 1 == y) {
710             // we're done
711             break;
712         }
713
714         if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) {
715             return return_false(cinfo, *bm, "skip rows");
716         }
717     }
718
719     // we formally skip the rest, so we don't get a complaint from libjpeg
720     if (!skip_src_rows(&cinfo, srcRow,
721                        cinfo.output_height - cinfo.output_scanline)) {
722         return return_false(cinfo, *bm, "skip rows");
723     }
724     jpeg_finish_decompress(&cinfo);
725
726     return true;
727 }
728
729 #ifdef SK_BUILD_FOR_ANDROID
730 bool SkJPEGImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, int *width, int *height) {
731
732     SkAutoTDelete<SkJPEGImageIndex> imageIndex(SkNEW_ARGS(SkJPEGImageIndex, (stream, this)));
733     jpeg_decompress_struct* cinfo = imageIndex->cinfo();
734
735     skjpeg_error_mgr sk_err;
736     set_error_mgr(cinfo, &sk_err);
737
738     // All objects need to be instantiated before this setjmp call so that
739     // they will be cleaned up properly if an error occurs.
740     if (setjmp(sk_err.fJmpBuf)) {
741         return false;
742     }
743
744     // create the cinfo used to create/build the huffmanIndex
745     if (!imageIndex->initializeInfoAndReadHeader()) {
746         return false;
747     }
748
749     if (!imageIndex->buildHuffmanIndex()) {
750         return false;
751     }
752
753     // destroy the cinfo used to create/build the huffman index
754     imageIndex->destroyInfo();
755
756     // Init decoder to image decode mode
757     if (!imageIndex->initializeInfoAndReadHeader()) {
758         return false;
759     }
760
761     // FIXME: This sets cinfo->out_color_space, which we may change later
762     // based on the config in onDecodeSubset. This should be fine, since
763     // jpeg_init_read_tile_scanline will check out_color_space again after
764     // that change (when it calls jinit_color_deconverter).
765     (void) this->getBitmapColorType(cinfo);
766
767     turn_off_visual_optimizations(cinfo);
768
769     // instead of jpeg_start_decompress() we start a tiled decompress
770     if (!imageIndex->startTileDecompress()) {
771         return false;
772     }
773
774     SkASSERT(1 == cinfo->scale_num);
775     fImageWidth = cinfo->output_width;
776     fImageHeight = cinfo->output_height;
777
778     if (width) {
779         *width = fImageWidth;
780     }
781     if (height) {
782         *height = fImageHeight;
783     }
784
785     SkDELETE(fImageIndex);
786     fImageIndex = imageIndex.detach();
787
788     return true;
789 }
790
791 bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
792     if (NULL == fImageIndex) {
793         return false;
794     }
795     jpeg_decompress_struct* cinfo = fImageIndex->cinfo();
796
797     SkIRect rect = SkIRect::MakeWH(fImageWidth, fImageHeight);
798     if (!rect.intersect(region)) {
799         // If the requested region is entirely outside the image return false
800         return false;
801     }
802
803
804     skjpeg_error_mgr errorManager;
805     set_error_mgr(cinfo, &errorManager);
806
807     if (setjmp(errorManager.fJmpBuf)) {
808         return false;
809     }
810
811     int requestedSampleSize = this->getSampleSize();
812     cinfo->scale_denom = requestedSampleSize;
813
814     set_dct_method(*this, cinfo);
815
816     const SkColorType colorType = this->getBitmapColorType(cinfo);
817     adjust_out_color_space_and_dither(cinfo, colorType, *this);
818
819     int startX = rect.fLeft;
820     int startY = rect.fTop;
821     int width = rect.width();
822     int height = rect.height();
823
824     jpeg_init_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(),
825                                  &startX, &startY, &width, &height);
826     int skiaSampleSize = recompute_sampleSize(requestedSampleSize, *cinfo);
827     int actualSampleSize = skiaSampleSize * (DCTSIZE / cinfo->min_DCT_scaled_size);
828
829     SkScaledBitmapSampler sampler(width, height, skiaSampleSize);
830
831     SkBitmap bitmap;
832     // Assume an A8 bitmap is not opaque to avoid the check of each
833     // individual pixel. It is very unlikely to be opaque, since
834     // an opaque A8 bitmap would not be very interesting.
835     // Otherwise, a jpeg image is opaque.
836     bitmap.setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(), colorType,
837                                      kAlpha_8_SkColorType == colorType ?
838                                          kPremul_SkAlphaType : kOpaque_SkAlphaType));
839
840     // Check ahead of time if the swap(dest, src) is possible or not.
841     // If yes, then we will stick to AllocPixelRef since it's cheaper with the
842     // swap happening. If no, then we will use alloc to allocate pixels to
843     // prevent garbage collection.
844     int w = rect.width() / actualSampleSize;
845     int h = rect.height() / actualSampleSize;
846     bool swapOnly = (rect == region) && bm->isNull() &&
847                     (w == bitmap.width()) && (h == bitmap.height()) &&
848                     ((startX - rect.x()) / actualSampleSize == 0) &&
849                     ((startY - rect.y()) / actualSampleSize == 0);
850     if (swapOnly) {
851         if (!this->allocPixelRef(&bitmap, NULL)) {
852             return return_false(*cinfo, bitmap, "allocPixelRef");
853         }
854     } else {
855         if (!bitmap.tryAllocPixels()) {
856             return return_false(*cinfo, bitmap, "allocPixels");
857         }
858     }
859
860     SkAutoLockPixels alp(bitmap);
861
862 #ifdef ANDROID_RGB
863     /* short-circuit the SkScaledBitmapSampler when possible, as this gives
864        a significant performance boost.
865     */
866     if (skiaSampleSize == 1 &&
867         ((kN32_SkColorType == colorType && cinfo->out_color_space == JCS_RGBA_8888) ||
868          (kRGB_565_SkColorType == colorType && cinfo->out_color_space == JCS_RGB_565)))
869     {
870         JSAMPLE* rowptr = (JSAMPLE*)bitmap.getPixels();
871         INT32 const bpr = bitmap.rowBytes();
872         int rowTotalCount = 0;
873
874         while (rowTotalCount < height) {
875             int rowCount = jpeg_read_tile_scanline(cinfo,
876                                                    fImageIndex->huffmanIndex(),
877                                                    &rowptr);
878             // if rowCount == 0, then we didn't get a scanline, so abort.
879             // onDecodeSubset() relies on onBuildTileIndex(), which
880             // needs a complete image to succeed.
881             if (0 == rowCount) {
882                 return return_false(*cinfo, bitmap, "read_scanlines");
883             }
884             if (this->shouldCancelDecode()) {
885                 return return_false(*cinfo, bitmap, "shouldCancelDecode");
886             }
887             rowTotalCount += rowCount;
888             rowptr += bpr;
889         }
890
891         if (swapOnly) {
892             bm->swap(bitmap);
893         } else {
894             cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(),
895                        region.width(), region.height(), startX, startY);
896         }
897         return true;
898     }
899 #endif
900
901     // check for supported formats
902     SkScaledBitmapSampler::SrcConfig sc;
903     int srcBytesPerPixel;
904
905     if (!get_src_config(*cinfo, &sc, &srcBytesPerPixel)) {
906         return return_false(*cinfo, *bm, "jpeg colorspace");
907     }
908
909     if (!sampler.begin(&bitmap, sc, *this)) {
910         return return_false(*cinfo, bitmap, "sampler.begin");
911     }
912
913     SkAutoMalloc  srcStorage(width * srcBytesPerPixel);
914     uint8_t* srcRow = (uint8_t*)srcStorage.get();
915
916     //  Possibly skip initial rows [sampler.srcY0]
917     if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler.srcY0())) {
918         return return_false(*cinfo, bitmap, "skip rows");
919     }
920
921     // now loop through scanlines until y == bitmap->height() - 1
922     for (int y = 0;; y++) {
923         JSAMPLE* rowptr = (JSAMPLE*)srcRow;
924         int row_count = jpeg_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(), &rowptr);
925         // if row_count == 0, then we didn't get a scanline, so abort.
926         // onDecodeSubset() relies on onBuildTileIndex(), which
927         // needs a complete image to succeed.
928         if (0 == row_count) {
929             return return_false(*cinfo, bitmap, "read_scanlines");
930         }
931         if (this->shouldCancelDecode()) {
932             return return_false(*cinfo, bitmap, "shouldCancelDecode");
933         }
934
935         if (JCS_CMYK == cinfo->out_color_space) {
936             convert_CMYK_to_RGB(srcRow, width);
937         }
938
939         sampler.next(srcRow);
940         if (bitmap.height() - 1 == y) {
941             // we're done
942             break;
943         }
944
945         if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow,
946                                 sampler.srcDY() - 1)) {
947             return return_false(*cinfo, bitmap, "skip rows");
948         }
949     }
950     if (swapOnly) {
951         bm->swap(bitmap);
952     } else {
953         cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(),
954                    region.width(), region.height(), startX, startY);
955     }
956     return true;
957 }
958 #endif
959
960 ///////////////////////////////////////////////////////////////////////////////
961
962 #include "SkColorPriv.h"
963
964 // taken from jcolor.c in libjpeg
965 #if 0   // 16bit - precise but slow
966     #define CYR     19595   // 0.299
967     #define CYG     38470   // 0.587
968     #define CYB      7471   // 0.114
969
970     #define CUR    -11059   // -0.16874
971     #define CUG    -21709   // -0.33126
972     #define CUB     32768   // 0.5
973
974     #define CVR     32768   // 0.5
975     #define CVG    -27439   // -0.41869
976     #define CVB     -5329   // -0.08131
977
978     #define CSHIFT  16
979 #else      // 8bit - fast, slightly less precise
980     #define CYR     77    // 0.299
981     #define CYG     150    // 0.587
982     #define CYB      29    // 0.114
983
984     #define CUR     -43    // -0.16874
985     #define CUG    -85    // -0.33126
986     #define CUB     128    // 0.5
987
988     #define CVR      128   // 0.5
989     #define CVG     -107   // -0.41869
990     #define CVB      -21   // -0.08131
991
992     #define CSHIFT  8
993 #endif
994
995 static void rgb2yuv_32(uint8_t dst[], SkPMColor c) {
996     int r = SkGetPackedR32(c);
997     int g = SkGetPackedG32(c);
998     int b = SkGetPackedB32(c);
999
1000     int  y = ( CYR*r + CYG*g + CYB*b ) >> CSHIFT;
1001     int  u = ( CUR*r + CUG*g + CUB*b ) >> CSHIFT;
1002     int  v = ( CVR*r + CVG*g + CVB*b ) >> CSHIFT;
1003
1004     dst[0] = SkToU8(y);
1005     dst[1] = SkToU8(u + 128);
1006     dst[2] = SkToU8(v + 128);
1007 }
1008
1009 static void rgb2yuv_4444(uint8_t dst[], U16CPU c) {
1010     int r = SkGetPackedR4444(c);
1011     int g = SkGetPackedG4444(c);
1012     int b = SkGetPackedB4444(c);
1013
1014     int  y = ( CYR*r + CYG*g + CYB*b ) >> (CSHIFT - 4);
1015     int  u = ( CUR*r + CUG*g + CUB*b ) >> (CSHIFT - 4);
1016     int  v = ( CVR*r + CVG*g + CVB*b ) >> (CSHIFT - 4);
1017
1018     dst[0] = SkToU8(y);
1019     dst[1] = SkToU8(u + 128);
1020     dst[2] = SkToU8(v + 128);
1021 }
1022
1023 static void rgb2yuv_16(uint8_t dst[], U16CPU c) {
1024     int r = SkGetPackedR16(c);
1025     int g = SkGetPackedG16(c);
1026     int b = SkGetPackedB16(c);
1027
1028     int  y = ( 2*CYR*r + CYG*g + 2*CYB*b ) >> (CSHIFT - 2);
1029     int  u = ( 2*CUR*r + CUG*g + 2*CUB*b ) >> (CSHIFT - 2);
1030     int  v = ( 2*CVR*r + CVG*g + 2*CVB*b ) >> (CSHIFT - 2);
1031
1032     dst[0] = SkToU8(y);
1033     dst[1] = SkToU8(u + 128);
1034     dst[2] = SkToU8(v + 128);
1035 }
1036
1037 ///////////////////////////////////////////////////////////////////////////////
1038
1039 typedef void (*WriteScanline)(uint8_t* SK_RESTRICT dst,
1040                               const void* SK_RESTRICT src, int width,
1041                               const SkPMColor* SK_RESTRICT ctable);
1042
1043 static void Write_32_YUV(uint8_t* SK_RESTRICT dst,
1044                          const void* SK_RESTRICT srcRow, int width,
1045                          const SkPMColor*) {
1046     const uint32_t* SK_RESTRICT src = (const uint32_t*)srcRow;
1047     while (--width >= 0) {
1048 #ifdef WE_CONVERT_TO_YUV
1049         rgb2yuv_32(dst, *src++);
1050 #else
1051         uint32_t c = *src++;
1052         dst[0] = SkGetPackedR32(c);
1053         dst[1] = SkGetPackedG32(c);
1054         dst[2] = SkGetPackedB32(c);
1055 #endif
1056         dst += 3;
1057     }
1058 }
1059
1060 static void Write_4444_YUV(uint8_t* SK_RESTRICT dst,
1061                            const void* SK_RESTRICT srcRow, int width,
1062                            const SkPMColor*) {
1063     const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)srcRow;
1064     while (--width >= 0) {
1065 #ifdef WE_CONVERT_TO_YUV
1066         rgb2yuv_4444(dst, *src++);
1067 #else
1068         SkPMColor16 c = *src++;
1069         dst[0] = SkPacked4444ToR32(c);
1070         dst[1] = SkPacked4444ToG32(c);
1071         dst[2] = SkPacked4444ToB32(c);
1072 #endif
1073         dst += 3;
1074     }
1075 }
1076
1077 static void Write_16_YUV(uint8_t* SK_RESTRICT dst,
1078                          const void* SK_RESTRICT srcRow, int width,
1079                          const SkPMColor*) {
1080     const uint16_t* SK_RESTRICT src = (const uint16_t*)srcRow;
1081     while (--width >= 0) {
1082 #ifdef WE_CONVERT_TO_YUV
1083         rgb2yuv_16(dst, *src++);
1084 #else
1085         uint16_t c = *src++;
1086         dst[0] = SkPacked16ToR32(c);
1087         dst[1] = SkPacked16ToG32(c);
1088         dst[2] = SkPacked16ToB32(c);
1089 #endif
1090         dst += 3;
1091     }
1092 }
1093
1094 static void Write_Index_YUV(uint8_t* SK_RESTRICT dst,
1095                             const void* SK_RESTRICT srcRow, int width,
1096                             const SkPMColor* SK_RESTRICT ctable) {
1097     const uint8_t* SK_RESTRICT src = (const uint8_t*)srcRow;
1098     while (--width >= 0) {
1099 #ifdef WE_CONVERT_TO_YUV
1100         rgb2yuv_32(dst, ctable[*src++]);
1101 #else
1102         uint32_t c = ctable[*src++];
1103         dst[0] = SkGetPackedR32(c);
1104         dst[1] = SkGetPackedG32(c);
1105         dst[2] = SkGetPackedB32(c);
1106 #endif
1107         dst += 3;
1108     }
1109 }
1110
1111 static WriteScanline ChooseWriter(const SkBitmap& bm) {
1112     switch (bm.colorType()) {
1113         case kN32_SkColorType:
1114             return Write_32_YUV;
1115         case kRGB_565_SkColorType:
1116             return Write_16_YUV;
1117         case kARGB_4444_SkColorType:
1118             return Write_4444_YUV;
1119         case kIndex_8_SkColorType:
1120             return Write_Index_YUV;
1121         default:
1122             return NULL;
1123     }
1124 }
1125
1126 class SkJPEGImageEncoder : public SkImageEncoder {
1127 protected:
1128     virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) {
1129 #ifdef TIME_ENCODE
1130         SkAutoTime atm("JPEG Encode");
1131 #endif
1132
1133         SkAutoLockPixels alp(bm);
1134         if (NULL == bm.getPixels()) {
1135             return false;
1136         }
1137
1138         jpeg_compress_struct    cinfo;
1139         skjpeg_error_mgr        sk_err;
1140         skjpeg_destination_mgr  sk_wstream(stream);
1141
1142         // allocate these before set call setjmp
1143         SkAutoMalloc    oneRow;
1144         SkAutoLockColors ctLocker;
1145
1146         cinfo.err = jpeg_std_error(&sk_err);
1147         sk_err.error_exit = skjpeg_error_exit;
1148         if (setjmp(sk_err.fJmpBuf)) {
1149             return false;
1150         }
1151
1152         // Keep after setjmp or mark volatile.
1153         const WriteScanline writer = ChooseWriter(bm);
1154         if (NULL == writer) {
1155             return false;
1156         }
1157
1158         jpeg_create_compress(&cinfo);
1159         cinfo.dest = &sk_wstream;
1160         cinfo.image_width = bm.width();
1161         cinfo.image_height = bm.height();
1162         cinfo.input_components = 3;
1163 #ifdef WE_CONVERT_TO_YUV
1164         cinfo.in_color_space = JCS_YCbCr;
1165 #else
1166         cinfo.in_color_space = JCS_RGB;
1167 #endif
1168         cinfo.input_gamma = 1;
1169
1170         jpeg_set_defaults(&cinfo);
1171         jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
1172 #ifdef DCT_IFAST_SUPPORTED
1173         cinfo.dct_method = JDCT_IFAST;
1174 #endif
1175
1176         jpeg_start_compress(&cinfo, TRUE);
1177
1178         const int       width = bm.width();
1179         uint8_t*        oneRowP = (uint8_t*)oneRow.reset(width * 3);
1180
1181         const SkPMColor* colors = ctLocker.lockColors(bm);
1182         const void*      srcRow = bm.getPixels();
1183
1184         while (cinfo.next_scanline < cinfo.image_height) {
1185             JSAMPROW row_pointer[1];    /* pointer to JSAMPLE row[s] */
1186
1187             writer(oneRowP, srcRow, width, colors);
1188             row_pointer[0] = oneRowP;
1189             (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
1190             srcRow = (const void*)((const char*)srcRow + bm.rowBytes());
1191         }
1192
1193         jpeg_finish_compress(&cinfo);
1194         jpeg_destroy_compress(&cinfo);
1195
1196         return true;
1197     }
1198 };
1199
1200 ///////////////////////////////////////////////////////////////////////////////
1201 DEFINE_DECODER_CREATOR(JPEGImageDecoder);
1202 DEFINE_ENCODER_CREATOR(JPEGImageEncoder);
1203 ///////////////////////////////////////////////////////////////////////////////
1204
1205 static bool is_jpeg(SkStreamRewindable* stream) {
1206     static const unsigned char gHeader[] = { 0xFF, 0xD8, 0xFF };
1207     static const size_t HEADER_SIZE = sizeof(gHeader);
1208
1209     char buffer[HEADER_SIZE];
1210     size_t len = stream->read(buffer, HEADER_SIZE);
1211
1212     if (len != HEADER_SIZE) {
1213         return false;   // can't read enough
1214     }
1215     if (memcmp(buffer, gHeader, HEADER_SIZE)) {
1216         return false;
1217     }
1218     return true;
1219 }
1220
1221
1222 static SkImageDecoder* sk_libjpeg_dfactory(SkStreamRewindable* stream) {
1223     if (is_jpeg(stream)) {
1224         return SkNEW(SkJPEGImageDecoder);
1225     }
1226     return NULL;
1227 }
1228
1229 static SkImageDecoder::Format get_format_jpeg(SkStreamRewindable* stream) {
1230     if (is_jpeg(stream)) {
1231         return SkImageDecoder::kJPEG_Format;
1232     }
1233     return SkImageDecoder::kUnknown_Format;
1234 }
1235
1236 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) {
1237     return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL;
1238 }
1239
1240 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory);
1241 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg);
1242 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory);