osg::PNGImageFileType Class Reference
[Image]

PNG File Handler. See Image for a detailed description. More...

#include <OSGPNGImageFileType.h>

Inheritance diagram for osg::PNGImageFileType:

osg::ImageFileType

List of all members.

Safe Store/Restore



UInt64 store (const ImagePtr &image, UChar8 *buffer, Int32 memSize=-1)
virtual UInt64 maxBufferSize (const ImagePtr &image)
static UInt64 restore (ImagePtr &image, const UChar8 *buffer, Int32 memSize=-1)
static UInt64 store (const ImagePtr &image, const char *mimeType, UChar8 *buffer, Int32 memSize=-1)

Public Types

Flags


enum  { OSG_READ_SUPPORTED = 1, OSG_WRITE_SUPPORTED = 2 }

Public Member Functions

Destructor


virtual ~PNGImageFileType (void)
Read/Write


virtual bool validateHeader (const Char8 *fileName, bool &implemented)
virtual bool read (ImagePtr &image, std::istream &is, const std::string &mimetype)
virtual bool write (const ImagePtr &image, std::ostream &os, const std::string &mimetype)
virtual std::string determineMimetypeFromStream (std::istream &is)
Buffer


virtual UInt64 restoreData (ImagePtr &image, const UChar8 *buffer, Int32 memSize=-1)
virtual UInt64 storeData (const ImagePtr &image, UChar8 *buffer, Int32 memSize=-1)
Set


void setOptions (const Char8 *options)
Get Methods


const Char8getMimeType (void) const
const std::list< IDString > & getSuffixList (void) const
virtual UInt32 getFlags (void) const
const Char8getOptions (void)
Read/Write


virtual bool read (ImagePtr &image, const Char8 *fileName)
virtual bool write (const ImagePtr &image, const Char8 *fileName)
dump


void dump (void)

Static Public Member Functions

Get Method


static PNGImageFileTypethe (void)

Protected Member Functions

Default Constructor


 PNGImageFileType (const Char8 *mimeType, const Char8 *suffixArray[], UInt16 suffixByteCount, UInt32 flags)

Protected Attributes

MTD Header


std::string _options

Private Member Functions

Copy Constructor


 PNGImageFileType (const PNGImageFileType &obj)
Copy Operator


const PNGImageFileTypeoperator= (const PNGImageFileType &obj)

Static Private Attributes

static PNGImageFileType _the


Detailed Description

Image File Type to read/write and store/restore Image objects as PNG data.

To be able to load PNG images you need the PNG library, (check the Prerequisites page on www.opensg.org). The lib comes with all Linux distributions.

You have to --enable-png in the configure line to enable the singleton object.

Definition at line 56 of file OSGPNGImageFileType.h.


Member Enumeration Documentation

anonymous enum [inherited]

Enumerator:
OSG_READ_SUPPORTED 
OSG_WRITE_SUPPORTED 

Definition at line 66 of file OSGImageFileType.h.

00067     {
00068         OSG_READ_SUPPORTED = 1,
00069         OSG_WRITE_SUPPORTED = 2
00070     };


Constructor & Destructor Documentation

PNGImageFileType::~PNGImageFileType ( void   )  [virtual]

Destructor

Definition at line 948 of file OSGPNGImageFileType.cpp.

00948 {}

PNGImageFileType::PNGImageFileType ( const Char8 mimeType,
const Char8 suffixArray[],
UInt16  suffixByteCount,
UInt32  flags 
) [protected]

Constructor used for the singleton object

Definition at line 937 of file OSGPNGImageFileType.cpp.

00940                                                    :
00941     ImageFileType(mimeType, suffixArray, suffixByteCount, flags)
00942 {}

osg::PNGImageFileType::PNGImageFileType ( const PNGImageFileType obj  )  [private]


Member Function Documentation

bool PNGImageFileType::validateHeader ( const Char8 fileName,
bool &  implemented 
) [virtual]

Reimplemented from osg::ImageFileType.

Definition at line 571 of file OSGPNGImageFileType.cpp.

00572 {
00573     implemented = true;
00574 
00575     if(fileName == NULL)
00576         return false;
00577 
00578     FILE *file = fopen(fileName, "rb");
00579     if(file == NULL)
00580         return false;
00581 
00582     std::string magic;
00583     magic.resize(4);
00584     fread((void *) &magic[0], 4, 1, file);
00585     fclose(file);
00586 
00587     if(magic == "\x89PNG")
00588     {
00589         return true;
00590     }
00591 
00592     return false;
00593 }

bool PNGImageFileType::read ( ImagePtr image,
std::istream &  is,
const std::string &  mimetype 
) [virtual]

Tries to fill the image object with the data read from the given input stream. Returns true on success.

Reimplemented from osg::ImageFileType.

Definition at line 165 of file OSGPNGImageFileType.cpp.

References FWARNING, osg::ImageFileType::getMimeType(), osg::Image::OSG_INVALID_PF, osg::Image::OSG_L_PF, osg::Image::OSG_LA_PF, osg::Image::OSG_RESUNIT_INCH, osg::Image::OSG_RGB_PF, osg::Image::OSG_RGBA_PF, osg::Image::OSG_UINT16_IMAGEDATA, osg::Image::OSG_UINT8_IMAGEDATA, and SWARNING.

00167 {
00168 #ifdef OSG_WITH_PNG
00169 
00170     bool                retCode;
00171     Image::PixelFormat  pixelFormat = osg::Image::OSG_INVALID_PF;
00172     png_structp         png_ptr;
00173     png_infop           info_ptr;
00174     png_uint_32         width, wc, height, h, i, res_x, res_y;
00175     png_byte            bit_depth, channels, color_type;
00176     png_bytep           *row_pointers, base;
00177 
00178     png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
00179     if(!png_ptr)
00180         return false;
00181 
00182     png_set_error_fn(png_ptr, 0, &errorOutput, &warningOutput);
00183 
00184     info_ptr = png_create_info_struct(png_ptr);
00185     if(!info_ptr)
00186     {
00187         png_destroy_read_struct(&png_ptr, 0, 0);
00188         return false;
00189     }
00190 
00191     if(setjmp(png_ptr->jmpbuf))
00192     {
00193         png_destroy_read_struct(&png_ptr, &info_ptr, 0);
00194         return false;
00195     }
00196 
00197     png_set_read_fn(png_ptr, &is, &isReadFunc);
00198 
00199     png_read_info(png_ptr, info_ptr);
00200 
00201     width = png_get_image_width(png_ptr, info_ptr);
00202     height = png_get_image_height(png_ptr, info_ptr);
00203     bit_depth = png_get_bit_depth(png_ptr, info_ptr);
00204     res_x = png_get_x_pixels_per_meter(png_ptr, info_ptr);
00205     res_y = png_get_y_pixels_per_meter(png_ptr, info_ptr);
00206     channels = png_get_channels(png_ptr, info_ptr);
00207     color_type = png_get_color_type(png_ptr, info_ptr);
00208 
00209     // Convert paletted images to RGB
00210     if (color_type == PNG_COLOR_TYPE_PALETTE)
00211     {
00212       png_set_palette_to_rgb(png_ptr);
00213       channels = 3;
00214       bit_depth = 8;
00215     }
00216 
00217     // Convert < 8 bit to 8 bit
00218     if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
00219       png_set_gray_1_2_4_to_8(png_ptr);
00220       bit_depth = 8;
00221     }
00222 
00223 #if BYTE_ORDER == LITTLE_ENDIAN
00224     if (bit_depth == 16)
00225       png_set_swap(png_ptr);
00226 #endif
00227 
00228     // Add a full alpha channel if there is transparency
00229     // information in a tRNS chunk
00230     if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
00231     {
00232       png_set_tRNS_to_alpha(png_ptr);
00233       ++channels;
00234     }                                                                                
00235     Int32 dataType;
00236     switch (bit_depth) {
00237     case 8:
00238       dataType = Image::OSG_UINT8_IMAGEDATA;
00239       break;
00240     case 16:
00241       dataType = Image::OSG_UINT16_IMAGEDATA;
00242       break;
00243     default:
00244       FWARNING (( "Invalid bit_depth: %d, can not read png-data\n",
00245                   bit_depth ));
00246       return false;
00247     }
00248 
00249     switch(channels)
00250     {
00251     case 1:
00252         pixelFormat = Image::OSG_L_PF;
00253         break;
00254     case 2:
00255         pixelFormat = Image::OSG_LA_PF;
00256         break;
00257     case 3:
00258         pixelFormat = Image::OSG_RGB_PF;
00259         break;
00260     case 4:
00261         pixelFormat = Image::OSG_RGBA_PF;
00262         break;
00263     };
00264 
00265     if(image->set( pixelFormat, width, height,
00266                    1, 1, 1, 0.0, 0,
00267                    dataType ))
00268     {
00269         // set resolution png supports only pixel per meter,
00270         // so we do a conversion to dpi with some rounding.
00271         res_x = png_uint_32((Real32(res_x) / 39.37007874f) < 0.0f ?
00272                             (Real32(res_x) / 39.37007874f) - 0.5f :
00273                             (Real32(res_x) / 39.37007874f) + 0.5f);
00274         res_y = png_uint_32((Real32(res_y) / 39.37007874f) < 0.0f ?
00275                             (Real32(res_y) / 39.37007874f) - 0.5f :
00276                             (Real32(res_y) / 39.37007874f) + 0.5f);
00277 
00278         image->setResX(Real32(res_x));
00279         image->setResY(Real32(res_y));
00280         image->setResUnit(Image::OSG_RESUNIT_INCH);
00281 
00282         // Calculate the row pointers
00283         row_pointers = new png_bytep[height];
00284         wc = width * channels * (bit_depth / 8);
00285         h = height - 1;
00286         base = image->getData();
00287         for(i = 0; i < height; ++i)
00288             row_pointers[i] = base + (h - i) * wc;
00289 
00290         // Read the image data
00291         png_read_image(png_ptr, row_pointers);
00292 
00293         delete[] row_pointers;
00294 
00295         retCode = true;
00296     }
00297     else
00298         retCode = false;
00299 
00300     png_destroy_read_struct(&png_ptr, &info_ptr, 0);
00301 
00302     return retCode;
00303 
00304 #else
00305 
00306     SWARNING <<
00307         getMimeType() <<
00308         " read is not compiled into the current binary " <<
00309         std::endl;
00310     return false;
00311 
00312 #endif
00313 
00314 }

bool PNGImageFileType::write ( const ImagePtr img,
std::ostream &  os,
const std::string &  mimetype 
) [virtual]

Tries to write the image object to the given output stream. Returns true on success. Based on the public domain example.c from the PNG dist.

Reimplemented from osg::ImageFileType.

Definition at line 322 of file OSGPNGImageFileType.cpp.

References osg::endLog(), FWARNING, osg::ImageFileType::getMimeType(), osg::Image::OSG_BGR_PF, osg::Image::OSG_BGRA_PF, osg::Image::OSG_L_PF, osg::Image::OSG_LA_PF, osg::Image::OSG_RESUNIT_INCH, osg::Image::OSG_RGB_PF, osg::Image::OSG_RGBA_PF, osg::Image::OSG_UINT16_IMAGEDATA, osg::Image::OSG_UINT8_IMAGEDATA, and SWARNING.

00324 {
00325 #ifdef OSG_WITH_PNG
00326 
00327     png_structp png_ptr;
00328     png_infop info_ptr;
00329 
00330     if(img->getDimension() < 1 || img->getDimension() > 2)
00331     {
00332         FWARNING(("PNGImageFileType::write: invalid dimension %d!\n",
00333             img->getDimension()));
00334         return false;
00335     }
00336     
00337     /* Create and initialize the png_struct with the desired error handler
00338     * functions.  If you want to use the default stderr and longjump method,
00339     * you can supply NULL for the last three parameters.  We also check that
00340     * the library version is compatible with the one used at compile time,
00341     * in case we are using dynamically linked libraries.  REQUIRED.
00342     */
00343     png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
00344                                 0, &errorOutput, &warningOutput);
00345 
00346     if (png_ptr == NULL)
00347       return false;
00348 
00349     /* Allocate/initialize the image information data.  REQUIRED */
00350     info_ptr = png_create_info_struct(png_ptr);
00351     if (info_ptr == NULL)
00352     {
00353       png_destroy_write_struct(&png_ptr,  NULL);
00354       return false;
00355     }
00356 
00357     /* set up the output handlers */
00358     png_set_write_fn(png_ptr, &os, &osWriteFunc, &osFlushFunc);
00359 
00360     /* This is the hard way */
00361 
00362     /* Set the image information here.  Width and height are up to 2^31,
00363     * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
00364     * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
00365     * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
00366     * or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
00367     * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
00368     * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
00369     */
00370     Int32 ctype;
00371     switch(img->getPixelFormat())
00372     {
00373     case Image::OSG_L_PF:       ctype = PNG_COLOR_TYPE_GRAY;        
00374                                 break;
00375                                 
00376     case Image::OSG_LA_PF:      ctype = PNG_COLOR_TYPE_GRAY_ALPHA;          
00377                                 break;
00378                                 
00379 #if defined(GL_BGR) || defined(GL_BGR_EXT)
00380     case Image::OSG_BGR_PF:
00381 #endif
00382     case Image::OSG_RGB_PF:     ctype = PNG_COLOR_TYPE_RGB;                 
00383                                 break;
00384                                 
00385 #if defined(GL_BGRA) || defined(GL_BGRA_EXT)
00386     case Image::OSG_BGRA_PF:
00387 #endif
00388     case Image::OSG_RGBA_PF:    ctype = PNG_COLOR_TYPE_RGB_ALPHA;           
00389                                 break;
00390 
00391     default:
00392         FWARNING(("PNGImageFileType::write: unknown pixel format %d!\n",
00393             img->getPixelFormat()));
00394         png_destroy_write_struct(&png_ptr,  NULL);
00395         return false;
00396         
00397     }
00398     
00399     Int32 bit_depth;
00400     switch (img->getDataType()) {
00401     case Image::OSG_UINT8_IMAGEDATA:
00402       bit_depth = 8;
00403       break;
00404     case Image::OSG_UINT16_IMAGEDATA:
00405       bit_depth = 16;
00406       break;
00407     default:
00408       FWARNING (("Invalid pixeldepth, cannot store data\n"));
00409       return false;
00410     };
00411 
00412     png_set_IHDR(png_ptr, info_ptr, img->getWidth(), img->getHeight(),
00413                  bit_depth, ctype,      
00414                  PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
00415 
00416     // set resolution png supports only meter per pixel,
00417     // so we do a conversion from dpi with some rounding.
00418     png_uint_32 res_x = img->getResX();
00419     png_uint_32 res_y = img->getResY();
00420     if(img->getResUnit() == Image::OSG_RESUNIT_INCH)
00421     {
00422         res_x = png_uint_32((img->getResX() * 39.37007874f) < 0.0f ?
00423                             (img->getResX() * 39.37007874f) - 0.5f :
00424                             (img->getResX() * 39.37007874f) + 0.5f);
00425         res_y = png_uint_32((img->getResY() * 39.37007874f) < 0.0f ?
00426                             (img->getResY() * 39.37007874f) - 0.5f :
00427                             (img->getResY() * 39.37007874f) + 0.5f);
00428     }
00429 
00430     png_set_pHYs(png_ptr, info_ptr, res_x, res_y,
00431                  PNG_RESOLUTION_METER);
00432 
00433 #if 0
00434     /* optional significant bit chunk */
00435     /* if we are dealing with a grayscale image then */
00436     sig_bit.gray = true_bit_depth;
00437     /* otherwise, if we are dealing with a color image then */
00438     sig_bit.red = true_red_bit_depth;
00439     sig_bit.green = true_green_bit_depth;
00440     sig_bit.blue = true_blue_bit_depth;
00441     /* if the image has an alpha channel then */
00442     sig_bit.alpha = true_alpha_bit_depth;
00443     png_set_sBIT(png_ptr, info_ptr, sig_bit);
00444 
00445 
00446     /* Optional gamma chunk is strongly suggested if you have any guess
00447     * as to the correct gamma of the image.
00448     */
00449     png_set_gAMA(png_ptr, info_ptr, gamma);
00450 
00451     /* Optionally write comments into the image */
00452     text_ptr[0].key = "Title";
00453     text_ptr[0].text = "Mona Lisa";
00454     text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
00455     text_ptr[1].key = "Author";
00456     text_ptr[1].text = "Leonardo DaVinci";
00457     text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
00458     text_ptr[2].key = "Description";
00459     text_ptr[2].text = "<long text>";
00460     text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt;
00461 #ifdef PNG_iTXt_SUPPORTED
00462     text_ptr[0].lang = NULL;
00463     text_ptr[1].lang = NULL;
00464     text_ptr[2].lang = NULL;
00465 #endif
00466     png_set_text(png_ptr, info_ptr, text_ptr, 3);
00467 #endif
00468     /* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */
00469     /* note that if sRGB is present the gAMA and cHRM chunks must be ignored
00470     * on read and must be written in accordance with the sRGB profile */
00471 
00472     /* Write the file header information.  REQUIRED */
00473     png_write_info(png_ptr, info_ptr);
00474 
00475 #if BYTE_ORDER == LITTLE_ENDIAN
00476 
00477     if (bit_depth == 16) 
00478       png_set_swap(png_ptr);
00479 
00480 #endif
00481 
00482 
00483 #if 0
00484     /* invert monochrome pixels */
00485     png_set_invert_mono(png_ptr);
00486 
00487     /* Shift the pixels up to a legal bit depth and fill in
00488     * as appropriate to correctly scale the image.
00489     */
00490     png_set_shift(png_ptr, &sig_bit);
00491 
00492     /* pack pixels into bytes */
00493     png_set_packing(png_ptr);
00494 
00495     /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into
00496     * RGB (4 channels -> 3 channels). The second parameter is not used.
00497     */
00498     png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
00499 
00500     /* swap bytes of 16-bit files to most significant byte first */
00501     png_set_swap(png_ptr);
00502 
00503     /* swap bits of 1, 2, 4 bit packed pixel formats */
00504     png_set_packswap(png_ptr);
00505 #endif
00506 
00507     if(img->getPixelFormat() == Image::OSG_BGR_PF ||
00508        img->getPixelFormat() == Image::OSG_BGRA_PF
00509       )
00510     {
00511         /* flip BGR pixels to RGB */
00512         png_set_bgr(png_ptr);
00513 
00514         /* swap location of alpha bytes from ARGB to RGBA */
00515         png_set_swap_alpha(png_ptr);
00516     }
00517     
00518     /* The easiest way to write the image (you may have a different memory
00519     * layout, however, so choose what fits your needs best).  You need to
00520     * use the first method if you aren't handling interlacing yourself.
00521     */
00522     png_bytep *row_pointers = new png_bytep [img->getHeight()];
00523     
00524     for(Int32 k = 0; k < img->getHeight(); k++)
00525     {
00526         row_pointers[k] = img->getData() + 
00527                           (img->getHeight() - 1 - k) * 
00528                             img->getWidth() * img->getBpp();
00529     }
00530     
00531     /* write out the entire image data in one call */
00532     png_write_image(png_ptr, row_pointers);
00533 
00534     /* It is REQUIRED to call this to finish writing the rest of the file */
00535     png_write_end(png_ptr, info_ptr);
00536     
00537     /* clean up after the write, and free any memory allocated */
00538     png_destroy_write_struct(&png_ptr, &info_ptr);
00539 
00540     delete [] row_pointers;
00541 
00542     /* that's it */
00543     return true;
00544 
00545 #else
00546     SWARNING <<
00547         getMimeType() <<
00548         " write is not compiled into the current binary " <<
00549         endLog;
00550     return false;
00551 #endif
00552 }

std::string PNGImageFileType::determineMimetypeFromStream ( std::istream &  is  )  [virtual]

Tries to determine the mime type of the data provided by an input stream by searching for magic bytes. Returns the mime type or an empty string when the function could not determine the mime type.

Reimplemented from osg::ImageFileType.

Definition at line 560 of file OSGPNGImageFileType.cpp.

References osg::ImageFileType::getMimeType().

00561 {
00562     char filecode[4];
00563     is.read(filecode, 4);
00564     is.seekg(-4, std::ios::cur);
00565     return strncmp(filecode, "\x89PNG", 4) == 0 ?
00566         std::string(getMimeType()) : std::string();
00567 }

UInt64 PNGImageFileType::restoreData ( ImagePtr image,
const UChar8 buffer,
Int32  memSize = -1 
) [virtual]

Reimplemented from osg::ImageFileType.

Definition at line 614 of file OSGPNGImageFileType.cpp.

References FWARNING, osg::ImageFileType::getMimeType(), osg::Image::OSG_INVALID_PF, osg::Image::OSG_L_PF, osg::Image::OSG_LA_PF, osg::Image::OSG_RGB_PF, osg::Image::OSG_RGBA_PF, osg::Image::OSG_UINT16_IMAGEDATA, osg::Image::OSG_UINT8_IMAGEDATA, and SWARNING.

00617 {
00618 #ifdef OSG_WITH_PNG
00619 
00620     UInt64              retCode;
00621     Image::PixelFormat  pixelFormat = osg::Image::OSG_INVALID_PF;
00622     png_structp         png_ptr;
00623     png_infop           info_ptr;
00624     png_uint_32         width, wc, height, h, i;
00625     png_byte            bit_depth, channels, color_type;
00626     png_bytep           *row_pointers, base;
00627 
00628     png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
00629     if(!png_ptr)
00630     {
00631         return 0;
00632     }
00633 
00634     png_set_error_fn(png_ptr, 0, &errorOutput, &warningOutput);
00635 
00636     info_ptr = png_create_info_struct(png_ptr);
00637     if(!info_ptr)
00638     {
00639         png_destroy_read_struct(&png_ptr, 0, 0);
00640         return 0;
00641     }
00642 
00643     if(setjmp(png_ptr->jmpbuf))
00644     {
00645         png_destroy_read_struct(&png_ptr, &info_ptr, 0);
00646         return 0;
00647     }
00648 
00649     BufferInfo bufferInfo;
00650     bufferInfo.buffer = (UChar8 *) buffer;
00651     bufferInfo.length = 0;
00652     png_set_read_fn(png_ptr, (void *) &bufferInfo, user_read_data);
00653 
00654     png_read_info(png_ptr, info_ptr);
00655 
00656     width = png_get_image_width(png_ptr, info_ptr);
00657     height = png_get_image_height(png_ptr, info_ptr);
00658     bit_depth = png_get_bit_depth(png_ptr, info_ptr);
00659     channels = png_get_channels(png_ptr, info_ptr);
00660     color_type = png_get_color_type(png_ptr, info_ptr);
00661 
00662     // Convert paletted images to RGB
00663     if (color_type == PNG_COLOR_TYPE_PALETTE)
00664     {
00665         png_set_palette_to_rgb(png_ptr);
00666         channels = 3;
00667         bit_depth = 8;
00668     }
00669 
00670     // Convert < 8 bit to 8 bit
00671     if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
00672         png_set_gray_1_2_4_to_8(png_ptr);
00673         bit_depth = 8;
00674     }
00675     
00676 #if BYTE_ORDER == LITTLE_ENDIAN
00677     if (bit_depth == 16)
00678       png_set_swap(png_ptr);
00679 #endif
00680 
00681     // Add a full alpha channel if there is transparency
00682     // information in a tRNS chunk
00683     if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
00684     {
00685         png_set_tRNS_to_alpha(png_ptr);
00686         ++channels;
00687     }                                                                                
00688     Int32 dataType;
00689     switch (bit_depth) {
00690     case 8:
00691       dataType = Image::OSG_UINT8_IMAGEDATA;
00692       break;
00693     case 16:
00694       dataType = Image::OSG_UINT16_IMAGEDATA;
00695       break;
00696     default:
00697       FWARNING (( "Invalid bit_depth: %d, can not read png-data\n",
00698                   bit_depth ));
00699       return false;
00700     }
00701 
00702     switch(channels)
00703     {
00704     case 1:
00705         pixelFormat = Image::OSG_L_PF;
00706         break;
00707     case 2:
00708         pixelFormat = Image::OSG_LA_PF;
00709         break;
00710     case 3:
00711         pixelFormat = Image::OSG_RGB_PF;
00712         break;
00713     case 4:
00714         pixelFormat = Image::OSG_RGBA_PF;
00715         break;
00716     };
00717 
00718     if(image->set( pixelFormat, width, height,
00719                    1, 1, 1, 0.0, 0,
00720                    dataType ))
00721     {
00722         // Calculate the row pointers
00723         row_pointers = new png_bytep[height];
00724         wc = width * channels * (bit_depth / 8);
00725         h = height - 1;
00726         base = image->getData();
00727         for(i = 0; i < height; ++i)
00728             row_pointers[i] = base + (h - i) * wc;
00729 
00730         // Read the image data
00731         png_read_image(png_ptr, row_pointers);
00732 
00733         delete[] row_pointers;
00734 
00735         retCode = bufferInfo.length;
00736     }
00737     else
00738         retCode = 0;
00739 
00740     png_destroy_read_struct(&png_ptr, &info_ptr, 0);
00741 
00742     return retCode;
00743 
00744 #else
00745     SWARNING <<
00746         getMimeType() <<
00747         " restoreData is not compiled into the current binary " <<
00748         std::endl;
00749     return 0;
00750 #endif
00751 }

UInt64 PNGImageFileType::storeData ( const ImagePtr image,
UChar8 buffer,
Int32  memSize = -1 
) [virtual]

Tries to restore the image data from the given memblock. Returns the amount of data read.

Reimplemented from osg::ImageFileType.

Definition at line 775 of file OSGPNGImageFileType.cpp.

References FWARNING, osg::ImageFileType::getMimeType(), osg::Image::OSG_BGR_PF, osg::Image::OSG_BGRA_PF, osg::Image::OSG_L_PF, osg::Image::OSG_LA_PF, osg::Image::OSG_RGB_PF, osg::Image::OSG_RGBA_PF, osg::Image::OSG_UINT16_IMAGEDATA, osg::Image::OSG_UINT8_IMAGEDATA, and SWARNING.

00778 {
00779 #ifdef OSG_WITH_PNG
00780 
00781     png_structp png_ptr;
00782     png_infop info_ptr;
00783 
00784     if(image->getDimension() < 1 || image->getDimension() > 2)
00785     {
00786         FWARNING(("PNGImageFileType::write: invalid dimension %d!\n",
00787             image->getDimension()));
00788         return 0;
00789     }
00790 
00791     /* Create and initialize the png_struct with the desired error handler
00792     * functions.  If you want to use the default stderr and longjump method,
00793     * you can supply NULL for the last three parameters.  We also check that
00794     * the library version is compatible with the one used at compile time,
00795     * in case we are using dynamically linked libraries.  REQUIRED.
00796     */
00797     png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
00798                                 0, &errorOutput, &warningOutput);
00799 
00800     if (png_ptr == NULL)
00801     {
00802         return 0;
00803     }
00804 
00805     /* Allocate/initialize the image information data.  REQUIRED */
00806     info_ptr = png_create_info_struct(png_ptr);
00807     if (info_ptr == NULL)
00808     {
00809         png_destroy_write_struct(&png_ptr,  NULL);
00810         return 0;
00811     }
00812 
00813     BufferInfo bufferInfo;
00814     bufferInfo.buffer = buffer;
00815     bufferInfo.length = 0;
00816     png_set_write_fn(png_ptr, (void *) &bufferInfo, user_write_data, user_flush_data);
00817 
00818     /* This is the hard way */
00819 
00820     /* Set the image information here.  Width and height are up to 2^31,
00821     * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
00822     * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
00823     * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
00824     * or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
00825     * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
00826     * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
00827     */
00828     Int32 ctype;
00829     switch(image->getPixelFormat())
00830     {
00831     case Image::OSG_L_PF:       ctype = PNG_COLOR_TYPE_GRAY;        
00832                                 break;
00833                                 
00834     case Image::OSG_LA_PF:      ctype = PNG_COLOR_TYPE_GRAY_ALPHA;          
00835                                 break;
00836                                 
00837 #if defined(GL_BGR) || defined(GL_BGR_EXT)
00838     case Image::OSG_BGR_PF:
00839 #endif
00840     case Image::OSG_RGB_PF:     ctype = PNG_COLOR_TYPE_RGB;                 
00841                                 break;
00842                                 
00843 #if defined(GL_BGRA) || defined(GL_BGRA_EXT)
00844     case Image::OSG_BGRA_PF:
00845 #endif
00846     case Image::OSG_RGBA_PF:    ctype = PNG_COLOR_TYPE_RGB_ALPHA;           
00847                                 break;
00848 
00849     default:
00850         FWARNING(("PNGImageFileType::write: unknown pixel format %d!\n",
00851             image->getPixelFormat()));
00852         png_destroy_write_struct(&png_ptr,  NULL);
00853         return 0;
00854         
00855     }
00856     
00857     Int32 bit_depth;
00858     switch (image->getDataType()) {
00859     case Image::OSG_UINT8_IMAGEDATA:
00860       bit_depth = 8;
00861       break;
00862     case Image::OSG_UINT16_IMAGEDATA:
00863       bit_depth = 16;
00864       break;
00865     default:
00866       FWARNING (("Invalid pixeldepth, cannot store data\n"));
00867       return 0;
00868     };
00869       
00870     png_set_IHDR(png_ptr, info_ptr, image->getWidth(), image->getHeight(),
00871         bit_depth, ctype,      
00872         PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
00873 
00874     /* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */
00875     /* note that if sRGB is present the gAMA and cHRM chunks must be ignored
00876     * on read and must be written in accordance with the sRGB profile */
00877 
00878     /* Write the file header information.  REQUIRED */
00879     png_write_info(png_ptr, info_ptr);
00880 
00881 #if BYTE_ORDER == LITTLE_ENDIAN
00882     if (bit_depth == 16)
00883       png_set_swap(png_ptr);
00884 #endif
00885 
00886     if(image->getPixelFormat() == Image::OSG_BGR_PF ||
00887        image->getPixelFormat() == Image::OSG_BGRA_PF
00888       )
00889     {
00890         /* flip BGR pixels to RGB */
00891         png_set_bgr(png_ptr);
00892 
00893         /* swap location of alpha bytes from ARGB to RGBA */
00894         png_set_swap_alpha(png_ptr);
00895     }
00896     
00897     /* The easiest way to write the image (you may have a different memory
00898     * layout, however, so choose what fits your needs best).  You need to
00899     * use the first method if you aren't handling interlacing yourself.
00900     */
00901     png_bytep *row_pointers = new png_bytep [image->getHeight()];
00902     
00903     for(Int32 k = 0; k < image->getHeight(); k++)
00904     {
00905         row_pointers[k] = image->getData() + 
00906                           (image->getHeight() - 1 - k) * 
00907                             image->getWidth() * image->getBpp();
00908     }
00909     
00910     /* write out the entire image data in one call */
00911     png_write_image(png_ptr, row_pointers);
00912 
00913     /* It is REQUIRED to call this to finish writing the rest of the file */
00914     png_write_end(png_ptr, info_ptr);
00915     
00916     /* clean up after the write, and free any memory allocated */
00917     png_destroy_write_struct(&png_ptr, &info_ptr);
00918 
00919     delete [] row_pointers;
00920 
00921     /* that's it */
00922     return bufferInfo.length;
00923 
00924 #else
00925     SWARNING <<
00926         getMimeType() <<
00927         " storeData is not compiled into the current binary " <<
00928         std::endl;
00929     return 0;
00930 #endif
00931 }

PNGImageFileType & PNGImageFileType::the ( void   )  [static]

Definition at line 151 of file OSGPNGImageFileType.cpp.

References _the.

00152 {
00153   return _the;
00154 }

const PNGImageFileType& osg::PNGImageFileType::operator= ( const PNGImageFileType obj  )  [private]

void ImageFileType::setOptions ( const Char8 options  )  [inherited]

Definition at line 243 of file OSGImageFileType.cpp.

References osg::ImageFileType::_options.

Referenced by osg::ImageFileHandler::setOptions().

00244 {
00245     _options = options;
00246 }

const Char8 * ImageFileType::getMimeType ( void   )  const [inherited]

const std::list< IDString > & ImageFileType::getSuffixList ( void   )  const [inherited]

Get method for the suffix list container

Definition at line 134 of file OSGImageFileType.cpp.

References osg::ImageFileType::_suffixList.

Referenced by osg::ImageFileHandler::addImageFileType().

00135 {
00136     return _suffixList; 
00137 }

UInt32 ImageFileType::getFlags ( void   )  const [virtual, inherited]

Get method for the flags indicating read/write support. Most image types only support reading.

Definition at line 117 of file OSGImageFileType.cpp.

References osg::ImageFileType::_flags.

Referenced by osg::ImageFileHandler::getSuffixList().

00118 {
00119     return _flags;
00120 }

const Char8 * ImageFileType::getOptions ( void   )  [inherited]

Get method for the mime type

Definition at line 124 of file OSGImageFileType.cpp.

References osg::ImageFileType::_options.

Referenced by osg::ImageFileHandler::getOptions().

00125 {
00126     return _options.c_str();
00127 }

bool ImageFileType::read ( ImagePtr image,
const Char8 fileName 
) [virtual, inherited]

Reimplemented in osg::DATImageFileType, and osg::HDRImageFileType.

Definition at line 141 of file OSGImageFileType.cpp.

Referenced by osg::ImageFileHandler::read().

00142 {
00143     std::ifstream is(fileName, std::ios::binary);
00144     if (is.good() == false)
00145         return false;
00146     return read(image, is, std::string());
00147 }

bool ImageFileType::write ( const ImagePtr image,
const Char8 fileName 
) [virtual, inherited]

Reimplemented in osg::DATImageFileType, and osg::HDRImageFileType.

Definition at line 151 of file OSGImageFileType.cpp.

Referenced by osg::ImageFileHandler::write().

00152 {
00153     std::ofstream os(fileName, std::ios::binary);
00154     if (os.good() == false)
00155         return false;
00156     return write(image, os, std::string());
00157 }

UInt64 ImageFileType::restore ( ImagePtr image,
const UChar8 buffer,
Int32  memSize = -1 
) [static, inherited]

Tries to restore the Imagedata from the given memblock. The buffer must include a ImageFileType::Head data block.

Definition at line 283 of file OSGImageFileType.cpp.

References osg::ImageFileType::Head::dataType, osg::ImageFileType::Head::depth, osg::ImageFileHandler::determineMimetypeFromSuffix(), FDEBUG, osg::ImageFileType::Head::frameCount, osg::ImageFileType::Head::frameDelay, FWARNING, osg::ImageFileType::Head::height, osg::ImageFileType::Head::mipmapCount, osg::ImageFileType::Head::netToHost(), osg::NullFC, osg::Image::OSG_UINT8_IMAGEDATA, osg::ImageFileType::Head::pixelFormat, osg::ImageFileType::Head::sideCount, osg::ImageFileType::Head::suffix, osg::ImageFileHandler::the(), and osg::ImageFileType::Head::width.

Referenced by osg::ClusterViewBuffer::recv(), osg::ImageFileHandler::restore(), and osg::SimpleSceneManager::useOpenSGLogo().

00285 {
00286     unsigned long   imageSize, headSize = sizeof(Head);
00287     unsigned long   size = 0, attachmentSize;
00288     Head            head;
00289     const UChar8    *data = buffer ? (buffer + headSize) : 0;
00290     ImageFileType   *type;
00291     std::string     mimeType;
00292     Image::Type     dataType;
00293 
00294     if ((image != osg::NullFC) && buffer && (memSize >= headSize)) {
00295 
00296         // Copy header. Otherwise netToHost would change the original
00297         // data structur.
00298         memcpy(&head,buffer,sizeof(Head));
00299         head.netToHost();
00300         mimeType = ImageFileHandler::the().determineMimetypeFromSuffix(head.suffix);
00301         
00302         if((type = ImageFileHandler::the().getFileType(mimeType.c_str(), 0)))
00303         {
00304             if (head.dataType)
00305               dataType = Image::Type(head.dataType);
00306             else
00307               dataType = Image::OSG_UINT8_IMAGEDATA;
00308 
00309             image->set(Image::PixelFormat(head.pixelFormat), head.width,
00310                        head.height, head.depth, head.mipmapCount,
00311                        head.frameCount, float(head.frameDelay) / 1000.0, 0,
00312                        dataType,true,head.sideCount );
00313             imageSize = static_cast<unsigned long>(
00314                 type->restoreData(image, data, memSize - headSize));
00315             attachmentSize = 0; // head->attachmentSize;
00316 
00317             /*
00318             if ((attachmentSize = head->attachmentSize))
00319             {
00320                 attData = (char*)(buffer + headSize + imageSize);
00321                 attKey = attData;
00322                 attValue = 0;
00323                 for (i = 0; i < (attachmentSize-1); i++) {
00324                     if (attData[i] == 0) 
00325                         if (attKey) {
00326                             attValue = &(attData[i+1]);
00327                             image->setAttachmentField (attKey,attValue);
00328                             attKey = attValue = 0;
00329                         }
00330                         else
00331                             attKey = &(attData[i+1]);
00332                 }
00333                 if (attKey || attValue) {
00334                     FFATAL (("Attachment restore error\n"));
00335                 }
00336             }
00337             */
00338 
00339             size = headSize + imageSize + attachmentSize;
00340       
00341             FDEBUG (( "Restore image data: %lu (%lu/%lu/%lu)\n",
00342                       size, headSize, imageSize, attachmentSize ));
00343 
00344         }
00345         else
00346         {
00347             imageSize = 0;
00348             FWARNING(("Can not restore image data, invalid mimeType: %s\n",
00349                       mimeType.empty() == false ? mimeType.c_str() : "Unknown"));
00350         }
00351 
00352       
00353     }
00354 
00355     return size;
00356 }

UInt64 ImageFileType::store ( const ImagePtr image,
const char *  mimeType,
UChar8 buffer,
Int32  memSize = -1 
) [static, inherited]

Tries to store the raster data to the given mem block. Will include a ImageFileType::Head description and the data encoded as 'mimeType'

Definition at line 364 of file OSGImageFileType.cpp.

References osg::ImageFileHandler::getFileType(), osg::ImageFileType::store(), and osg::ImageFileHandler::the().

Referenced by osg::ClusterViewBuffer::send(), osg::ImageFileType::store(), and osg::ImageFileHandler::store().

00366 {
00367   ImageFileType   *type = ImageFileHandler::the().getFileType(mimeType);
00368   
00369   return type ? type->store(image, buffer, memSize) : 0;
00370 }

UInt64 ImageFileType::store ( const ImagePtr image,
UChar8 buffer,
Int32  memSize = -1 
) [inherited]

Tries to store the raster data to the given mem block. Will include a ImageFileType::Head description for the derived concreate mimeType.

Definition at line 378 of file OSGImageFileType.cpp.

References osg::ImageFileType::_suffixList, osg::ImageFileType::Head::attachmentSize, osg::ImageFileType::Head::dataType, osg::ImageFileType::Head::depth, FDEBUG, FFATAL, osg::ImageFileType::Head::frameCount, osg::ImageFileType::Head::frameDelay, osg::ImageFileType::Head::height, osg::ImageFileType::Head::hostToNet(), osg::ImageFileType::Head::mipmapCount, osg::ImageFileType::Head::pixelFormat, osg::ImageFileType::Head::sideCount, osg::ImageFileType::storeData(), osg::ImageFileType::Head::suffix, and osg::ImageFileType::Head::width.

00380 {
00381     Head            *head;
00382     unsigned long   dataSize = 0, headSize = sizeof(Head);
00383     unsigned long   attachmentSize;
00384     UChar8          *dest;
00385     const UChar8    *src = image->getData();
00386     std::map<std::string, std::string>::const_iterator aI;
00387     std::string     value;
00388 
00389     attachmentSize = 0;
00390 
00391     // get attachment size
00392     /*
00393     ImageGenericAttPtr att=ImageGenericAttPtr::dcast(
00394         const_cast<Image*>(image.getCPtr())->findAttachment(
00395             ImageGenericAtt::getClassType().getGroupId()));
00396     if(att != NullFC)
00397     {
00398         for(i = 0; i < (att->getType().getNumFieldDescs()-1); ++i)
00399         {
00400             FieldDescription *fieldDesc=att->getType().getFieldDescription(i);
00401             Field *field=att->getField(i);
00402             if (fieldDesc && field) 
00403             {
00404                 field->getValueByStr(value);
00405                 attachmentSize += strlen( fieldDesc->getName().str() ) + 1;
00406                 attachmentSize += value.length() + 1;
00407               
00408                 std::cout << fieldDesc->getName().str() << std::endl; 
00409                 std::cout << value << std::endl; 
00410             }
00411             else 
00412             {
00413                 FFATAL (("Invalid Attachment in ImageFileType::store()\n"));
00414             }
00415         }
00416     }
00417     */
00418 
00419     if (buffer) 
00420     {
00421         head = (Head *)buffer;
00422 
00423         head->pixelFormat    = image->getPixelFormat();
00424         head->width          = image->getWidth();
00425         head->height         = image->getHeight();
00426         head->depth          = image->getDepth();
00427         head->mipmapCount    = image->getMipMapCount();
00428         head->frameCount     = image->getFrameCount();
00429         head->frameDelay     = short(image->getFrameDelay() * 1000.0);
00430         head->sideCount      = image->getSideCount();
00431         head->dataType       = image->getDataType();
00432         head->attachmentSize = static_cast<unsigned short>(attachmentSize);
00433         head->hostToNet();
00434       
00435         strcpy(head->suffix, _suffixList.front().str());
00436       
00437         dest = (UChar8 *) (buffer + headSize);
00438 
00439         if (src) 
00440             dataSize = static_cast<unsigned long>(
00441                 storeData(image, dest, memSize - headSize));
00442 
00443         dest = (UChar8 *) (buffer + headSize + dataSize);
00444 
00445         /*
00446         if(att != NullFC)
00447         {
00448             for(i = 0; i < (att->getType().getNumFieldDescs()-1); ++i)
00449             {
00450                 FieldDescription *fieldDesc=att->getType().getFieldDescription(i);
00451                 Field *field=att->getField(i);
00452                 if (field && fieldDesc) 
00453                 {
00454                     field->getValueByStr(value);
00455 
00456                     l = strlen( fieldDesc->getName().str() );
00457                     for (i = 0; i < l; i++)
00458                       *dest++ = fieldDesc->getName().str()[i];
00459                     *dest++ = 0;
00460                     l = value.length();
00461                     for (i = 0; i < l; i++)
00462                       *dest++ = value[i];
00463                     *dest++ = 0;
00464                 }
00465                 else
00466                 {
00467                     FFATAL (("Invalid Attachment in ImageFileType::store()\n"));
00468                 }
00469             }
00470         }
00471         */
00472 
00473         FDEBUG (( "Store image data: %lu (%lu/%lu/%lu)\n",
00474                   headSize + dataSize + attachmentSize, headSize, dataSize, 
00475                   attachmentSize ));
00476     }
00477     else {
00478         FFATAL (("Invalid buffer in ImageFileType::store()\n"));
00479     }
00480   
00481     return (headSize + dataSize + attachmentSize);
00482 
00483 }

UInt64 ImageFileType::maxBufferSize ( const ImagePtr image  )  [virtual, inherited]

Returns the max buffer size needed to store the Image (Head + mimeType specific data block)

Definition at line 490 of file OSGImageFileType.cpp.

References FINFO.

Referenced by osg::ClusterViewBuffer::send(), and osg::ImageFileHandler::store().

00491 {
00492     std::string value;
00493     unsigned long size, attachmentSize;
00494     unsigned long imageSize = image->getSize(), headSize = sizeof(Head);
00495 
00496     std::map<std::string, std::string>::const_iterator aI;
00497 
00498     attachmentSize = 0;
00499 
00500     // get attachment size
00501         /*
00502     ImageGenericAttPtr att=ImageGenericAttPtr::dcast(
00503         const_cast<Image*>(image.getCPtr())->findAttachment(
00504             ImageGenericAtt::getClassType().getGroupId()));
00505     if(att != NullFC)
00506     {
00507         for(i = 0; i < (att->getType().getNumFieldDescs()-1); ++i)
00508         {
00509             FieldDescription *fieldDesc=att->getType().getFieldDescription(i);
00510             Field *field=att->getField(i);
00511             if (field && fieldDesc) 
00512             {
00513                 field->getValueByStr(value);
00514                 attachmentSize += strlen( fieldDesc->getName().str() ) + 1;
00515                 attachmentSize += value.length() + 1;
00516             }
00517             else 
00518             {
00519                 FFATAL (("Invalid Attachment in ImageFileType::maxBufferSize()\n"));
00520             }
00521         }
00522     }
00523         */
00524 
00525     size = headSize + imageSize + attachmentSize;
00526   
00527     FINFO (( "ImageFileType::maxBufferSize(): %lu (%lu/%lu/%lu)\n", 
00528              size, headSize, imageSize, attachmentSize ));
00529   
00530     return size;
00531 }

void ImageFileType::dump ( void   )  [inherited]

The dump method just writes some object debugging info to the LOG stream

Definition at line 537 of file OSGImageFileType.cpp.

References osg::ImageFileType::_suffixList, osg::ImageFileType::getMimeType(), osg::LOG_DEBUG, and SLOG.

00538 {
00539     std::list<IDString>::iterator    sI;
00540 
00541     SLOG << getMimeType();
00542 
00543     if(_suffixList.empty())
00544     {
00545         SLOG << ": Suffix: ";
00546         for(sI = _suffixList.begin(); sI != _suffixList.end(); sI++)
00547         {
00548             Log().stream(OSG::LOG_DEBUG) << sI->str() << " ";
00549         }
00550     }
00551 
00552     std::cerr << std::endl;
00553 }


Member Data Documentation

Definition at line 131 of file OSGPNGImageFileType.h.

Referenced by the().

std::string osg::ImageFileType::_options [protected, inherited]


The documentation for this class was generated from the following files:

Generated on Mon Mar 17 12:05:54 2008 for OpenSG by  doxygen 1.5.5