home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / openglso.zip / pic.c < prev    next >
C/C++ Source or Header  |  2000-02-16  |  8KB  |  257 lines

  1. /* ======================================================================== */
  2. /* Include Files */
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include "pic.h"
  6.  
  7. /* ======================================================================== */
  8. /* Memory allocation and other macros */
  9.  
  10. #define PicAlloc()      ((Pic *) malloc((unsigned)(sizeof(Pic))))
  11.  
  12. #define NUMCHANNELS 3   /* 3 channels (RGB) per pixel, no Alpha */
  13. #define CHANNELDEPTH 8  /* 8 bits per colour channel */
  14.  
  15. /* ===========================================================================
  16.  
  17.     Pic* PicOpen(filename, width, height)
  18.  
  19.     Purpose:
  20.         This function opens an image file and writes the
  21.      appropriate header for the given resolution.
  22.  
  23.      The image file is a compressed PNG file, with 8 bits
  24.      for each of red, green and blue.  Only the resolution
  25.      is variable.
  26.  
  27.     Parameters:
  28.         char*  filename (in) : name of image file to open.
  29.         short  width (in)    : number of pixels per scanline.
  30.         short  height (in)   : number of scanlines for image.
  31.  
  32.     Returned:
  33.         Pic*   pngFile       : file pointer for the image file,
  34.                     NULL if an error occured.
  35.  
  36.     Notes:
  37.         Any error conditions are indicated by writing to
  38.      `stderr', in addition to returning the NULL file
  39.      pointer.
  40.  
  41. --------------------------------------------------------------------------- */
  42.  
  43. Pic*
  44. PicOpen(const char *filename, short width, short height)
  45. {
  46.   Pic     *pngFile;    /* structure to hold image info */
  47.   FILE    *fptr;    /* the output file */
  48.   png_structp png_ptr;  /* structure needed by PNG library */
  49.   png_infop info_ptr;   /* structure needed by PNG library */
  50.   
  51.   pngFile = (Pic *) NULL;
  52.   
  53.   if (width <= 0) 
  54.     {
  55.       fprintf(stderr,
  56.           "ERROR: PicOpen() - `%d' is an invalid scanline width.\n",
  57.           width);
  58.       
  59.     } 
  60.   else if (height <= 0) 
  61.     {
  62.       fprintf(stderr,
  63.           "ERROR: PicOpen() - `%d' is an invalid number of scanlines.\n",
  64.           height);
  65.       
  66.     } 
  67.   else if (! (fptr = fopen(filename, "w"))) 
  68.     {
  69.       fprintf(stderr,
  70.           "ERROR: PicOpen() - couldn't open file `%s' for writing.\n",
  71.           filename);
  72.       
  73.     } 
  74.   else if (! (pngFile = PicAlloc())) 
  75.     {
  76.       fprintf(stderr,
  77.           "ERROR: PicOpen() - cannot allocate `Pic' structure.\n");
  78.       fclose(fptr);
  79.     } 
  80.   else if ( !(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 
  81.                         NULL, NULL, NULL)) )
  82.     {
  83.       /* Couldn't allocate PNG data structure */
  84.       fprintf(stderr,
  85.           "ERROR: PicOpen() - cannot allocate `PNG' structure.\n");
  86.       free(pngFile);
  87.       pngFile = NULL;
  88.       fclose(fptr);
  89.     } 
  90.   else if ( !(info_ptr = png_create_info_struct(png_ptr)) )
  91.     {
  92.       /* Couldn't allocate PNG info structure */
  93.       fprintf(stderr,
  94.           "ERROR: PicOpen() - cannot allocate `PNG' info struct.\n");
  95.       png_destroy_write_struct(&png_ptr,
  96.                    (png_infopp)NULL);
  97.       free(pngFile);
  98.       pngFile = NULL;
  99.       fclose(fptr);
  100.     }
  101.   /* setup PNG error handling */
  102.   else if ( setjmp(png_ptr->jmpbuf) )
  103.     {
  104.       fprintf(stderr,
  105.           "ERROR: PicOpen() - cannot setup PNG error handling\n");
  106.       png_destroy_write_struct(&png_ptr, &info_ptr);
  107.       free(pngFile);
  108.       pngFile = NULL;
  109.       fclose(fptr);
  110.     }
  111.   /* allocate a temporary row */
  112.   else if ( !(pngFile->tempLine = (Pic_byte*) 
  113.           malloc((unsigned)(width*height*NUMCHANNELS*sizeof(Pic_byte)))) )
  114.     {
  115.       fprintf(stderr,
  116.           "ERROR: PicOpen() - cannot allocate temp buffer\n");
  117.       png_destroy_write_struct(&png_ptr, &info_ptr);
  118.       free(pngFile);
  119.       pngFile = NULL;
  120.       fclose(fptr);
  121.     }
  122.   else
  123.     {
  124.       /* setup the pngFile structure */
  125.       pngFile->width    = width;
  126.       pngFile->height   = height;
  127.       pngFile->scanline = 0;
  128.       pngFile->fptr     = fptr;
  129.       pngFile->filename = StrAlloc(strlen(filename) + 1);
  130.       (void) strcpy(pngFile->filename, filename);
  131.       pngFile->png_ptr  = png_ptr;
  132.       pngFile->info_ptr = info_ptr;
  133.  
  134.       /* Setup PNG I/O */
  135.       png_init_io(png_ptr, fptr);
  136.      
  137.       /* Optionally setup a callback to indicate when a row has been
  138.        * written. */  
  139.  
  140.       /* Setup filtering. Use Paeth filtering */
  141.       png_set_filter(png_ptr, 0, PNG_FILTER_PAETH);
  142.  
  143.       /* Setup compression level. */
  144.       png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
  145.  
  146.  
  147.       /* Setup PNG header information and write it to the file */
  148.       png_set_IHDR(png_ptr, info_ptr,
  149.            width, height,
  150.            CHANNELDEPTH, 
  151.            PNG_COLOR_TYPE_RGB, 
  152.            PNG_INTERLACE_NONE, 
  153.            PNG_COMPRESSION_TYPE_DEFAULT, 
  154.            PNG_FILTER_TYPE_DEFAULT);
  155.       png_write_info(png_ptr, info_ptr); 
  156.     }
  157.   
  158.     return(pngFile);
  159. }
  160. /* ===========================================================================
  161.                                                              
  162.     boolean    PicWriteLine(pngFile, pixels)             
  163.                                                              
  164.     Purpose:                             
  165.         This function writes the given scanline to the given     
  166.      image file.                         
  167.                                                              
  168.     Parameters:                             
  169.         Pic*   pngFile (in) : name of image file to write.     
  170.         Pixel* pixels(in)   : scanline of rendered pixels.     
  171.                                                              
  172.     Returned:                             
  173.         boolean   status : TRUE - scanline written, else FALSE     
  174.                                                              
  175.     Notes:                             
  176.         The scanline will not be written if the given image     
  177.      file has been completed.                 
  178.  
  179. --------------------------------------------------------------------------- */
  180.  
  181. boolean 
  182. PicWriteLine(Pic* pngFile, Pic_Pixel* pixels)
  183. {
  184.   /* Don't do anything if the file is already complete: */
  185.   if (pngFile->scanline == pngFile->height) {
  186.     fprintf(stderr,
  187.         "WARNING: PicWriteLine() - `%s' is complete, scanline ignored.\n",
  188.         pngFile->filename);
  189.     
  190.     return(FALSE);
  191.   }
  192.   else
  193.     { 
  194.       /* The file isn't complete. Copy the array of "Pixel" structures
  195.        * the temporary line. */
  196.       int i;
  197.       for (i = 0; i < pngFile->width; ++i) {
  198.     pngFile->tempLine[NUMCHANNELS*i]   = pixels[i].r;
  199.     pngFile->tempLine[NUMCHANNELS*i+1] = pixels[i].g;
  200.     pngFile->tempLine[NUMCHANNELS*i+2] = pixels[i].b;
  201.       }
  202.  
  203.       /* Write the current line to the file */
  204.       png_write_row(pngFile->png_ptr, pngFile->tempLine);
  205.       
  206.       /* Increment the current scanline */
  207.       ++pngFile->scanline;
  208.       
  209.       return(TRUE);
  210.     }
  211. }
  212.  
  213. /* ===========================================================================
  214.                                                              
  215.     void     PicClose(pngFile)                 
  216.                                                              
  217.     Purpose:                             
  218.         This function closes an image file.             
  219.                                                              
  220.     Parameters:                             
  221.         Pic*   pngFile (in) : image file to be closed.     
  222.                                                              
  223.     Notes:                             
  224.         A warning will be issued if the image file is         
  225.      incomplete, ie) all scanlines have not yet been         
  226.      written. The file will still be closed, though.
  227.                                                              
  228. --------------------------------------------------------------------------- */
  229. void 
  230. PicClose(Pic* pngFile)
  231. {
  232.  
  233.   /* Check to see if the file is incomplete. */
  234.   if (pngFile->scanline < pngFile->height) {
  235.     fprintf(stderr,
  236.         "WARNING: PicClose() - only %d of %d scanlines "
  237.         "written to `%s'.\n",
  238.         pngFile->scanline,
  239.         pngFile->height,
  240.         pngFile->filename);
  241.     }
  242.   else
  243.     {
  244.       /* Finish off the PNG file and release all allocated memory. */
  245.       png_write_end(pngFile->png_ptr, pngFile->info_ptr);
  246.       png_destroy_write_struct(&pngFile->png_ptr, &pngFile->info_ptr);
  247.       free(pngFile->tempLine);
  248.       free(pngFile->filename);
  249.       
  250.       fclose(pngFile->fptr);
  251.     }
  252. }
  253.  
  254. /* ======================================================================== */
  255.  
  256.  
  257.