JPEGImageDecoder.cpp revision 65f03d4f644ce73618e5f4f50dd694b26f55ae12
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 182692e5dbf12901edacf14812a6fae25462920af42Steve Block bool decode(const Vector<char>& 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; 225692e5dbf12901edacf14812a6fae25462920af42Steve Block break; 226692e5dbf12901edacf14812a6fae25462920af42Steve Block default: 22721939df44de1705786c545cd1bf519d47250322dBen Murdoch return m_decoder->setFailed(); 228692e5dbf12901edacf14812a6fae25462920af42Steve Block } 2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 230692e5dbf12901edacf14812a6fae25462920af42Steve Block // Don't allocate a giant and superfluous memory buffer when the 231692e5dbf12901edacf14812a6fae25462920af42Steve Block // image is a sequential JPEG. 232692e5dbf12901edacf14812a6fae25462920af42Steve Block m_info.buffered_image = jpeg_has_multiple_scans(&m_info); 2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 234692e5dbf12901edacf14812a6fae25462920af42Steve Block // Used to set up image size so arrays can be allocated. 235692e5dbf12901edacf14812a6fae25462920af42Steve Block jpeg_calc_output_dimensions(&m_info); 2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 237692e5dbf12901edacf14812a6fae25462920af42Steve Block // Make a one-row-high sample array that will go away when done with 238692e5dbf12901edacf14812a6fae25462920af42Steve Block // image. Always make it big enough to hold an RGB row. Since this 239692e5dbf12901edacf14812a6fae25462920af42Steve Block // uses the IJG memory manager, it must be allocated before the call 240692e5dbf12901edacf14812a6fae25462920af42Steve Block // to jpeg_start_compress(). 241692e5dbf12901edacf14812a6fae25462920af42Steve Block m_samples = (*m_info.mem->alloc_sarray)((j_common_ptr) &m_info, JPOOL_IMAGE, m_info.output_width * 4, 1); 2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 243692e5dbf12901edacf14812a6fae25462920af42Steve Block m_state = JPEG_START_DECOMPRESS; 2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 245692e5dbf12901edacf14812a6fae25462920af42Steve Block // We can fill in the size now that the header is available. 246dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!m_decoder->setSize(m_info.image_width, m_info.image_height)) 247ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block return false; 2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2494576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang if (!m_decoder->ignoresGammaAndColorProfile()) 2504576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang m_decoder->setColorProfile(readColorProfile(info())); 25128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu 252692e5dbf12901edacf14812a6fae25462920af42Steve Block if (m_decodingSizeOnly) { 253692e5dbf12901edacf14812a6fae25462920af42Steve Block // We can stop here. Reduce our buffer length and available 254692e5dbf12901edacf14812a6fae25462920af42Steve Block // data. 255692e5dbf12901edacf14812a6fae25462920af42Steve Block m_bufferLength -= m_info.src->bytes_in_buffer; 256692e5dbf12901edacf14812a6fae25462920af42Steve Block m_info.src->bytes_in_buffer = 0; 257692e5dbf12901edacf14812a6fae25462920af42Steve Block return true; 2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 259692e5dbf12901edacf14812a6fae25462920af42Steve Block // FALL THROUGH 260692e5dbf12901edacf14812a6fae25462920af42Steve Block 261692e5dbf12901edacf14812a6fae25462920af42Steve Block case JPEG_START_DECOMPRESS: 262692e5dbf12901edacf14812a6fae25462920af42Steve Block // Set parameters for decompression. 263692e5dbf12901edacf14812a6fae25462920af42Steve Block // FIXME -- Should reset dct_method and dither mode for final pass 264692e5dbf12901edacf14812a6fae25462920af42Steve Block // of progressive JPEG. 265692e5dbf12901edacf14812a6fae25462920af42Steve Block m_info.dct_method = JDCT_ISLOW; 266692e5dbf12901edacf14812a6fae25462920af42Steve Block m_info.dither_mode = JDITHER_FS; 267692e5dbf12901edacf14812a6fae25462920af42Steve Block m_info.do_fancy_upsampling = true; 268692e5dbf12901edacf14812a6fae25462920af42Steve Block m_info.enable_2pass_quant = false; 269692e5dbf12901edacf14812a6fae25462920af42Steve Block m_info.do_block_smoothing = true; 270692e5dbf12901edacf14812a6fae25462920af42Steve Block 271692e5dbf12901edacf14812a6fae25462920af42Steve Block // Start decompressor. 272692e5dbf12901edacf14812a6fae25462920af42Steve Block if (!jpeg_start_decompress(&m_info)) 27321939df44de1705786c545cd1bf519d47250322dBen Murdoch return false; // I/O suspension. 274692e5dbf12901edacf14812a6fae25462920af42Steve Block 275692e5dbf12901edacf14812a6fae25462920af42Steve Block // If this is a progressive JPEG ... 276692e5dbf12901edacf14812a6fae25462920af42Steve Block m_state = (m_info.buffered_image) ? JPEG_DECOMPRESS_PROGRESSIVE : JPEG_DECOMPRESS_SEQUENTIAL; 277692e5dbf12901edacf14812a6fae25462920af42Steve Block // FALL THROUGH 278692e5dbf12901edacf14812a6fae25462920af42Steve Block 279692e5dbf12901edacf14812a6fae25462920af42Steve Block case JPEG_DECOMPRESS_SEQUENTIAL: 280692e5dbf12901edacf14812a6fae25462920af42Steve Block if (m_state == JPEG_DECOMPRESS_SEQUENTIAL) { 281692e5dbf12901edacf14812a6fae25462920af42Steve Block 282692e5dbf12901edacf14812a6fae25462920af42Steve Block if (!m_decoder->outputScanlines()) 28321939df44de1705786c545cd1bf519d47250322dBen Murdoch return false; // I/O suspension. 284692e5dbf12901edacf14812a6fae25462920af42Steve Block 285692e5dbf12901edacf14812a6fae25462920af42Steve Block // If we've completed image output... 286692e5dbf12901edacf14812a6fae25462920af42Steve Block ASSERT(m_info.output_scanline == m_info.output_height); 287692e5dbf12901edacf14812a6fae25462920af42Steve Block m_state = JPEG_DONE; 2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 289692e5dbf12901edacf14812a6fae25462920af42Steve Block // FALL THROUGH 290692e5dbf12901edacf14812a6fae25462920af42Steve Block 291692e5dbf12901edacf14812a6fae25462920af42Steve Block case JPEG_DECOMPRESS_PROGRESSIVE: 292692e5dbf12901edacf14812a6fae25462920af42Steve Block if (m_state == JPEG_DECOMPRESS_PROGRESSIVE) { 293692e5dbf12901edacf14812a6fae25462920af42Steve Block int status; 294692e5dbf12901edacf14812a6fae25462920af42Steve Block do { 295692e5dbf12901edacf14812a6fae25462920af42Steve Block status = jpeg_consume_input(&m_info); 296692e5dbf12901edacf14812a6fae25462920af42Steve Block } while ((status != JPEG_SUSPENDED) && (status != JPEG_REACHED_EOI)); 297692e5dbf12901edacf14812a6fae25462920af42Steve Block 298692e5dbf12901edacf14812a6fae25462920af42Steve Block for (;;) { 299692e5dbf12901edacf14812a6fae25462920af42Steve Block if (!m_info.output_scanline) { 300692e5dbf12901edacf14812a6fae25462920af42Steve Block int scan = m_info.input_scan_number; 301692e5dbf12901edacf14812a6fae25462920af42Steve Block 302692e5dbf12901edacf14812a6fae25462920af42Steve Block // If we haven't displayed anything yet 303692e5dbf12901edacf14812a6fae25462920af42Steve Block // (output_scan_number == 0) and we have enough data for 304692e5dbf12901edacf14812a6fae25462920af42Steve Block // a complete scan, force output of the last full scan. 305692e5dbf12901edacf14812a6fae25462920af42Steve Block if (!m_info.output_scan_number && (scan > 1) && (status != JPEG_REACHED_EOI)) 306692e5dbf12901edacf14812a6fae25462920af42Steve Block --scan; 307692e5dbf12901edacf14812a6fae25462920af42Steve Block 308692e5dbf12901edacf14812a6fae25462920af42Steve Block if (!jpeg_start_output(&m_info, scan)) 30921939df44de1705786c545cd1bf519d47250322dBen Murdoch return false; // I/O suspension. 310692e5dbf12901edacf14812a6fae25462920af42Steve Block } 311692e5dbf12901edacf14812a6fae25462920af42Steve Block 312692e5dbf12901edacf14812a6fae25462920af42Steve Block if (m_info.output_scanline == 0xffffff) 313692e5dbf12901edacf14812a6fae25462920af42Steve Block m_info.output_scanline = 0; 3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 315692e5dbf12901edacf14812a6fae25462920af42Steve Block if (!m_decoder->outputScanlines()) { 316692e5dbf12901edacf14812a6fae25462920af42Steve Block if (!m_info.output_scanline) 317692e5dbf12901edacf14812a6fae25462920af42Steve Block // Didn't manage to read any lines - flag so we 318692e5dbf12901edacf14812a6fae25462920af42Steve Block // don't call jpeg_start_output() multiple times for 319692e5dbf12901edacf14812a6fae25462920af42Steve Block // the same scan. 320692e5dbf12901edacf14812a6fae25462920af42Steve Block m_info.output_scanline = 0xffffff; 32121939df44de1705786c545cd1bf519d47250322dBen Murdoch return false; // I/O suspension. 3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 324692e5dbf12901edacf14812a6fae25462920af42Steve Block if (m_info.output_scanline == m_info.output_height) { 325692e5dbf12901edacf14812a6fae25462920af42Steve Block if (!jpeg_finish_output(&m_info)) 32621939df44de1705786c545cd1bf519d47250322dBen Murdoch return false; // I/O suspension. 3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 328692e5dbf12901edacf14812a6fae25462920af42Steve Block if (jpeg_input_complete(&m_info) && (m_info.input_scan_number == m_info.output_scan_number)) 329692e5dbf12901edacf14812a6fae25462920af42Steve Block break; 3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 331692e5dbf12901edacf14812a6fae25462920af42Steve Block m_info.output_scanline = 0; 332692e5dbf12901edacf14812a6fae25462920af42Steve Block } 333692e5dbf12901edacf14812a6fae25462920af42Steve Block } 3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 335692e5dbf12901edacf14812a6fae25462920af42Steve Block m_state = JPEG_DONE; 3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 337692e5dbf12901edacf14812a6fae25462920af42Steve Block // FALL THROUGH 3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 339692e5dbf12901edacf14812a6fae25462920af42Steve Block case JPEG_DONE: 340692e5dbf12901edacf14812a6fae25462920af42Steve Block // Finish decompression. 34121939df44de1705786c545cd1bf519d47250322dBen Murdoch return jpeg_finish_decompress(&m_info); 34206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen 343692e5dbf12901edacf14812a6fae25462920af42Steve Block case JPEG_ERROR: 344dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // We can get here if the constructor failed. 345dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return m_decoder->setFailed(); 3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project jpeg_decompress_struct* info() { return &m_info; } 3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project JSAMPARRAY samples() const { return m_samples; } 3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project JPEGImageDecoder* decoder() { return m_decoder; } 3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectprivate: 3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project JPEGImageDecoder* m_decoder; 3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unsigned m_bufferLength; 3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int m_bytesToSkip; 3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool m_decodingSizeOnly; 3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool m_initialized; 3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project jpeg_decompress_struct m_info; 3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project decoder_error_mgr m_err; 3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project jstate m_state; 3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project JSAMPARRAY m_samples; 3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}; 3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 369692e5dbf12901edacf14812a6fae25462920af42Steve Block// Override the standard error method in the IJG JPEG decoder code. 3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid error_exit(j_common_ptr cinfo) 3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 372692e5dbf12901edacf14812a6fae25462920af42Steve Block // Return control to the setjmp point. 3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project decoder_error_mgr *err = (decoder_error_mgr *) cinfo->err; 3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project longjmp(err->setjmp_buffer, -1); 3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid init_source(j_decompress_ptr jd) 3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid skip_input_data(j_decompress_ptr jd, long num_bytes) 3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project decoder_source_mgr *src = (decoder_source_mgr *)jd->src; 3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project src->decoder->skipBytes(num_bytes); 3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectboolean fill_input_buffer(j_decompress_ptr jd) 3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Our decode step always sets things up properly, so if this method is ever 390692e5dbf12901edacf14812a6fae25462920af42Steve Block // called, then we have hit the end of the buffer. A return value of false 391692e5dbf12901edacf14812a6fae25462920af42Steve Block // indicates that we have no data to supply yet. 3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 395692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid term_source(j_decompress_ptr jd) 3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project decoder_source_mgr *src = (decoder_source_mgr *)jd->src; 3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project src->decoder->decoder()->jpegComplete(); 3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 401f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochJPEGImageDecoder::JPEGImageDecoder(ImageSource::AlphaOption alphaOption, 402f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption) 403f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch : ImageDecoder(alphaOption, gammaAndColorProfileOption) 404d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 405d0825bca7fe65beaee391d30da42e937db621564Steve Block} 4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectJPEGImageDecoder::~JPEGImageDecoder() 4088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochbool JPEGImageDecoder::isSizeAvailable() 4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 413dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!ImageDecoder::isSizeAvailable()) 4140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch decode(true); 4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return ImageDecoder::isSizeAvailable(); 4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 419d0825bca7fe65beaee391d30da42e937db621564Steve Blockbool JPEGImageDecoder::setSize(unsigned width, unsigned height) 420d0825bca7fe65beaee391d30da42e937db621564Steve Block{ 421d0825bca7fe65beaee391d30da42e937db621564Steve Block if (!ImageDecoder::setSize(width, height)) 422d0825bca7fe65beaee391d30da42e937db621564Steve Block return false; 423692e5dbf12901edacf14812a6fae25462920af42Steve Block 424d0825bca7fe65beaee391d30da42e937db621564Steve Block prepareScaleDataIfNecessary(); 425d0825bca7fe65beaee391d30da42e937db621564Steve Block return true; 426d0825bca7fe65beaee391d30da42e937db621564Steve Block} 427d0825bca7fe65beaee391d30da42e937db621564Steve Block 42865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben MurdochImageFrame* JPEGImageDecoder::frameBufferAtIndex(size_t index) 4298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (index) 4318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 433e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block if (m_frameBufferCache.isEmpty()) { 4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_frameBufferCache.resize(1); 435e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block m_frameBufferCache[0].setPremultiplyAlpha(m_premultiplyAlpha); 436e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block } 4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 43865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch ImageFrame& frame = m_frameBufferCache[0]; 43965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if (frame.status() != ImageFrame::FrameComplete) 440692e5dbf12901edacf14812a6fae25462920af42Steve Block decode(false); 4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return &frame; 4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 44406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenbool JPEGImageDecoder::setFailed() 44506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen{ 44606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen m_reader.clear(); 44706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen return ImageDecoder::setFailed(); 44806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen} 44906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen 4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool JPEGImageDecoder::outputScanlines() 4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_frameBufferCache.isEmpty()) 4538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 4548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // Initialize the framebuffer if needed. 45665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch ImageFrame& buffer = m_frameBufferCache[0]; 45765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if (buffer.status() == ImageFrame::FrameEmpty) { 458dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!buffer.setSize(scaledSize().width(), scaledSize().height())) 459dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return setFailed(); 46065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch buffer.setStatus(ImageFrame::FramePartial); 4610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch buffer.setHasAlpha(false); 46228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu buffer.setColorProfile(m_colorProfile); 4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // For JPEGs, the frame always fills the entire image. 4650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch buffer.setRect(IntRect(IntPoint(), size())); 4668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project jpeg_decompress_struct* info = m_reader->info(); 4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project JSAMPARRAY samples = m_reader->samples(); 4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (info->output_scanline < info->output_height) { 472231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // jpeg_read_scanlines will increase the scanline counter, so we 473231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // save the scanline before calling it. 474231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block int sourceY = info->output_scanline; 4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project /* Request one scanline. Returns 0 or 1 scanlines. */ 4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (jpeg_read_scanlines(info, samples, 1) != 1) 4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 479d0825bca7fe65beaee391d30da42e937db621564Steve Block int destY = scaledY(sourceY); 480d0825bca7fe65beaee391d30da42e937db621564Steve Block if (destY < 0) 481d0825bca7fe65beaee391d30da42e937db621564Steve Block continue; 482d0825bca7fe65beaee391d30da42e937db621564Steve Block int width = m_scaled ? m_scaledColumns.size() : info->output_width; 483d0825bca7fe65beaee391d30da42e937db621564Steve Block for (int x = 0; x < width; ++x) { 484d0825bca7fe65beaee391d30da42e937db621564Steve Block JSAMPLE* jsample = *samples + (m_scaled ? m_scaledColumns[x] : x) * ((info->out_color_space == JCS_RGB) ? 3 : 4); 485d0825bca7fe65beaee391d30da42e937db621564Steve Block if (info->out_color_space == JCS_RGB) 486d0825bca7fe65beaee391d30da42e937db621564Steve Block buffer.setRGBA(x, destY, jsample[0], jsample[1], jsample[2], 0xFF); 487d0825bca7fe65beaee391d30da42e937db621564Steve Block else if (info->out_color_space == JCS_CMYK) { 488d0825bca7fe65beaee391d30da42e937db621564Steve Block // Source is 'Inverted CMYK', output is RGB. 489d0825bca7fe65beaee391d30da42e937db621564Steve Block // See: http://www.easyrgb.com/math.php?MATH=M12#text12 490d0825bca7fe65beaee391d30da42e937db621564Steve Block // Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb 491d0825bca7fe65beaee391d30da42e937db621564Steve Block // From CMYK to CMY: 492d0825bca7fe65beaee391d30da42e937db621564Steve Block // X = X * (1 - K ) + K [for X = C, M, or Y] 493d0825bca7fe65beaee391d30da42e937db621564Steve Block // Thus, from Inverted CMYK to CMY is: 494d0825bca7fe65beaee391d30da42e937db621564Steve Block // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK 495d0825bca7fe65beaee391d30da42e937db621564Steve Block // From CMY (0..1) to RGB (0..1): 496d0825bca7fe65beaee391d30da42e937db621564Steve Block // R = 1 - C => 1 - (1 - iC*iK) => iC*iK [G and B similar] 497d0825bca7fe65beaee391d30da42e937db621564Steve Block unsigned k = jsample[3]; 498d0825bca7fe65beaee391d30da42e937db621564Steve Block buffer.setRGBA(x, destY, jsample[0] * k / 255, jsample[1] * k / 255, jsample[2] * k / 255, 0xFF); 499d0825bca7fe65beaee391d30da42e937db621564Steve Block } else { 500d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT_NOT_REACHED(); 501dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return setFailed(); 502d0825bca7fe65beaee391d30da42e937db621564Steve Block } 503231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 5048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 5058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 5078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid JPEGImageDecoder::jpegComplete() 5108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 5118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_frameBufferCache.isEmpty()) 5128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 5138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 514692e5dbf12901edacf14812a6fae25462920af42Steve Block // Hand back an appropriately sized buffer, even if the image ended up being 515692e5dbf12901edacf14812a6fae25462920af42Steve Block // empty. 51665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch m_frameBufferCache[0].setStatus(ImageFrame::FrameComplete); 517692e5dbf12901edacf14812a6fae25462920af42Steve Block} 518692e5dbf12901edacf14812a6fae25462920af42Steve Block 519692e5dbf12901edacf14812a6fae25462920af42Steve Blockvoid JPEGImageDecoder::decode(bool onlySize) 520692e5dbf12901edacf14812a6fae25462920af42Steve Block{ 521dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (failed()) 522692e5dbf12901edacf14812a6fae25462920af42Steve Block return; 523692e5dbf12901edacf14812a6fae25462920af42Steve Block 524dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (!m_reader) 525dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_reader.set(new JPEGImageReader(this)); 526dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 52721939df44de1705786c545cd1bf519d47250322dBen Murdoch // If we couldn't decode the image but we've received all the data, decoding 52821939df44de1705786c545cd1bf519d47250322dBen Murdoch // has failed. 52921939df44de1705786c545cd1bf519d47250322dBen Murdoch if (!m_reader->decode(m_data->buffer(), onlySize) && isAllDataReceived()) 530dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block setFailed(); 53106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen // If we're done decoding the image, we don't need the JPEGImageReader 53206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen // anymore. (If we failed, |m_reader| has already been cleared.) 53365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch else if (!m_frameBufferCache.isEmpty() && (m_frameBufferCache[0].status() == ImageFrame::FrameComplete)) 534692e5dbf12901edacf14812a6fae25462920af42Steve Block m_reader.clear(); 5358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 5378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 538