home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / fbm / src / flsun.c < prev    next >
C/C++ Source or Header  |  1990-06-24  |  9KB  |  354 lines

  1. /*****************************************************************
  2.  * flsun.c: FBM Release 1.0 25-Feb-90 Michael Mauldin
  3.  *
  4.  * Copyright (C) 1989,1990 by Michael Mauldin.  Permission is granted
  5.  * to use this file in whole or in part for any purpose, educational,
  6.  * recreational or commercial, provided that this copyright notice
  7.  * is retained unchanged.  This software is available to all free of
  8.  * charge by anonymous FTP and in the UUNET archives.
  9.  *
  10.  * flsun.c: 
  11.  *
  12.  * CONTENTS
  13.  *    read_sun (image, rfile, mstr, mlen)
  14.  *    write_sun (image, wfile)
  15.  *
  16.  * EDITLOG
  17.  *    LastEditDate = Mon Jun 25 00:18:04 1990 - Michael Mauldin
  18.  *    LastFileName = /usr2/mlm/src/misc/fbm/flsun.c
  19.  *
  20.  * HISTORY
  21.  * 25-Jun-90  Michael Mauldin (mlm@cs.cmu.edu) Carnegie Mellon
  22.  *    Package for Release 1.0
  23.  *
  24.  * 20-May-89  Michael Mauldin (mlm) at Carnegie Mellon University
  25.  *    Fixed problem with odd length rows on reading
  26.  *
  27.  * 26-Aug-89  Michael Mauldin (mlm) at Carnegie Mellon University
  28.  *    Beta release (version 0.96) mlm@cs.cmu.edu
  29.  *
  30.  * 12-Nov-88  Michael Mauldin (mlm) at Carnegie-Mellon University
  31.  *    Created.
  32.  *****************************************************************/
  33.  
  34. # include <stdio.h>
  35. # include <math.h>
  36. # include <ctype.h>
  37. # include "fbm.h"
  38.  
  39. typedef struct rasterfile {
  40.     long ras_magic;
  41.     long ras_width;
  42.     long ras_height;
  43.     long ras_depth;
  44.     long ras_length;
  45.     long ras_type;
  46.     long ras_maptype;
  47.     long ras_maplength;
  48. } RASHDR;
  49.  
  50. # define RT_STANDARD    1
  51. # define RMT_NONE    0
  52. # define RMT_EQUAL_RGB    1
  53. # define RMT_RAW    2
  54.  
  55. # define RED 0
  56. # define GRN 1
  57. # define BLU 2
  58.  
  59. /****************************************************************
  60.  * write_sun (image, wfile)
  61.  ****************************************************************/
  62.  
  63. #ifndef lint
  64. static char *fbmid =
  65. "$FBM flsun.c <1.0> 25-Jun-90  (C) 1989,1990 by Michael Mauldin, source \
  66. code available free from MLM@CS.CMU.EDU and from UUNET archives$";
  67. #endif
  68.  
  69. write_sun (image, wfile)
  70. FBM *image;
  71. FILE *wfile;
  72. { RASHDR rhdr;
  73.   register int i, j, byte;
  74.   register unsigned char *bmp, *rp, *gp, *bp;
  75.   int width, height, plnlen, clrlen, rowlen, depth, bits;
  76.  
  77.   if (image->hdr.planes != 1 && image->hdr.planes != 3)
  78.   { fprintf (stderr,
  79.          "Error, write_sun can only handle images with depth 1 or 3\n");
  80.     return (0);
  81.   }
  82.  
  83.   if (image->hdr.physbits != 8)
  84.   { fprintf (stderr,
  85.          "Error, write_sun can only handle 8 physical bits per pixel\n");
  86.     return (0);
  87.   }
  88.  
  89.   /* This restriction should be fixed */
  90.   if (image->hdr.bits == 1 && (image->hdr.rowlen % 16) != 0)
  91.   { fprintf (stderr,
  92.     "Error, 1 bit deep files must have rowlen (%d) divisible by 16");
  93.     return (0);
  94.   }
  95.  
  96.   /* Allow for input rowlen to be greater than output rowlen */
  97.   if (image->hdr.bits == 1)
  98.   { bits = 1; }
  99.   else
  100.   { bits = 8; }
  101.  
  102. # ifdef DEBUG
  103.   fprintf (stderr,
  104.        "write_sun: [%dx%d] rowlen %d, planes %d, bits %d, physbits %d, using %d\n",
  105.        image->hdr.cols,
  106.        image->hdr.rows,
  107.        image->hdr.rowlen,
  108.        image->hdr.planes,
  109.        image->hdr.bits,
  110.        image->hdr.physbits,
  111.            bits);
  112. # endif
  113.  
  114.   width = image->hdr.cols;
  115.   height = image->hdr.rows;
  116.   rowlen = image->hdr.rowlen;
  117.   plnlen = image->hdr.plnlen;
  118.   clrlen = image->hdr.clrlen;
  119.   depth = bits * image->hdr.planes;
  120.  
  121.   /* Initialize Sun raster header */
  122.   rhdr.ras_magic = SUN_MAGIC;
  123.   rhdr.ras_width = width;
  124.   rhdr.ras_height = height;
  125.   rhdr.ras_depth = depth;
  126.   rhdr.ras_length = plnlen * bits / 8;
  127.   rhdr.ras_type = RT_STANDARD;
  128.   rhdr.ras_maptype = depth > 8 ? RMT_RAW : clrlen ? RMT_EQUAL_RGB : RMT_NONE;
  129.   rhdr.ras_maplength = clrlen;
  130.  
  131.   /* Write rasterfile header - note: use Sun byte order */
  132.   put_long (rhdr.ras_magic, wfile, BIG);
  133.   put_long (rhdr.ras_width, wfile, BIG);
  134.   put_long (rhdr.ras_height, wfile, BIG);
  135.   put_long (rhdr.ras_depth, wfile, BIG);
  136.   put_long (rhdr.ras_length, wfile, BIG);
  137.   put_long (rhdr.ras_type, wfile, BIG);
  138.   put_long (rhdr.ras_maptype, wfile, BIG);
  139.   put_long (rhdr.ras_maplength, wfile, BIG);
  140.   
  141.   /* Dump colormap if need be */
  142.   if (clrlen > 0)
  143.   { fwrite (image->cm, 1, clrlen, wfile); }
  144.   
  145.   /* Write bytes */
  146.   switch (depth)
  147.   { case 24:    rp = &image->bm[0];
  148.         gp = rp + plnlen;
  149.         bp = gp + plnlen;
  150.  
  151.         for (i=0; i<plnlen; i++)
  152.         { fputc (*rp++, wfile);
  153.           fputc (*gp++, wfile);
  154.           fputc (*bp++, wfile);
  155.         }
  156.         break;
  157.  
  158.     case 8:    fwrite (image->bm, 1, plnlen, wfile);
  159.         break;
  160.  
  161.     case 1:    
  162. # ifdef DEBUG
  163.         fprintf (stderr, "Writing Sun 1bit file [%dx%d] rowlen %d\n",
  164.              width, height, rowlen);
  165. # endif
  166.         for (j=0; j<height; j++)
  167.         { bmp = &(image->bm[j*rowlen]);
  168.           byte = 0;
  169.  
  170.           for (i=0; i<rowlen; i++)
  171.           { byte = (byte << 1) | (*bmp++ ? 0 : 1);
  172.  
  173.             if ((i & 7) == 7)
  174.             { fputc (byte, wfile); byte = 0; }
  175.           }
  176.         }
  177.         break;
  178.  
  179.     default:    fprintf  (stderr,
  180.                   "Error, write_sun given invalid depth %d bits\n",
  181.               depth);
  182.         return (0);
  183.   }
  184.   return (1);
  185. }
  186.  
  187. /****************************************************************
  188.  * read_sun (image, rfile)
  189.  ****************************************************************/
  190.  
  191. read_sun (image, rfile, mstr, mlen)
  192. FBM *image;
  193. FILE *rfile;
  194. char *mstr;
  195. int mlen;
  196. { RASHDR rhdr;
  197.   int width, height, plnlen, rowlen, clrlen, res, depth;
  198.   register int i, j, byte;
  199.   register unsigned char *bmp, *rp, *gp, *bp;
  200.   int m1, m2, m3, m4;
  201.  
  202.   m1 = NEXTMCH(rfile,mstr,mlen) & 0xff;
  203.   m2 = NEXTMCH(rfile,mstr,mlen) & 0xff;
  204.   m3 = NEXTMCH(rfile,mstr,mlen) & 0xff;
  205.   m4 = NEXTMCH(rfile,mstr,mlen) & 0xff;
  206.  
  207.   rhdr.ras_magic = (m1 << 24) | (m2 << 16) | (m3 << 8)| (m4);
  208.  
  209.   /* Write rasterfile header - note: use Sun byte order */
  210.   if (rhdr.ras_magic != SUN_MAGIC)
  211.   { fprintf (stderr, "Error, not a Sun raster file (bad magic %08x)\n",
  212.          rhdr.ras_magic);
  213.     return (0);
  214.   }
  215.  
  216.   rhdr.ras_width = get_long (rfile, BIG);
  217.   rhdr.ras_height = get_long (rfile, BIG);
  218.   rhdr.ras_depth = get_long (rfile, BIG);
  219.   rhdr.ras_length = get_long (rfile, BIG);
  220.   rhdr.ras_type = get_long (rfile, BIG);
  221.   rhdr.ras_maptype = get_long (rfile, BIG);
  222.   rhdr.ras_maplength = get_long (rfile, BIG);
  223.  
  224.   /* Check for nonstandard rasterfile formats */
  225.   if (rhdr.ras_type != RT_STANDARD)
  226.   { fprintf (stderr, "Error: rasterfile is not a Sun RT_STANDARD file\n");
  227.     return (0);
  228.   }
  229.  
  230.   if (rhdr.ras_maplength > 0 && rhdr.ras_maptype != RMT_EQUAL_RGB)
  231.   { fprintf (stderr, "Error: color rasterfile is not RMT_EQUAL_RGB\n");
  232.     return (0);
  233.   }
  234.   
  235.   if (rhdr.ras_maplength == 0 &&
  236.       rhdr.ras_maptype != RMT_NONE &&
  237.       rhdr.ras_maptype != RMT_RAW)
  238.   { fprintf (stderr, "Error: black and white rasterfile is not RMT_NONE\n");
  239.     return (0);
  240.   }
  241.  
  242.   if (rhdr.ras_depth != 24 && rhdr.ras_depth != 8 && rhdr.ras_depth != 1)
  243.   { fprintf (stderr, "Error, bits per pixel (%d) must be 1, 8 or 24\n", 
  244.          rhdr.ras_depth);
  245.     return (0);
  246.   }
  247.  
  248.   /* Initialize and allocate input image */  
  249.   width = rhdr.ras_width;
  250.   height = rhdr.ras_height;
  251.   depth = rhdr.ras_depth;
  252.   clrlen = rhdr.ras_maplength;
  253.  
  254.   if (depth == 1)
  255.   { rowlen = 16 * ((width + 15) / 16);
  256.     plnlen = rowlen * height;
  257.   }
  258.   else
  259.   { rowlen = width;
  260.     if (rowlen & 1) rowlen++;
  261.     
  262.     plnlen = rowlen * height; /* Corrected 4-6-90 Gary W. Sherwin */
  263.   }
  264.  
  265. # ifdef DEBUG
  266.   fprintf (stderr, "Reading Sun raster, [%dx%d], rowlen %d, depth %d, clrlen %d\n",
  267.        width, height, rowlen, depth, clrlen );
  268. # endif
  269.   
  270.   /* Check for consitency between colormap and depth */
  271.   if (depth > 8 && clrlen > 0)
  272.   { fprintf (stderr,
  273.     "Error, input has colormap of length %d, but %d bits per pixel\n",
  274.     clrlen, depth);
  275.     return (0);
  276.   }
  277.  
  278.   /* Initialize image header */
  279.   image->hdr.cols = width;
  280.   image->hdr.rows = height;
  281.   image->hdr.planes = (depth == 24) ? 3 : 1;
  282.   image->hdr.bits = (depth == 24) ? 8 : depth;
  283.   image->hdr.physbits = 8;
  284.   image->hdr.rowlen = rowlen;
  285.   image->hdr.plnlen = plnlen;
  286.   image->hdr.clrlen = clrlen;
  287.   image->hdr.aspect = 1.0;
  288.   image->hdr.title[0] = '\0';
  289.   image->hdr.credits[0] = '\0';
  290.  
  291.   /* Allocate space */
  292.   alloc_fbm (image);
  293.  
  294.   /* Read colormap if need be */
  295.   if (clrlen > 0 && (res = fread (image->cm, 1, clrlen, rfile)) != clrlen) 
  296.   { fprintf (stderr, "Error: couldn't read colormap, read %d of %d bytes\n",
  297.          res, clrlen);
  298.     return (0);
  299.   }
  300.  
  301.   /* Read bytes */
  302.   switch (depth)
  303.   { case 24:    rp = &image->bm[0];
  304.         gp = rp + plnlen;
  305.         bp = gp + plnlen;
  306.  
  307.         for (i=0; i<plnlen && !feof (rfile); i++)
  308.         { *rp++ = fgetc (rfile);
  309.           *gp++ = fgetc (rfile);
  310.           *bp++ = fgetc (rfile);
  311.         }
  312.         
  313.         if (i<plnlen)
  314.         { fprintf (stderr, "Error: %s %d of %d pixels (%d bytes)\n",
  315.                "EOF on bitmap after",
  316.                i, plnlen, plnlen * image->hdr.planes);
  317.           return (0);
  318.         }
  319.         
  320.         break;
  321.  
  322.     case 8:    if ((res = fread (image->bm, 1, plnlen, rfile)) != plnlen)
  323.         { fprintf (stderr,
  324.                "Error: EOF on bitmap after %d of %d bytes\n",
  325.                res, plnlen);
  326.           return (0);
  327.         }
  328.         break;
  329.  
  330.     case 1:    for (j=0; j<height; j++)
  331.         { bmp = &(image->bm[j * rowlen]);
  332.     
  333.           for (i=0; i<rowlen; i++)
  334.           { if ((i&7) == 0)
  335.             { if ((byte = fgetc (rfile)) == EOF)
  336.               { fprintf (stderr,
  337.                  "Error: EOF on bitmap after %d of %d bytes\n",
  338.                  j*rowlen + i, height*rowlen);
  339.             return (0);
  340.               }
  341.             }
  342.         
  343.             *bmp++ = (byte & 0x80) ? BLACK : WHITE;
  344.             byte <<= 1;
  345.           }
  346.         }
  347.         break;
  348.     default:    fprintf (stderr, "Invalid depth %d bits\n", depth);
  349.         return (0);
  350.   }
  351.  
  352.   return (1);
  353. }
  354.