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

OSGPNGImageFileType.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 #include <string.h>
00044 
00045 #include "OSGConfig.h"
00046 
00047 #ifdef   OSG_SGI_LIB
00048 #include <limits>
00049 #endif
00050 #ifdef OSG_WITH_PNG
00051 #include <png.h>
00052 #endif 
00053 
00054 #include "OSGPNGImageFileType.h"
00055 #include <OSGLog.h>
00056 
00057 #ifndef OSG_DO_DOC
00058 #    ifdef OSG_WITH_PNG
00059 #        define OSG_PNG_ARG(ARG) ARG
00060 #    else
00061 #        define OSG_PNG_ARG(ARG)
00062 #    endif
00063 #else
00064 #    define OSG_PNG_ARG(ARG) ARG
00065 #endif
00066 
00067 OSG_USING_NAMESPACE
00068 
00084 /*****************************
00085  *   Types
00086  *****************************/
00087 /*****************************
00088  *  Classvariables
00089  *****************************/
00090 // Static Class Varible implementations:
00091 static const Char8 *suffixArray[] = {
00092   "png"
00093 };
00094 
00095 /*****************************
00096  *  PNG lib helper
00097  *****************************/
00098 
00099 #ifdef OSG_WITH_PNG
00100 
00101 static void errorOutput (png_structp png_ptr, const char *message)
00102 {
00103   FFATAL   (("PNG: %s\n", message ));
00104 
00105   longjmp(png_ptr->jmpbuf, 1);
00106 }
00107 
00108 static void warningOutput (png_structp OSG_CHECK_ARG(png_ptr), 
00109                            const char *message)
00110 {
00111   FWARNING (("PNG: %s\n", message )); 
00112 }
00113 
00114 #endif
00115 
00116 PNGImageFileType PNGImageFileType:: _the("png",
00117                                          suffixArray, sizeof(suffixArray),
00118                                          OSG_READ_SUPPORTED | 
00119                                          OSG_WRITE_SUPPORTED);
00120 
00121 /********************************
00122  *  Class methodes
00123  *******************************/
00124 
00125 PNGImageFileType& PNGImageFileType::the (void)
00126 {
00127   return _the;
00128 }
00129 
00130 /*******************************
00131 *public
00132 *******************************/
00133 
00134 //-------------------------------------------------------------------------
00139 bool PNGImageFileType::read(      ImagePtr &OSG_PNG_ARG(image), 
00140                             const Char8    *OSG_PNG_ARG(fileName))
00141 {
00142 
00143 #ifdef OSG_WITH_PNG
00144 
00145     bool                retCode;
00146     Image::PixelFormat  pixelFormat = osg::Image::OSG_INVALID_PF;
00147     png_structp         png_ptr;
00148     png_infop           info_ptr;
00149     png_uint_32         width, wc, height, h, i;
00150     png_byte            bit_depth, channels, color_type;
00151     png_bytep           *row_pointers, base;
00152     FILE                *fd;
00153 
00154     if((fd = fopen(fileName, "rb")) == NULL)
00155         return false;
00156 
00157     png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
00158     if(!png_ptr)
00159     {
00160         fclose(fd);
00161         return false;
00162     }
00163 
00164     png_set_error_fn(png_ptr, 0, &errorOutput, &warningOutput);
00165 
00166     info_ptr = png_create_info_struct(png_ptr);
00167     if(!info_ptr)
00168     {
00169         fclose(fd);
00170         png_destroy_read_struct(&png_ptr, 0, 0);
00171         return false;
00172     }
00173 
00174     if(setjmp(png_ptr->jmpbuf))
00175     {
00176         png_destroy_read_struct(&png_ptr, &info_ptr, 0);
00177         fclose(fd);
00178         return false;
00179     }
00180 
00181     png_init_io(png_ptr, fd);
00182 
00183     png_read_info(png_ptr, info_ptr);
00184 
00185     width = png_get_image_width(png_ptr, info_ptr);
00186     height = png_get_image_height(png_ptr, info_ptr);
00187     bit_depth = png_get_bit_depth(png_ptr, info_ptr);
00188     channels = png_get_channels(png_ptr, info_ptr);
00189     color_type = png_get_color_type(png_ptr, info_ptr);
00190 
00191     // Convert paletted images to RGB
00192     if (color_type == PNG_COLOR_TYPE_PALETTE)
00193     {
00194       png_set_palette_to_rgb(png_ptr);
00195       channels = 3;
00196     }
00197 
00198     // Convert < 8 bit to 8 bit
00199     if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
00200       png_set_gray_1_2_4_to_8(png_ptr);
00201     
00202     // Add a full alpha channel if there is transparency
00203     // information in a tRNS chunk
00204     if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
00205     {
00206       png_set_tRNS_to_alpha(png_ptr);
00207       ++channels;
00208     }                                                                                
00209     // Convert 16 bit to 8 bit
00210     if (bit_depth == 16)
00211       png_set_strip_16(png_ptr);
00212 
00213     switch(channels)
00214     {
00215     case 1:
00216         pixelFormat = Image::OSG_L_PF;
00217         break;
00218     case 2:
00219         pixelFormat = Image::OSG_LA_PF;
00220         break;
00221     case 3:
00222         pixelFormat = Image::OSG_RGB_PF;
00223         break;
00224     case 4:
00225         pixelFormat = Image::OSG_RGBA_PF;
00226         break;
00227     };
00228 
00229     if(image->set(pixelFormat, width, height))
00230     {
00231         // Calculate the row pointers
00232         row_pointers = new png_bytep[height];
00233         wc = width * channels;
00234         h = height - 1;
00235         base = image->getData();
00236         for(i = 0; i < height; ++i)
00237             row_pointers[i] = base + (h - i) * wc;
00238 
00239         // Read the image data
00240         png_read_image(png_ptr, row_pointers);
00241 
00242         delete[] row_pointers;
00243 
00244         retCode = true;
00245     }
00246     else
00247         retCode = false;
00248 
00249     png_destroy_read_struct(&png_ptr, &info_ptr, 0);
00250 
00251     fclose(fd);
00252 
00253     return retCode;
00254 
00255 #else
00256 
00257     SWARNING <<
00258         getMimeType() <<
00259         " read is not compiled into the current binary " <<
00260         std::endl;
00261     return false;
00262 
00263 #endif
00264 
00265 }
00266 
00267 //-------------------------------------------------------------------------
00273 bool PNGImageFileType::write(const ImagePtr &img, 
00274                              const Char8 *fileName)
00275 {
00276 #ifdef OSG_WITH_PNG
00277 
00278     FILE *fp;
00279     png_structp png_ptr;
00280     png_infop info_ptr;
00281 
00282     if(img->getDimension() < 1 || img->getDimension() > 2)
00283     {
00284         FWARNING(("PNGImageFileType::write: invalid dimension %d!\n",
00285             img->getDimension()));
00286         return false;
00287     }
00288     
00289     /* open the file */
00290     fp = fopen(fileName, "wb");
00291     if (fp == NULL)
00292     {
00293         FWARNING(("PNGImageFileType::write: couldn't open %s for writing!\n",
00294             fileName));
00295         return false;
00296     }
00297 
00298     /* Create and initialize the png_struct with the desired error handler
00299     * functions.  If you want to use the default stderr and longjump method,
00300     * you can supply NULL for the last three parameters.  We also check that
00301     * the library version is compatible with the one used at compile time,
00302     * in case we are using dynamically linked libraries.  REQUIRED.
00303     */
00304     png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
00305                                 0, &errorOutput, &warningOutput);
00306 
00307     if (png_ptr == NULL)
00308     {
00309       fclose(fp);
00310       return false;
00311     }
00312 
00313     /* Allocate/initialize the image information data.  REQUIRED */
00314     info_ptr = png_create_info_struct(png_ptr);
00315     if (info_ptr == NULL)
00316     {
00317       fclose(fp);
00318       png_destroy_write_struct(&png_ptr,  NULL);
00319       return false;
00320     }
00321 
00322     /* set up the output control if you are using standard C streams */
00323     png_init_io(png_ptr, fp);
00324 
00325     /* This is the hard way */
00326 
00327     /* Set the image information here.  Width and height are up to 2^31,
00328     * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
00329     * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
00330     * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
00331     * or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
00332     * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
00333     * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
00334     */
00335     Int32 ctype;
00336     switch(img->getPixelFormat())
00337     {
00338     case Image::OSG_L_PF:       ctype = PNG_COLOR_TYPE_GRAY;        
00339                                 break;
00340                                 
00341     case Image::OSG_LA_PF:      ctype = PNG_COLOR_TYPE_GRAY_ALPHA;          
00342                                 break;
00343                                 
00344 #if defined(GL_BGR) || defined(GL_BGR_EXT)
00345     case Image::OSG_BGR_PF:
00346 #endif
00347     case Image::OSG_RGB_PF:     ctype = PNG_COLOR_TYPE_RGB;                 
00348                                 break;
00349                                 
00350 #if defined(GL_BGRA) || defined(GL_BGRA_EXT)
00351     case Image::OSG_BGRA_PF:
00352 #endif
00353     case Image::OSG_RGBA_PF:    ctype = PNG_COLOR_TYPE_RGB_ALPHA;           
00354                                 break;
00355 
00356     default:
00357         FWARNING(("PNGImageFileType::write: unknown pixel format %d!\n",
00358             img->getPixelFormat()));
00359         png_destroy_write_struct(&png_ptr,  NULL);
00360         return false;
00361         
00362     }
00363     
00364     png_set_IHDR(png_ptr, info_ptr, img->getWidth(), img->getHeight(),
00365         8, ctype,      
00366         PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
00367 
00368 #if 0
00369     /* optional significant bit chunk */
00370     /* if we are dealing with a grayscale image then */
00371     sig_bit.gray = true_bit_depth;
00372     /* otherwise, if we are dealing with a color image then */
00373     sig_bit.red = true_red_bit_depth;
00374     sig_bit.green = true_green_bit_depth;
00375     sig_bit.blue = true_blue_bit_depth;
00376     /* if the image has an alpha channel then */
00377     sig_bit.alpha = true_alpha_bit_depth;
00378     png_set_sBIT(png_ptr, info_ptr, sig_bit);
00379 
00380 
00381     /* Optional gamma chunk is strongly suggested if you have any guess
00382     * as to the correct gamma of the image.
00383     */
00384     png_set_gAMA(png_ptr, info_ptr, gamma);
00385 
00386     /* Optionally write comments into the image */
00387     text_ptr[0].key = "Title";
00388     text_ptr[0].text = "Mona Lisa";
00389     text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
00390     text_ptr[1].key = "Author";
00391     text_ptr[1].text = "Leonardo DaVinci";
00392     text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
00393     text_ptr[2].key = "Description";
00394     text_ptr[2].text = "<long text>";
00395     text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt;
00396 #ifdef PNG_iTXt_SUPPORTED
00397     text_ptr[0].lang = NULL;
00398     text_ptr[1].lang = NULL;
00399     text_ptr[2].lang = NULL;
00400 #endif
00401     png_set_text(png_ptr, info_ptr, text_ptr, 3);
00402 #endif
00403     /* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */
00404     /* note that if sRGB is present the gAMA and cHRM chunks must be ignored
00405     * on read and must be written in accordance with the sRGB profile */
00406 
00407     /* Write the file header information.  REQUIRED */
00408     png_write_info(png_ptr, info_ptr);
00409 
00410 #if 0
00411     /* invert monochrome pixels */
00412     png_set_invert_mono(png_ptr);
00413 
00414     /* Shift the pixels up to a legal bit depth and fill in
00415     * as appropriate to correctly scale the image.
00416     */
00417     png_set_shift(png_ptr, &sig_bit);
00418 
00419     /* pack pixels into bytes */
00420     png_set_packing(png_ptr);
00421 
00422     /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into
00423     * RGB (4 channels -> 3 channels). The second parameter is not used.
00424     */
00425     png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
00426 
00427     /* swap bytes of 16-bit files to most significant byte first */
00428     png_set_swap(png_ptr);
00429 
00430     /* swap bits of 1, 2, 4 bit packed pixel formats */
00431     png_set_packswap(png_ptr);
00432 #endif
00433 
00434     if(img->getPixelFormat() == Image::OSG_BGR_PF ||
00435        img->getPixelFormat() == Image::OSG_BGRA_PF
00436       )
00437     {
00438         /* flip BGR pixels to RGB */
00439         png_set_bgr(png_ptr);
00440 
00441         /* swap location of alpha bytes from ARGB to RGBA */
00442         png_set_swap_alpha(png_ptr);
00443     }
00444     
00445     /* The easiest way to write the image (you may have a different memory
00446     * layout, however, so choose what fits your needs best).  You need to
00447     * use the first method if you aren't handling interlacing yourself.
00448     */
00449     png_bytep *row_pointers = new png_bytep [img->getHeight()];
00450     
00451     for(Int32 k = 0; k < img->getHeight(); k++)
00452     {
00453         row_pointers[k] = img->getData() + 
00454                           (img->getHeight() - 1 - k) * 
00455                             img->getWidth() * img->getBpp();
00456     }
00457     
00458     /* write out the entire image data in one call */
00459     png_write_image(png_ptr, row_pointers);
00460 
00461     /* It is REQUIRED to call this to finish writing the rest of the file */
00462     png_write_end(png_ptr, info_ptr);
00463     
00464     /* clean up after the write, and free any memory allocated */
00465     png_destroy_write_struct(&png_ptr, &info_ptr);
00466 
00467     delete [] row_pointers;
00468 
00469     /* close the file */
00470     fclose(fp);
00471 
00472     /* that's it */
00473     return true;
00474 
00475 #else
00476     SWARNING <<
00477         getMimeType() <<
00478         " write is not compiled into the current binary " <<
00479         endLog;
00480     return false;
00481 #endif
00482 }
00483 
00484 bool PNGImageFileType::validateHeader( const Char8 *fileName, bool &implemented)
00485 {
00486     implemented = true;
00487 
00488     if(fileName == NULL)
00489         return false;
00490 
00491     FILE *file = fopen(fileName, "rb");
00492     if(file == NULL)
00493         return false;
00494 
00495     std::string magic;
00496     magic.resize(4);
00497     fread((void *) &magic[0], 4, 1, file);
00498     fclose(file);
00499 
00500     if(magic == "\x89PNG")
00501     {
00502         return true;
00503     }
00504 
00505     return false;
00506 }
00507 
00508 #ifdef OSG_WITH_PNG
00509 typedef struct
00510 {
00511     UChar8 *buffer;
00512     UInt64 length;
00513 } BufferInfo;
00514 
00515 static void user_read_data(png_structp png_ptr,
00516                            png_bytep data, png_size_t length)
00517 {
00518     BufferInfo *bufferInfo = (BufferInfo *) png_get_io_ptr(png_ptr);
00519     memcpy((void *) data, (void *) bufferInfo->buffer, length);
00520     bufferInfo->buffer += length;
00521     bufferInfo->length += length;
00522 }
00523 #endif
00524 
00525 
00526 /* */
00527 UInt64 PNGImageFileType::restoreData(      ImagePtr &OSG_PNG_ARG(image  ), 
00528                                      const UChar8   *OSG_PNG_ARG(buffer ),
00529                                            Int32     OSG_CHECK_ARG(memSize))
00530 {
00531 #ifdef OSG_WITH_PNG
00532 
00533     UInt64              retCode;
00534     Image::PixelFormat  pixelFormat = osg::Image::OSG_INVALID_PF;
00535     png_structp         png_ptr;
00536     png_infop           info_ptr;
00537     png_uint_32         width, wc, height, h, i;
00538     png_byte            bit_depth, channels, color_type;
00539     png_bytep           *row_pointers, base;
00540 
00541     png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
00542     if(!png_ptr)
00543     {
00544         return 0;
00545     }
00546 
00547     png_set_error_fn(png_ptr, 0, &errorOutput, &warningOutput);
00548 
00549     info_ptr = png_create_info_struct(png_ptr);
00550     if(!info_ptr)
00551     {
00552         png_destroy_read_struct(&png_ptr, 0, 0);
00553         return 0;
00554     }
00555 
00556     if(setjmp(png_ptr->jmpbuf))
00557     {
00558         png_destroy_read_struct(&png_ptr, &info_ptr, 0);
00559         return 0;
00560     }
00561 
00562     BufferInfo bufferInfo;
00563     bufferInfo.buffer = (UChar8 *) buffer;
00564     bufferInfo.length = 0;
00565     png_set_read_fn(png_ptr, (void *) &bufferInfo, user_read_data);
00566 
00567     png_read_info(png_ptr, info_ptr);
00568 
00569     width = png_get_image_width(png_ptr, info_ptr);
00570     height = png_get_image_height(png_ptr, info_ptr);
00571     bit_depth = png_get_bit_depth(png_ptr, info_ptr);
00572     channels = png_get_channels(png_ptr, info_ptr);
00573     color_type = png_get_color_type(png_ptr, info_ptr);
00574 
00575     // Convert paletted images to RGB
00576     if (color_type == PNG_COLOR_TYPE_PALETTE)
00577     {
00578         png_set_palette_to_rgb(png_ptr);
00579         channels = 3;
00580     }
00581 
00582     // Convert < 8 bit to 8 bit
00583     if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
00584         png_set_gray_1_2_4_to_8(png_ptr);
00585     
00586     // Add a full alpha channel if there is transparency
00587     // information in a tRNS chunk
00588     if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
00589     {
00590         png_set_tRNS_to_alpha(png_ptr);
00591         ++channels;
00592     }                                                                                
00593     // Convert 16 bit to 8 bit
00594     if (bit_depth == 16)
00595         png_set_strip_16(png_ptr);
00596 
00597     switch(channels)
00598     {
00599     case 1:
00600         pixelFormat = Image::OSG_L_PF;
00601         break;
00602     case 2:
00603         pixelFormat = Image::OSG_LA_PF;
00604         break;
00605     case 3:
00606         pixelFormat = Image::OSG_RGB_PF;
00607         break;
00608     case 4:
00609         pixelFormat = Image::OSG_RGBA_PF;
00610         break;
00611     };
00612 
00613     if(image->set(pixelFormat, width, height))
00614     {
00615         // Calculate the row pointers
00616         row_pointers = new png_bytep[height];
00617         wc = width * channels;
00618         h = height - 1;
00619         base = image->getData();
00620         for(i = 0; i < height; ++i)
00621             row_pointers[i] = base + (h - i) * wc;
00622 
00623         // Read the image data
00624         png_read_image(png_ptr, row_pointers);
00625 
00626         delete[] row_pointers;
00627 
00628         retCode = bufferInfo.length;
00629     }
00630     else
00631         retCode = 0;
00632 
00633     png_destroy_read_struct(&png_ptr, &info_ptr, 0);
00634 
00635     return retCode;
00636 
00637 #else
00638     SWARNING <<
00639         getMimeType() <<
00640         " restoreData is not compiled into the current binary " <<
00641         std::endl;
00642     return 0;
00643 #endif
00644 }
00645 
00646 #ifdef OSG_WITH_PNG
00647 
00648 static void user_write_data(png_structp png_ptr,
00649                             png_bytep data, png_size_t length)
00650 {
00651     BufferInfo *bufferInfo = (BufferInfo *) png_get_io_ptr(png_ptr);
00652     memcpy((void *) bufferInfo->buffer, (void *) data, length);
00653     bufferInfo->buffer += length;
00654     bufferInfo->length += length;
00655 }
00656 
00657 static void user_flush_data(png_structp OSG_CHECK_ARG(png_ptr))
00658 {
00659 }
00660 
00661 #endif
00662 
00663 //-------------------------------------------------------------------------
00668 UInt64 PNGImageFileType::storeData(const ImagePtr &OSG_PNG_ARG(image  ), 
00669                                    UChar8         *OSG_PNG_ARG(buffer ),
00670                                    Int32           OSG_CHECK_ARG(memSize))
00671 {
00672 #ifdef OSG_WITH_PNG
00673 
00674     png_structp png_ptr;
00675     png_infop info_ptr;
00676 
00677     if(image->getDimension() < 1 || image->getDimension() > 2)
00678     {
00679         FWARNING(("PNGImageFileType::write: invalid dimension %d!\n",
00680             image->getDimension()));
00681         return 0;
00682     }
00683 
00684     /* Create and initialize the png_struct with the desired error handler
00685     * functions.  If you want to use the default stderr and longjump method,
00686     * you can supply NULL for the last three parameters.  We also check that
00687     * the library version is compatible with the one used at compile time,
00688     * in case we are using dynamically linked libraries.  REQUIRED.
00689     */
00690     png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
00691                                 0, &errorOutput, &warningOutput);
00692 
00693     if (png_ptr == NULL)
00694     {
00695         return 0;
00696     }
00697 
00698     /* Allocate/initialize the image information data.  REQUIRED */
00699     info_ptr = png_create_info_struct(png_ptr);
00700     if (info_ptr == NULL)
00701     {
00702         png_destroy_write_struct(&png_ptr,  NULL);
00703         return 0;
00704     }
00705 
00706     BufferInfo bufferInfo;
00707     bufferInfo.buffer = buffer;
00708     bufferInfo.length = 0;
00709     png_set_write_fn(png_ptr, (void *) &bufferInfo, user_write_data, user_flush_data);
00710 
00711     /* This is the hard way */
00712 
00713     /* Set the image information here.  Width and height are up to 2^31,
00714     * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
00715     * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
00716     * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
00717     * or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
00718     * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
00719     * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
00720     */
00721     Int32 ctype;
00722     switch(image->getPixelFormat())
00723     {
00724     case Image::OSG_L_PF:       ctype = PNG_COLOR_TYPE_GRAY;        
00725                                 break;
00726                                 
00727     case Image::OSG_LA_PF:      ctype = PNG_COLOR_TYPE_GRAY_ALPHA;          
00728                                 break;
00729                                 
00730 #if defined(GL_BGR) || defined(GL_BGR_EXT)
00731     case Image::OSG_BGR_PF:
00732 #endif
00733     case Image::OSG_RGB_PF:     ctype = PNG_COLOR_TYPE_RGB;                 
00734                                 break;
00735                                 
00736 #if defined(GL_BGRA) || defined(GL_BGRA_EXT)
00737     case Image::OSG_BGRA_PF:
00738 #endif
00739     case Image::OSG_RGBA_PF:    ctype = PNG_COLOR_TYPE_RGB_ALPHA;           
00740                                 break;
00741 
00742     default:
00743         FWARNING(("PNGImageFileType::write: unknown pixel format %d!\n",
00744             image->getPixelFormat()));
00745         png_destroy_write_struct(&png_ptr,  NULL);
00746         return false;
00747         
00748     }
00749     
00750     png_set_IHDR(png_ptr, info_ptr, image->getWidth(), image->getHeight(),
00751         8, ctype,      
00752         PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
00753 
00754     /* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */
00755     /* note that if sRGB is present the gAMA and cHRM chunks must be ignored
00756     * on read and must be written in accordance with the sRGB profile */
00757 
00758     /* Write the file header information.  REQUIRED */
00759     png_write_info(png_ptr, info_ptr);
00760 
00761     if(image->getPixelFormat() == Image::OSG_BGR_PF ||
00762        image->getPixelFormat() == Image::OSG_BGRA_PF
00763       )
00764     {
00765         /* flip BGR pixels to RGB */
00766         png_set_bgr(png_ptr);
00767 
00768         /* swap location of alpha bytes from ARGB to RGBA */
00769         png_set_swap_alpha(png_ptr);
00770     }
00771     
00772     /* The easiest way to write the image (you may have a different memory
00773     * layout, however, so choose what fits your needs best).  You need to
00774     * use the first method if you aren't handling interlacing yourself.
00775     */
00776     png_bytep *row_pointers = new png_bytep [image->getHeight()];
00777     
00778     for(Int32 k = 0; k < image->getHeight(); k++)
00779     {
00780         row_pointers[k] = image->getData() + 
00781                           (image->getHeight() - 1 - k) * 
00782                             image->getWidth() * image->getBpp();
00783     }
00784     
00785     /* write out the entire image data in one call */
00786     png_write_image(png_ptr, row_pointers);
00787 
00788     /* It is REQUIRED to call this to finish writing the rest of the file */
00789     png_write_end(png_ptr, info_ptr);
00790     
00791     /* clean up after the write, and free any memory allocated */
00792     png_destroy_write_struct(&png_ptr, &info_ptr);
00793 
00794     delete [] row_pointers;
00795 
00796     /* that's it */
00797     return bufferInfo.length;
00798 
00799 #else
00800     SWARNING <<
00801         getMimeType() <<
00802         " storeData is not compiled into the current binary " <<
00803         std::endl;
00804     return 0;
00805 #endif
00806 }
00807 
00808 //-------------------------------------------------------------------------
00812 PNGImageFileType::PNGImageFileType ( const Char8 *mimeType,
00813                                      const Char8 *suffixArray[],
00814                                      UInt16 suffixByteCount,
00815                                      UInt32 flags) :
00816     ImageFileType(mimeType, suffixArray, suffixByteCount, flags)
00817 {
00818     return;
00819 }
00820 
00821 //-------------------------------------------------------------------------
00825 PNGImageFileType::PNGImageFileType(const PNGImageFileType &obj) :
00826     ImageFileType(obj)
00827 {
00828     return;
00829 }
00830 
00831 
00832 //-------------------------------------------------------------------------
00836 PNGImageFileType::~PNGImageFileType(void)
00837 {
00838     return;
00839 }

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