Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

provider_jpeg_generic.cpp

Go to the documentation of this file.
00001 /*
00002         ------------------------------------------------------------------------
00003         ClanLib, the platform independent game SDK.
00004 
00005         This library is distributed under the GNU LIBRARY GENERAL PUBLIC LICENSE
00006         version 2. See COPYING for details.
00007 
00008         For a total list of contributers see CREDITS.
00009 
00010         ------------------------------------------------------------------------
00011 */
00012 
00013 #include "provider_jpeg_generic.h"
00014 #include <setjmp.h>
00015 #include <jerror.h>
00016 
00017 #define INPUT_BUF_SIZE  4096
00018 
00019 CL_JPEGProvider_Generic::CL_JPEGProvider_Generic(
00020         CL_String name,
00021         CL_InputSourceProvider *_provider,
00022         bool _transparent,
00023         bool _ignore_alphachannel)
00024 {
00025         if (_provider == NULL)
00026         {
00027                 input_provider = CL_InputSourceProvider::create_file_provider(".");
00028         }
00029         else
00030         {
00031                 input_provider = _provider->clone();
00032         }
00033 
00034         ignore_alphachannel = _ignore_alphachannel;
00035         transparent = _transparent;
00036         use_alphapixels = transparent && !ignore_alphachannel;
00037 
00038         trans_redcol = 0;
00039         trans_greencol = 0;
00040         trans_bluecol = 0;
00041                 
00042         locked = 0;
00043         filename = name;
00044         image = NULL;
00045 }
00046 
00047 CL_JPEGProvider_Generic::~CL_JPEGProvider_Generic()
00048 {
00049         perform_unlock();
00050         delete input_provider;
00051 }
00052 
00053 unsigned int CL_JPEGProvider_Generic::get_red_mask() const
00054 {
00055         return CL_Color::get_red_mask(RGB888);
00056 }
00057 
00058 unsigned int CL_JPEGProvider_Generic::get_green_mask() const
00059 {
00060         return CL_Color::get_green_mask(RGB888);
00061 }
00062 
00063 unsigned int CL_JPEGProvider_Generic::get_blue_mask() const
00064 {
00065         return CL_Color::get_blue_mask(RGB888);
00066 }
00067 
00068 unsigned int CL_JPEGProvider_Generic::get_alpha_mask() const
00069 {
00070         return CL_Color::get_alpha_mask(RGB888);
00071 }
00072   
00073 void *CL_JPEGProvider_Generic::get_data() const
00074 {
00075         return image;
00076 }
00077 
00078 /*
00079         Lock the surfaceprovider - which basically means open the file
00080         and read the image into a temporary memory buffer - until
00081         unlock() is called.
00082 */
00083 void CL_JPEGProvider_Generic::perform_lock()
00084 {
00085         if (locked++) return;
00086 
00087         struct jpeg_error_mgr jerr;     
00088         struct jpeg_decompress_struct cinfo;
00089         //      FILE * infile;          
00090         JSAMPARRAY buffer;      
00091         int row_stride;         
00092         
00093         input_source = input_provider->open_source(filename);
00094 
00095         cinfo.err = jpeg_std_error(&jerr);
00096         jpeg_create_decompress(&cinfo);
00097         jpeg_InputSource_src(&cinfo, this);
00098         jpeg_read_header(&cinfo, TRUE);
00099         jpeg_start_decompress(&cinfo);
00100 
00101         row_stride = cinfo.output_width * cinfo.output_components;
00102 
00103         width = cinfo.output_width;
00104         height = cinfo.output_height;
00105         pitch = width * 3;
00106 
00107         // FIXME: Where is the allocated memory freed?
00108         buffer = (*cinfo.mem->alloc_sarray)
00109                 ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 32);
00110 
00111         image = new unsigned char[get_pitch() * cinfo.output_height];
00112 
00113         // RGB Image
00114         if (cinfo.output_components == 3)
00115         {
00116                 while (cinfo.output_scanline < cinfo.output_height) 
00117                 {
00118                         jpeg_read_scanlines(&cinfo, buffer, 1);
00119                 
00120                         for(unsigned int i=0; i < get_pitch(); i += 3)
00121                         {
00122                                 image[pitch * (cinfo.output_scanline - 1) + i + 0] = buffer[0][i + 2];
00123                                 image[pitch * (cinfo.output_scanline - 1) + i + 1] = buffer[0][i + 1];
00124                                 image[pitch * (cinfo.output_scanline - 1) + i + 2] = buffer[0][i + 0];
00125                         }
00126                 }
00127         }
00128         // Greyscale Image
00129         else if (cinfo.output_components == 1)
00130         {
00131                 while (cinfo.output_scanline < cinfo.output_height) 
00132                 {
00133                         jpeg_read_scanlines(&cinfo, buffer, 1);
00134                         
00135                         for(int i=0; i < width; i += 1)
00136                         {
00137                                 image[pitch * (cinfo.output_scanline - 1) + 3*i + 0] = buffer[0][i];
00138                                 image[pitch * (cinfo.output_scanline - 1) + 3*i + 1] = buffer[0][i];
00139                                 image[pitch * (cinfo.output_scanline - 1) + 3*i + 2] = buffer[0][i];
00140                         }                       
00141                 }
00142         }
00143         else
00144         {
00145                 std::cout << "CL_JPEGProvider: Unsupported color completion: " << cinfo.output_components << std::endl;
00146         }
00147         
00148         jpeg_finish_decompress(&cinfo);
00149         jpeg_destroy_decompress(&cinfo);
00150         delete input_source;
00151         input_source = 0;
00152 }
00153 
00154 void CL_JPEGProvider_Generic::perform_unlock()
00155 {
00156         if (!(--locked))
00157         {
00158                 delete[] image;
00159                 image = NULL;
00160         }
00161 }
00162 
00163 void CL_JPEGProvider_Generic::jpeg_InputSource_src (j_decompress_ptr cinfo, CL_JPEGProvider_Generic* provider)
00164 {
00165         InputSource_src_ptr src;
00166         
00167         if (cinfo->src == NULL) /* first time for this JPEG object? */
00168         {
00169                 cinfo->src = (struct jpeg_source_mgr*)
00170                         (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
00171                                                     sizeof(InputSource_source_mgr));
00172                 src = (InputSource_src_ptr) cinfo->src;
00173                 src->buffer = (JOCTET *)
00174                         (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
00175                                                     INPUT_BUF_SIZE * sizeof(JOCTET));
00176         }
00177 
00178         src = (InputSource_src_ptr) cinfo->src;
00179         src->pub.init_source = CL_JPEGProvider_Generic::init_source;
00180         src->pub.fill_input_buffer = CL_JPEGProvider_Generic::fill_input_buffer;
00181         src->pub.skip_input_data = CL_JPEGProvider_Generic::skip_input_data;
00182         src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
00183         src->pub.term_source = CL_JPEGProvider_Generic::term_source;
00184         src->jpeg_provider = provider;
00185         src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
00186         src->pub.next_input_byte = NULL; /* until buffer loaded */
00187 }
00188 
00189 void CL_JPEGProvider_Generic::init_source (j_decompress_ptr cinfo)
00190 {
00191         InputSource_src_ptr src = (InputSource_src_ptr) cinfo->src;
00192         src->start_of_file = TRUE;      
00193 }
00194 
00195 boolean CL_JPEGProvider_Generic::fill_input_buffer (j_decompress_ptr cinfo)
00196 {
00197         InputSource_src_ptr src = (InputSource_src_ptr) cinfo->src;
00198         size_t nbytes;
00199 
00200         nbytes = src->jpeg_provider->input_source->read (src->buffer, INPUT_BUF_SIZE);
00201         
00202         if (nbytes <= 0) 
00203         {
00204                 if (src->start_of_file) /* Treat empty input file as fatal error */
00205                         ERREXIT(cinfo, JERR_INPUT_EMPTY);
00206                 WARNMS(cinfo, JWRN_JPEG_EOF);
00207                 /* Insert a fake EOI marker */
00208                 src->buffer[0] = (JOCTET) 0xFF;
00209                 src->buffer[1] = (JOCTET) JPEG_EOI;
00210                 nbytes = 2;
00211         }
00212         src->pub.next_input_byte = src->buffer;
00213         src->pub.bytes_in_buffer = nbytes;
00214         src->start_of_file = FALSE;
00215         
00216         return TRUE;
00217 }
00218 
00219 void CL_JPEGProvider_Generic::skip_input_data (j_decompress_ptr cinfo, long num_bytes)
00220 {
00221         InputSource_src_ptr src = (InputSource_src_ptr) cinfo->src;
00222         
00223         /* Just a dumb implementation for now.  Could use fseek() except
00224          * it doesn't work on pipes.  Not clear that being smart is worth
00225          * any trouble anyway --- large skips are infrequent.
00226          */
00227         if (num_bytes > 0)
00228         {
00229                 while (num_bytes > (long) src->pub.bytes_in_buffer)
00230                 {
00231                         num_bytes -= (long) src->pub.bytes_in_buffer;
00232                         (void) fill_input_buffer(cinfo);
00233                         /* note we assume that fill_input_buffer will never return FALSE,
00234                          * so suspension need not be handled.
00235                          */
00236                 }
00237                 src->pub.next_input_byte += (size_t) num_bytes;
00238                 src->pub.bytes_in_buffer -= (size_t) num_bytes;
00239         }
00240 }
00241 
00242 void CL_JPEGProvider_Generic::term_source (j_decompress_ptr cinfo)
00243 {
00244         // do nothing
00245 }

Generated at Wed Apr 4 19:54:02 2001 for ClanLib by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001