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