180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2007 The Android Open Source Project
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkImageDecoder.h"
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkImageEncoder.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkJpegUtility.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkColorPriv.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkDither.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkScaledBitmapSampler.h"
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkStream.h"
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTemplates.h"
17e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#include "SkTime.h"
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkUtils.h"
19e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#include "SkRect.h"
20e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#include "SkCanvas.h"
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include <stdio.h>
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruextern "C" {
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #include "jpeglib.h"
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #include "jerror.h"
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger// These enable timing code that report milliseconds for an encoding/decoding
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//#define TIME_ENCODE
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//#define TIME_DECODE
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// this enables our rgb->yuv code, which is faster than libjpeg on ARM
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define WE_CONVERT_TO_YUV
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger// If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offers
36e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger// support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565.
37e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//////////////////////////////////////////////////////////////////////////
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//////////////////////////////////////////////////////////////////////////
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenbergerstatic void overwrite_mem_buffer_size(jpeg_decompress_struct* cinfo) {
42e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
43e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    /* Check if the device indicates that it has a large amount of system memory
44e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger     * if so, increase the memory allocation to 30MB instead of the default 5MB.
45e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger     */
46e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#ifdef ANDROID_LARGE_MEMORY_DEVICE
47e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    cinfo->mem->max_memory_to_use = 30 * 1024 * 1024;
48e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#else
49e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    cinfo->mem->max_memory_to_use = 5 * 1024 * 1024;
50e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#endif
51e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#endif // SK_BUILD_FOR_ANDROID
52e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger}
53e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
54e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger//////////////////////////////////////////////////////////////////////////
55e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger//////////////////////////////////////////////////////////////////////////
56e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
57e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenbergerstatic void initialize_info(jpeg_decompress_struct* cinfo, skjpeg_source_mgr* src_mgr) {
58e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkASSERT(cinfo != NULL);
59e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkASSERT(src_mgr != NULL);
60e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    jpeg_create_decompress(cinfo);
61e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    overwrite_mem_buffer_size(cinfo);
62e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    cinfo->src = src_mgr;
63e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger}
64e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
65e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
66e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenbergerclass SkJPEGImageIndex {
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
68e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    SkJPEGImageIndex(SkStream* stream, SkImageDecoder* decoder)
69e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        : fSrcMgr(stream, decoder)
70e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        , fInfoInitialized(false)
71e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        , fHuffmanCreated(false)
72e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        , fDecompressStarted(false)
73e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        {
74e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            SkDEBUGCODE(fReadHeaderSucceeded = false;)
75e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        }
76e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
77e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    ~SkJPEGImageIndex() {
78e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        if (fHuffmanCreated) {
79e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            // Set to false before calling the libjpeg function, in case
80e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            // the libjpeg function calls longjmp. Our setjmp handler may
81e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            // attempt to delete this SkJPEGImageIndex, thus entering this
82e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            // destructor again. Setting fHuffmanCreated to false first
83e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            // prevents an infinite loop.
84e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            fHuffmanCreated = false;
85e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            jpeg_destroy_huffman_index(&fHuffmanIndex);
86e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        }
87e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        if (fDecompressStarted) {
88e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            // Like fHuffmanCreated, set to false before calling libjpeg
89e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            // function to prevent potential infinite loop.
90e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            fDecompressStarted = false;
91e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            jpeg_finish_decompress(&fCInfo);
92e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        }
93e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        if (fInfoInitialized) {
94e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            this->destroyInfo();
95e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        }
96e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
97e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
98e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    /**
99e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     *  Destroy the cinfo struct.
100e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     *  After this call, if a huffman index was already built, it
101e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     *  can be used after calling initializeInfoAndReadHeader
102e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     *  again. Must not be called after startTileDecompress except
103e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     *  in the destructor.
104e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     */
105e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    void destroyInfo() {
106e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        SkASSERT(fInfoInitialized);
107e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        SkASSERT(!fDecompressStarted);
108e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        // Like fHuffmanCreated, set to false before calling libjpeg
109e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        // function to prevent potential infinite loop.
110e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        fInfoInitialized = false;
111e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        jpeg_destroy_decompress(&fCInfo);
112e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        SkDEBUGCODE(fReadHeaderSucceeded = false;)
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
115e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    /**
116e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     *  Initialize the cinfo struct.
117e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     *  Calls jpeg_create_decompress, makes customizations, and
118e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     *  finally calls jpeg_read_header. Returns true if jpeg_read_header
119e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     *  returns JPEG_HEADER_OK.
120e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     *  If cinfo was already initialized, destroyInfo must be called to
121e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     *  destroy the old one. Must not be called after startTileDecompress.
122e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger     */
123e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    bool initializeInfoAndReadHeader() {
124e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        SkASSERT(!fInfoInitialized && !fDecompressStarted);
125e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        initialize_info(&fCInfo, &fSrcMgr);
126e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        fInfoInitialized = true;
127e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        const bool success = (JPEG_HEADER_OK == jpeg_read_header(&fCInfo, true));
128e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        SkDEBUGCODE(fReadHeaderSucceeded = success;)
129e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        return success;
130e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    }
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
132e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    jpeg_decompress_struct* cinfo() { return &fCInfo; }
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
134e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    huffman_index* huffmanIndex() { return &fHuffmanIndex; }
135e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
136e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    /**
137e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     *  Build the index to be used for tile based decoding.
138e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     *  Must only be called after a successful call to
139e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     *  initializeInfoAndReadHeader and must not be called more
140e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     *  than once.
141e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     */
142e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    bool buildHuffmanIndex() {
143e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        SkASSERT(fReadHeaderSucceeded);
144e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        SkASSERT(!fHuffmanCreated);
145e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        jpeg_create_huffman_index(&fCInfo, &fHuffmanIndex);
146e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        SkASSERT(1 == fCInfo.scale_num && 1 == fCInfo.scale_denom);
1474495d5ff20e5a4923d708fa335371f0c8e9b2752Leon Scroggins III        fHuffmanCreated = jpeg_build_huffman_index(&fCInfo, &fHuffmanIndex);
1484495d5ff20e5a4923d708fa335371f0c8e9b2752Leon Scroggins III        return fHuffmanCreated;
149e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
150e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
151e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    /**
152e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     *  Start tile based decoding. Must only be called after a
153e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     *  successful call to buildHuffmanIndex, and must only be
154e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     *  called once.
155e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     */
156e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    bool startTileDecompress() {
157e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        SkASSERT(fHuffmanCreated);
158e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        SkASSERT(fReadHeaderSucceeded);
159e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        SkASSERT(!fDecompressStarted);
160e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        if (jpeg_start_tile_decompress(&fCInfo)) {
161e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            fDecompressStarted = true;
162e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            return true;
163e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        }
164e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        return false;
165e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
166e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
167e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenbergerprivate:
168e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    skjpeg_source_mgr  fSrcMgr;
169e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    jpeg_decompress_struct fCInfo;
170e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    huffman_index fHuffmanIndex;
171e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    bool fInfoInitialized;
172e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    bool fHuffmanCreated;
173e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    bool fDecompressStarted;
174e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkDEBUGCODE(bool fReadHeaderSucceeded;)
175e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger};
176e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#endif
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
178e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenbergerclass SkJPEGImageDecoder : public SkImageDecoder {
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
180e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
181e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    SkJPEGImageDecoder() {
182e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        fImageIndex = NULL;
183e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        fImageWidth = 0;
184e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        fImageHeight = 0;
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
186e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
187e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    virtual ~SkJPEGImageDecoder() {
188e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        SkDELETE(fImageIndex);
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
190e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#endif
191e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
192e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    virtual Format getFormat() const {
193e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        return kJPEG_Format;
194e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    }
195e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
196e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenbergerprotected:
197e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
198e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    virtual bool onBuildTileIndex(SkStream *stream, int *width, int *height) SK_OVERRIDE;
1997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRIDE;
200e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#endif
201e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE;
202e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
204e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
205e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    SkJPEGImageIndex* fImageIndex;
206e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    int fImageWidth;
207e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    int fImageHeight;
208e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#endif
209e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
210e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    /**
211e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     *  Determine the appropriate bitmap config and out_color_space based on
212e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     *  both the preference of the caller and the jpeg_color_space on the
213e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     *  jpeg_decompress_struct passed in.
214e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     *  Must be called after jpeg_read_header.
215e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     */
216e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkBitmap::Config getBitmapConfig(jpeg_decompress_struct*);
217e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
218e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    typedef SkImageDecoder INHERITED;
21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
221e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger//////////////////////////////////////////////////////////////////////////
222e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* Automatically clean up after throwing an exception */
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass JPEGAutoClean {
22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    JPEGAutoClean(): cinfo_ptr(NULL) {}
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ~JPEGAutoClean() {
22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (cinfo_ptr) {
22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            jpeg_destroy_decompress(cinfo_ptr);
23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void set(jpeg_decompress_struct* info) {
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        cinfo_ptr = info;
23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    jpeg_decompress_struct* cinfo_ptr;
23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*  If we need to better match the request, we might examine the image and
24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     output dimensions, and determine if the downsampling jpeg provided is
24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     not sufficient. If so, we can recompute a modified sampleSize value to
24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     make up the difference.
24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     To skip this additional scaling, just set sampleSize = 1; below.
24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic int recompute_sampleSize(int sampleSize,
24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                const jpeg_decompress_struct& cinfo) {
25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return sampleSize * cinfo.output_width / cinfo.image_width;
25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic bool valid_output_dimensions(const jpeg_decompress_struct& cinfo) {
25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /* These are initialized to 0, so if they have non-zero values, we assume
25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru       they are "valid" (i.e. have been computed by libjpeg)
25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
257e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    return 0 != cinfo.output_width && 0 != cinfo.output_height;
25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
260e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenbergerstatic bool skip_src_rows(jpeg_decompress_struct* cinfo, void* buffer, int count) {
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < count; i++) {
26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        JSAMPLE* rowptr = (JSAMPLE*)buffer;
26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int row_count = jpeg_read_scanlines(cinfo, &rowptr, 1);
264e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        if (1 != row_count) {
26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
271e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
272e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenbergerstatic bool skip_src_rows_tile(jpeg_decompress_struct* cinfo,
273e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger                               huffman_index *index, void* buffer, int count) {
274e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    for (int i = 0; i < count; i++) {
275e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        JSAMPLE* rowptr = (JSAMPLE*)buffer;
276e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        int row_count = jpeg_read_tile_scanline(cinfo, index, &rowptr);
277e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        if (1 != row_count) {
278e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger            return false;
279e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        }
280e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    }
281e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    return true;
282e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger}
283e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#endif
284e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// This guy exists just to aid in debugging, as it allows debuggers to just
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// set a break-point in one place to see all error exists.
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic bool return_false(const jpeg_decompress_struct& cinfo,
28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         const SkBitmap& bm, const char msg[]) {
289e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#ifdef SK_DEBUG
29058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n", cinfo.err->msg_code,
29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             cinfo.err->jpeg_message_table[cinfo.err->msg_code], msg,
29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru             bm.width(), bm.height());
29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;   // must always return false
29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// Convert a scanline of CMYK samples to RGBX in place. Note that this
29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// method moves the "scanline" pointer in its processing
29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) {
30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // At this point we've received CMYK pixels from libjpeg. We
30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // perform a crude conversion to RGB (based on the formulae
30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // from easyrgb.com):
30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //  CMYK -> CMY
30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //    C = ( C * (1 - K) + K )      // for each CMY component
30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //  CMY -> RGB
30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //    R = ( 1 - C ) * 255          // for each RGB component
30780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Unfortunately we are seeing inverted CMYK so all the original terms
30880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // are 1-. This yields:
30980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //  CMYK -> CMY
31080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //    C = ( (1-C) * (1 - (1-K) + (1-K) ) -> C = 1 - C*K
31180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // The conversion from CMY->RGB remains the same
31280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (unsigned int x = 0; x < width; ++x, scanline += 4) {
31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        scanline[0] = SkMulDiv255Round(scanline[0], scanline[3]);
31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        scanline[1] = SkMulDiv255Round(scanline[1], scanline[3]);
31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        scanline[2] = SkMulDiv255Round(scanline[2], scanline[3]);
31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        scanline[3] = 255;
31780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
31980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
320e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger/**
321e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger *  Common code for setting the error manager.
322e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger */
323e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenbergerstatic void set_error_mgr(jpeg_decompress_struct* cinfo, skjpeg_error_mgr* errorManager) {
324e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkASSERT(cinfo != NULL);
325e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkASSERT(errorManager != NULL);
326e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    cinfo->err = jpeg_std_error(errorManager);
327e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    errorManager->error_exit = skjpeg_error_exit;
328e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger}
329e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
330e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger/**
331e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger *  Common code for turning off upsampling and smoothing. Turning these
332e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger *  off helps performance without showing noticable differences in the
333e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger *  resulting bitmap.
334e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger */
335e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenbergerstatic void turn_off_visual_optimizations(jpeg_decompress_struct* cinfo) {
336e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkASSERT(cinfo != NULL);
337e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    /* this gives about 30% performance improvement. In theory it may
338e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger       reduce the visual quality, in practice I'm not seeing a difference
339e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger     */
340e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    cinfo->do_fancy_upsampling = 0;
341e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
342e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    /* this gives another few percents */
343e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    cinfo->do_block_smoothing = 0;
344e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger}
345e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
346e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger/**
347e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * Common code for setting the dct method.
348e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger */
349e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenbergerstatic void set_dct_method(const SkImageDecoder& decoder, jpeg_decompress_struct* cinfo) {
350e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkASSERT(cinfo != NULL);
351e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#ifdef DCT_IFAST_SUPPORTED
352e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    if (decoder.getPreferQualityOverSpeed()) {
353e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        cinfo->dct_method = JDCT_ISLOW;
354e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    } else {
355e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        cinfo->dct_method = JDCT_IFAST;
356e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
357e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#else
358e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    cinfo->dct_method = JDCT_ISLOW;
359e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#endif
360e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger}
361e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
362e27eefc4844477cee5d32f51ab45ff62020cdb36Derek SollenbergerSkBitmap::Config SkJPEGImageDecoder::getBitmapConfig(jpeg_decompress_struct* cinfo) {
363e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkASSERT(cinfo != NULL);
364e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
365e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SrcDepth srcDepth = k32Bit_SrcDepth;
366e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    if (JCS_GRAYSCALE == cinfo->jpeg_color_space) {
367e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        srcDepth = k8BitGray_SrcDepth;
368e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
369e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
370e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkBitmap::Config config = this->getPrefConfig(srcDepth, /*hasAlpha*/ false);
371e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    switch (config) {
372e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        case SkBitmap::kA8_Config:
373e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            // Only respect A8 config if the original is grayscale,
374e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            // in which case we will treat the grayscale as alpha
375e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            // values.
376e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            if (cinfo->jpeg_color_space != JCS_GRAYSCALE) {
377e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                config = SkBitmap::kARGB_8888_Config;
378e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            }
379e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            break;
380e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        case SkBitmap::kARGB_8888_Config:
381e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            // Fall through.
382e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        case SkBitmap::kARGB_4444_Config:
383e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            // Fall through.
384e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        case SkBitmap::kRGB_565_Config:
385e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            // These are acceptable destination configs.
386e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            break;
387e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        default:
388e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            // Force all other configs to 8888.
389e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            config = SkBitmap::kARGB_8888_Config;
390e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            break;
391e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
392e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
393e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    switch (cinfo->jpeg_color_space) {
394e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        case JCS_CMYK:
395e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            // Fall through.
396e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        case JCS_YCCK:
397e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            // libjpeg cannot convert from CMYK or YCCK to RGB - here we set up
398e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            // so libjpeg will give us CMYK samples back and we will later
399e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            // manually convert them to RGB
400e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            cinfo->out_color_space = JCS_CMYK;
401e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            break;
402e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        case JCS_GRAYSCALE:
403e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            if (SkBitmap::kA8_Config == config) {
404e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                cinfo->out_color_space = JCS_GRAYSCALE;
405e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                break;
406e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            }
407e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            // The data is JCS_GRAYSCALE, but the caller wants some sort of RGB
408e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            // config. Fall through to set to the default.
409e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        default:
410e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            cinfo->out_color_space = JCS_RGB;
411e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            break;
412e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
413e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    return config;
414e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger}
415e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
416e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#ifdef ANDROID_RGB
417e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger/**
418e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger *  Based on the config and dither mode, adjust out_color_space and
419e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger *  dither_mode of cinfo.
420e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger */
421e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenbergerstatic void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo,
422e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                                              SkBitmap::Config config,
423e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                                              const SkImageDecoder& decoder) {
424e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkASSERT(cinfo != NULL);
425e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    cinfo->dither_mode = JDITHER_NONE;
426e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    if (JCS_CMYK == cinfo->out_color_space) {
427e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        return;
428e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
429e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    switch(config) {
430e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        case SkBitmap::kARGB_8888_Config:
431e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            cinfo->out_color_space = JCS_RGBA_8888;
432e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            break;
433e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        case SkBitmap::kRGB_565_Config:
434e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            cinfo->out_color_space = JCS_RGB_565;
435e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            if (decoder.getDitherImage()) {
436e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger                cinfo->dither_mode = JDITHER_ORDERED;
437e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            }
438e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            break;
439e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        default:
440e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            break;
441e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
442e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger}
443e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#endif
444e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
44580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
44680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef TIME_DECODE
447e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    SkAutoTime atm("JPEG Decode");
44880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
44980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    JPEGAutoClean autoClean;
45180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    jpeg_decompress_struct  cinfo;
453e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    skjpeg_source_mgr       srcManager(stream, this);
45480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
455e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    skjpeg_error_mgr errorManager;
456e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    set_error_mgr(&cinfo, &errorManager);
45780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // All objects need to be instantiated before this setjmp call so that
45980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // they will be cleaned up properly if an error occurs.
460e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    if (setjmp(errorManager.fJmpBuf)) {
46180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return return_false(cinfo, *bm, "setjmp");
46280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
46380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
464e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    initialize_info(&cinfo, &srcManager);
46580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    autoClean.set(&cinfo);
46680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int status = jpeg_read_header(&cinfo, true);
46880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (status != JPEG_HEADER_OK) {
46980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return return_false(cinfo, *bm, "read_header");
47080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
47180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
47280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /*  Try to fulfill the requested sampleSize. Since jpeg can do it (when it
47380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        can) much faster that we, just use their num/denom api to approximate
47480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        the size.
47580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    */
47680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int sampleSize = this->getSampleSize();
47780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
478e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    set_dct_method(*this, &cinfo);
479e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
480e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkASSERT(1 == cinfo.scale_num);
48180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    cinfo.scale_denom = sampleSize;
48280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
483e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    turn_off_visual_optimizations(&cinfo);
48480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
485e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    const SkBitmap::Config config = this->getBitmapConfig(&cinfo);
48680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
48780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef ANDROID_RGB
488e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    adjust_out_color_space_and_dither(&cinfo, config, *this);
48980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
49080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
491e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) {
49280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        bm->setConfig(config, cinfo.image_width, cinfo.image_height);
49358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        bm->setIsOpaque(config != SkBitmap::kA8_Config);
49480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
49580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
49680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
49780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /*  image_width and image_height are the original dimensions, available
49880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        after jpeg_read_header(). To see the scaled dimensions, we have to call
49980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        jpeg_start_decompress(), and then read output_width and output_height.
50080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    */
50180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!jpeg_start_decompress(&cinfo)) {
50280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        /*  If we failed here, we may still have enough information to return
50380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            to the caller if they just wanted (subsampled bounds). If sampleSize
50480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            was 1, then we would have already returned. Thus we just check if
50580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            we're in kDecodeBounds_Mode, and that we have valid output sizes.
50680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
50780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            One reason to fail here is that we have insufficient stream data
50880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            to complete the setup. However, output dimensions seem to get
50980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            computed very early, which is why this special check can pay off.
51080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru         */
511e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimensions(cinfo)) {
51280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height,
51380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                       recompute_sampleSize(sampleSize, cinfo));
51480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            bm->setConfig(config, smpl.scaledWidth(), smpl.scaledHeight());
51558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            bm->setIsOpaque(config != SkBitmap::kA8_Config);
51680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return true;
51780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
51880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return return_false(cinfo, *bm, "start_decompress");
51980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
52080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
52180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    sampleSize = recompute_sampleSize(sampleSize, cinfo);
52280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
52380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // should we allow the Chooser (if present) to pick a config for us???
524e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    if (!this->chooseFromOneChoice(config, cinfo.output_width, cinfo.output_height)) {
52580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return return_false(cinfo, *bm, "chooseFromOneChoice");
52680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
52780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
528e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampleSize);
52958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight());
53058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    bm->setIsOpaque(config != SkBitmap::kA8_Config);
53158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (SkImageDecoder::kDecodeBounds_Mode == mode) {
53258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return true;
53358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
53458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (!this->allocPixelRef(bm, NULL)) {
53558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return return_false(cinfo, *bm, "allocPixelRef");
536e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    }
537e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
538e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    SkAutoLockPixels alp(*bm);
539e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
54080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef ANDROID_RGB
54180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /* short-circuit the SkScaledBitmapSampler when possible, as this gives
54280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru       a significant performance boost.
54380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    */
54480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (sampleSize == 1 &&
54580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        ((config == SkBitmap::kARGB_8888_Config &&
54680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                cinfo.out_color_space == JCS_RGBA_8888) ||
54780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        (config == SkBitmap::kRGB_565_Config &&
54880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                cinfo.out_color_space == JCS_RGB_565)))
54980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
55058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
55180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        INT32 const bpr =  bm->rowBytes();
55280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
55380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        while (cinfo.output_scanline < cinfo.output_height) {
55480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
55580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // if row_count == 0, then we didn't get a scanline, so abort.
55680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // if we supported partial images, we might return true in this case
55780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (0 == row_count) {
55880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return return_false(cinfo, *bm, "read_scanlines");
55980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
56080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (this->shouldCancelDecode()) {
56180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return return_false(cinfo, *bm, "shouldCancelDecode");
56280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
56380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            rowptr += bpr;
56480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
56580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        jpeg_finish_decompress(&cinfo);
56680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
56780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
56880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
56980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
57080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // check for supported formats
57180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScaledBitmapSampler::SrcConfig sc;
57280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (JCS_CMYK == cinfo.out_color_space) {
57380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // In this case we will manually convert the CMYK values to RGB
57480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sc = SkScaledBitmapSampler::kRGBX;
57580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_space) {
57680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sc = SkScaledBitmapSampler::kRGB;
57780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef ANDROID_RGB
57880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else if (JCS_RGBA_8888 == cinfo.out_color_space) {
57980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sc = SkScaledBitmapSampler::kRGBX;
58080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else if (JCS_RGB_565 == cinfo.out_color_space) {
58180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sc = SkScaledBitmapSampler::kRGB_565;
58280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
58380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else if (1 == cinfo.out_color_components &&
58480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru               JCS_GRAYSCALE == cinfo.out_color_space) {
58580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sc = SkScaledBitmapSampler::kGray;
58680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
58780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return return_false(cinfo, *bm, "jpeg colorspace");
58880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
58980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
59034835907d8ed21079a9ee09e0e16082a98637d42Leon Scroggins III    if (!sampler.begin(bm, sc, *this)) {
59180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return return_false(cinfo, *bm, "sampler.begin");
59280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
59380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
59480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // The CMYK work-around relies on 4 components per pixel here
595e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    SkAutoMalloc srcStorage(cinfo.output_width * 4);
596e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    uint8_t* srcRow = (uint8_t*)srcStorage.get();
59780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
59880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //  Possibly skip initial rows [sampler.srcY0]
59980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) {
60080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return return_false(cinfo, *bm, "skip rows");
60180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
60280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
60380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // now loop through scanlines until y == bm->height() - 1
60480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int y = 0;; y++) {
60580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        JSAMPLE* rowptr = (JSAMPLE*)srcRow;
60680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
60780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (0 == row_count) {
60880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return return_false(cinfo, *bm, "read_scanlines");
60980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
61080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (this->shouldCancelDecode()) {
61180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return return_false(cinfo, *bm, "shouldCancelDecode");
61280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
61380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
61480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (JCS_CMYK == cinfo.out_color_space) {
61580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            convert_CMYK_to_RGB(srcRow, cinfo.output_width);
61680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
61780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
61880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sampler.next(srcRow);
61980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (bm->height() - 1 == y) {
62080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // we're done
62180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
62280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
62380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
62480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) {
62580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return return_false(cinfo, *bm, "skip rows");
62680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
62780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
62880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
62980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we formally skip the rest, so we don't get a complaint from libjpeg
63080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!skip_src_rows(&cinfo, srcRow,
63180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                       cinfo.output_height - cinfo.output_scanline)) {
63280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return return_false(cinfo, *bm, "skip rows");
63380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
63480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    jpeg_finish_decompress(&cinfo);
63580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
63680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
63780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
63880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
639e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
640e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenbergerbool SkJPEGImageDecoder::onBuildTileIndex(SkStream* stream, int *width, int *height) {
641e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
642e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTDelete<SkJPEGImageIndex> imageIndex(SkNEW_ARGS(SkJPEGImageIndex, (stream, this)));
643e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    jpeg_decompress_struct* cinfo = imageIndex->cinfo();
644e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
645e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    skjpeg_error_mgr sk_err;
646e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    set_error_mgr(cinfo, &sk_err);
647e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
648e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    // All objects need to be instantiated before this setjmp call so that
649e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    // they will be cleaned up properly if an error occurs.
650e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    if (setjmp(sk_err.fJmpBuf)) {
651e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        return false;
652e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    }
653e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
654e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    // create the cinfo used to create/build the huffmanIndex
655e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    if (!imageIndex->initializeInfoAndReadHeader()) {
656e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        return false;
657e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    }
658e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
659e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    if (!imageIndex->buildHuffmanIndex()) {
660e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        return false;
661e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    }
662e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
663e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    // destroy the cinfo used to create/build the huffman index
664e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    imageIndex->destroyInfo();
665e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
666e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    // Init decoder to image decode mode
667e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    if (!imageIndex->initializeInfoAndReadHeader()) {
668e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        return false;
669e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    }
670e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
671e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    // FIXME: This sets cinfo->out_color_space, which we may change later
672e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    // based on the config in onDecodeSubset. This should be fine, since
673e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    // jpeg_init_read_tile_scanline will check out_color_space again after
674e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    // that change (when it calls jinit_color_deconverter).
675e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    (void) this->getBitmapConfig(cinfo);
676e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
677e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    turn_off_visual_optimizations(cinfo);
678e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
679e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    // instead of jpeg_start_decompress() we start a tiled decompress
680e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    if (!imageIndex->startTileDecompress()) {
681e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        return false;
682e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
683e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
684e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkASSERT(1 == cinfo->scale_num);
685e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    fImageWidth = cinfo->output_width;
686e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    fImageHeight = cinfo->output_height;
687e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
688e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    if (width) {
689e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        *width = fImageWidth;
690e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
691e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    if (height) {
692e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        *height = fImageHeight;
693e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
694e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
695e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    SkDELETE(fImageIndex);
696e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    fImageIndex = imageIndex.detach();
697e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
698e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    return true;
699e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger}
700e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
7017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerbool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
702e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    if (NULL == fImageIndex) {
703e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        return false;
704e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    }
705e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    jpeg_decompress_struct* cinfo = fImageIndex->cinfo();
706e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
707e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    SkIRect rect = SkIRect::MakeWH(fImageWidth, fImageHeight);
708e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    if (!rect.intersect(region)) {
709e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        // If the requested region is entirely outside the image return false
710e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        return false;
711e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    }
712e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
713e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
714e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    skjpeg_error_mgr errorManager;
715e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    set_error_mgr(cinfo, &errorManager);
716e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
717e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    if (setjmp(errorManager.fJmpBuf)) {
718e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        return false;
719e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    }
720e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
721e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    int requestedSampleSize = this->getSampleSize();
722e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    cinfo->scale_denom = requestedSampleSize;
723e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
724e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    set_dct_method(*this, cinfo);
725e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
726e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    const SkBitmap::Config config = this->getBitmapConfig(cinfo);
727e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#ifdef ANDROID_RGB
728e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    adjust_out_color_space_and_dither(cinfo, config, *this);
729e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#endif
730e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
731e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    int startX = rect.fLeft;
732e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    int startY = rect.fTop;
733e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    int width = rect.width();
734e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    int height = rect.height();
735e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
736e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    jpeg_init_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(),
737e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger                                 &startX, &startY, &width, &height);
738e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    int skiaSampleSize = recompute_sampleSize(requestedSampleSize, *cinfo);
739e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    int actualSampleSize = skiaSampleSize * (DCTSIZE / cinfo->min_DCT_scaled_size);
740e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
741e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    SkScaledBitmapSampler sampler(width, height, skiaSampleSize);
742e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
743e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    SkBitmap bitmap;
744e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    bitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight());
745e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    bitmap.setIsOpaque(true);
746e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
747e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    // Check ahead of time if the swap(dest, src) is possible or not.
748e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    // If yes, then we will stick to AllocPixelRef since it's cheaper with the
749e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    // swap happening. If no, then we will use alloc to allocate pixels to
750e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    // prevent garbage collection.
751e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    int w = rect.width() / actualSampleSize;
752e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    int h = rect.height() / actualSampleSize;
753e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    bool swapOnly = (rect == region) && bm->isNull() &&
754e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger                    (w == bitmap.width()) && (h == bitmap.height()) &&
755e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger                    ((startX - rect.x()) / actualSampleSize == 0) &&
756e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger                    ((startY - rect.y()) / actualSampleSize == 0);
757e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    if (swapOnly) {
758e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        if (!this->allocPixelRef(&bitmap, NULL)) {
759e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger            return return_false(*cinfo, bitmap, "allocPixelRef");
760e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        }
761e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    } else {
762e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        if (!bitmap.allocPixels()) {
763e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger            return return_false(*cinfo, bitmap, "allocPixels");
764e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        }
765e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    }
766e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
767e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    SkAutoLockPixels alp(bitmap);
768e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
769e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#ifdef ANDROID_RGB
770e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    /* short-circuit the SkScaledBitmapSampler when possible, as this gives
771e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger       a significant performance boost.
772e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    */
773e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    if (skiaSampleSize == 1 &&
774e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        ((config == SkBitmap::kARGB_8888_Config &&
775e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger                cinfo->out_color_space == JCS_RGBA_8888) ||
776e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        (config == SkBitmap::kRGB_565_Config &&
777e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger                cinfo->out_color_space == JCS_RGB_565)))
778e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    {
779e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        JSAMPLE* rowptr = (JSAMPLE*)bitmap.getPixels();
780e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        INT32 const bpr = bitmap.rowBytes();
781e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        int rowTotalCount = 0;
782e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
783e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        while (rowTotalCount < height) {
784e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger            int rowCount = jpeg_read_tile_scanline(cinfo,
785e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger                                                   fImageIndex->huffmanIndex(),
786e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger                                                   &rowptr);
787e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger            // if row_count == 0, then we didn't get a scanline, so abort.
788e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger            // if we supported partial images, we might return true in this case
789e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger            if (0 == rowCount) {
790e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger                return return_false(*cinfo, bitmap, "read_scanlines");
791e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger            }
792e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger            if (this->shouldCancelDecode()) {
793e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger                return return_false(*cinfo, bitmap, "shouldCancelDecode");
794e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger            }
795e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger            rowTotalCount += rowCount;
796e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger            rowptr += bpr;
797e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        }
798e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
799e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        if (swapOnly) {
800e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger            bm->swap(bitmap);
801e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        } else {
802e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger            cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(),
803e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger                       region.width(), region.height(), startX, startY);
804e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        }
805e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        return true;
806e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    }
807e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#endif
808e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
809e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    // check for supported formats
810e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    SkScaledBitmapSampler::SrcConfig sc;
811e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    if (JCS_CMYK == cinfo->out_color_space) {
812e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        // In this case we will manually convert the CMYK values to RGB
813e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        sc = SkScaledBitmapSampler::kRGBX;
814e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    } else if (3 == cinfo->out_color_components && JCS_RGB == cinfo->out_color_space) {
815e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        sc = SkScaledBitmapSampler::kRGB;
816e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#ifdef ANDROID_RGB
817e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    } else if (JCS_RGBA_8888 == cinfo->out_color_space) {
818e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        sc = SkScaledBitmapSampler::kRGBX;
819e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    } else if (JCS_RGB_565 == cinfo->out_color_space) {
820e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        sc = SkScaledBitmapSampler::kRGB_565;
821e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#endif
822e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    } else if (1 == cinfo->out_color_components &&
823e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger               JCS_GRAYSCALE == cinfo->out_color_space) {
824e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        sc = SkScaledBitmapSampler::kGray;
825e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    } else {
826e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        return return_false(*cinfo, *bm, "jpeg colorspace");
827e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    }
828e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
82934835907d8ed21079a9ee09e0e16082a98637d42Leon Scroggins III    if (!sampler.begin(&bitmap, sc, *this)) {
830e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        return return_false(*cinfo, bitmap, "sampler.begin");
831e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    }
832e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
833e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    // The CMYK work-around relies on 4 components per pixel here
834e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    SkAutoMalloc  srcStorage(width * 4);
835e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    uint8_t* srcRow = (uint8_t*)srcStorage.get();
836e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
837e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    //  Possibly skip initial rows [sampler.srcY0]
838e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler.srcY0())) {
839e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        return return_false(*cinfo, bitmap, "skip rows");
840e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    }
841e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
842e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    // now loop through scanlines until y == bitmap->height() - 1
843e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    for (int y = 0;; y++) {
844e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        JSAMPLE* rowptr = (JSAMPLE*)srcRow;
845e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        int row_count = jpeg_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(), &rowptr);
846e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        if (0 == row_count) {
847e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger            return return_false(*cinfo, bitmap, "read_scanlines");
848e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        }
849e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        if (this->shouldCancelDecode()) {
850e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger            return return_false(*cinfo, bitmap, "shouldCancelDecode");
851e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        }
852e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
853e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        if (JCS_CMYK == cinfo->out_color_space) {
854e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger            convert_CMYK_to_RGB(srcRow, width);
855e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        }
856e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
857e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        sampler.next(srcRow);
858e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        if (bitmap.height() - 1 == y) {
859e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger            // we're done
860e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger            break;
861e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        }
862e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
863e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow,
864e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger                                sampler.srcDY() - 1)) {
865e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger            return return_false(*cinfo, bitmap, "skip rows");
866e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        }
867e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    }
868e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    if (swapOnly) {
869e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        bm->swap(bitmap);
870e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    } else {
871e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(),
872e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger                   region.width(), region.height(), startX, startY);
873e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    }
874e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger    return true;
875e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger}
876e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#endif
877e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger
87880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
87980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
88080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkColorPriv.h"
88180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
88280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// taken from jcolor.c in libjpeg
88380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0   // 16bit - precise but slow
88480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define CYR     19595   // 0.299
88580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define CYG     38470   // 0.587
88680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define CYB      7471   // 0.114
88780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
88880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define CUR    -11059   // -0.16874
88980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define CUG    -21709   // -0.33126
89080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define CUB     32768   // 0.5
89180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
89280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define CVR     32768   // 0.5
89380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define CVG    -27439   // -0.41869
89480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define CVB     -5329   // -0.08131
89580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
89680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define CSHIFT  16
89780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else      // 8bit - fast, slightly less precise
89880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define CYR     77    // 0.299
89980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define CYG     150    // 0.587
90080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define CYB      29    // 0.114
90180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
90280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define CUR     -43    // -0.16874
90380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define CUG    -85    // -0.33126
90480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define CUB     128    // 0.5
90580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
90680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define CVR      128   // 0.5
90780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define CVG     -107   // -0.41869
90880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define CVB      -21   // -0.08131
90980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
91080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define CSHIFT  8
91180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
91280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
91380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void rgb2yuv_32(uint8_t dst[], SkPMColor c) {
91480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int r = SkGetPackedR32(c);
91580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int g = SkGetPackedG32(c);
91680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int b = SkGetPackedB32(c);
91780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
91880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int  y = ( CYR*r + CYG*g + CYB*b ) >> CSHIFT;
91980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int  u = ( CUR*r + CUG*g + CUB*b ) >> CSHIFT;
92080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int  v = ( CVR*r + CVG*g + CVB*b ) >> CSHIFT;
92180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
92280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst[0] = SkToU8(y);
92380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst[1] = SkToU8(u + 128);
92480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst[2] = SkToU8(v + 128);
92580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
92680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
92780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void rgb2yuv_4444(uint8_t dst[], U16CPU c) {
92880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int r = SkGetPackedR4444(c);
92980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int g = SkGetPackedG4444(c);
93080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int b = SkGetPackedB4444(c);
93180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
93280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int  y = ( CYR*r + CYG*g + CYB*b ) >> (CSHIFT - 4);
93380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int  u = ( CUR*r + CUG*g + CUB*b ) >> (CSHIFT - 4);
93480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int  v = ( CVR*r + CVG*g + CVB*b ) >> (CSHIFT - 4);
93580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
93680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst[0] = SkToU8(y);
93780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst[1] = SkToU8(u + 128);
93880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst[2] = SkToU8(v + 128);
93980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
94080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
94180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void rgb2yuv_16(uint8_t dst[], U16CPU c) {
94280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int r = SkGetPackedR16(c);
94380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int g = SkGetPackedG16(c);
94480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int b = SkGetPackedB16(c);
94580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
94680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int  y = ( 2*CYR*r + CYG*g + 2*CYB*b ) >> (CSHIFT - 2);
94780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int  u = ( 2*CUR*r + CUG*g + 2*CUB*b ) >> (CSHIFT - 2);
94880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int  v = ( 2*CVR*r + CVG*g + 2*CVB*b ) >> (CSHIFT - 2);
94980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
95080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst[0] = SkToU8(y);
95180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst[1] = SkToU8(u + 128);
95280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst[2] = SkToU8(v + 128);
95380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
95480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
95580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
95680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
95780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutypedef void (*WriteScanline)(uint8_t* SK_RESTRICT dst,
95880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                              const void* SK_RESTRICT src, int width,
95980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                              const SkPMColor* SK_RESTRICT ctable);
96080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
96180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void Write_32_YUV(uint8_t* SK_RESTRICT dst,
96280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         const void* SK_RESTRICT srcRow, int width,
96380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         const SkPMColor*) {
96480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const uint32_t* SK_RESTRICT src = (const uint32_t*)srcRow;
96580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (--width >= 0) {
96680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef WE_CONVERT_TO_YUV
96780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rgb2yuv_32(dst, *src++);
96880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
96980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        uint32_t c = *src++;
97080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst[0] = SkGetPackedR32(c);
97180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst[1] = SkGetPackedG32(c);
97280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst[2] = SkGetPackedB32(c);
97380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
97480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst += 3;
97580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
97680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
97780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
97880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void Write_4444_YUV(uint8_t* SK_RESTRICT dst,
97980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           const void* SK_RESTRICT srcRow, int width,
98080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           const SkPMColor*) {
98180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)srcRow;
98280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (--width >= 0) {
98380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef WE_CONVERT_TO_YUV
98480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rgb2yuv_4444(dst, *src++);
98580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
98680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkPMColor16 c = *src++;
98780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst[0] = SkPacked4444ToR32(c);
98880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst[1] = SkPacked4444ToG32(c);
98980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst[2] = SkPacked4444ToB32(c);
99080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
99180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst += 3;
99280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
99380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
99480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
99580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void Write_16_YUV(uint8_t* SK_RESTRICT dst,
99680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         const void* SK_RESTRICT srcRow, int width,
99780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         const SkPMColor*) {
99880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const uint16_t* SK_RESTRICT src = (const uint16_t*)srcRow;
99980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (--width >= 0) {
100080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef WE_CONVERT_TO_YUV
100180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rgb2yuv_16(dst, *src++);
100280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
100380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        uint16_t c = *src++;
100480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst[0] = SkPacked16ToR32(c);
100580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst[1] = SkPacked16ToG32(c);
100680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst[2] = SkPacked16ToB32(c);
100780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
100880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst += 3;
100980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
101080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
101180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
101280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void Write_Index_YUV(uint8_t* SK_RESTRICT dst,
101380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            const void* SK_RESTRICT srcRow, int width,
101480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            const SkPMColor* SK_RESTRICT ctable) {
101580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const uint8_t* SK_RESTRICT src = (const uint8_t*)srcRow;
101680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (--width >= 0) {
101780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef WE_CONVERT_TO_YUV
101880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rgb2yuv_32(dst, ctable[*src++]);
101980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
102080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        uint32_t c = ctable[*src++];
102180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst[0] = SkGetPackedR32(c);
102280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst[1] = SkGetPackedG32(c);
102380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst[2] = SkGetPackedB32(c);
102480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
102580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst += 3;
102680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
102780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
102880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
102980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic WriteScanline ChooseWriter(const SkBitmap& bm) {
103080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (bm.config()) {
103180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkBitmap::kARGB_8888_Config:
103280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return Write_32_YUV;
103380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkBitmap::kRGB_565_Config:
103480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return Write_16_YUV;
103580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkBitmap::kARGB_4444_Config:
103680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return Write_4444_YUV;
103780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkBitmap::kIndex8_Config:
103880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return Write_Index_YUV;
103980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        default:
104080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return NULL;
104180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
104280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
104380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
104480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkJPEGImageEncoder : public SkImageEncoder {
104580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprotected:
104680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) {
104780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef TIME_ENCODE
1048e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger        SkAutoTime atm("JPEG Encode");
104980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
105080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
105180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkAutoLockPixels alp(bm);
105280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL == bm.getPixels()) {
105380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
105480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
105580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
105680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        jpeg_compress_struct    cinfo;
105780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        skjpeg_error_mgr        sk_err;
105880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        skjpeg_destination_mgr  sk_wstream(stream);
105980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
106080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // allocate these before set call setjmp
106180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkAutoMalloc    oneRow;
106280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkAutoLockColors ctLocker;
106380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
106480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        cinfo.err = jpeg_std_error(&sk_err);
106580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sk_err.error_exit = skjpeg_error_exit;
106680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (setjmp(sk_err.fJmpBuf)) {
106780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
106880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
106980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
107058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // Keep after setjmp or mark volatile.
107158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        const WriteScanline writer = ChooseWriter(bm);
107258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        if (NULL == writer) {
107358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            return false;
107458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
107558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
107658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        jpeg_create_compress(&cinfo);
107780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        cinfo.dest = &sk_wstream;
107880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        cinfo.image_width = bm.width();
107980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        cinfo.image_height = bm.height();
108080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        cinfo.input_components = 3;
108180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef WE_CONVERT_TO_YUV
108280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        cinfo.in_color_space = JCS_YCbCr;
108380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
108480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        cinfo.in_color_space = JCS_RGB;
108580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
108680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        cinfo.input_gamma = 1;
108780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
108880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        jpeg_set_defaults(&cinfo);
108980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
10907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#ifdef DCT_IFAST_SUPPORTED
109180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        cinfo.dct_method = JDCT_IFAST;
10927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#endif
109380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
109480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        jpeg_start_compress(&cinfo, TRUE);
109580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
109680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const int       width = bm.width();
109780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        uint8_t*        oneRowP = (uint8_t*)oneRow.reset(width * 3);
109880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
109980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const SkPMColor* colors = ctLocker.lockColors(bm);
110080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const void*      srcRow = bm.getPixels();
110180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
110280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        while (cinfo.next_scanline < cinfo.image_height) {
110380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            JSAMPROW row_pointer[1];    /* pointer to JSAMPLE row[s] */
110480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
110580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            writer(oneRowP, srcRow, width, colors);
110680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            row_pointer[0] = oneRowP;
110780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
110880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            srcRow = (const void*)((const char*)srcRow + bm.rowBytes());
110980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
111080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
111180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        jpeg_finish_compress(&cinfo);
111280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        jpeg_destroy_compress(&cinfo);
111380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
111480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
111580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
111680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
111780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
111880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
111980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruDEFINE_DECODER_CREATOR(JPEGImageDecoder);
112080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruDEFINE_ENCODER_CREATOR(JPEGImageEncoder);
112180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
112280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic bool is_jpeg(SkStream* stream) {
112480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const unsigned char gHeader[] = { 0xFF, 0xD8, 0xFF };
112580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const size_t HEADER_SIZE = sizeof(gHeader);
112680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
112780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char buffer[HEADER_SIZE];
112880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t len = stream->read(buffer, HEADER_SIZE);
112980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
113080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (len != HEADER_SIZE) {
11317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return false;   // can't read enough
113280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
113380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (memcmp(buffer, gHeader, HEADER_SIZE)) {
11347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return false;
11357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
11367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return true;
11377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
11387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
11397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkTRegistry.h"
11407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
11417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic SkImageDecoder* sk_libjpeg_dfactory(SkStream* stream) {
11427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (is_jpeg(stream)) {
11437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return SkNEW(SkJPEGImageDecoder);
11447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
11457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return NULL;
11467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
11477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
11487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic SkImageDecoder::Format get_format_jpeg(SkStream* stream) {
11497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (is_jpeg(stream)) {
11507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return SkImageDecoder::kJPEG_Format;
115180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
11527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return SkImageDecoder::kUnknown_Format;
115380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
115480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
115580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) {
115680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL;
115780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
115880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
115980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
116080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libjpeg_dfactory);
11617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_jpeg);
116280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libjpeg_efactory);
1163