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