home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / xloadimg.zip / xloadimage.4.1 / niff.c < prev    next >
C/C++ Source or Header  |  1993-10-28  |  7KB  |  273 lines

  1. /* niff.c:
  2.  *
  3.  * xloadimage native image format.  This is used for loading and dumping
  4.  * xloadimage images.
  5.  *
  6.  * jim frost 10.29.91
  7.  *
  8.  * this is in the public domain.
  9.  */
  10.  
  11. #include "image.h"
  12. #include "niff.h"
  13.  
  14. static void babble(name, header, title)
  15.      struct niff_header *header;
  16.      char *title;
  17. {
  18.   printf("%s is a %dx%d ", name,
  19.      memToVal(header->width, 4),
  20.      memToVal(header->height, 4),
  21.      memToVal(header->depth, 4));
  22.   if (memToVal(header->version, 4) != NIFF_VERSION)
  23.     printf("version %d ", memToVal(header->version, 4));
  24.   printf("NIFF ");
  25.   switch (header->type) {
  26.   case NIFF_BITMAP:
  27.     printf("bitmap image");
  28.     break;
  29.   case NIFF_RGB:
  30.     printf("%d-bit RGB image with %d colors",
  31.        memToVal(header->depth, 4), memToVal(header->cmap_size, 4));
  32.     break;
  33.   case NIFF_TRUE:
  34.     printf("%d-bit true color image", memToVal(header->depth, 4));
  35.     break;
  36.   default:
  37.     printf("image with an unknown type");
  38.   }
  39.   if (title && title[0])
  40.     printf(" entitled \"%s\"", title);
  41.   printf("\n");
  42. }
  43.  
  44. static int readHeader(zf, header, rtitle)
  45.      ZFILE *zf;
  46.      struct niff_header *header;
  47.      char **rtitle;
  48. { unsigned int title_len;
  49.   char *title = NULL;
  50.  
  51.   /* read in header
  52.    */
  53.   if (zread(zf, (byte *)header, sizeof(struct niff_header)) !=
  54.       sizeof(struct niff_header)) {
  55.     zclose(zf);
  56.     return(0);
  57.   }
  58.  
  59.   /* check magic number to see if this is a NIFF image
  60.    */
  61.   if (memToVal(header->magic, 4) != NIFF_MAGIC)
  62.     return(0);
  63.  
  64.   /* read in title if there is one
  65.    */
  66.   title_len= memToVal(header->title_len, 4);
  67.   if (title_len != 0) {
  68.     title= (char *)lmalloc(title_len + 1);
  69.     if (zread(zf, (byte *)title, title_len) != title_len) {
  70.       lfree((byte *)title);
  71.       return(0);
  72.     }
  73.     title[title_len]= '\0';
  74.   }
  75.   if (rtitle)
  76.     *rtitle= title;
  77.   else
  78.     lfree((byte *)title);
  79.   return(1);
  80. }
  81.  
  82. int niffIdent(fullname, name)
  83.      char *fullname, *name;
  84. { ZFILE *zf;
  85.   struct niff_header header;
  86.   char *title;
  87.  
  88.   if (! (zf= zopen(fullname)))
  89.     return(0);
  90.  
  91.   if (!readHeader(zf, &header, &title))
  92.     return(0);
  93.   zclose(zf);
  94.   babble(name, &header, title);
  95.   lfree((byte *)title);
  96.   return(1);
  97. }
  98.  
  99. static int readColormap(zf, image)
  100.      ZFILE *zf;
  101.      Image *image;
  102. { unsigned int a;
  103.   struct niff_cmap cmap;
  104.  
  105.   for (a= 0; a < image->rgb.used; a++) {
  106.     if (zread(zf, (byte *)&cmap, sizeof(struct niff_cmap)) != sizeof(struct niff_cmap)) {
  107.       fprintf(stderr, "niffLoad: short read in colormap!\n");
  108.       return(0);
  109.     }
  110.     image->rgb.red[a]= memToVal(cmap.red, 2);
  111.     image->rgb.green[a]= memToVal(cmap.green, 2);
  112.     image->rgb.blue[a]= memToVal(cmap.blue, 2);
  113.   }
  114.   return(1);
  115. }
  116.  
  117. Image *niffLoad(fullname, name, verbose)
  118.      char *fullname, *name;
  119.      unsigned int verbose;
  120. { ZFILE *zf;
  121.   struct niff_header header;
  122.   char *title;
  123.   unsigned int width, height, depth;
  124.   Image *image;
  125.   unsigned int data_size;
  126.  
  127.   if (! (zf= zopen(fullname)))
  128.     return(NULL);
  129.  
  130.   if (!readHeader(zf, &header, &title)) {
  131.     zclose(zf);
  132.     return(NULL);
  133.   }
  134.   if (verbose)
  135.     babble(name, &header, title);
  136.   znocache(zf);
  137.  
  138.   width= memToVal(header.width, 4);
  139.   height= memToVal(header.height, 4);
  140.   depth= memToVal(header.depth, 4);
  141.   switch (header.type) {
  142.   case NIFF_BITMAP:
  143.     image= newBitImage(width, height);
  144.     if (memToVal(header.cmap_size, 4) != 2)
  145.       fprintf(stderr, "niffLoad: bitmap image has wrong number of colormap entries!\n");
  146.     if (!readColormap(zf, image)) {
  147.       freeImage(image);
  148.       zclose(zf);
  149.       return(NULL);
  150.     }
  151.     data_size= ((image->width / 8) + (image->width % 8 ? 1 : 0)) * image->height;
  152.     break;
  153.   case NIFF_RGB:
  154.     image= newRGBImage(width, height, depth);
  155.     image->rgb.used= memToVal(header.cmap_size, 4);
  156.     if (image->rgb.used > image->rgb.size) {
  157.       fprintf(stderr, "niffLoad: too many colormap entries!\n");
  158.       image->rgb.used= image->rgb.size;
  159.     }
  160.     if (!readColormap(zf, image)) {
  161.       freeImage(image);
  162.       zclose(zf);
  163.       return(NULL);
  164.     }
  165.     data_size= image->width * image->height * image->pixlen;
  166.     break;
  167.   case NIFF_TRUE:
  168.     image= newTrueImage(width, height);
  169.     data_size= image->width * image->height * 3;
  170.   }
  171.   image->title= title;
  172.  
  173.   /* read in image data
  174.    */
  175.  
  176.   if (zread(zf, image->data, data_size) != data_size)
  177.     fprintf(stderr, "Short read on image data\n");
  178.   zclose(zf);
  179.   return(image);
  180. }
  181.  
  182. /* this takes an Image and dumps it into a file in NIFF format.  returns
  183.  * zero if successful.
  184.  */
  185. void niffDump(image, options, filename, verbose)
  186.      Image *image;
  187.      char *options; /* ignored */
  188.      char *filename;
  189.      int verbose;
  190. { FILE *f;
  191.   unsigned int a;
  192.   struct niff_header header;
  193.   struct niff_cmap cmap;
  194.   unsigned int data_size;
  195.  
  196.   if (verbose)
  197.     printf("Dumping NIFF image to %s.\n", filename);
  198.  
  199.   if (!(f= fopen(filename, "w"))) {
  200.     perror(filename);
  201.     return;
  202.   }
  203.  
  204.   valToMem(NIFF_MAGIC, header.magic, 4);
  205.   valToMem(NIFF_VERSION, header.version, 4);
  206.   valToMem(image->width, header.width, 4);
  207.   valToMem(image->height, header.height, 4);
  208.   valToMem(image->depth, header.depth, 4);
  209.   switch (image->type) {
  210.   case IBITMAP:
  211.     header.type= NIFF_BITMAP;
  212.     valToMem(image->rgb.used, header.cmap_size, 4);
  213.     data_size= ((image->width / 8) + (image->width % 8 ? 1 : 0)) * image->height;
  214.     break;
  215.   case IRGB:
  216.     header.type= NIFF_RGB;
  217.     valToMem(image->rgb.used, header.cmap_size, 4);
  218.     data_size= image->width * image->height * image->pixlen;
  219.     break;
  220.   case ITRUE:
  221.     header.type= NIFF_TRUE;
  222.     valToMem(0, header.cmap_size, 4);
  223.     data_size= image->width * image->height * 3;
  224.     break;
  225.   }
  226.   valToMem((image->title ? strlen(image->title) : 0), header.title_len, 4);
  227.  
  228.   /* write header
  229.    */
  230.   if (fwrite(&header, sizeof(struct niff_header), 1, f) != 1) {
  231.     perror(filename);
  232.     unlink(filename);
  233.     return;
  234.   }
  235.  
  236.   /* write title if there is one
  237.    */
  238.   if (image->title && (strlen(image->title) > 0)) {
  239.     if (fwrite(image->title, strlen(image->title), 1, f) != 1) {
  240.       perror(filename);
  241.       unlink(filename);
  242.       return;
  243.     }
  244.   }
  245.  
  246.   /* write cmap if we need one
  247.    */
  248.   switch (image->type) {
  249.   case IBITMAP:
  250.   case IRGB:
  251.     for (a= 0; a < image->rgb.used; a++) {
  252.       valToMem(image->rgb.red[a], cmap.red, 2);
  253.       valToMem(image->rgb.green[a], cmap.green, 2);
  254.       valToMem(image->rgb.blue[a], cmap.blue, 2);
  255.       if (fwrite(&cmap, sizeof(struct niff_cmap), 1, f) != 1) {
  256.     perror(filename);
  257.     unlink(filename);
  258.     return;
  259.       }
  260.     }
  261.   }
  262.  
  263.   /* write image data
  264.    */
  265.  
  266.   if (fwrite(image->data, data_size, 1, f) != 1) {
  267.     perror(filename);
  268.     unlink(filename);
  269.     return;
  270.   }
  271.   return;
  272. }
  273.