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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 "io/stream.h"
00036 #include "debug.h"
00037 #include "jfifcontainer.h"
00038 
00039 namespace OpenRaw {
00040 
00041     using namespace Debug;
00042 
00043     namespace Internals {
00044         
00047         #define BUF_SIZE 1024
00048 
00049         typedef struct {
00050             struct JPEG::jpeg_source_mgr pub; 
00051             JFIFContainer * self;       
00052             off_t offset;
00053             JPEG::JOCTET* buf;
00054         } jpeg_src_t;
00055 
00056         JFIFContainer::JFIFContainer(IO::Stream *file, off_t offset)
00057             : RawContainer(file, offset),
00058                 m_cinfo(), m_jerr(),
00059                 m_headerLoaded(false)
00060         {
00061             /* this is a hack because jpeg_create_decompress is
00062              * implemented as a Macro 
00063              */
00064             using namespace JPEG;
00065 
00066             m_cinfo.err = JPEG::jpeg_std_error(&m_jerr);
00067             m_jerr.error_exit = &j_error_exit;
00068             JPEG::jpeg_create_decompress(&m_cinfo);
00069 
00070             /* inspired by jdatasrc.c */
00071 
00072             jpeg_src_t *src = (jpeg_src_t *)
00073                 (*m_cinfo.mem->alloc_small)((JPEG::j_common_ptr)&m_cinfo, 
00074                                                                         JPOOL_PERMANENT,
00075                                                                         sizeof(jpeg_src_t));
00076             m_cinfo.src = (JPEG::jpeg_source_mgr*)src;
00077             src->pub.init_source = j_init_source;
00078             src->pub.fill_input_buffer = j_fill_input_buffer;
00079             src->pub.skip_input_data = j_skip_input_data;
00080             src->pub.resync_to_restart = JPEG::jpeg_resync_to_restart;
00081             src->pub.term_source = j_term_source;
00082             src->self = this;
00083             src->pub.bytes_in_buffer = 0;
00084             src->pub.next_input_byte = NULL;
00085             src->buf = (JPEG::JOCTET*)(*m_cinfo.mem->alloc_small)
00086                 ((JPEG::j_common_ptr)&m_cinfo, 
00087                  JPOOL_PERMANENT,
00088                  BUF_SIZE * sizeof(JPEG::JOCTET));
00089         }
00090 
00091         JFIFContainer::~JFIFContainer()
00092         {
00093             JPEG::jpeg_destroy_decompress(&m_cinfo);
00094         }
00095 
00096 
00097         bool JFIFContainer::getDimensions(uint32_t &x, uint32_t &y)
00098         {
00099             if(!m_headerLoaded) {
00100                 if (_loadHeader() == 0) {
00101                     Trace(DEBUG1) << "load error failed\n";
00102                     return false;
00103                 }
00104             }
00105             x = m_cinfo.output_width;
00106             y = m_cinfo.output_height;
00107             return true;
00108         }
00109 
00110         int JFIFContainer::_loadHeader()
00111         {
00112             int ret = 0;
00113             if (::setjmp(m_jpegjmp) == 0) {
00114                 ret = JPEG::jpeg_read_header(&m_cinfo, TRUE);
00115                 //Trace(DEBUG1) << "jpeg_read_header " << ret << "\n";
00116                 
00117                 JPEG::jpeg_calc_output_dimensions(&m_cinfo);
00118             }
00119             m_headerLoaded = (ret == 1);
00120             return ret;
00121         }
00122 
00123 
00124         void JFIFContainer::j_error_exit(JPEG::j_common_ptr cinfo)
00125         {
00126             (*cinfo->err->output_message) (cinfo);
00127             JFIFContainer *self = ((jpeg_src_t *)(((JPEG::j_decompress_ptr)cinfo)->src))->self;
00128             ::longjmp(self->m_jpegjmp, 1);
00129         }
00130 
00131         void JFIFContainer::j_init_source(JPEG::j_decompress_ptr)
00132         {
00133         }
00134 
00135 
00136         JPEG::boolean 
00137         JFIFContainer::j_fill_input_buffer(JPEG::j_decompress_ptr cinfo)
00138         {
00139             jpeg_src_t *src = (jpeg_src_t*)cinfo->src;
00140             JFIFContainer *self = src->self;
00141             size_t n = self->file()->read(src->buf, BUF_SIZE * sizeof(*src->buf));
00142             if (n >= 0) {
00143                 src->pub.next_input_byte = src->buf;
00144                 src->pub.bytes_in_buffer = n;
00145             }
00146             else {
00147                 src->pub.next_input_byte = NULL;
00148                 src->pub.bytes_in_buffer = 0;
00149             }
00150             return TRUE;
00151         }
00152 
00153 
00154         void JFIFContainer::j_skip_input_data(JPEG::j_decompress_ptr cinfo, 
00155                                                                                     long num_bytes)
00156         {
00157             jpeg_src_t *src = (jpeg_src_t*)cinfo->src;
00158             if (num_bytes > 0) {
00159                 while ((size_t)num_bytes > src->pub.bytes_in_buffer) {
00160                     num_bytes -= src->pub.bytes_in_buffer;
00161                     j_fill_input_buffer(cinfo);
00162                 }
00163                 src->pub.next_input_byte += (size_t) num_bytes;
00164                 src->pub.bytes_in_buffer -= (size_t) num_bytes;             
00165             }
00166         }
00167 
00168 
00169         void JFIFContainer::j_term_source(JPEG::j_decompress_ptr)
00170         {
00171         }
00172 
00173 
00174     }
00175 }

Generated on Sat Jan 27 11:36:13 2007 for libopenraw by  doxygen 1.4.7