Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

ImageIO.C

Go to the documentation of this file.
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

Generated on Fri Mar 29 02:45:20 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002