1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 //-------------------------------
41 //-------------------------------
46 #include "OSGConfig.h"
55 #include "OSGPNGImageFileType.h"
60 # define OSG_PNG_ARG(ARG) ARG
62 # define OSG_PNG_ARG(ARG)
65 # define OSG_PNG_ARG(ARG) ARG
68 static const OSG::Char8
*suffixArray
[] =
75 /*! \class PNGImageFileType
77 Image File Type to read/write and store/restore Image objects as
80 To be able to load PNG images you need the PNG library,
81 (check the Prerequisites page on www.opensg.org).
82 The lib comes with all Linux distributions.
84 You have to --enable-png in the configure line to enable
91 static void isReadFunc(png_structp png_ptr
, png_bytep data
, png_size_t length
)
94 reinterpret_cast<std::istream
*>(png_get_io_ptr(png_ptr
));
96 is
->read(reinterpret_cast<char*>(data
), length
);
98 if(png_size_t(is
->gcount()) != length
)
99 png_error(png_ptr
, "Cannot read from input stream");
102 static void osWriteFunc(png_structp png_ptr
, png_bytep data
, png_size_t length
)
105 reinterpret_cast<std::ostream
*>(png_get_io_ptr(png_ptr
));
107 os
->write(reinterpret_cast<char*>(data
), length
);
109 if(os
->good() == false)
110 png_error(png_ptr
, "Cannot write to output stream");
113 static void osFlushFunc(png_structp png_ptr
)
116 reinterpret_cast<std::ostream
*>(png_get_io_ptr(png_ptr
));
120 if(os
->good() == false)
121 png_error(png_ptr
, "Cannot flush output stream");
124 static void errorOutput (png_structp png_ptr
, const char *message
)
126 FFATAL (("PNG: %s\n", message
));
128 longjmp(png_jmpbuf(png_ptr
), 1);
131 static void warningOutput (png_structp
OSG_CHECK_ARG(png_ptr
),
134 FWARNING (("PNG: %s\n", message
));
139 PNGImageFileType
PNGImageFileType:: _the("image/png",
140 suffixArray
, sizeof(suffixArray
),
141 (OSG_READ_SUPPORTED
|
142 OSG_WRITE_SUPPORTED
));
144 //-------------------------------------------------------------------------
145 /*! Tries to fill the image object with the data read from
146 the given stream. Returns true on success.
149 bool PNGImageFileType::read( Image
*OSG_PNG_ARG(pImage
),
150 std::istream
&OSG_PNG_ARG(is
),
151 const std::string
&OSG_PNG_ARG(mimetype
))
156 Image::PixelFormat pixelFormat
= OSG::Image::OSG_INVALID_PF
;
159 png_uint_32 width
, wc
, height
, h
, i
, res_x
, res_y
;
160 png_byte bit_depth
, channels
, color_type
;
161 png_bytep
*row_pointers
, base
;
163 png_ptr
= png_create_read_struct(PNG_LIBPNG_VER_STRING
, 0, 0, 0);
168 png_set_error_fn(png_ptr
, 0, &errorOutput
, &warningOutput
);
170 info_ptr
= png_create_info_struct(png_ptr
);
174 png_destroy_read_struct(&png_ptr
, 0, 0);
178 if(setjmp(png_jmpbuf(png_ptr
)))
180 png_destroy_read_struct(&png_ptr
, &info_ptr
, 0);
184 png_set_read_fn(png_ptr
, &is
, &isReadFunc
);
186 png_read_info(png_ptr
, info_ptr
);
188 width
= png_get_image_width(png_ptr
, info_ptr
);
189 height
= png_get_image_height(png_ptr
, info_ptr
);
190 bit_depth
= png_get_bit_depth(png_ptr
, info_ptr
);
191 res_x
= png_get_x_pixels_per_meter(png_ptr
, info_ptr
);
192 res_y
= png_get_y_pixels_per_meter(png_ptr
, info_ptr
);
193 channels
= png_get_channels(png_ptr
, info_ptr
);
194 color_type
= png_get_color_type(png_ptr
, info_ptr
);
196 // Convert paletted images to RGB
197 if (color_type
== PNG_COLOR_TYPE_PALETTE
)
199 png_set_palette_to_rgb(png_ptr
);
204 // Convert < 8 bit to 8 bit
205 if(color_type
== PNG_COLOR_TYPE_GRAY
&& bit_depth
< 8)
207 png_set_expand_gray_1_2_4_to_8(png_ptr
);
211 #if BYTE_ORDER == LITTLE_ENDIAN
213 png_set_swap(png_ptr
);
216 // Add a full alpha channel if there is transparency
217 // information in a tRNS chunk
218 if(png_get_valid(png_ptr
, info_ptr
, PNG_INFO_tRNS
))
220 png_set_tRNS_to_alpha(png_ptr
);
229 dataType
= Image::OSG_UINT8_IMAGEDATA
;
232 dataType
= Image::OSG_UINT16_IMAGEDATA
;
235 FWARNING (( "Invalid bit_depth: %d, can not read png-data\n",
243 pixelFormat
= Image::OSG_L_PF
;
246 pixelFormat
= Image::OSG_LA_PF
;
249 pixelFormat
= Image::OSG_RGB_PF
;
252 pixelFormat
= Image::OSG_RGBA_PF
;
256 if(pImage
->set(pixelFormat
, width
, height
,
260 // set resolution png supports only pixel per meter,
261 // so we do a conversion to dpi with some rounding.
262 res_x
= png_uint_32((Real32(res_x
) / 39.37007874f
) < 0.0f
?
263 (Real32(res_x
) / 39.37007874f
) - 0.5f
:
264 (Real32(res_x
) / 39.37007874f
) + 0.5f
);
265 res_y
= png_uint_32((Real32(res_y
) / 39.37007874f
) < 0.0f
?
266 (Real32(res_y
) / 39.37007874f
) - 0.5f
:
267 (Real32(res_y
) / 39.37007874f
) + 0.5f
);
269 pImage
->setResX(Real32(res_x
));
270 pImage
->setResY(Real32(res_y
));
271 pImage
->setResUnit(Image::OSG_RESUNIT_INCH
);
273 // Calculate the row pointers
274 row_pointers
= new png_bytep
[height
];
275 wc
= width
* channels
* (bit_depth
/ 8);
277 base
= pImage
->editData();
279 for(i
= 0; i
< height
; ++i
)
280 row_pointers
[i
] = base
+ (h
- i
) * wc
;
282 // Read the image data
283 png_read_image(png_ptr
, row_pointers
);
285 delete[] row_pointers
;
294 png_destroy_read_struct(&png_ptr
, &info_ptr
, 0);
300 SWARNING
<< getMimeType()
301 << " read is not compiled into the current binary "
310 //-------------------------------------------------------------------------
311 /*! Tries to write the image object to the given fileName.
312 Returns true on success. Based on the public domain example.c
316 bool PNGImageFileType::write(const Image
*OSG_PNG_ARG(pImage
),
317 std::ostream
&OSG_PNG_ARG(os
),
318 const std::string
&OSG_PNG_ARG(mimetype
))
325 if(pImage
->getDimension() < 1 || pImage
->getDimension() > 2)
327 FWARNING(("PNGImageFileType::write: invalid dimension %d!\n",
328 pImage
->getDimension()));
333 /* Create and initialize the png_struct with the desired error handler
334 * functions. If you want to use the default stderr and longjump method,
335 * you can supply NULL for the last three parameters. We also check that
336 * the library version is compatible with the one used at compile time,
337 * in case we are using dynamically linked libraries. REQUIRED.
339 png_ptr
= png_create_write_struct(PNG_LIBPNG_VER_STRING
,
340 0, &errorOutput
, &warningOutput
);
345 /* Allocate/initialize the image information data. REQUIRED */
346 info_ptr
= png_create_info_struct(png_ptr
);
350 png_destroy_write_struct(&png_ptr
, NULL
);
354 /* set up the output handlers */
355 png_set_write_fn(png_ptr
, &os
, &osWriteFunc
, &osFlushFunc
);
357 /* This is the hard way */
359 /* Set the image information here. Width and height are up to 2^31,
360 * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
361 * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
362 * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
363 * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
364 * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
365 * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
369 switch(pImage
->getPixelFormat())
371 case Image::OSG_L_PF
:
372 ctype
= PNG_COLOR_TYPE_GRAY
;
375 case Image::OSG_LA_PF
:
376 ctype
= PNG_COLOR_TYPE_GRAY_ALPHA
;
379 #if defined(GL_BGR) || defined(GL_BGR_EXT)
380 case Image::OSG_BGR_PF
:
382 case Image::OSG_RGB_PF
:
383 ctype
= PNG_COLOR_TYPE_RGB
;
386 #if defined(GL_BGRA) || defined(GL_BGRA_EXT)
387 case Image::OSG_BGRA_PF
:
389 case Image::OSG_RGBA_PF
:
390 ctype
= PNG_COLOR_TYPE_RGB_ALPHA
;
394 FWARNING(("PNGImageFileType::write: unknown pixel format %d!\n",
395 pImage
->getPixelFormat()));
396 png_destroy_write_struct(&png_ptr
, NULL
);
402 switch(pImage
->getDataType())
404 case Image::OSG_UINT8_IMAGEDATA
:
407 case Image::OSG_UINT16_IMAGEDATA
:
411 FWARNING (("Invalid pixeldepth, cannot store data\n"));
415 png_set_IHDR(png_ptr
, info_ptr
, pImage
->getWidth(), pImage
->getHeight(),
418 PNG_COMPRESSION_TYPE_BASE
,
419 PNG_FILTER_TYPE_BASE
);
421 // set resolution png supports only meter per pixel,
422 // so we do a conversion from dpi with some rounding.
423 png_uint_32 res_x
= png_uint_32(pImage
->getResX());
424 png_uint_32 res_y
= png_uint_32(pImage
->getResY());
425 if(pImage
->getResUnit() == Image::OSG_RESUNIT_INCH
)
427 res_x
= png_uint_32((pImage
->getResX() * 39.37007874f
) < 0.0f
?
428 (pImage
->getResX() * 39.37007874f
) - 0.5f
:
429 (pImage
->getResX() * 39.37007874f
) + 0.5f
);
430 res_y
= png_uint_32((pImage
->getResY() * 39.37007874f
) < 0.0f
?
431 (pImage
->getResY() * 39.37007874f
) - 0.5f
:
432 (pImage
->getResY() * 39.37007874f
) + 0.5f
);
435 png_set_pHYs(png_ptr
, info_ptr
, res_x
, res_y
,
436 PNG_RESOLUTION_METER
);
439 /* optional significant bit chunk */
440 /* if we are dealing with a grayscale image then */
441 sig_bit
.gray
= true_bit_depth
;
442 /* otherwise, if we are dealing with a color image then */
443 sig_bit
.red
= true_red_bit_depth
;
444 sig_bit
.green
= true_green_bit_depth
;
445 sig_bit
.blue
= true_blue_bit_depth
;
446 /* if the image has an alpha channel then */
447 sig_bit
.alpha
= true_alpha_bit_depth
;
448 png_set_sBIT(png_ptr
, info_ptr
, sig_bit
);
451 /* Optional gamma chunk is strongly suggested if you have any guess
452 * as to the correct gamma of the image.
454 png_set_gAMA(png_ptr
, info_ptr
, gamma
);
456 /* Optionally write comments into the image */
457 text_ptr
[0].key
= "Title";
458 text_ptr
[0].text
= "Mona Lisa";
459 text_ptr
[0].compression
= PNG_TEXT_COMPRESSION_NONE
;
460 text_ptr
[1].key
= "Author";
461 text_ptr
[1].text
= "Leonardo DaVinci";
462 text_ptr
[1].compression
= PNG_TEXT_COMPRESSION_NONE
;
463 text_ptr
[2].key
= "Description";
464 text_ptr
[2].text
= "<long text>";
465 text_ptr
[2].compression
= PNG_TEXT_COMPRESSION_zTXt
;
466 #ifdef PNG_iTXt_SUPPORTED
467 text_ptr
[0].lang
= NULL
;
468 text_ptr
[1].lang
= NULL
;
469 text_ptr
[2].lang
= NULL
;
471 png_set_text(png_ptr
, info_ptr
, text_ptr
, 3);
473 /* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */
474 /* note that if sRGB is present the gAMA and cHRM chunks must be ignored
475 * on read and must be written in accordance with the sRGB profile */
477 /* Write the file header information. REQUIRED */
478 png_write_info(png_ptr
, info_ptr
);
480 #if BYTE_ORDER == LITTLE_ENDIAN
482 png_set_swap(png_ptr
);
486 /* invert monochrome pixels */
487 png_set_invert_mono(png_ptr
);
489 /* Shift the pixels up to a legal bit depth and fill in
490 * as appropriate to correctly scale the image.
492 png_set_shift(png_ptr
, &sig_bit
);
494 /* pack pixels into bytes */
495 png_set_packing(png_ptr
);
497 /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into
498 * RGB (4 channels -> 3 channels). The second parameter is not used.
500 png_set_filler(png_ptr
, 0, PNG_FILLER_BEFORE
);
502 /* swap bytes of 16-bit files to most significant byte first */
503 png_set_swap(png_ptr
);
505 /* swap bits of 1, 2, 4 bit packed pixel formats */
506 png_set_packswap(png_ptr
);
509 if(pImage
->getPixelFormat() == Image::OSG_BGR_PF
||
510 pImage
->getPixelFormat() == Image::OSG_BGRA_PF
)
512 /* flip BGR pixels to RGB */
513 png_set_bgr(png_ptr
);
515 /* swap location of alpha bytes from ARGB to RGBA */
516 png_set_swap_alpha(png_ptr
);
519 /* The easiest way to write the image (you may have a different memory
520 * layout, however, so choose what fits your needs best). You need to
521 * use the first method if you aren't handling interlacing yourself.
523 png_bytep
*row_pointers
= new png_bytep
[pImage
->getHeight()];
525 for(Int32 k
= 0; k
< pImage
->getHeight(); k
++)
528 (const_cast<UInt8
*>(pImage
->getData())) +
529 (pImage
->getHeight() - 1 - k
) *
530 pImage
->getWidth() * pImage
->getBpp();
533 /* write out the entire image data in one call */
534 png_write_image(png_ptr
, row_pointers
);
536 /* It is REQUIRED to call this to finish writing the rest of the file */
537 png_write_end(png_ptr
, info_ptr
);
539 /* clean up after the write, and free any memory allocated */
540 png_destroy_write_struct(&png_ptr
, &info_ptr
);
542 delete [] row_pointers
;
548 SWARNING
<< getMimeType()
549 << " write is not compiled into the current binary "
557 //-------------------------------------------------------------------------
559 Tries to determine the mime type of the data provided by an input stream
560 by searching for magic bytes. Returns the mime type or an empty string
561 when the function could not determine the mime type.
563 std::string
PNGImageFileType::determineMimetypeFromStream(std::istream
&is
)
566 is
.read(filecode
, 4);
567 is
.seekg(-4, std::ios::cur
);
569 return strncmp(filecode
, "\x89PNG", 4) == 0 ?
570 std::string(getMimeType()) : std::string();
575 bool PNGImageFileType::validateHeader(const Char8
*fileName
, bool &implemented
)
582 FILE *file
= fopen(fileName
, "rb");
591 fread(static_cast<void *>(&magic
[0]), 4, 1, file
);
595 if(magic
== "\x89PNG")
610 static void user_read_data(png_structp png_ptr
,
611 png_bytep data
, png_size_t length
)
613 BufferInfo
*bufferInfo
= static_cast<BufferInfo
*>(png_get_io_ptr(png_ptr
));
614 memcpy(static_cast<void *>(data
),
615 static_cast<void *>(bufferInfo
->buffer
),
617 bufferInfo
->buffer
+= length
;
618 bufferInfo
->length
+= length
;
623 UInt64
PNGImageFileType::restoreData( Image
*OSG_PNG_ARG (pImage
),
624 const UChar8
*OSG_PNG_ARG (buffer
),
625 Int32
OSG_CHECK_ARG(memSize
)) const
630 Image::PixelFormat pixelFormat
= Image::OSG_INVALID_PF
;
633 png_uint_32 width
, wc
, height
, h
, i
;
634 png_byte bit_depth
, channels
, color_type
;
635 png_bytep
*row_pointers
, base
;
637 png_ptr
= png_create_read_struct(PNG_LIBPNG_VER_STRING
, 0, 0, 0);
644 png_set_error_fn(png_ptr
, 0, &errorOutput
, &warningOutput
);
646 info_ptr
= png_create_info_struct(png_ptr
);
650 png_destroy_read_struct(&png_ptr
, 0, 0);
654 if(setjmp(png_jmpbuf(png_ptr
)))
656 png_destroy_read_struct(&png_ptr
, &info_ptr
, 0);
660 BufferInfo bufferInfo
;
661 bufferInfo
.buffer
= const_cast<UChar8
*>(buffer
);
662 bufferInfo
.length
= 0;
663 png_set_read_fn(png_ptr
, static_cast<void *>(&bufferInfo
), user_read_data
);
665 png_read_info(png_ptr
, info_ptr
);
667 width
= png_get_image_width(png_ptr
, info_ptr
);
668 height
= png_get_image_height(png_ptr
, info_ptr
);
669 bit_depth
= png_get_bit_depth(png_ptr
, info_ptr
);
670 channels
= png_get_channels(png_ptr
, info_ptr
);
671 color_type
= png_get_color_type(png_ptr
, info_ptr
);
673 // Convert paletted images to RGB
674 if(color_type
== PNG_COLOR_TYPE_PALETTE
)
676 png_set_palette_to_rgb(png_ptr
);
681 // Convert < 8 bit to 8 bit
682 if(color_type
== PNG_COLOR_TYPE_GRAY
&& bit_depth
< 8)
684 png_set_expand_gray_1_2_4_to_8(png_ptr
);
688 #if BYTE_ORDER == LITTLE_ENDIAN
690 png_set_swap(png_ptr
);
693 // Add a full alpha channel if there is transparency
694 // information in a tRNS chunk
695 if(png_get_valid(png_ptr
, info_ptr
, PNG_INFO_tRNS
))
697 png_set_tRNS_to_alpha(png_ptr
);
706 dataType
= Image::OSG_UINT8_IMAGEDATA
;
709 dataType
= Image::OSG_UINT16_IMAGEDATA
;
712 FWARNING (( "Invalid bit_depth: %d, can not read png-data\n",
720 pixelFormat
= Image::OSG_L_PF
;
723 pixelFormat
= Image::OSG_LA_PF
;
726 pixelFormat
= Image::OSG_RGB_PF
;
729 pixelFormat
= Image::OSG_RGBA_PF
;
733 if(pImage
->set(pixelFormat
, width
, height
,
737 // Calculate the row pointers
738 row_pointers
= new png_bytep
[height
];
739 wc
= width
* channels
* (bit_depth
/ 8);
741 base
= pImage
->editData();
743 for(i
= 0; i
< height
; ++i
)
744 row_pointers
[i
] = base
+ (h
- i
) * wc
;
746 // Read the image data
747 png_read_image(png_ptr
, row_pointers
);
749 delete[] row_pointers
;
751 retCode
= bufferInfo
.length
;
758 png_destroy_read_struct(&png_ptr
, &info_ptr
, 0);
763 SWARNING
<< getMimeType()
764 << " restoreData is not compiled into the current binary "
773 static void user_write_data(png_structp png_ptr
,
774 png_bytep data
, png_size_t length
)
776 BufferInfo
*bufferInfo
= static_cast<BufferInfo
*>(png_get_io_ptr(png_ptr
));
777 memcpy(static_cast<void *>(bufferInfo
->buffer
),
778 static_cast<void *>(data
),
780 bufferInfo
->buffer
+= length
;
781 bufferInfo
->length
+= length
;
784 static void user_flush_data(png_structp
OSG_CHECK_ARG(png_ptr
))
790 //-------------------------------------------------------------------------
791 /*! Tries to restore the image data from the given memblock.
792 Returns the amount of data read.
795 UInt64
PNGImageFileType::storeData(const Image
*OSG_PNG_ARG (pImage
),
796 UChar8
*OSG_PNG_ARG (buffer
),
797 Int32
OSG_CHECK_ARG(memSize
)) const
804 if(pImage
->getDimension() < 1 || pImage
->getDimension() > 2)
806 FWARNING(("PNGImageFileType::write: invalid dimension %d!\n",
807 pImage
->getDimension()));
811 /* Create and initialize the png_struct with the desired error handler
812 * functions. If you want to use the default stderr and longjump method,
813 * you can supply NULL for the last three parameters. We also check that
814 * the library version is compatible with the one used at compile time,
815 * in case we are using dynamically linked libraries. REQUIRED.
818 png_ptr
= png_create_write_struct(PNG_LIBPNG_VER_STRING
,
819 0, &errorOutput
, &warningOutput
);
826 /* Allocate/initialize the image information data. REQUIRED */
827 info_ptr
= png_create_info_struct(png_ptr
);
831 png_destroy_write_struct(&png_ptr
, NULL
);
835 BufferInfo bufferInfo
;
836 bufferInfo
.buffer
= buffer
;
837 bufferInfo
.length
= 0;
839 png_set_write_fn(png_ptr
,
840 static_cast<void *>(&bufferInfo
),
844 /* This is the hard way */
846 /* Set the image information here. Width and height are up to 2^31,
847 * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
848 * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
849 * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
850 * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
851 * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
852 * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
856 switch(pImage
->getPixelFormat())
858 case Image::OSG_L_PF
:
859 ctype
= PNG_COLOR_TYPE_GRAY
;
862 case Image::OSG_LA_PF
:
863 ctype
= PNG_COLOR_TYPE_GRAY_ALPHA
;
866 #if defined(GL_BGR) || defined(GL_BGR_EXT)
867 case Image::OSG_BGR_PF
:
869 case Image::OSG_RGB_PF
:
870 ctype
= PNG_COLOR_TYPE_RGB
;
873 #if defined(GL_BGRA) || defined(GL_BGRA_EXT)
874 case Image::OSG_BGRA_PF
:
876 case Image::OSG_RGBA_PF
:
877 ctype
= PNG_COLOR_TYPE_RGB_ALPHA
;
881 FWARNING(("PNGImageFileType::write: unknown pixel format %d!\n",
882 pImage
->getPixelFormat()));
883 png_destroy_write_struct(&png_ptr
, NULL
);
890 switch (pImage
->getDataType())
892 case Image::OSG_UINT8_IMAGEDATA
:
895 case Image::OSG_UINT16_IMAGEDATA
:
899 FWARNING (("Invalid pixeldepth, cannot store data\n"));
903 png_set_IHDR(png_ptr
,
910 PNG_COMPRESSION_TYPE_BASE
,
911 PNG_FILTER_TYPE_BASE
);
913 /* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */
914 /* note that if sRGB is present the gAMA and cHRM chunks must be ignored
915 * on read and must be written in accordance with the sRGB profile */
917 /* Write the file header information. REQUIRED */
919 png_write_info(png_ptr
, info_ptr
);
921 #if BYTE_ORDER == LITTLE_ENDIAN
923 png_set_swap(png_ptr
);
926 if(pImage
->getPixelFormat() == Image::OSG_BGR_PF
||
927 pImage
->getPixelFormat() == Image::OSG_BGRA_PF
)
929 /* flip BGR pixels to RGB */
930 png_set_bgr(png_ptr
);
932 /* swap location of alpha bytes from ARGB to RGBA */
933 png_set_swap_alpha(png_ptr
);
936 /* The easiest way to write the image (you may have a different memory
937 * layout, however, so choose what fits your needs best). You need to
938 * use the first method if you aren't handling interlacing yourself.
941 png_bytep
*row_pointers
= new png_bytep
[pImage
->getHeight()];
943 for(Int32 k
= 0; k
< pImage
->getHeight(); k
++)
946 (const_cast<UInt8
*>(pImage
->getData())) +
947 (pImage
->getHeight() - 1 - k
) *
948 pImage
->getWidth() * pImage
->getBpp();
951 /* write out the entire image data in one call */
952 png_write_image(png_ptr
, row_pointers
);
954 /* It is REQUIRED to call this to finish writing the rest of the file */
955 png_write_end(png_ptr
, info_ptr
);
957 /* clean up after the write, and free any memory allocated */
958 png_destroy_write_struct(&png_ptr
, &info_ptr
);
960 delete [] row_pointers
;
963 return bufferInfo
.length
;
965 SWARNING
<< getMimeType()
966 << " storeData is not compiled into the current binary "
973 const PNGImageFileType
&PNGImageFileType::the(void)
978 //-------------------------------------------------------------------------
979 /*! Constructor used for the singleton object
982 PNGImageFileType::PNGImageFileType(const Char8
*mimeType
,
983 const Char8
*suffixArray
[],
984 UInt16 suffixByteCount
,
987 Inherited(mimeType
, suffixArray
, suffixByteCount
, flags
)
992 //-------------------------------------------------------------------------
996 PNGImageFileType::~PNGImageFileType(void)