00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "pngio.h"
00025 #include "error.h"
00026 #include "error.h"
00027 #include "osfunc.h"
00028 #include <png.h>
00029
00030 namespace lux {
00031
00032
00033 void lux_png_error(png_structp png_, png_const_charp msg)
00034 {
00035 std::stringstream ss;
00036 ss<< "Cannot open PNG file '"<<msg<<"' for output";
00037 luxError(LUX_SYSTEM, LUX_SEVERE, ss.str().c_str());
00038 }
00039
00040
00041 void WritePngImage(int channeltype, bool ubit, bool savezbuf, const string &name, vector<RGBColor> &pixels,
00042 vector<float> &alpha, int xPixelCount, int yPixelCount,
00043 int xResolution, int yResolution,
00044 int xPixelStart, int yPixelStart, ColorSystem &cSystem, float screenGamma) {
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 FILE *fp = fopen(name.c_str(), "wb");
00055 if (!fp) {
00056 std::stringstream ss;
00057 ss << "Cannot open PNG file '" << name << "' for output";
00058 luxError(LUX_SYSTEM, LUX_SEVERE, ss.str().c_str());
00059 return;
00060 }
00061
00062 png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr) lux_png_error, NULL);
00063 png_infop info = png_create_info_struct(png);
00064 png_init_io(png, fp);
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 png_text text;
00079 text.compression = PNG_TEXT_COMPRESSION_NONE;
00080 text.key = (png_charp) "Software";
00081 text.text = (png_charp) "LuxRender";
00082 text.text_length = 4;
00083 png_set_text(png, info, &text, 1);
00084
00085 png_color_16 black = {0, 0, 0, 0, 0};
00086 png_set_background(png, &black, PNG_BACKGROUND_GAMMA_SCREEN, 0, 255.0);
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 float fileGamma = 1.0f;
00120 png_set_gamma(png, screenGamma, fileGamma);
00121
00122 png_set_cHRM(png, info, cSystem.xWhite, cSystem.yWhite, cSystem.xRed,
00123 cSystem.yRed, cSystem.xGreen, cSystem.yGreen, cSystem.xBlue, cSystem.yBlue);
00124
00125 int colorType;
00126 switch (channeltype) {
00127 case 0:
00128 colorType = PNG_COLOR_TYPE_GRAY;
00129 break;
00130 case 1:
00131 colorType = PNG_COLOR_TYPE_GRAY_ALPHA;
00132 break;
00133 case 2:
00134 colorType = PNG_COLOR_TYPE_RGB;
00135 break;
00136 case 3:
00137 colorType = PNG_COLOR_TYPE_RGB_ALPHA;
00138 break;
00139 default:
00140 colorType = PNG_COLOR_TYPE_RGB;
00141 }
00142
00143
00144 png_set_IHDR(
00145 png, info,
00146 xPixelCount, yPixelCount, ubit ? 16 : 8,
00147 colorType, PNG_INTERLACE_NONE,
00148 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
00149
00150 png_write_info(png, info);
00151
00152
00153
00154 if (ubit && osIsLittleEndian())
00155 png_set_swap(png);
00156
00157
00158 if (ubit) {
00159
00160 std::vector<png_uint_16> row(xPixelCount*4);
00161
00162 for (int y = 0; y < yPixelCount; ++y)
00163 {
00164 int i = 0;
00165
00166 switch (colorType) {
00167 case PNG_COLOR_TYPE_GRAY:
00168 {
00169 for (int x = 0; x < xPixelCount; ++x)
00170 {
00171
00172
00173 png_uint_16 gray = static_cast<png_uint_16>(Clamp(65535.f *
00174 pixels[x + y * xPixelCount].Y(), 0.f, 65535.f));
00175
00176 row[i++] = gray;
00177 }
00178 }
00179 break;
00180 case PNG_COLOR_TYPE_GRAY_ALPHA:
00181 {
00182 for (int x = 0; x < xPixelCount; ++x)
00183 {
00184
00185
00186 png_uint_16 gray = static_cast<png_uint_16>(Clamp(65535.f *
00187 pixels[x + y * xPixelCount].Y(), 0.f, 65535.f));
00188 png_uint_16 a = static_cast<png_uint_16>(Clamp(65535.f * alpha[x + y * xPixelCount], 0.f, 65535.f));
00189
00190 row[i++] = gray;
00191 row[i++] = a;
00192 }
00193 }
00194 break;
00195 case PNG_COLOR_TYPE_RGB:
00196 {
00197 for (int x = 0; x < xPixelCount; ++x)
00198 {
00199 const RGBColor &c = pixels[(x + y * xPixelCount)];
00200 png_uint_16 r = static_cast<png_uint_16>(Clamp(65535.f * c.c[0], 0.f, 65535.f));
00201 png_uint_16 g = static_cast<png_uint_16>(Clamp(65535.f * c.c[1], 0.f, 65535.f));
00202 png_uint_16 b = static_cast<png_uint_16>(Clamp(65535.f * c.c[2], 0.f, 65535.f));
00203
00204 row[i++] = r;
00205 row[i++] = g;
00206 row[i++] = b;
00207 }
00208 }
00209 break;
00210 case PNG_COLOR_TYPE_RGB_ALPHA:
00211 {
00212 for (int x = 0; x < xPixelCount; ++x)
00213 {
00214 const RGBColor &c = pixels[(x + y * xPixelCount)];
00215 png_uint_16 r = static_cast<png_uint_16>(Clamp(65535.f * c.c[0], 0.f, 65535.f));
00216 png_uint_16 g = static_cast<png_uint_16>(Clamp(65535.f * c.c[1], 0.f, 65535.f));
00217 png_uint_16 b = static_cast<png_uint_16>(Clamp(65535.f * c.c[2], 0.f, 65535.f));
00218 png_uint_16 a = static_cast<png_uint_16>(Clamp(65535.f * alpha[x + y * xPixelCount], 0.f, 65535.f));
00219
00220 row[i++] = r;
00221 row[i++] = g;
00222 row[i++] = b;
00223 row[i++] = a;
00224 }
00225 }
00226 break;
00227 }
00228
00229 png_write_row(png, reinterpret_cast<png_bytep>(&row[0]));
00230 }
00231 } else {
00232
00233 std::vector<png_byte> row(xPixelCount*4);
00234
00235 for (int y = 0; y < yPixelCount; ++y)
00236 {
00237 int i = 0;
00238
00239 switch (colorType) {
00240 case PNG_COLOR_TYPE_GRAY:
00241 {
00242 for (int x = 0; x < xPixelCount; ++x)
00243 {
00244
00245
00246 png_byte gray = static_cast<png_byte>(Clamp(255.f *
00247 pixels[x + y * xPixelCount].Y(), 0.f, 255.f));
00248
00249 row[i++] = gray;
00250 }
00251 }
00252 break;
00253 case PNG_COLOR_TYPE_GRAY_ALPHA:
00254 {
00255 for (int x = 0; x < xPixelCount; ++x)
00256 {
00257
00258
00259 png_byte gray = static_cast<png_byte>(Clamp(255.f *
00260 pixels[x + y * xPixelCount].Y(), 0.f, 255.f));
00261 png_byte a = static_cast<png_byte>(Clamp(255.f * alpha[x + y * xPixelCount], 0.f, 255.f));
00262
00263 row[i++] = gray;
00264 row[i++] = a;
00265 }
00266 }
00267 break;
00268 case PNG_COLOR_TYPE_RGB:
00269 {
00270 for (int x = 0; x < xPixelCount; ++x)
00271 {
00272 const RGBColor &c = pixels[(x + y * xPixelCount)];
00273 png_byte r = static_cast<png_byte>(Clamp(255.f * c.c[0], 0.f, 255.f));
00274 png_byte g = static_cast<png_byte>(Clamp(255.f * c.c[1], 0.f, 255.f));
00275 png_byte b = static_cast<png_byte>(Clamp(255.f * c.c[2], 0.f, 255.f));
00276
00277 row[i++] = r;
00278 row[i++] = g;
00279 row[i++] = b;
00280 }
00281 }
00282 break;
00283 case PNG_COLOR_TYPE_RGB_ALPHA:
00284 {
00285 for (int x = 0; x < xPixelCount; ++x)
00286 {
00287 const RGBColor &c = pixels[(x + y * xPixelCount)];
00288 png_byte r = static_cast<png_byte>(Clamp(255.f * c.c[0], 0.f, 255.f));
00289 png_byte g = static_cast<png_byte>(Clamp(255.f * c.c[1], 0.f, 255.f));
00290 png_byte b = static_cast<png_byte>(Clamp(255.f * c.c[2], 0.f, 255.f));
00291 png_byte a = static_cast<png_byte>(Clamp(255.f * alpha[x + y * xPixelCount], 0.f, 255.f));
00292
00293 row[i++] = r;
00294 row[i++] = g;
00295 row[i++] = b;
00296 row[i++] = a;
00297 }
00298 }
00299 break;
00300 }
00301
00302 png_write_row(png, &row[0]);
00303 }
00304 }
00305
00306
00307 png_write_end(png, info);
00308 png_destroy_write_struct(&png, &info);
00309
00310 fclose(fp);
00311
00312 }
00313
00314 }