jfifcontainer.cpp

00001 /*
00002  * libopenraw - jfifcontainer.h
00003  *
00004  * Copyright (C) 2006-2007 Hubert Figuiere
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
00019  */
00020 
00021 
00022 #include <setjmp.h>
00023 #include <cstdio>
00024 
00025 namespace JPEG {
00026     /*
00027      * The extern "C" below is REQUIRED for libjpeg-mmx-dev
00028      * as found on debian because some people have this installed.
00029      */
00030     extern "C" {
00031 #include <jpeglib.h>
00032     }
00033 }
00034 
00035 #include <string.h>
00036 #include <libopenraw++/bitmapdata.h>
00037 #include "io/stream.h"
00038 #include "debug.h"
00039 #include "jfifcontainer.h"
00040 
00041 namespace OpenRaw {
00042 
00043     using namespace Debug;
00044 
00045     namespace Internals {
00046         
00049         #define BUF_SIZE 1024
00050 
00051         typedef struct {
00052             struct JPEG::jpeg_source_mgr pub; 
00053             JFIFContainer * self;       
00054             off_t offset;
00055             JPEG::JOCTET* buf;
00056         } jpeg_src_t;
00057 
00058         JFIFContainer::JFIFContainer(IO::Stream *_file, off_t offset)
00059             : RawContainer(_file, offset),
00060                 m_cinfo(), m_jerr(),
00061                 m_headerLoaded(false)
00062         {
00063             setEndian(ENDIAN_BIG);
00064             /* this is a hack because jpeg_create_decompress is
00065              * implemented as a Macro 
00066              */
00067             using namespace JPEG;
00068 
00069             m_cinfo.err = JPEG::jpeg_std_error(&m_jerr);
00070             m_jerr.error_exit = &j_error_exit;
00071             JPEG::jpeg_create_decompress(&m_cinfo);
00072 
00073             /* inspired by jdatasrc.c */
00074 
00075             jpeg_src_t *src = (jpeg_src_t *)
00076                 (*m_cinfo.mem->alloc_small)((JPEG::j_common_ptr)&m_cinfo, 
00077                                                                         JPOOL_PERMANENT,
00078                                                                         sizeof(jpeg_src_t));
00079             m_cinfo.src = (JPEG::jpeg_source_mgr*)src;
00080             src->pub.init_source = j_init_source;
00081             src->pub.fill_input_buffer = j_fill_input_buffer;
00082             src->pub.skip_input_data = j_skip_input_data;
00083             src->pub.resync_to_restart = JPEG::jpeg_resync_to_restart;
00084             src->pub.term_source = j_term_source;
00085             src->self = this;
00086             src->pub.bytes_in_buffer = 0;
00087             src->pub.next_input_byte = NULL;
00088             src->buf = (JPEG::JOCTET*)(*m_cinfo.mem->alloc_small)
00089                 ((JPEG::j_common_ptr)&m_cinfo, 
00090                  JPOOL_PERMANENT,
00091                  BUF_SIZE * sizeof(JPEG::JOCTET));
00092         }
00093 
00094         JFIFContainer::~JFIFContainer()
00095         {
00096             JPEG::jpeg_destroy_decompress(&m_cinfo);
00097         }
00098 
00099 
00100         bool JFIFContainer::getDimensions(uint32_t &x, uint32_t &y)
00101         {
00102             if(!m_headerLoaded) {
00103                 if (_loadHeader() == 0) {
00104                     Trace(DEBUG1) << "load header failed\n";
00105                     return false;
00106                 }
00107             }
00108             x = m_cinfo.output_width;
00109             y = m_cinfo.output_height;
00110             return true;
00111         }
00112 
00113 
00114         bool JFIFContainer::getDecompressedData(BitmapData &data)
00115         {
00116             if(!m_headerLoaded) {
00117                 if (_loadHeader() == 0) {
00118                     Trace(DEBUG1) << "load header failed\n";
00119                     return false;
00120                 }
00121             }
00122             if (::setjmp(m_jpegjmp) != 0) {
00123                 return false;
00124             }
00125             JPEG::jpeg_start_decompress(&m_cinfo);
00126             int row_size = m_cinfo.output_width * m_cinfo.output_components; 
00127             char *dataPtr = (char*)data.allocData(row_size * m_cinfo.output_height);
00128             char *currentPtr = dataPtr;
00129             JPEG::JSAMPARRAY buffer = (*m_cinfo.mem->alloc_sarray)((JPEG::j_common_ptr)&m_cinfo, 
00130                                                                                                          JPOOL_IMAGE, row_size, 
00131                                                                                                          1); 
00132             while (m_cinfo.output_scanline < m_cinfo.output_height) { 
00133                 jpeg_read_scanlines(&m_cinfo, buffer, 1); 
00134                 memcpy(currentPtr, buffer, row_size);
00135                 currentPtr += row_size;
00136             }
00137             data.setDimensions(m_cinfo.output_width, m_cinfo.output_height);
00138 
00139             JPEG::jpeg_finish_decompress(&m_cinfo);
00140             return true;
00141         }
00142 
00143 
00144         int JFIFContainer::_loadHeader()
00145         {
00146             int ret = 0;
00147             if (::setjmp(m_jpegjmp) == 0) {
00148                 ret = JPEG::jpeg_read_header(&m_cinfo, TRUE);
00149                 //Trace(DEBUG1) << "jpeg_read_header " << ret << "\n";
00150                 
00151                 JPEG::jpeg_calc_output_dimensions(&m_cinfo);
00152             }
00153             m_headerLoaded = (ret == 1);
00154             return ret;
00155         }
00156 
00157 
00158         void JFIFContainer::j_error_exit(JPEG::j_common_ptr cinfo)
00159         {
00160             (*cinfo->err->output_message) (cinfo);
00161             JFIFContainer *self = ((jpeg_src_t *)(((JPEG::j_decompress_ptr)cinfo)->src))->self;
00162             ::longjmp(self->m_jpegjmp, 1);
00163         }
00164 
00165         void JFIFContainer::j_init_source(JPEG::j_decompress_ptr)
00166         {
00167         }
00168 
00169 
00170         JPEG::boolean 
00171         JFIFContainer::j_fill_input_buffer(JPEG::j_decompress_ptr cinfo)
00172         {
00173             jpeg_src_t *src = (jpeg_src_t*)cinfo->src;
00174             JFIFContainer *self = src->self;
00175             int n = self->file()->read(src->buf, BUF_SIZE * sizeof(*src->buf));
00176             if (n >= 0) {
00177                 src->pub.next_input_byte = src->buf;
00178                 src->pub.bytes_in_buffer = n;
00179             }
00180             else {
00181                 src->pub.next_input_byte = NULL;
00182                 src->pub.bytes_in_buffer = 0;
00183             }
00184             return TRUE;
00185         }
00186 
00187 
00188         void JFIFContainer::j_skip_input_data(JPEG::j_decompress_ptr cinfo, 
00189                                                                                     long num_bytes)
00190         {
00191             jpeg_src_t *src = (jpeg_src_t*)cinfo->src;
00192             if (num_bytes > 0) {
00193                 while ((size_t)num_bytes > src->pub.bytes_in_buffer) {
00194                     num_bytes -= src->pub.bytes_in_buffer;
00195                     j_fill_input_buffer(cinfo);
00196                 }
00197                 src->pub.next_input_byte += (size_t) num_bytes;
00198                 src->pub.bytes_in_buffer -= (size_t) num_bytes;             
00199             }
00200         }
00201 
00202 
00203         void JFIFContainer::j_term_source(JPEG::j_decompress_ptr)
00204         {
00205         }
00206 
00207 
00208     }
00209 }

Generated on Tue Jun 17 11:47:19 2008 for libopenraw by  doxygen 1.5.6