18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2006 Apple Computer, Inc.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Portions are Copyright (C) 2001-6 mozilla.org
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Other contributors:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *   Stuart Parmenter <stuart@mozilla.com>
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
90bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * Copyright (C) 2007-2009 Torch Mobile, Inc.
100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is free software; you can redistribute it and/or
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modify it under the terms of the GNU Lesser General Public
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License as published by the Free Software Foundation; either
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version 2.1 of the License, or (at your option) any later version.
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is distributed in the hope that it will be useful,
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Lesser General Public License for more details.
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * You should have received a copy of the GNU Lesser General Public
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License along with this library; if not, write to the Free Software
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Alternatively, the contents of this file may be used under the terms
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * of either the Mozilla Public License Version 1.1, found at
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (the "GPL"), in which case the provisions of the MPL or the GPL are
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * applicable instead of those above.  If you wish to allow use of your
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version of this file only under the terms of one of those two
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * licenses (the MPL or the GPL) and not to allow others to use your
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version of this file under the LGPL, indicate your decision by
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * deletingthe provisions above and replace them with the notice and
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * other provisions required by the MPL or the GPL, as the case may be.
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * If you do not delete the provisions above, a recipient may use your
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version of this file under any of the LGPL, the MPL or the GPL.
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "JPEGImageDecoder.h"
420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include <stdio.h>  // Needed by jpeglib.h for FILE.
430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
448a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#if OS(WINCE) || PLATFORM(BREWMP_SIMULATOR)
450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// Remove warning: 'FAR' macro redefinition
460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#undef FAR
470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// jmorecfg.h in libjpeg checks for XMD_H with the comment: "X11/xmd.h correctly defines INT32"
490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// fix INT32 redefinition error by pretending we are X11/xmd.h
500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#define XMD_H
510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectextern "C" {
5428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "jpeglib.h"
5628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
5728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu#if USE(ICCJPEG)
5828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu#include "iccjpeg.h"
5928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu#endif
6028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <setjmp.h>
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstruct decoder_error_mgr {
68692e5dbf12901edacf14812a6fae25462920af42Steve Block    struct jpeg_error_mgr pub; // "public" fields for IJG library
69692e5dbf12901edacf14812a6fae25462920af42Steve Block    jmp_buf setjmp_buffer;     // For handling catastropic errors
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectenum jstate {
73692e5dbf12901edacf14812a6fae25462920af42Steve Block    JPEG_HEADER,                 // Reading JFIF headers
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    JPEG_START_DECOMPRESS,
75692e5dbf12901edacf14812a6fae25462920af42Steve Block    JPEG_DECOMPRESS_PROGRESSIVE, // Output progressive pixels
76692e5dbf12901edacf14812a6fae25462920af42Steve Block    JPEG_DECOMPRESS_SEQUENTIAL,  // Output sequential pixels
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    JPEG_DONE,
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    JPEG_ERROR
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid init_source(j_decompress_ptr jd);
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectboolean fill_input_buffer(j_decompress_ptr jd);
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid skip_input_data(j_decompress_ptr jd, long num_bytes);
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid term_source(j_decompress_ptr jd);
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid error_exit(j_common_ptr cinfo);
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
87692e5dbf12901edacf14812a6fae25462920af42Steve Block// Implementation of a JPEG src object that understands our state machine
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstruct decoder_source_mgr {
89692e5dbf12901edacf14812a6fae25462920af42Steve Block    // public fields; must be first in this struct!
90692e5dbf12901edacf14812a6fae25462920af42Steve Block    struct jpeg_source_mgr pub;
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
92692e5dbf12901edacf14812a6fae25462920af42Steve Block    JPEGImageReader* decoder;
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhustatic ColorProfile readColorProfile(jpeg_decompress_struct* info)
9628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
9728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu#if USE(ICCJPEG)
9828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    JOCTET* profile;
9928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    unsigned int profileLength;
10028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
10128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    if (!read_icc_profile(info, &profile, &profileLength))
10228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        return ColorProfile();
10328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
10428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    ColorProfile colorProfile;
10528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    colorProfile.append(reinterpret_cast<char*>(profile), profileLength);
10628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    free(profile);
10728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    return colorProfile;
10828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu#else
10928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    return ColorProfile();
11028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu#endif
11128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
11228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectclass JPEGImageReader
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectpublic:
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    JPEGImageReader(JPEGImageDecoder* decoder)
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        : m_decoder(decoder)
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        , m_bufferLength(0)
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        , m_bytesToSkip(0)
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        , m_state(JPEG_HEADER)
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        , m_samples(0)
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        memset(&m_info, 0, sizeof(jpeg_decompress_struct));
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
125692e5dbf12901edacf14812a6fae25462920af42Steve Block        // We set up the normal JPEG error routines, then override error_exit.
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_info.err = jpeg_std_error(&m_err.pub);
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_err.pub.error_exit = error_exit;
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
129692e5dbf12901edacf14812a6fae25462920af42Steve Block        // Allocate and initialize JPEG decompression object.
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        jpeg_create_decompress(&m_info);
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        decoder_source_mgr* src = 0;
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!m_info.src) {
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            src = (decoder_source_mgr*)fastCalloc(sizeof(decoder_source_mgr), 1);
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (!src) {
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                m_state = JPEG_ERROR;
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return;
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_info.src = (jpeg_source_mgr*)src;
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
143692e5dbf12901edacf14812a6fae25462920af42Steve Block        // Set up callback functions.
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        src->pub.init_source = init_source;
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        src->pub.fill_input_buffer = fill_input_buffer;
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        src->pub.skip_input_data = skip_input_data;
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        src->pub.resync_to_restart = jpeg_resync_to_restart;
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        src->pub.term_source = term_source;
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        src->decoder = this;
15028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
15128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        // Enable these markers for the ICC color profile.
15228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        // Apparently there are 16 of these markers.  I don't see anywhere in the header with this constant.
15328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        for (unsigned i = 0; i < 0xF; ++i)
15428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu            jpeg_save_markers(&m_info, JPEG_APP0 + i, 0xFFFF);
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ~JPEGImageReader()
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        close();
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
162dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    void close()
163dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    {
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        decoder_source_mgr* src = (decoder_source_mgr*)m_info.src;
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (src)
1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            fastFree(src);
1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_info.src = 0;
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        jpeg_destroy_decompress(&m_info);
1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
172dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    void skipBytes(long numBytes)
173dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    {
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        decoder_source_mgr* src = (decoder_source_mgr*)m_info.src;
175dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        long bytesToSkip = std::min(numBytes, (long)src->pub.bytes_in_buffer);
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        src->pub.bytes_in_buffer -= (size_t)bytesToSkip;
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        src->pub.next_input_byte += bytesToSkip;
178692e5dbf12901edacf14812a6fae25462920af42Steve Block
179dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        m_bytesToSkip = std::max(numBytes - bytesToSkip, static_cast<long>(0));
1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
18281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    bool decode(const SharedBuffer& data, bool onlySize)
183692e5dbf12901edacf14812a6fae25462920af42Steve Block    {
184692e5dbf12901edacf14812a6fae25462920af42Steve Block        m_decodingSizeOnly = onlySize;
185692e5dbf12901edacf14812a6fae25462920af42Steve Block
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        unsigned newByteCount = data.size() - m_bufferLength;
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        unsigned readOffset = m_bufferLength - m_info.src->bytes_in_buffer;
1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_info.src->bytes_in_buffer += newByteCount;
1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_info.src->next_input_byte = (JOCTET*)(data.data()) + readOffset;
191692e5dbf12901edacf14812a6fae25462920af42Steve Block
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // If we still have bytes to skip, try to skip those now.
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (m_bytesToSkip)
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            skipBytes(m_bytesToSkip);
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_bufferLength = data.size();
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // We need to do the setjmp here. Otherwise bad things will happen
19906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        if (setjmp(m_err.setjmp_buffer))
20021939df44de1705786c545cd1bf519d47250322dBen Murdoch            return m_decoder->setFailed();
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        switch (m_state) {
203692e5dbf12901edacf14812a6fae25462920af42Steve Block        case JPEG_HEADER:
204692e5dbf12901edacf14812a6fae25462920af42Steve Block            // Read file parameters with jpeg_read_header().
205692e5dbf12901edacf14812a6fae25462920af42Steve Block            if (jpeg_read_header(&m_info, true) == JPEG_SUSPENDED)
20621939df44de1705786c545cd1bf519d47250322dBen Murdoch                return false; // I/O suspension.
207692e5dbf12901edacf14812a6fae25462920af42Steve Block
208692e5dbf12901edacf14812a6fae25462920af42Steve Block            // Let libjpeg take care of gray->RGB and YCbCr->RGB conversions.
209692e5dbf12901edacf14812a6fae25462920af42Steve Block            switch (m_info.jpeg_color_space) {
210692e5dbf12901edacf14812a6fae25462920af42Steve Block            case JCS_GRAYSCALE:
211692e5dbf12901edacf14812a6fae25462920af42Steve Block            case JCS_YCbCr:
2124a156157940f51b91eadd76f6c86f862ec0a1da0Ben Murdoch                // Grayscale images get "upsampled" by libjpeg.  If we use
2134a156157940f51b91eadd76f6c86f862ec0a1da0Ben Murdoch                // their color profile, CoreGraphics will "upsample" them
2144a156157940f51b91eadd76f6c86f862ec0a1da0Ben Murdoch                // again, resulting in horizontal distortions.
2154a156157940f51b91eadd76f6c86f862ec0a1da0Ben Murdoch                m_decoder->setIgnoreGammaAndColorProfile(true);
2164a156157940f51b91eadd76f6c86f862ec0a1da0Ben Murdoch                // Note fall-through!
2174a156157940f51b91eadd76f6c86f862ec0a1da0Ben Murdoch            case JCS_RGB:
218692e5dbf12901edacf14812a6fae25462920af42Steve Block                m_info.out_color_space = JCS_RGB;
219692e5dbf12901edacf14812a6fae25462920af42Steve Block                break;
220692e5dbf12901edacf14812a6fae25462920af42Steve Block            case JCS_CMYK:
221692e5dbf12901edacf14812a6fae25462920af42Steve Block            case JCS_YCCK:
222692e5dbf12901edacf14812a6fae25462920af42Steve Block                // jpeglib cannot convert these to rgb, but it can convert ycck
223692e5dbf12901edacf14812a6fae25462920af42Steve Block                // to cmyk.
224692e5dbf12901edacf14812a6fae25462920af42Steve Block                m_info.out_color_space = JCS_CMYK;
2252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                // Same as with grayscale images, we convert CMYK images to RGBA
2272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                // ones. When we keep the color profiles of these CMYK images,
2282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                // CoreGraphics will convert their colors again. So, we discard
2292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                // their color profiles to prevent color corruption.
2302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                m_decoder->setIgnoreGammaAndColorProfile(true);
231692e5dbf12901edacf14812a6fae25462920af42Steve Block                break;
232692e5dbf12901edacf14812a6fae25462920af42Steve Block            default:
23321939df44de1705786c545cd1bf519d47250322dBen Murdoch                return m_decoder->setFailed();
234692e5dbf12901edacf14812a6fae25462920af42Steve Block            }
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
236692e5dbf12901edacf14812a6fae25462920af42Steve Block            // Don't allocate a giant and superfluous memory buffer when the
237692e5dbf12901edacf14812a6fae25462920af42Steve Block            // image is a sequential JPEG.
238692e5dbf12901edacf14812a6fae25462920af42Steve Block            m_info.buffered_image = jpeg_has_multiple_scans(&m_info);
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
240692e5dbf12901edacf14812a6fae25462920af42Steve Block            // Used to set up image size so arrays can be allocated.
241692e5dbf12901edacf14812a6fae25462920af42Steve Block            jpeg_calc_output_dimensions(&m_info);
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
243692e5dbf12901edacf14812a6fae25462920af42Steve Block            // Make a one-row-high sample array that will go away when done with
244692e5dbf12901edacf14812a6fae25462920af42Steve Block            // image. Always make it big enough to hold an RGB row.  Since this
245692e5dbf12901edacf14812a6fae25462920af42Steve Block            // uses the IJG memory manager, it must be allocated before the call
246692e5dbf12901edacf14812a6fae25462920af42Steve Block            // to jpeg_start_compress().
247692e5dbf12901edacf14812a6fae25462920af42Steve Block            m_samples = (*m_info.mem->alloc_sarray)((j_common_ptr) &m_info, JPOOL_IMAGE, m_info.output_width * 4, 1);
2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
249692e5dbf12901edacf14812a6fae25462920af42Steve Block            m_state = JPEG_START_DECOMPRESS;
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
251692e5dbf12901edacf14812a6fae25462920af42Steve Block            // We can fill in the size now that the header is available.
252dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (!m_decoder->setSize(m_info.image_width, m_info.image_height))
253ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block                return false;
2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2554576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            if (!m_decoder->ignoresGammaAndColorProfile())
2564576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang                m_decoder->setColorProfile(readColorProfile(info()));
25728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
258692e5dbf12901edacf14812a6fae25462920af42Steve Block            if (m_decodingSizeOnly) {
259692e5dbf12901edacf14812a6fae25462920af42Steve Block                // We can stop here.  Reduce our buffer length and available
260692e5dbf12901edacf14812a6fae25462920af42Steve Block                // data.
261692e5dbf12901edacf14812a6fae25462920af42Steve Block                m_bufferLength -= m_info.src->bytes_in_buffer;
262692e5dbf12901edacf14812a6fae25462920af42Steve Block                m_info.src->bytes_in_buffer = 0;
263692e5dbf12901edacf14812a6fae25462920af42Steve Block                return true;
2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
265692e5dbf12901edacf14812a6fae25462920af42Steve Block        // FALL THROUGH
266692e5dbf12901edacf14812a6fae25462920af42Steve Block
267692e5dbf12901edacf14812a6fae25462920af42Steve Block        case JPEG_START_DECOMPRESS:
268692e5dbf12901edacf14812a6fae25462920af42Steve Block            // Set parameters for decompression.
269692e5dbf12901edacf14812a6fae25462920af42Steve Block            // FIXME -- Should reset dct_method and dither mode for final pass
270692e5dbf12901edacf14812a6fae25462920af42Steve Block            // of progressive JPEG.
271692e5dbf12901edacf14812a6fae25462920af42Steve Block            m_info.dct_method =  JDCT_ISLOW;
272692e5dbf12901edacf14812a6fae25462920af42Steve Block            m_info.dither_mode = JDITHER_FS;
273692e5dbf12901edacf14812a6fae25462920af42Steve Block            m_info.do_fancy_upsampling = true;
274692e5dbf12901edacf14812a6fae25462920af42Steve Block            m_info.enable_2pass_quant = false;
275692e5dbf12901edacf14812a6fae25462920af42Steve Block            m_info.do_block_smoothing = true;
276692e5dbf12901edacf14812a6fae25462920af42Steve Block
277692e5dbf12901edacf14812a6fae25462920af42Steve Block            // Start decompressor.
278692e5dbf12901edacf14812a6fae25462920af42Steve Block            if (!jpeg_start_decompress(&m_info))
27921939df44de1705786c545cd1bf519d47250322dBen Murdoch                return false; // I/O suspension.
280692e5dbf12901edacf14812a6fae25462920af42Steve Block
281692e5dbf12901edacf14812a6fae25462920af42Steve Block            // If this is a progressive JPEG ...
282692e5dbf12901edacf14812a6fae25462920af42Steve Block            m_state = (m_info.buffered_image) ? JPEG_DECOMPRESS_PROGRESSIVE : JPEG_DECOMPRESS_SEQUENTIAL;
283692e5dbf12901edacf14812a6fae25462920af42Steve Block        // FALL THROUGH
284692e5dbf12901edacf14812a6fae25462920af42Steve Block
285692e5dbf12901edacf14812a6fae25462920af42Steve Block        case JPEG_DECOMPRESS_SEQUENTIAL:
286692e5dbf12901edacf14812a6fae25462920af42Steve Block            if (m_state == JPEG_DECOMPRESS_SEQUENTIAL) {
287692e5dbf12901edacf14812a6fae25462920af42Steve Block
288692e5dbf12901edacf14812a6fae25462920af42Steve Block                if (!m_decoder->outputScanlines())
28921939df44de1705786c545cd1bf519d47250322dBen Murdoch                    return false; // I/O suspension.
290692e5dbf12901edacf14812a6fae25462920af42Steve Block
291692e5dbf12901edacf14812a6fae25462920af42Steve Block                // If we've completed image output...
292692e5dbf12901edacf14812a6fae25462920af42Steve Block                ASSERT(m_info.output_scanline == m_info.output_height);
293692e5dbf12901edacf14812a6fae25462920af42Steve Block                m_state = JPEG_DONE;
2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
295692e5dbf12901edacf14812a6fae25462920af42Steve Block        // FALL THROUGH
296692e5dbf12901edacf14812a6fae25462920af42Steve Block
297692e5dbf12901edacf14812a6fae25462920af42Steve Block        case JPEG_DECOMPRESS_PROGRESSIVE:
298692e5dbf12901edacf14812a6fae25462920af42Steve Block            if (m_state == JPEG_DECOMPRESS_PROGRESSIVE) {
299692e5dbf12901edacf14812a6fae25462920af42Steve Block                int status;
300692e5dbf12901edacf14812a6fae25462920af42Steve Block                do {
301692e5dbf12901edacf14812a6fae25462920af42Steve Block                    status = jpeg_consume_input(&m_info);
302692e5dbf12901edacf14812a6fae25462920af42Steve Block                } while ((status != JPEG_SUSPENDED) && (status != JPEG_REACHED_EOI));
303692e5dbf12901edacf14812a6fae25462920af42Steve Block
304692e5dbf12901edacf14812a6fae25462920af42Steve Block                for (;;) {
305692e5dbf12901edacf14812a6fae25462920af42Steve Block                    if (!m_info.output_scanline) {
306692e5dbf12901edacf14812a6fae25462920af42Steve Block                        int scan = m_info.input_scan_number;
307692e5dbf12901edacf14812a6fae25462920af42Steve Block
308692e5dbf12901edacf14812a6fae25462920af42Steve Block                        // If we haven't displayed anything yet
309692e5dbf12901edacf14812a6fae25462920af42Steve Block                        // (output_scan_number == 0) and we have enough data for
310692e5dbf12901edacf14812a6fae25462920af42Steve Block                        // a complete scan, force output of the last full scan.
311692e5dbf12901edacf14812a6fae25462920af42Steve Block                        if (!m_info.output_scan_number && (scan > 1) && (status != JPEG_REACHED_EOI))
312692e5dbf12901edacf14812a6fae25462920af42Steve Block                            --scan;
313692e5dbf12901edacf14812a6fae25462920af42Steve Block
314692e5dbf12901edacf14812a6fae25462920af42Steve Block                        if (!jpeg_start_output(&m_info, scan))
31521939df44de1705786c545cd1bf519d47250322dBen Murdoch                            return false; // I/O suspension.
316692e5dbf12901edacf14812a6fae25462920af42Steve Block                    }
317692e5dbf12901edacf14812a6fae25462920af42Steve Block
318692e5dbf12901edacf14812a6fae25462920af42Steve Block                    if (m_info.output_scanline == 0xffffff)
319692e5dbf12901edacf14812a6fae25462920af42Steve Block                        m_info.output_scanline = 0;
3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
321692e5dbf12901edacf14812a6fae25462920af42Steve Block                    if (!m_decoder->outputScanlines()) {
322692e5dbf12901edacf14812a6fae25462920af42Steve Block                        if (!m_info.output_scanline)
323692e5dbf12901edacf14812a6fae25462920af42Steve Block                            // Didn't manage to read any lines - flag so we
324692e5dbf12901edacf14812a6fae25462920af42Steve Block                            // don't call jpeg_start_output() multiple times for
325692e5dbf12901edacf14812a6fae25462920af42Steve Block                            // the same scan.
326692e5dbf12901edacf14812a6fae25462920af42Steve Block                            m_info.output_scanline = 0xffffff;
32721939df44de1705786c545cd1bf519d47250322dBen Murdoch                        return false; // I/O suspension.
3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
330692e5dbf12901edacf14812a6fae25462920af42Steve Block                    if (m_info.output_scanline == m_info.output_height) {
331692e5dbf12901edacf14812a6fae25462920af42Steve Block                        if (!jpeg_finish_output(&m_info))
33221939df44de1705786c545cd1bf519d47250322dBen Murdoch                            return false; // I/O suspension.
3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
334692e5dbf12901edacf14812a6fae25462920af42Steve Block                        if (jpeg_input_complete(&m_info) && (m_info.input_scan_number == m_info.output_scan_number))
335692e5dbf12901edacf14812a6fae25462920af42Steve Block                            break;
3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
337692e5dbf12901edacf14812a6fae25462920af42Steve Block                        m_info.output_scanline = 0;
338692e5dbf12901edacf14812a6fae25462920af42Steve Block                    }
339692e5dbf12901edacf14812a6fae25462920af42Steve Block                }
3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
341692e5dbf12901edacf14812a6fae25462920af42Steve Block                m_state = JPEG_DONE;
3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
343692e5dbf12901edacf14812a6fae25462920af42Steve Block        // FALL THROUGH
3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
345692e5dbf12901edacf14812a6fae25462920af42Steve Block        case JPEG_DONE:
346692e5dbf12901edacf14812a6fae25462920af42Steve Block            // Finish decompression.
34721939df44de1705786c545cd1bf519d47250322dBen Murdoch            return jpeg_finish_decompress(&m_info);
34806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
349692e5dbf12901edacf14812a6fae25462920af42Steve Block        case JPEG_ERROR:
350dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            // We can get here if the constructor failed.
351dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            return m_decoder->setFailed();
3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jpeg_decompress_struct* info() { return &m_info; }
3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    JSAMPARRAY samples() const { return m_samples; }
3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    JPEGImageDecoder* decoder() { return m_decoder; }
3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectprivate:
3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    JPEGImageDecoder* m_decoder;
3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned m_bufferLength;
3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int m_bytesToSkip;
3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool m_decodingSizeOnly;
3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool m_initialized;
3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jpeg_decompress_struct m_info;
3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    decoder_error_mgr m_err;
3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jstate m_state;
3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    JSAMPARRAY m_samples;
3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
375692e5dbf12901edacf14812a6fae25462920af42Steve Block// Override the standard error method in the IJG JPEG decoder code.
3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid error_exit(j_common_ptr cinfo)
3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
378692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Return control to the setjmp point.
3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    decoder_error_mgr *err = (decoder_error_mgr *) cinfo->err;
3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    longjmp(err->setjmp_buffer, -1);
3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid init_source(j_decompress_ptr jd)
3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid skip_input_data(j_decompress_ptr jd, long num_bytes)
3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    src->decoder->skipBytes(num_bytes);
3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectboolean fill_input_buffer(j_decompress_ptr jd)
3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Our decode step always sets things up properly, so if this method is ever
396692e5dbf12901edacf14812a6fae25462920af42Steve Block    // called, then we have hit the end of the buffer.  A return value of false
397692e5dbf12901edacf14812a6fae25462920af42Steve Block    // indicates that we have no data to supply yet.
3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
401692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid term_source(j_decompress_ptr jd)
4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    src->decoder->decoder()->jpegComplete();
4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
407f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochJPEGImageDecoder::JPEGImageDecoder(ImageSource::AlphaOption alphaOption,
408f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch                                   ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
409f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    : ImageDecoder(alphaOption, gammaAndColorProfileOption)
410d0825bca7fe65beaee391d30da42e937db621564Steve Block{
411d0825bca7fe65beaee391d30da42e937db621564Steve Block}
4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectJPEGImageDecoder::~JPEGImageDecoder()
4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochbool JPEGImageDecoder::isSizeAvailable()
4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
419dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!ImageDecoder::isSizeAvailable())
4200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch         decode(true);
4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return ImageDecoder::isSizeAvailable();
4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
425d0825bca7fe65beaee391d30da42e937db621564Steve Blockbool JPEGImageDecoder::setSize(unsigned width, unsigned height)
426d0825bca7fe65beaee391d30da42e937db621564Steve Block{
427d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (!ImageDecoder::setSize(width, height))
428d0825bca7fe65beaee391d30da42e937db621564Steve Block        return false;
429692e5dbf12901edacf14812a6fae25462920af42Steve Block
430d0825bca7fe65beaee391d30da42e937db621564Steve Block    prepareScaleDataIfNecessary();
431d0825bca7fe65beaee391d30da42e937db621564Steve Block    return true;
432d0825bca7fe65beaee391d30da42e937db621564Steve Block}
433d0825bca7fe65beaee391d30da42e937db621564Steve Block
43465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben MurdochImageFrame* JPEGImageDecoder::frameBufferAtIndex(size_t index)
4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (index)
4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
439e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (m_frameBufferCache.isEmpty()) {
4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_frameBufferCache.resize(1);
441e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        m_frameBufferCache[0].setPremultiplyAlpha(m_premultiplyAlpha);
442e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    }
4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
44465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ImageFrame& frame = m_frameBufferCache[0];
44565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (frame.status() != ImageFrame::FrameComplete)
446692e5dbf12901edacf14812a6fae25462920af42Steve Block        decode(false);
4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return &frame;
4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
45006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenbool JPEGImageDecoder::setFailed()
45106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen{
45206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    m_reader.clear();
45306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    return ImageDecoder::setFailed();
45406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen}
45506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool JPEGImageDecoder::outputScanlines()
4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_frameBufferCache.isEmpty())
4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Initialize the framebuffer if needed.
46265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ImageFrame& buffer = m_frameBufferCache[0];
46365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (buffer.status() == ImageFrame::FrameEmpty) {
464dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (!buffer.setSize(scaledSize().width(), scaledSize().height()))
465dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            return setFailed();
46665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        buffer.setStatus(ImageFrame::FramePartial);
4670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        buffer.setHasAlpha(false);
46828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        buffer.setColorProfile(m_colorProfile);
4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // For JPEGs, the frame always fills the entire image.
4712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jpeg_decompress_struct* info = m_reader->info();
4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    JSAMPARRAY samples = m_reader->samples();
4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (info->output_scanline < info->output_height) {
478231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // jpeg_read_scanlines will increase the scanline counter, so we
479231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // save the scanline before calling it.
480231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        int sourceY = info->output_scanline;
4818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        /* Request one scanline.  Returns 0 or 1 scanlines. */
4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (jpeg_read_scanlines(info, samples, 1) != 1)
4838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
485d0825bca7fe65beaee391d30da42e937db621564Steve Block        int destY = scaledY(sourceY);
486d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (destY < 0)
487d0825bca7fe65beaee391d30da42e937db621564Steve Block            continue;
488d0825bca7fe65beaee391d30da42e937db621564Steve Block        int width = m_scaled ? m_scaledColumns.size() : info->output_width;
489d0825bca7fe65beaee391d30da42e937db621564Steve Block        for (int x = 0; x < width; ++x) {
490d0825bca7fe65beaee391d30da42e937db621564Steve Block            JSAMPLE* jsample = *samples + (m_scaled ? m_scaledColumns[x] : x) * ((info->out_color_space == JCS_RGB) ? 3 : 4);
491d0825bca7fe65beaee391d30da42e937db621564Steve Block            if (info->out_color_space == JCS_RGB)
492d0825bca7fe65beaee391d30da42e937db621564Steve Block                buffer.setRGBA(x, destY, jsample[0], jsample[1], jsample[2], 0xFF);
493d0825bca7fe65beaee391d30da42e937db621564Steve Block            else if (info->out_color_space == JCS_CMYK) {
494d0825bca7fe65beaee391d30da42e937db621564Steve Block                // Source is 'Inverted CMYK', output is RGB.
495d0825bca7fe65beaee391d30da42e937db621564Steve Block                // See: http://www.easyrgb.com/math.php?MATH=M12#text12
496d0825bca7fe65beaee391d30da42e937db621564Steve Block                // Or:  http://www.ilkeratalay.com/colorspacesfaq.php#rgb
497d0825bca7fe65beaee391d30da42e937db621564Steve Block                // From CMYK to CMY:
498d0825bca7fe65beaee391d30da42e937db621564Steve Block                // X =   X    * (1 -   K   ) +   K  [for X = C, M, or Y]
499d0825bca7fe65beaee391d30da42e937db621564Steve Block                // Thus, from Inverted CMYK to CMY is:
500d0825bca7fe65beaee391d30da42e937db621564Steve Block                // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK
501d0825bca7fe65beaee391d30da42e937db621564Steve Block                // From CMY (0..1) to RGB (0..1):
502d0825bca7fe65beaee391d30da42e937db621564Steve Block                // R = 1 - C => 1 - (1 - iC*iK) => iC*iK  [G and B similar]
503d0825bca7fe65beaee391d30da42e937db621564Steve Block                unsigned k = jsample[3];
504d0825bca7fe65beaee391d30da42e937db621564Steve Block                buffer.setRGBA(x, destY, jsample[0] * k / 255, jsample[1] * k / 255, jsample[2] * k / 255, 0xFF);
505d0825bca7fe65beaee391d30da42e937db621564Steve Block            } else {
506d0825bca7fe65beaee391d30da42e937db621564Steve Block                ASSERT_NOT_REACHED();
507dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                return setFailed();
508d0825bca7fe65beaee391d30da42e937db621564Steve Block            }
509231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
5108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
5138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid JPEGImageDecoder::jpegComplete()
5168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_frameBufferCache.isEmpty())
5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
520692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Hand back an appropriately sized buffer, even if the image ended up being
521692e5dbf12901edacf14812a6fae25462920af42Steve Block    // empty.
52265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_frameBufferCache[0].setStatus(ImageFrame::FrameComplete);
523692e5dbf12901edacf14812a6fae25462920af42Steve Block}
524692e5dbf12901edacf14812a6fae25462920af42Steve Block
525692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JPEGImageDecoder::decode(bool onlySize)
526692e5dbf12901edacf14812a6fae25462920af42Steve Block{
527dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (failed())
528692e5dbf12901edacf14812a6fae25462920af42Steve Block        return;
529692e5dbf12901edacf14812a6fae25462920af42Steve Block
530dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!m_reader)
531dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        m_reader.set(new JPEGImageReader(this));
532dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
53321939df44de1705786c545cd1bf519d47250322dBen Murdoch    // If we couldn't decode the image but we've received all the data, decoding
53421939df44de1705786c545cd1bf519d47250322dBen Murdoch    // has failed.
53581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!m_reader->decode(*m_data, onlySize) && isAllDataReceived())
536dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        setFailed();
53706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // If we're done decoding the image, we don't need the JPEGImageReader
53806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // anymore.  (If we failed, |m_reader| has already been cleared.)
53965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    else if (!m_frameBufferCache.isEmpty() && (m_frameBufferCache[0].status() == ImageFrame::FrameComplete))
540692e5dbf12901edacf14812a6fae25462920af42Steve Block        m_reader.clear();
5418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
544