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

ImageIO.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2011 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.12 $       $Date: 2012/03/08 22:36:36 $
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 
00033 #if defined(VMDPNG)
00034 #include "png.h" // libpng header file
00035 #endif
00036 
00037 static void putbyte(FILE * outf, unsigned char val) {
00038   unsigned char buf[1];
00039   buf[0] = val;  
00040   fwrite(buf, 1, 1, outf);
00041 }
00042 
00043 static void putshort(FILE * outf, unsigned short val) {
00044   unsigned char buf[2];
00045   buf[0] = val >> 8;  
00046   buf[1] = val & 0xff;  
00047   fwrite(buf, 2, 1, outf);
00048 }
00049 
00050 static void putint(FILE * outf, unsigned int val) {
00051   unsigned char buf[4];
00052   buf[0] = (unsigned char) (val >> 24);  
00053   buf[1] = (unsigned char) (val >> 16);  
00054   buf[2] = (unsigned char) (val >>  8);  
00055   buf[3] = (unsigned char) (val & 0xff);  
00056   fwrite(buf, 4, 1, outf);
00057 }
00058 
00059 void vmd_writergb(FILE *dfile, unsigned char * img, int xs, int ys) {
00060   char iname[80];               /* Image name */
00061   int x, y, i;
00062 
00063   if (img == NULL) 
00064     return;
00065 
00066     putshort(dfile, 474);         /* Magic                       */
00067     putbyte(dfile, 0);            /* STORAGE is VERBATIM         */
00068     putbyte(dfile, 1);            /* BPC is 1                    */
00069     putshort(dfile, 3);           /* DIMENSION is 3              */
00070     putshort(dfile, xs);          /* XSIZE                       */
00071     putshort(dfile, ys);          /* YSIZE                       */
00072     putshort(dfile, 3);           /* ZSIZE                       */
00073     putint(dfile, 0);             /* PIXMIN is 0                 */
00074     putint(dfile, 255);           /* PIXMAX is 255               */
00075 
00076     for(i=0; i<4; i++)            /* DUMMY 4 bytes               */
00077       putbyte(dfile, 0);
00078 
00079     strcpy(iname, "VMD Snapshot");
00080     fwrite(iname, 80, 1, dfile);  /* IMAGENAME                   */
00081     putint(dfile, 0);             /* COLORMAP is 0               */
00082     for(i=0; i<404; i++)          /* DUMMY 404 bytes             */
00083       putbyte(dfile,0);
00084 
00085     for(i=0; i<3; i++)
00086       for(y=0; y<ys; y++)
00087         for(x=0; x<xs; x++)
00088           fwrite(&img[(y*xs + x)*3 + i], 1, 1, dfile);
00089 
00090 }
00091 
00092 static void write_le_int32(FILE * dfile, int num) {
00093   fputc((num      ) & 0xFF, dfile);
00094   fputc((num >> 8 ) & 0xFF, dfile);
00095   fputc((num >> 16) & 0xFF, dfile);
00096   fputc((num >> 24) & 0xFF, dfile);
00097 }
00098 
00099 static void write_le_int16(FILE * dfile, int num) {
00100   fputc((num      ) & 0xFF, dfile);
00101   fputc((num >> 8 ) & 0xFF, dfile);
00102 }
00103 
00104 
00105 void vmd_writebmp(FILE *dfile, unsigned char * img, int xs, int ys) {
00106   if (img != NULL) {
00107       int imgdataoffset = 14 + 40;     // file header size + bitmap header size
00108       int rowsz = ((xs * 3) + 3) & -4; // size of one padded row of pixels
00109       int imgdatasize = rowsz * ys;    // size of image data
00110       int filesize = imgdataoffset + imgdatasize;
00111 
00112       // write out bitmap file header (14 bytes)
00113       fputc('B', dfile); 
00114       fputc('M', dfile);
00115       write_le_int32(dfile, filesize);
00116       write_le_int16(dfile, 0);
00117       write_le_int16(dfile, 0);
00118       write_le_int32(dfile, imgdataoffset);
00119 
00120       // write out bitmap header (40 bytes)
00121       write_le_int32(dfile, 40); // size of bitmap header structure
00122       write_le_int32(dfile, xs); // size of image in x
00123       write_le_int32(dfile, ys); // size of image in y
00124       write_le_int16(dfile, 1);  // number of color planes (only "1" is legal)
00125       write_le_int16(dfile, 24); // bits per pixel
00126 
00127       // fields added in Win 3.x
00128       write_le_int32(dfile, 0);           // compression used (0 == none)
00129       write_le_int32(dfile, imgdatasize); // size of bitmap in bytes 
00130 #if 1
00131       // imported improvements from the Tachyon BMP writer to address 
00132       // the behavior of BMP files loaded for display on Android devices
00133       write_le_int32(dfile, 11811);       // X pixels per meter (300dpi)
00134       write_le_int32(dfile, 11811);       // Y pixels per meter (300dpi)
00135       write_le_int32(dfile, 0);           // color count (0 for RGB)
00136       write_le_int32(dfile, 0);           // important colors (0 for RGB)
00137 #else
00138       write_le_int32(dfile, 1000);        // horizontal pixels per meter
00139       write_le_int32(dfile, 1000);        // vertical pixels per meter
00140       write_le_int32(dfile, 1 << 24);     // number of colors in the image    
00141       write_le_int32(dfile, 0);           // minimum number of important colors
00142 #endif
00143        
00144       // write out actual image data
00145       int i, y;
00146       unsigned char * rowbuf = (unsigned char *) malloc(rowsz);
00147       if (rowbuf != NULL) { 
00148         memset(rowbuf, 0, rowsz); // clear the buffer (and padding) to black.
00149 
00150         for (y=0; y<ys; y++) {
00151           int addr = xs * 3 * y;
00152 
00153           // write one row of the image, in reversed RGB -> BGR pixel order
00154           // padding bytes should remain 0's, shouldn't have to re-clear them.
00155           for (i=0; i<rowsz; i+=3) {
00156             rowbuf[i    ] = img[addr + i + 2]; // blue
00157             rowbuf[i + 1] = img[addr + i + 1]; // green
00158             rowbuf[i + 2] = img[addr + i    ]; // red 
00159           }
00160 
00161           fwrite(rowbuf, rowsz, 1, dfile); // write the whole row of pixels 
00162         }
00163         free(rowbuf); 
00164       } else {
00165         msgErr << "Failed to save snapshot image!" << sendmsg;
00166       }
00167 
00168   }  // img != NULL
00169 }
00170 
00171 
00172 void vmd_writeppm(FILE *dfile, unsigned char * img, int xs, int ys) {
00173   if (img != NULL) {
00174     int y;
00175 
00176     fprintf(dfile,"%s\n","P6");
00177     fprintf(dfile,"%d\n", xs);
00178     fprintf(dfile,"%d\n", ys);
00179     fprintf(dfile,"%d\n",255); /* maxval */
00180   
00181     for (y=(ys - 1); y>=0; y--) {
00182       fwrite(&img[xs * 3 * y], 1, (xs * 3), dfile);
00183     }
00184   }
00185 }
00186 
00187 
00188 void vmd_writetga(FILE *dfile, unsigned char * img, int xs, int ys) {
00189   int x, y;
00190 
00191   unsigned char * bufpos;
00192   int filepos, numbytes;
00193   unsigned char * fixbuf;
00194 
00195   fputc(0, dfile); /* IdLength      */
00196   fputc(0, dfile); /* ColorMapType  */
00197   fputc(2, dfile); /* ImageTypeCode */
00198   fputc(0, dfile); /* ColorMapOrigin, low byte */
00199   fputc(0, dfile); /* ColorMapOrigin, high byte */
00200   fputc(0, dfile); /* ColorMapLength, low byte */
00201   fputc(0, dfile); /* ColorMapLength, high byte */
00202   fputc(0, dfile); /* ColorMapEntrySize */
00203   fputc(0, dfile); /* XOrigin, low byte */
00204   fputc(0, dfile); /* XOrigin, high byte */
00205   fputc(0, dfile); /* YOrigin, low byte */
00206   fputc(0, dfile); /* YOrigin, high byte */
00207   fputc((xs & 0xff),         dfile); /* Width, low byte */
00208   fputc(((xs >> 8) & 0xff),  dfile); /* Width, high byte */
00209   fputc((ys & 0xff),         dfile); /* Height, low byte */
00210   fputc(((ys >> 8) & 0xff),  dfile); /* Height, high byte */
00211   fputc(24, dfile);   /* ImagePixelSize */
00212   fputc(0x20, dfile); /* ImageDescriptorByte 0x20 == flip vertically */
00213 
00214   fixbuf = (unsigned char *) malloc(xs * 3);
00215   if (fixbuf == NULL) {
00216     msgErr << "vmd_writetga: failed memory allocation!" << sendmsg;
00217     return;
00218   }
00219 
00220   for (y=0; y<ys; y++) {
00221     bufpos=img + (xs*3)*(ys-y-1);
00222     filepos=18 + xs*3*y;
00223 
00224     if (filepos >= 18) {
00225       fseek(dfile, filepos, 0);
00226 
00227       for (x=0; x<(3*xs); x+=3) {
00228         fixbuf[x    ] = bufpos[x + 2];
00229         fixbuf[x + 1] = bufpos[x + 1];
00230         fixbuf[x + 2] = bufpos[x    ];
00231       }
00232 
00233       numbytes = fwrite(fixbuf, 3, xs, dfile);
00234 
00235       if (numbytes != xs) {
00236         msgErr << "vmd_writetga: file write problem, " 
00237                << numbytes << " bytes written." << sendmsg;
00238       }
00239     }
00240     else {
00241       msgErr << "vmd_writetga: file ptr out of range!!!" << sendmsg;
00242       return;  /* don't try to continue */
00243     }
00244   }
00245 
00246   free(fixbuf);
00247 }
00248 
00249 #if defined(VMDPNG)
00250 void vmd_writepng(FILE *dfile, unsigned char * img, int xs, int ys) {
00251   png_structp png_ptr;
00252   png_infop info_ptr;
00253   png_bytep *row_pointers;
00254   png_textp text_ptr;
00255   int y;
00256 
00257   /* Create and initialize the png_struct with the default error handlers */
00258   png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00259   if (png_ptr == NULL) {
00260     msgErr << "Failed to write PNG file" << sendmsg;
00261     return; /* Could not initialize PNG library, return error */
00262   }
00263 
00264   /* Allocate/initialize the memory for image information.  REQUIRED. */
00265   info_ptr = png_create_info_struct(png_ptr);
00266   if (info_ptr == NULL) {
00267     png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
00268     msgErr << "Failed to write PNG file" << sendmsg;
00269     return; /* Could not initialize PNG library, return error */
00270   }
00271 
00272   /* Set error handling for setjmp/longjmp method of libpng error handling */
00273   if (setjmp(png_jmpbuf(png_ptr))) {
00274     /* Free all of the memory associated with the png_ptr and info_ptr */
00275     png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
00276     /* If we get here, we had a problem writing the file */
00277     msgErr << "Failed to write PNG file" << sendmsg;
00278     return; /* Could not open image, return error */
00279   }
00280 
00281   /* Set up the input control if you are using standard C streams */
00282   png_init_io(png_ptr, dfile);
00283 
00284   png_set_IHDR(png_ptr, info_ptr, xs, ys,
00285                8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
00286                PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
00287 
00288   png_set_gAMA(png_ptr, info_ptr, 1.0);
00289 
00290   text_ptr = (png_textp) png_malloc(png_ptr, (png_uint_32)sizeof(png_text) * 2);
00291 
00292   text_ptr[0].key = "Description";
00293   text_ptr[0].text = "A molecular scene rendered by VMD";
00294   text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
00295 #ifdef PNG_iTXt_SUPPORTED
00296   text_ptr[0].lang = NULL;
00297 #endif
00298 
00299   text_ptr[1].key = "Software";
00300   text_ptr[1].text = "VMD -- Visual Molecular Dynamics";
00301   text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
00302 #ifdef PNG_iTXt_SUPPORTED
00303   text_ptr[1].lang = NULL;
00304 #endif
00305   png_set_text(png_ptr, info_ptr, text_ptr, 1);
00306 
00307   row_pointers = (png_bytep *) png_malloc(png_ptr, ys*sizeof(png_bytep));
00308   for (y=0; y<ys; y++) {
00309     row_pointers[ys - y - 1] = &img[y * xs * 3];
00310   }
00311 
00312   png_set_rows(png_ptr, info_ptr, row_pointers);
00313 
00314   /* one-shot call to write the whole PNG file into memory */
00315   png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
00316 
00317   png_free(png_ptr, row_pointers);
00318   png_free(png_ptr, text_ptr);
00319 
00320   /* clean up after the write and free any memory allocated - REQUIRED */
00321   png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
00322 
00323   return; /* No fatal errors */
00324 }
00325 #endif

Generated on Sat May 26 01:48:02 2012 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002