Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

OSGJPGImageFileType.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *             Copyright (C) 2000-2002 by the OpenSG Forum                   *
00006  *                                                                           *
00007  *                            www.opensg.org                                 *
00008  *                                                                           *
00009  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
00010  *                                                                           *
00011 \*---------------------------------------------------------------------------*/
00012 /*---------------------------------------------------------------------------*\
00013  *                                License                                    *
00014  *                                                                           *
00015  * This library is free software; you can redistribute it and/or modify it   *
00016  * under the terms of the GNU Library General Public License as published    *
00017  * by the Free Software Foundation, version 2.                               *
00018  *                                                                           *
00019  * This library is distributed in the hope that it will be useful, but       *
00020  * WITHOUT ANY WARRANTY; without even the implied warranty of                *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00022  * Library General Public License for more details.                          *
00023  *                                                                           *
00024  * You should have received a copy of the GNU Library General Public         *
00025  * License along with this library; if not, write to the Free Software       *
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00027  *                                                                           *
00028 \*---------------------------------------------------------------------------*/
00029 /*---------------------------------------------------------------------------*\
00030  *                                Changes                                    *
00031  *                                                                           *
00032  *                                                                           *
00033  *                                                                           *
00034  *                                                                           *
00035  *                                                                           *
00036  *                                                                           *
00037 \*---------------------------------------------------------------------------*/
00038 //-------------------------------
00039 // Includes  
00040 //-------------------------------
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043 
00044 #include "OSGConfig.h"
00045 
00046 #ifdef OSG_WITH_JPG
00047 extern "C" {
00048 
00049 #ifdef WIN32
00050 #define __WIN32__
00051 #endif
00052 
00053 #include <setjmp.h>
00054 #include <jpeglib.h>
00055 
00056 }
00057 #endif
00058 
00059 #ifdef   OSG_SGI_LIB
00060 #include <limits>
00061 #endif
00062 #include "OSGJPGImageFileType.h"
00063 #include <OSGLog.h>
00064 
00065 #ifndef OSG_DO_DOC
00066 #    ifdef OSG_WITH_JPG
00067 #        define OSG_JPG_ARG(ARG) ARG
00068 #    else
00069 #        define OSG_JPG_ARG(ARG)
00070 #    endif
00071 #else
00072 #    define OSG_JPG_ARG(ARG) ARG
00073 #endif
00074 
00075 OSG_USING_NAMESPACE
00076 
00092 #ifdef OSG_WITH_JPG
00093 
00094 struct jpeg_mem
00095 {
00096     struct jpeg_destination_mgr dest;
00097     struct jpeg_source_mgr      src;
00098     UChar8                      *buffer;
00099     UInt32                      memSize;
00100     UInt32                      dataSize;
00101 } jpeg_mem;
00102 
00103 /* */
00104 static void jpeg_mem_init_source(j_decompress_ptr OSG_CHECK_ARG(cinfo))
00105 {
00106     jpeg_mem.src.next_input_byte = (JOCTET *) jpeg_mem.buffer;
00107     jpeg_mem.src.bytes_in_buffer = (size_t) jpeg_mem.dataSize;
00108 }
00109 
00110 /* */
00111 static boolean jpeg_mem_fill_input_buffer(j_decompress_ptr OSG_CHECK_ARG(cinfo))
00112 {
00113     SFATAL << "Missing data. Given data block to small." << std::endl;
00114     return false;
00115 }
00116 
00117 /* */
00118 static void jpeg_mem_skip_input_data(j_decompress_ptr OSG_CHECK_ARG(cinfo    ),
00119                               long             OSG_CHECK_ARG(num_bytes))
00120 {
00121 }
00122 
00123 /* */
00124 static boolean jpeg_mem_resync_to_restart(j_decompress_ptr OSG_CHECK_ARG(cinfo  ),
00125                                    int              OSG_CHECK_ARG(desired))
00126 {
00127     return false;
00128 }
00129 
00130 /* */
00131 static void jpeg_mem_term_source(j_decompress_ptr OSG_CHECK_ARG(cinfo))
00132 {
00133 }
00134 
00135 /* */
00136 static void jpeg_mem_init_destination(j_compress_ptr OSG_CHECK_ARG(cinfo))
00137 {
00138     jpeg_mem.dest.next_output_byte = (JOCTET *) jpeg_mem.buffer;
00139     jpeg_mem.dest.free_in_buffer = (size_t) jpeg_mem.memSize;
00140 }
00141 
00142 /* */
00143 static boolean jpeg_mem_empty_output_buffer(j_compress_ptr OSG_CHECK_ARG(cinfo))
00144 {
00145     SFATAL << "Not enough space left in buffer." << std::endl;
00146     return false;
00147 }
00148 
00149 /* */
00150 static void jpeg_mem_term_destination(j_compress_ptr OSG_CHECK_ARG(cinfo))
00151 {
00152     jpeg_mem.dataSize = ((UChar8 *) jpeg_mem.dest.next_output_byte) - ((UChar8 *) jpeg_mem.buffer);
00153 }
00154 
00155 /* */
00156 static void jpeg_memory_dest(struct jpeg_compress_struct *cinfo, 
00157                              UChar8               *buffer,
00158                              UInt32                memSize)
00159 {
00160     jpeg_mem.buffer=buffer;
00161     jpeg_mem.memSize=memSize;
00162     jpeg_mem.dest.init_destination    = jpeg_mem_init_destination;
00163     jpeg_mem.dest.empty_output_buffer = jpeg_mem_empty_output_buffer;
00164     jpeg_mem.dest.term_destination    = jpeg_mem_term_destination;
00165     cinfo->dest=&jpeg_mem.dest;
00166 }
00167 
00168 /* */
00169 static void jpeg_memory_src(struct jpeg_decompress_struct *cinfo, 
00170                      const  UChar8                 *buffer,
00171                             UInt32                  dataSize)
00172 {
00173     jpeg_mem.buffer = const_cast < UChar8 * > (buffer);
00174     jpeg_mem.dataSize = dataSize;
00175     jpeg_mem.src.init_source       = jpeg_mem_init_source;
00176     jpeg_mem.src.fill_input_buffer = jpeg_mem_fill_input_buffer;
00177     jpeg_mem.src.skip_input_data   = jpeg_mem_skip_input_data;
00178     jpeg_mem.src.resync_to_restart = jpeg_mem_resync_to_restart;
00179     jpeg_mem.src.term_source       = jpeg_mem_term_source;
00180     cinfo->src = &jpeg_mem.src;
00181 }
00182 #endif
00183 
00184 /*****************************
00185  *   Types
00186  *****************************/
00187 /*****************************
00188  *  Classvariables
00189  *****************************/
00190 // Static Class Varible implementations:
00191 static const Char8                  *suffixArray[] = { "jpg", "jpeg" };
00192 
00193 JPGImageFileType JPGImageFileType:: _the("jpeg",
00194                                          suffixArray, sizeof(suffixArray),
00195                                          OSG_READ_SUPPORTED | 
00196                                          OSG_WRITE_SUPPORTED );
00197 
00198 /********************************
00199  *  Class methodes
00200  *******************************/
00201 
00202 
00203 //-------------------------------------------------------------------------
00207 JPGImageFileType& JPGImageFileType::the (void)
00208 {
00209   return _the;
00210 }
00211 
00212 /*******************************
00213 *public
00214 *******************************/
00215 
00216 void JPGImageFileType::setQuality(UInt32 cl)
00217 {
00218     if(cl > 100)
00219         cl = 100;
00220     
00221     _quality = cl;
00222 }
00223 
00224 UInt32 JPGImageFileType::getQuality(void)
00225 {
00226     return _quality;
00227 }
00228 
00229 //-------------------------------------------------------------------------
00234 bool JPGImageFileType::read(      ImagePtr &OSG_JPG_ARG(image), 
00235                             const Char8    *OSG_JPG_ARG(fileName))
00236 {
00237 #ifdef OSG_WITH_JPG
00238     bool    retCode = false;
00239     struct local_error_mgr
00240     {
00241         struct jpeg_error_mgr   pub;
00242         jmp_buf                 setjmp_buffer;
00243     };
00244 
00245     unsigned char                   *destData;
00246     Image::PixelFormat              pixelFormat = osg::Image::OSG_INVALID_PF;
00247 
00248     unsigned long                    imageSize;
00249     typedef struct local_error_mgr  *local_error_ptr;
00250     struct local_error_mgr          jerr;
00251     struct jpeg_decompress_struct   cinfo;
00252     FILE                            *infile;
00253     JSAMPARRAY                      buffer;
00254 
00255     int                             row_stride;
00256 
00257     if((infile = fopen(fileName, "rb")))
00258     {
00259         cinfo.err = jpeg_std_error(&jerr.pub);
00260         if(setjmp(jerr.setjmp_buffer))
00261         {
00262             jpeg_destroy_decompress(&cinfo);
00263             fclose(infile);
00264             return retCode;
00265         }
00266 
00267         jpeg_create_decompress(&cinfo);
00268         jpeg_stdio_src(&cinfo, infile);
00269         jpeg_read_header(&cinfo, TRUE);
00270         jpeg_start_decompress(&cinfo);
00271 
00272         switch(cinfo.output_components)
00273         {
00274         case 1:
00275             pixelFormat = Image::OSG_L_PF;
00276             break;
00277         case 2:
00278             pixelFormat = Image::OSG_LA_PF;
00279             break;
00280         case 3:
00281             pixelFormat = Image::OSG_RGB_PF;
00282             break;
00283         case 4:
00284             pixelFormat = Image::OSG_RGBA_PF;
00285             break;
00286         };
00287 
00288         if(image->set(pixelFormat, cinfo.output_width, cinfo.output_height))
00289         {
00290             imageSize = image->getSize();
00291             destData = image->getData() + imageSize;
00292             row_stride = cinfo.output_width * cinfo.output_components;
00293             buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) & cinfo, JPOOL_IMAGE, row_stride, 1);
00294             while(cinfo.output_scanline < cinfo.output_height)
00295             {
00296                 destData -= row_stride;
00297                 jpeg_read_scanlines(&cinfo, buffer, 1);
00298                 memcpy(destData, *buffer, row_stride);
00299             }
00300 
00301             retCode = true;
00302         }
00303         else
00304             retCode = false;
00305 
00306         jpeg_finish_decompress(&cinfo);
00307         jpeg_destroy_decompress(&cinfo);
00308         fclose(infile);
00309     }
00310 
00311     return retCode;
00312 
00313 #else
00314     SWARNING <<
00315         getMimeType() <<
00316         " read is not compiled into the current binary " <<
00317         std::endl;
00318     return false;
00319 #endif
00320 }
00321 
00322 //-------------------------------------------------------------------------
00327 bool JPGImageFileType::write(const ImagePtr &OSG_JPG_ARG(image), 
00328                              const Char8    *OSG_JPG_ARG(fileName))
00329 {
00330 #ifdef OSG_WITH_JPG
00331     if((image->getBpp() != 1 && 
00332         image->getBpp() != 3) || image->getDepth() != 1)
00333     {
00334         SWARNING <<
00335             getMimeType() <<
00336             " JPEG write only works for 2D 1 or 3 bpp images " <<
00337             std::endl;
00338         return false;
00339     }
00340 
00341     bool    retCode = false;
00342 
00343     struct local_error_mgr
00344     {
00345         struct jpeg_error_mgr   pub;
00346         jmp_buf                 setjmp_buffer;
00347     };
00348 
00349     typedef struct local_error_mgr  *local_error_ptr;
00350 
00351     struct local_error_mgr          jerr;
00352     struct jpeg_compress_struct     cinfo;
00353     FILE                            *outfile;
00354     JSAMPARRAY                      buffer;
00355     UChar8                          *data;
00356 
00357     if((outfile = fopen(fileName, "wb")) == NULL)
00358     {
00359         fprintf(stderr, "can't open %s\n", fileName);
00360         return retCode;
00361     }
00362 
00363     cinfo.err = jpeg_std_error(&jerr.pub);
00364     if(setjmp(jerr.setjmp_buffer))
00365     {
00366         jpeg_destroy_compress(&cinfo);
00367         fclose(outfile);
00368         return 0;
00369     }
00370 
00371     jpeg_create_compress(&cinfo);
00372     jpeg_stdio_dest(&cinfo, outfile);
00373 
00374     cinfo.image_width = image->getWidth();
00375     cinfo.image_height = image->getHeight();
00376     cinfo.input_components = image->getBpp();
00377     cinfo.in_color_space = (image->getBpp() == 1) ? JCS_GRAYSCALE : JCS_RGB;
00378 
00379     jpeg_set_defaults(&cinfo);
00380     jpeg_set_quality(&cinfo, _quality, TRUE);
00381     jpeg_start_compress(&cinfo, TRUE);
00382 
00383     buffer = &data;
00384     while(cinfo.next_scanline < cinfo.image_height)
00385     {
00386         data = image->getData() +
00387             (image->getHeight() - 1 - cinfo.next_scanline) *
00388             image->getWidth() *
00389             image->getBpp();
00390         jpeg_write_scanlines(&cinfo, buffer, 1);
00391     }
00392 
00393     jpeg_finish_compress(&cinfo);
00394     jpeg_destroy_compress(&cinfo);
00395     fclose(outfile);
00396 
00397     return true;
00398 
00399 #else
00400     SWARNING <<
00401         getMimeType() <<
00402         " write is not compiled into the current binary " <<
00403         std::endl;
00404     return false;
00405 #endif
00406 }
00407 
00408 bool JPGImageFileType::validateHeader( const Char8 *fileName, bool &implemented )
00409 {
00410     implemented = true;
00411 
00412     if(fileName == NULL)
00413         return false;
00414 
00415     FILE *file = fopen(fileName, "rb");
00416     if(file == NULL)
00417         return false;
00418 
00419     UInt16 magic = 0;
00420     fread((void *) &magic, sizeof(magic), 1, file);
00421     fclose(file);
00422 
00423 #if BYTE_ORDER == LITTLE_ENDIAN
00424     if(magic == 0xd8ff) // the magic header is big endian need to swap it.
00425 #else
00426     if(magic == 0xffd8)
00427 #endif
00428     {
00429         return true;
00430     }
00431 
00432     return false;
00433 }
00434 
00435 
00436 /* */
00437 UInt64 JPGImageFileType::restoreData(      ImagePtr &OSG_JPG_ARG(image  ), 
00438                                      const UChar8   *OSG_JPG_ARG(buffer ),
00439                                            Int32     OSG_JPG_ARG(memSize))
00440 {
00441 #ifdef OSG_WITH_JPG
00442     UInt64    retCode = 0;
00443     struct local_error_mgr
00444     {
00445         struct jpeg_error_mgr   pub;
00446         jmp_buf                 setjmp_buffer;
00447     };
00448 
00449     unsigned char                   *destData;
00450     Image::PixelFormat              pixelFormat = osg::Image::OSG_INVALID_PF;
00451 
00452     unsigned long                    imageSize;
00453     typedef struct local_error_mgr  *local_error_ptr;
00454     struct local_error_mgr          jerr;
00455     struct jpeg_decompress_struct   cinfo;
00456     JSAMPARRAY                      imagebuffer;
00457 
00458     int                             row_stride;
00459 
00460     cinfo.err = jpeg_std_error(&jerr.pub);
00461     if(setjmp(jerr.setjmp_buffer))
00462     {
00463         jpeg_destroy_decompress(&cinfo);
00464         return 0;
00465     }
00466 
00467     jpeg_create_decompress(&cinfo);
00468     jpeg_memory_src(&cinfo, buffer, memSize);
00469     jpeg_read_header(&cinfo, TRUE);
00470     jpeg_start_decompress(&cinfo);
00471 
00472     switch(cinfo.output_components)
00473     {
00474     case 1:
00475         pixelFormat = Image::OSG_L_PF;
00476         break;
00477     case 2:
00478         pixelFormat = Image::OSG_LA_PF;
00479         break;
00480     case 3:
00481         pixelFormat = Image::OSG_RGB_PF;
00482         break;
00483     case 4:
00484         pixelFormat = Image::OSG_RGBA_PF;
00485         break;
00486     };
00487 
00488     if(image->set(pixelFormat, cinfo.output_width, cinfo.output_height))
00489     {
00490         imageSize = image->getSize();
00491         destData = image->getData() + imageSize;
00492         row_stride = cinfo.output_width * cinfo.output_components;
00493         imagebuffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) & cinfo, JPOOL_IMAGE, row_stride, 1);
00494         while(cinfo.output_scanline < cinfo.output_height)
00495         {
00496             destData -= row_stride;
00497             jpeg_read_scanlines(&cinfo, imagebuffer, 1);
00498             memcpy(destData, *imagebuffer, row_stride);
00499         }
00500 
00501         retCode = imageSize;
00502     }
00503     else
00504         retCode = 0;
00505 
00506     jpeg_finish_decompress(&cinfo);
00507     jpeg_destroy_decompress(&cinfo);
00508 
00509     return retCode;
00510 
00511 #else
00512     SWARNING <<
00513         getMimeType() <<
00514         " read is not compiled into the current binary " <<
00515         std::endl;
00516     return 0;
00517 #endif
00518 }
00519 
00520 //-------------------------------------------------------------------------
00525 UInt64 JPGImageFileType::storeData(const ImagePtr &OSG_JPG_ARG(image  ), 
00526                                    UChar8         *OSG_JPG_ARG(buffer ),
00527                                    Int32           OSG_JPG_ARG(memSize))
00528 {
00529 #ifdef OSG_WITH_JPG
00530     if((image->getBpp() != 1 && image->getBpp() != 3)
00531        || image->getDepth() != 1)
00532     {
00533         SWARNING <<
00534             getMimeType() <<
00535             " JPEG storeData only works for 2D 1 or 3 bpp images " <<
00536             std::endl;
00537         return 0;
00538     }
00539 
00540     struct local_error_mgr
00541     {
00542         struct jpeg_error_mgr   pub;
00543         jmp_buf                 setjmp_buffer;
00544     };
00545 
00546     typedef struct local_error_mgr  *local_error_ptr;
00547 
00548     struct local_error_mgr          jerr;
00549     struct jpeg_compress_struct     cinfo;
00550     JSAMPARRAY                      imagebuffer;
00551     UChar8                          *data;
00552 
00553     cinfo.err = jpeg_std_error(&jerr.pub);
00554     if(setjmp(jerr.setjmp_buffer))
00555     {
00556         jpeg_destroy_compress(&cinfo);
00557         return 0;
00558     }
00559 
00560     jpeg_create_compress(&cinfo);
00561     jpeg_memory_dest(&cinfo, buffer, memSize);
00562 
00563     cinfo.image_width = image->getWidth();
00564     cinfo.image_height = image->getHeight();
00565     cinfo.input_components = image->getBpp();
00566     cinfo.in_color_space = (image->getBpp() == 1) ? JCS_GRAYSCALE : JCS_RGB;
00567 
00568     jpeg_set_defaults(&cinfo);
00569     jpeg_set_quality(&cinfo, _quality, TRUE);
00570     jpeg_start_compress(&cinfo, TRUE);
00571 
00572     imagebuffer = &data;
00573     while(cinfo.next_scanline < cinfo.image_height)
00574     {
00575         data = image->getData() +
00576             (image->getHeight() - 1 - cinfo.next_scanline) *
00577             image->getWidth() *
00578             image->getBpp();
00579         jpeg_write_scanlines(&cinfo, imagebuffer, 1);
00580     }
00581 
00582     jpeg_finish_compress(&cinfo);
00583     jpeg_destroy_compress(&cinfo);
00584 
00585     return jpeg_mem.dataSize;
00586 
00587 #else
00588     SWARNING <<
00589         getMimeType() <<
00590         " write is not compiled into the current binary " <<
00591         std::endl;
00592     return 0;
00593 #endif
00594 }
00595 
00596 //-------------------------------------------------------------------------
00600 JPGImageFileType::JPGImageFileType( const Char8 *mimeType,
00601                                     const Char8 *suffixArray[],
00602                                     UInt16 suffixByteCount,
00603                                     UInt32 flags) :
00604     ImageFileType(mimeType, suffixArray, suffixByteCount, flags),
00605     _quality(90)
00606 {
00607     return;
00608 }
00609 
00610 //-------------------------------------------------------------------------
00614 JPGImageFileType::JPGImageFileType(const JPGImageFileType &obj) :
00615     ImageFileType(obj),
00616     _quality(obj._quality)
00617 {
00618     return;
00619 }
00620 
00621 //-------------------------------------------------------------------------
00625 JPGImageFileType::~JPGImageFileType(void)
00626 {
00627     return;
00628 }

Generated on Thu Aug 25 04:06:41 2005 for OpenSG by  doxygen 1.4.3