Add support for saving PNG files. Patch by Frank Richter. Fixes issue 79.

pull/216/head
castano 16 years ago
parent 36dd7fb76b
commit 7741a99b90

@ -127,6 +127,11 @@ bool nv::ImageIO::save(const char * fileName, Stream & s, const Image * img)
if (strCaseCmp(extension, ".tga") == 0) {
return ImageIO::saveTGA(s, img);
}
#if defined(HAVE_PNG)
if (strCaseCmp(extension, ".png") == 0) {
return ImageIO::savePNG(s, img);
}
#endif
return false;
}
@ -985,6 +990,100 @@ Image * nv::ImageIO::loadPNG(Stream & s)
return img.release();
}
static void user_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
nvDebugCheck(png_ptr != NULL);
Stream * s = (Stream *)png_ptr->io_ptr;
s->serialize(data, (int)length);
if (s->isError()) {
png_error(png_ptr, "Write Error");
}
}
static void user_write_flush(png_structp png_ptr) { }
bool nv::ImageIO::savePNG(Stream & s, const Image * img)
{
nvCheck(!s.isError());
nvCheck(img != NULL);
nvCheck(img->pixels() != NULL);
// Set up a write buffer and check the library version
png_structp png_ptr;
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) {
return false;
}
// Allocate/initialize a memory block for the image information
png_infop info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) {
png_destroy_write_struct(&png_ptr, NULL);
return false;
}
// Set up the error handling
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_write_struct(&png_ptr, &info_ptr);
return false;
}
// Set up the I/O functions.
png_set_write_fn(png_ptr, (void*)&s, user_write_data, user_write_flush);
// Set image header information
int color_type = PNG_COLOR_TYPE_RGB;
switch(img->format())
{
case Image::Format_RGB: color_type = PNG_COLOR_TYPE_RGB; break;
case Image::Format_ARGB: color_type = PNG_COLOR_TYPE_RGBA; break;
}
png_set_IHDR(png_ptr, info_ptr, img->width(), img->height(),
8, color_type, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
// Set image data
png_bytep * row_data = new png_bytep[sizeof(png_byte) * img->height()];
for (uint i = 0; i < img->height(); i++) {
row_data[i] = (png_byte*)img->scanline (i);
}
png_set_rows(png_ptr, info_ptr, row_data);
png_text* text = 0;
/*if (comments.size() > 0)
{
text = new png_text[comments.size()];
memset(text, 0, comments.size() * sizeof(png_text));
int n = 0;
for (PngCommentsType::const_iterator comment = comments.begin(); comment != comments.end(); comment++)
{
text[n].compression = PNG_TEXT_COMPRESSION_NONE;
text[n].key = const_cast<char*> (comment->first.c_str());
text[n].text = const_cast<char*> (comment->second.c_str());
n++;
}
png_set_text(png_ptr, info_ptr, text, comments.size());
}*/
png_write_png(png_ptr, info_ptr,
// component order is BGR(A)
PNG_TRANSFORM_BGR
// Strip alpha byte for RGB images
| (img->format() == Image::Format_RGB ? PNG_TRANSFORM_STRIP_FILLER : 0),
NULL);
// Finish things up
png_destroy_write_struct(&png_ptr, &info_ptr);
delete [] row_data;
delete [] text;
return true;
}
#endif // defined(HAVE_PNG)
#if defined(HAVE_JPEG)

@ -5,6 +5,9 @@
#include <nvimage/nvimage.h>
#include <string>
#include <map>
namespace nv
{
class Image;
@ -30,6 +33,7 @@ namespace nv
#if defined(HAVE_PNG)
NVIMAGE_API Image * loadPNG(Stream & s);
NVIMAGE_API bool savePNG(Stream & s, const Image * img);
#endif
#if defined(HAVE_JPEG)

Loading…
Cancel
Save