00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pent_include.h"
00020
00021 #include "PNGWriter.h"
00022 #include "ODataSource.h"
00023 #include "Texture.h"
00024
00025 #include <png.h>
00026
00027 static void odatasource_png_write_data(png_structp png_ptr,
00028 png_bytep data, png_size_t length)
00029 {
00030 voidp write_io_ptr = png_get_io_ptr(png_ptr);
00031 ODataSource* ds = reinterpret_cast<ODataSource*>(write_io_ptr);
00032 ds->write(data, length);
00033 }
00034
00035 static void odatasource_png_flush_data(png_structp png_ptr)
00036 {
00037
00038 }
00039
00040
00041
00042 PNGWriter::PNGWriter(ODataSource* ods)
00043 {
00044 ds = ods;
00045 png = 0;
00046 }
00047
00048 PNGWriter::~PNGWriter()
00049 {
00050
00051 }
00052
00053 bool PNGWriter::init(uint32 width, uint32 height, const std::string& comment)
00054 {
00055 this->width = width;
00056
00057 png_structp png_ptr = png_create_write_struct
00058 (PNG_LIBPNG_VER_STRING, 0, 0, 0);
00059 if (!png_ptr)
00060 return false;
00061
00062 png_infop info_ptr = png_create_info_struct(png_ptr);
00063 if (!info_ptr)
00064 {
00065 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
00066 return false;
00067 }
00068
00069 if (setjmp(png_jmpbuf(png_ptr)))
00070 {
00071 png_destroy_write_struct(&png_ptr, &info_ptr);
00072 return false;
00073 }
00074
00075 png_set_write_fn(png_ptr, ds, odatasource_png_write_data,
00076 odatasource_png_flush_data);
00077
00078 png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
00079 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
00080 PNG_FILTER_TYPE_DEFAULT);
00081
00082
00083 if (!comment.empty()) {
00084 std::string::size_type len = comment.size();
00085 char* t = new char[len+1];
00086 std::memcpy(t, comment.c_str(), len+1);
00087
00088 png_text_struct text[1];
00089 text[0].compression = -1;
00090 text[0].key = "Comment";
00091 text[0].text = t;
00092 text[0].text_length = comment.size();
00093
00094 png_set_text(png_ptr, info_ptr, text, 1);
00095
00096 delete[] t;
00097 }
00098
00099 png_write_info(png_ptr, info_ptr);
00100
00101 png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
00102
00103 png_set_bgr(png_ptr);
00104
00105 png = reinterpret_cast<void*>(png_ptr);
00106 info = reinterpret_cast<void*>(info_ptr);
00107
00108 return true;
00109 }
00110
00111 bool PNGWriter::writeRows(uint32 nrows, Texture* img)
00112 {
00113 png_bytep* row_pointers = 0;
00114 png_structp png_ptr = reinterpret_cast<png_structp>(png);
00115 png_infop info_ptr = reinterpret_cast<png_infop>(info);
00116 if (!png_ptr) return false;
00117
00118 assert(img->width == static_cast<sint32>(width));
00119 assert(img->height >= static_cast<sint32>(nrows));
00120
00121 if (setjmp(png_jmpbuf(png_ptr)))
00122 {
00123 png_destroy_write_struct(&png_ptr, &info_ptr);
00124 delete[] row_pointers;
00125 return false;
00126 }
00127
00128 row_pointers = new png_bytep[nrows];
00129
00130 for (unsigned int i = 0; i < nrows; ++i) {
00131 row_pointers[i] = reinterpret_cast<png_bytep>(&img->buffer[i*width]);
00132 }
00133
00134 png_write_rows(png_ptr, row_pointers, nrows);
00135
00136 png_write_flush(png_ptr);
00137
00138 delete[] row_pointers;
00139
00140 return true;
00141 }
00142
00143 bool PNGWriter::finish()
00144 {
00145 png_structp png_ptr = reinterpret_cast<png_structp>(png);
00146 png_infop info_ptr = reinterpret_cast<png_infop>(info);
00147 if (!png_ptr) return false;
00148
00149 if (setjmp(png_jmpbuf(png_ptr)))
00150 {
00151 png_destroy_write_struct(&png_ptr, &info_ptr);
00152 return false;
00153 }
00154
00155 png_write_end(png_ptr, info_ptr);
00156 png_destroy_write_struct(&png_ptr, &info_ptr);
00157
00158 return true;
00159 }