00001 /*************************************************************************** 00002 *cr 00003 *cr (C) Copyright 1995-2019 The Board of Trustees of the 00004 *cr University of Illinois 00005 *cr All Rights Reserved 00006 *cr 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * RCS INFORMATION: 00011 * 00012 * $RCSfile: ImageIO.C,v $ 00013 * $Author: johns $ $Locker: $ $State: Exp $ 00014 * $Revision: 1.26 $ $Date: 2022年04月08日 06:11:00 $ 00015 * 00016 *************************************************************************** 00017 * DESCRIPTION: 00018 * Write an RGB image to a file. Image routines donated by John Stone, 00019 * derived from Tachyon source code. For now these image file writing 00020 * routines are statically linked into VMD and are not even in an extensible 00021 * list structure. Long-term the renderer interface should abstract from 00022 * most of the details, and use a plugin interface for extensibility. 00023 * For the short-term, this gets the job done. 00024 * 00025 ***************************************************************************/ 00026 00027 #include <stdio.h> 00028 #include <stdlib.h> 00029 #include <string.h> 00030 #include "ImageIO.h" 00031 #include "Inform.h" 00032 #include "utilities.h" 00033 00034 #if defined(VMDLIBPNG) 00035 #include "png.h" // libpng header file 00036 #endif 00037 00038 static void putbyte(FILE * outf, unsigned char val) { 00039 unsigned char buf[1]; 00040 buf[0] = val; 00041 fwrite(buf, 1, 1, outf); 00042 } 00043 00044 static void putshort(FILE * outf, unsigned short val) { 00045 unsigned char buf[2]; 00046 buf[0] = val >> 8; 00047 buf[1] = val & 0xff; 00048 fwrite(buf, 2, 1, outf); 00049 } 00050 00051 static void putint(FILE * outf, unsigned int val) { 00052 unsigned char buf[4]; 00053 buf[0] = (unsigned char) (val >> 24); 00054 buf[1] = (unsigned char) (val >> 16); 00055 buf[2] = (unsigned char) (val >> 8); 00056 buf[3] = (unsigned char) (val & 0xff); 00057 fwrite(buf, 4, 1, outf); 00058 } 00059 00060 00061 unsigned char * cvt_rgb4u_rgb3u(const unsigned char * rgb4u, int xs, int ys) { 00062 int rowlen3u = xs*3; 00063 int sz = xs * ys * 3; 00064 unsigned char * rgb3u = (unsigned char *) calloc(1, sz); 00065 00066 int x3u, x4f, y; 00067 for (y=0; y<ys; y++) { 00068 int addr3u = y * xs * 3; 00069 int addr4f = y * xs * 4; 00070 for (x3u=0,x4f=0; x3u<rowlen3u; x3u+=3,x4f+=4) { 00071 rgb3u[addr3u + x3u ] = rgb4u[addr4f + x4f ]; 00072 rgb3u[addr3u + x3u + 1] = rgb4u[addr4f + x4f + 1]; 00073 rgb3u[addr3u + x3u + 2] = rgb4u[addr4f + x4f + 2]; 00074 } 00075 } 00076 00077 return rgb3u; 00078 } 00079 00080 00081 unsigned char * cvt_rgb4f_rgb3u(const float * rgb4f, int xs, int ys) { 00082 int rowlen3u = xs*3; 00083 int sz = xs * ys * 3; 00084 unsigned char * rgb3u = (unsigned char *) calloc(1, sz); 00085 00086 int x3u, x4f, y; 00087 for (y=0; y<ys; y++) { 00088 int addr3u = y * xs * 3; 00089 int addr4f = y * xs * 4; 00090 for (x3u=0,x4f=0; x3u<rowlen3u; x3u+=3,x4f+=4) { 00091 int tmp; 00092 00093 tmp = int(rgb4f[addr4f + x4f ] * 255.0f); 00094 rgb3u[addr3u + x3u ] = (tmp < 0) ? 0 : ((tmp > 255) ? 255 : tmp); 00095 00096 tmp = int(rgb4f[addr4f + x4f + 1] * 255.0f); 00097 rgb3u[addr3u + x3u + 1] = (tmp < 0) ? 0 : ((tmp > 255) ? 255 : tmp); 00098 00099 tmp = int(rgb4f[addr4f + x4f + 2] * 255.0f); 00100 rgb3u[addr3u + x3u + 2] = (tmp < 0) ? 0 : ((tmp > 255) ? 255 : tmp); 00101 } 00102 } 00103 00104 return rgb3u; 00105 } 00106 00107 00108 unsigned char * cvt_rgba4f_rgba4u(const float * rgba4f, int xs, int ys) { 00109 int rowlen4u = xs*4; 00110 int sz = xs * ys * 4; 00111 unsigned char * rgba4u = (unsigned char *) calloc(1, sz); 00112 00113 int x4u, x4f, y; 00114 for (y=0; y<ys; y++) { 00115 int addr4 = y * xs * 4; 00116 for (x4u=0,x4f=0; x4u<rowlen4u; x4u+=4,x4f+=4) { 00117 int tmp; 00118 00119 tmp = int(rgba4f[addr4 + x4f ] * 255.0f); 00120 rgba4u[addr4 + x4u ] = (tmp < 0) ? 0 : ((tmp > 255) ? 255 : tmp); 00121 00122 tmp = int(rgba4f[addr4 + x4f + 1] * 255.0f); 00123 rgba4u[addr4 + x4u + 1] = (tmp < 0) ? 0 : ((tmp > 255) ? 255 : tmp); 00124 00125 tmp = int(rgba4f[addr4 + x4f + 2] * 255.0f); 00126 rgba4u[addr4 + x4u + 2] = (tmp < 0) ? 0 : ((tmp > 255) ? 255 : tmp); 00127 00128 tmp = int(rgba4f[addr4 + x4f + 3] * 255.0f); 00129 rgba4u[addr4 + x4u + 3] = (tmp < 0) ? 0 : ((tmp > 255) ? 255 : tmp); 00130 } 00131 } 00132 00133 return rgba4u; 00134 } 00135 00136 00137 static int checkfileextension(const char *s, const char *extension) { 00138 int sz, extsz; 00139 sz = strlen(s); 00140 extsz = strlen(extension); 00141 00142 if (extsz > sz) return 0; 00143 00144 if (!strupncmp(s + (sz - extsz), extension, extsz)) return 1; 00145 00146 return 0; 00147 } 00148 00149 00150 int write_image_file_rgb3u(const char *filename, 00151 const unsigned char *rgb3u, int xs, int ys) { 00152 FILE *outfile=NULL; 00153 if ((outfile = fopen(filename, "wb")) == NULL) { 00154 msgErr << "Could not open file " << filename 00155 << " in current directory for writing!" << sendmsg; 00156 return -1; 00157 } 00158 00159 // write the image to a file on disk 00160 if (checkfileextension(filename, ".bmp")) { 00161 vmd_writebmp(outfile, rgb3u, xs, ys); 00162 #if defined(VMDLIBPNG) 00163 } else if (checkfileextension(filename, ".png")) { 00164 vmd_writepng(outfile, rgb3u, xs, ys); 00165 #endif 00166 } else if (checkfileextension(filename, ".ppm")) { 00167 vmd_writeppm(outfile, rgb3u, xs, ys); 00168 } else if (checkfileextension(filename, ".rgb")) { 00169 vmd_writergb(outfile, rgb3u, xs, ys); 00170 } else if (checkfileextension(filename, ".tga")) { 00171 vmd_writetga(outfile, rgb3u, xs, ys); 00172 } else { 00173 #if defined(_MSC_VER) || defined(WIN32) 00174 msgErr << "Unrecognized image file extension, writing Windows Bitmap file." 00175 << sendmsg; 00176 vmd_writebmp(outfile, rgb3u, xs, ys); 00177 #else 00178 msgErr << "Unrecognized image file extension, writing Targa file." 00179 << sendmsg; 00180 vmd_writetga(outfile, rgb3u, xs, ys); 00181 #endif 00182 } 00183 00184 fclose(outfile); 00185 return 0; 00186 } 00187 00188 00189 int write_image_file_rgb4u(const char *filename, 00190 const unsigned char *rgb4u, int xs, int ys) { 00191 unsigned char *rgb3u = cvt_rgb4u_rgb3u(rgb4u, xs, ys); 00192 if (rgb3u == NULL) 00193 return -1; 00194 00195 if (write_image_file_rgb3u(filename, rgb3u, xs, ys)) { 00196 free(rgb3u); 00197 return -1; 00198 } 00199 00200 free(rgb3u); 00201 return 0; 00202 } 00203 00204 00205 int write_image_file_rgb4f(const char *filename, 00206 const float *rgb4f, int xs, int ys) { 00207 unsigned char *rgb3u = cvt_rgb4f_rgb3u(rgb4f, xs, ys); 00208 if (rgb3u == NULL) 00209 return -1; 00210 00211 if (write_image_file_rgb3u(filename, rgb3u, xs, ys)) { 00212 free(rgb3u); 00213 return -1; 00214 } 00215 00216 free(rgb3u); 00217 return 0; 00218 } 00219 00220 00221 int write_image_file_rgba4u(const char *filename, 00222 const unsigned char *rgba4u, int xs, int ys) { 00223 FILE *outfile=NULL; 00224 if ((outfile = fopen(filename, "wb")) == NULL) { 00225 msgErr << "Could not open file " << filename 00226 << " in current directory for writing!" << sendmsg; 00227 return -1; 00228 } 00229 00230 if (checkfileextension(filename, ".png")) { 00231 #if defined(VMDLIBPNG) 00232 vmd_writepng_alpha(outfile, rgba4u, xs, ys); 00233 #else 00234 msgErr << "Unrecognized or unsupported alpha-channel image format." 00235 << sendmsg; 00236 00237 fclose(outfile); 00238 return -1; 00239 #endif 00240 } else { 00241 msgErr << "Unrecognized or unsupported alpha-channel image format." 00242 << sendmsg; 00243 00244 fclose(outfile); 00245 return -1; 00246 } 00247 00248 fclose(outfile); 00249 return 0; 00250 } 00251 00252 00253 int write_image_file_rgba4f(const char *filename, 00254 const float *rgba4f, int xs, int ys) { 00255 unsigned char *rgba4u = cvt_rgba4f_rgba4u(rgba4f, xs, ys); 00256 if (rgba4u == NULL) 00257 return -1; 00258 00259 if (write_image_file_rgba4u(filename, rgba4u, xs, ys)) { 00260 free(rgba4u); 00261 return -1; 00262 } 00263 00264 free(rgba4u); 00265 return 0; 00266 } 00267 00268 00269 void vmd_writergb(FILE *dfile, const unsigned char * img, int xs, int ys) { 00270 char iname[80]; /* Image name */ 00271 int x, y, i; 00272 00273 if (img == NULL) 00274 return; 00275 00276 putshort(dfile, 474); /* Magic */ 00277 putbyte(dfile, 0); /* STORAGE is VERBATIM */ 00278 putbyte(dfile, 1); /* BPC is 1 */ 00279 putshort(dfile, 3); /* DIMENSION is 3 */ 00280 putshort(dfile, xs); /* XSIZE */ 00281 putshort(dfile, ys); /* YSIZE */ 00282 putshort(dfile, 3); /* ZSIZE */ 00283 putint(dfile, 0); /* PIXMIN is 0 */ 00284 putint(dfile, 255); /* PIXMAX is 255 */ 00285 00286 for(i=0; i<4; i++) /* DUMMY 4 bytes */ 00287 putbyte(dfile, 0); 00288 00289 strcpy(iname, "VMD Snapshot"); 00290 fwrite(iname, 80, 1, dfile); /* IMAGENAME */ 00291 putint(dfile, 0); /* COLORMAP is 0 */ 00292 for(i=0; i<404; i++) /* DUMMY 404 bytes */ 00293 putbyte(dfile,0); 00294 00295 for(i=0; i<3; i++) 00296 for(y=0; y<ys; y++) 00297 for(x=0; x<xs; x++) 00298 fwrite(&img[(y*xs + x)*3 + i], 1, 1, dfile); 00299 } 00300 00301 static void write_le_int32(FILE * dfile, int num) { 00302 fputc((num ) & 0xFF, dfile); 00303 fputc((num >> 8 ) & 0xFF, dfile); 00304 fputc((num >> 16) & 0xFF, dfile); 00305 fputc((num >> 24) & 0xFF, dfile); 00306 } 00307 00308 static void write_le_int16(FILE * dfile, int num) { 00309 fputc((num ) & 0xFF, dfile); 00310 fputc((num >> 8 ) & 0xFF, dfile); 00311 } 00312 00313 00314 void vmd_writebmp(FILE *dfile, const unsigned char * img, int xs, int ys) { 00315 if (img != NULL) { 00316 int imgdataoffset = 14 + 40; // file header size + bitmap header size 00317 int rowlen = xs * 3; // non-padded length of row of pixels 00318 int rowsz = ((rowlen) + 3) & -4; // size of one padded row of pixels 00319 int imgdatasize = rowsz * ys; // size of image data 00320 int filesize = imgdataoffset + imgdatasize; 00321 00322 // write out bitmap file header (14 bytes) 00323 fputc('B', dfile); 00324 fputc('M', dfile); 00325 write_le_int32(dfile, filesize); 00326 write_le_int16(dfile, 0); 00327 write_le_int16(dfile, 0); 00328 write_le_int32(dfile, imgdataoffset); 00329 00330 // write out bitmap header (40 bytes) 00331 write_le_int32(dfile, 40); // size of bitmap header structure 00332 write_le_int32(dfile, xs); // size of image in x 00333 write_le_int32(dfile, ys); // size of image in y 00334 write_le_int16(dfile, 1); // number of color planes (only "1" is legal) 00335 write_le_int16(dfile, 24); // bits per pixel 00336 00337 // fields added in Win 3.x 00338 write_le_int32(dfile, 0); // compression used (0 == none) 00339 write_le_int32(dfile, imgdatasize); // size of bitmap in bytes 00340 00341 // imported improvements from the Tachyon BMP writer to address 00342 // the behavior of BMP files loaded for display on Android devices 00343 write_le_int32(dfile, 11811); // X pixels per meter (300dpi) 00344 write_le_int32(dfile, 11811); // Y pixels per meter (300dpi) 00345 write_le_int32(dfile, 0); // color count (0 for RGB) 00346 write_le_int32(dfile, 0); // important colors (0 for RGB) 00347 00348 // write out actual image data 00349 int i, y; 00350 unsigned char * rowbuf = (unsigned char *) malloc(rowsz); 00351 if (rowbuf != NULL) { 00352 memset(rowbuf, 0, rowsz); // clear the buffer (and padding) to black. 00353 00354 for (y=0; y<ys; y++) { 00355 int addr = xs * 3 * y; 00356 00357 // write one row of the image, in reversed RGB -> BGR pixel order 00358 // padding bytes should remain 0's, shouldn't have to re-clear them. 00359 for (i=0; i<rowlen; i+=3) { 00360 rowbuf[i ] = img[addr + i + 2]; // blue 00361 rowbuf[i + 1] = img[addr + i + 1]; // green 00362 rowbuf[i + 2] = img[addr + i ]; // red 00363 } 00364 00365 fwrite(rowbuf, rowsz, 1, dfile); // write the whole row of pixels 00366 } 00367 free(rowbuf); 00368 } else { 00369 msgErr << "Failed to save snapshot image!" << sendmsg; 00370 } 00371 00372 } // img != NULL 00373 } 00374 00375 00376 void vmd_writeppm(FILE *dfile, const unsigned char * img, int xs, int ys) { 00377 if (img != NULL) { 00378 int y; 00379 00380 fprintf(dfile,"%s\n","P6"); 00381 fprintf(dfile,"%d\n", xs); 00382 fprintf(dfile,"%d\n", ys); 00383 fprintf(dfile,"%d\n",255); /* maxval */ 00384 00385 for (y=(ys - 1); y>=0; y--) { 00386 fwrite(&img[xs * 3 * y], 1, (xs * 3), dfile); 00387 } 00388 } 00389 } 00390 00391 00392 void vmd_writetga(FILE *dfile, const unsigned char * img, int xs, int ys) { 00393 int x, y; 00394 00395 const unsigned char * bufpos; 00396 int filepos, numbytes; 00397 unsigned char * fixbuf; 00398 00399 fputc(0, dfile); /* IdLength */ 00400 fputc(0, dfile); /* ColorMapType */ 00401 fputc(2, dfile); /* ImageTypeCode */ 00402 fputc(0, dfile); /* ColorMapOrigin, low byte */ 00403 fputc(0, dfile); /* ColorMapOrigin, high byte */ 00404 fputc(0, dfile); /* ColorMapLength, low byte */ 00405 fputc(0, dfile); /* ColorMapLength, high byte */ 00406 fputc(0, dfile); /* ColorMapEntrySize */ 00407 fputc(0, dfile); /* XOrigin, low byte */ 00408 fputc(0, dfile); /* XOrigin, high byte */ 00409 fputc(0, dfile); /* YOrigin, low byte */ 00410 fputc(0, dfile); /* YOrigin, high byte */ 00411 fputc((xs & 0xff), dfile); /* Width, low byte */ 00412 fputc(((xs >> 8) & 0xff), dfile); /* Width, high byte */ 00413 fputc((ys & 0xff), dfile); /* Height, low byte */ 00414 fputc(((ys >> 8) & 0xff), dfile); /* Height, high byte */ 00415 fputc(24, dfile); /* ImagePixelSize */ 00416 fputc(0x20, dfile); /* ImageDescriptorByte 0x20 == flip vertically */ 00417 00418 fixbuf = (unsigned char *) malloc(xs * 3); 00419 if (fixbuf == NULL) { 00420 msgErr << "vmd_writetga: failed memory allocation!" << sendmsg; 00421 return; 00422 } 00423 00424 for (y=0; y<ys; y++) { 00425 bufpos=img + (xs*3)*(ys-y-1); 00426 filepos=18 + xs*3*y; 00427 00428 if (filepos >= 18) { 00429 fseek(dfile, filepos, 0); 00430 00431 for (x=0; x<(3*xs); x+=3) { 00432 fixbuf[x ] = bufpos[x + 2]; 00433 fixbuf[x + 1] = bufpos[x + 1]; 00434 fixbuf[x + 2] = bufpos[x ]; 00435 } 00436 00437 numbytes = fwrite(fixbuf, 3, xs, dfile); 00438 00439 if (numbytes != xs) { 00440 msgErr << "vmd_writetga: file write problem, " 00441 << numbytes << " bytes written." << sendmsg; 00442 } 00443 } 00444 else { 00445 msgErr << "vmd_writetga: file ptr out of range!!!" << sendmsg; 00446 return; /* don't try to continue */ 00447 } 00448 } 00449 00450 free(fixbuf); 00451 } 00452 00453 #if defined(VMDLIBPNG) 00454 void vmd_writepng(FILE *dfile, const unsigned char * img, int xs, int ys) { 00455 png_structp png_ptr; 00456 png_infop info_ptr; 00457 png_bytep *row_pointers; 00458 png_textp text_ptr; 00459 int y; 00460 00461 /* Create and initialize the png_struct with the default error handlers */ 00462 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 00463 if (png_ptr == NULL) { 00464 msgErr << "Failed to write PNG file" << sendmsg; 00465 return; /* Could not initialize PNG library, return error */ 00466 } 00467 00468 /* Allocate/initialize the memory for image information. REQUIRED. */ 00469 info_ptr = png_create_info_struct(png_ptr); 00470 if (info_ptr == NULL) { 00471 png_destroy_write_struct(&png_ptr, (png_infopp)NULL); 00472 msgErr << "Failed to write PNG file" << sendmsg; 00473 return; /* Could not initialize PNG library, return error */ 00474 } 00475 00476 /* Set error handling for setjmp/longjmp method of libpng error handling */ 00477 if (setjmp(png_jmpbuf(png_ptr))) { 00478 /* Free all of the memory associated with the png_ptr and info_ptr */ 00479 png_destroy_write_struct(&png_ptr, (png_infopp)NULL); 00480 /* If we get here, we had a problem writing the file */ 00481 msgErr << "Failed to write PNG file" << sendmsg; 00482 return; /* Could not open image, return error */ 00483 } 00484 00485 /* Set up the input control if you are using standard C streams */ 00486 png_init_io(png_ptr, dfile); 00487 00488 png_set_IHDR(png_ptr, info_ptr, xs, ys, 00489 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, 00490 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); 00491 00492 png_set_gAMA(png_ptr, info_ptr, 1.0); 00493 00494 text_ptr = (png_textp) png_malloc(png_ptr, (png_uint_32)sizeof(png_text) * 2); 00495 00496 text_ptr[0].key = (char *) "Description"; 00497 text_ptr[0].text = (char *) "A molecular scene rendered by VMD"; 00498 text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE; 00499 #ifdef PNG_iTXt_SUPPORTED 00500 text_ptr[0].lang = NULL; 00501 #endif 00502 00503 text_ptr[1].key = (char *) "Software"; 00504 text_ptr[1].text = (char *) "VMD -- Visual Molecular Dynamics"; 00505 text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE; 00506 #ifdef PNG_iTXt_SUPPORTED 00507 text_ptr[1].lang = NULL; 00508 #endif 00509 png_set_text(png_ptr, info_ptr, text_ptr, 1); 00510 00511 row_pointers = (png_bytep *) png_malloc(png_ptr, ys*sizeof(png_bytep)); 00512 for (y=0; y<ys; y++) { 00513 row_pointers[ys - y - 1] = (png_bytep) &img[y * xs * 3]; 00514 } 00515 00516 png_set_rows(png_ptr, info_ptr, row_pointers); 00517 00518 /* one-shot call to write the whole PNG file into memory */ 00519 png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); 00520 00521 png_free(png_ptr, row_pointers); 00522 png_free(png_ptr, text_ptr); 00523 00524 /* clean up after the write and free any memory allocated - REQUIRED */ 00525 png_destroy_write_struct(&png_ptr, (png_infopp)NULL); 00526 00527 return; /* No fatal errors */ 00528 } 00529 00530 00531 void vmd_writepng_alpha(FILE *dfile, const unsigned char * img, int xs, int ys) { 00532 png_structp png_ptr; 00533 png_infop info_ptr; 00534 png_bytep *row_pointers; 00535 png_textp text_ptr; 00536 int y; 00537 00538 /* Create and initialize the png_struct with the default error handlers */ 00539 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 00540 if (png_ptr == NULL) { 00541 msgErr << "Failed to write PNG file" << sendmsg; 00542 return; /* Could not initialize PNG library, return error */ 00543 } 00544 00545 /* Allocate/initialize the memory for image information. REQUIRED. */ 00546 info_ptr = png_create_info_struct(png_ptr); 00547 if (info_ptr == NULL) { 00548 png_destroy_write_struct(&png_ptr, (png_infopp)NULL); 00549 msgErr << "Failed to write PNG file" << sendmsg; 00550 return; /* Could not initialize PNG library, return error */ 00551 } 00552 00553 /* Set error handling for setjmp/longjmp method of libpng error handling */ 00554 if (setjmp(png_jmpbuf(png_ptr))) { 00555 /* Free all of the memory associated with the png_ptr and info_ptr */ 00556 png_destroy_write_struct(&png_ptr, (png_infopp)NULL); 00557 /* If we get here, we had a problem writing the file */ 00558 msgErr << "Failed to write PNG file" << sendmsg; 00559 return; /* Could not open image, return error */ 00560 } 00561 00562 /* Set up the input control if you are using standard C streams */ 00563 png_init_io(png_ptr, dfile); 00564 00565 png_set_IHDR(png_ptr, info_ptr, xs, ys, 00566 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, 00567 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); 00568 00569 // png_set_alpha_mode(png_ptr, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); 00570 00571 #if 0 00572 /* optional significant bit chunk */ 00573 png_color_8 sig_bit; 00574 memset(&sig_bit, 0, sizeof(sig_bit)); 00575 00576 sig_bit.red = 8; 00577 sig_bit.green = 8; 00578 sig_bit.blue = 8; 00579 sig_bit.alpha = 8; 00580 00581 png_set_sBIT(png_ptr, info_ptr, &sig_bit); 00582 #endif 00583 00584 png_set_gAMA(png_ptr, info_ptr, 1.0); 00585 00586 text_ptr = (png_textp) png_malloc(png_ptr, (png_uint_32)sizeof(png_text) * 2); 00587 00588 text_ptr[0].key = (char *) "Description"; 00589 text_ptr[0].text = (char *) "A molecular scene rendered by VMD"; 00590 text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE; 00591 #ifdef PNG_iTXt_SUPPORTED 00592 text_ptr[0].lang = NULL; 00593 #endif 00594 00595 text_ptr[1].key = (char *) "Software"; 00596 text_ptr[1].text = (char *) "VMD -- Visual Molecular Dynamics"; 00597 text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE; 00598 #ifdef PNG_iTXt_SUPPORTED 00599 text_ptr[1].lang = NULL; 00600 #endif 00601 png_set_text(png_ptr, info_ptr, text_ptr, 1); 00602 00603 // png_write_info(png_ptr, info_ptr); 00604 00605 row_pointers = (png_bytep *) png_malloc(png_ptr, ys*sizeof(png_bytep)); 00606 for (y=0; y<ys; y++) { 00607 row_pointers[ys - y - 1] = (png_bytep) &img[y * xs * 4]; 00608 } 00609 00610 png_set_rows(png_ptr, info_ptr, row_pointers); 00611 00612 /* one-shot call to write the whole PNG file into memory */ 00613 png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); 00614 00615 png_free(png_ptr, row_pointers); 00616 png_free(png_ptr, text_ptr); 00617 00618 /* clean up after the write and free any memory allocated - REQUIRED */ 00619 png_destroy_write_struct(&png_ptr, (png_infopp)NULL); 00620 00621 return; /* No fatal errors */ 00622 } 00623 00624 #endif