home *** CD-ROM | disk | FTP | other *** search
/ Fractal Frenzy 1 / WalnutCreekFractalFrenzy-1.iso / pc / viewers / x11 / xv221.tz / xv221 / xv-2.21 / xvsunras.c < prev    next >
C/C++ Source or Header  |  1992-01-16  |  11KB  |  457 lines

  1. /*
  2.  * xvsunras.c - load routine for 'sun rasterfile' format pictures
  3.  *
  4.  * LoadSunRas(fname, numcols)  -  loads a PM pic, does 24to8 code if nec.
  5.  * WriteSunRas(fp, pic, w, h, r,g,b, numcols, style)
  6.  * WriteRaw(fp, pic, w, h, r,g,b, numcols, style)
  7.  *
  8.  * This file written by Dave Heath (heath@cs.jhu.edu)
  9.  * fixBGR() added by Ken Rossman (ken@shibuya.cc.columbia.edu)
  10.  */
  11.  
  12.  
  13. #include "xv.h"
  14. #include "sunras.h"
  15.  
  16. static int  SunRasError();
  17. static int  rle_read();
  18. static void flipl();
  19. static void SunRas1to8();
  20. static void SunRas8to1();
  21. static int  write_sun_long();
  22. static void fixBGR();
  23.  
  24.  
  25. /*******************************************/
  26. int LoadSunRas(fname,nc)
  27.      char *fname;
  28.      int   nc;
  29. /*******************************************/
  30. {
  31.   FILE    *fp;
  32.   int     linesize,lsize,csize,isize,flipit,i,w,h,d,rv;
  33.   byte     *image, *line;
  34.   struct rasterfile sunheader;
  35.  
  36.   rv = 0;
  37.  
  38.   /* read in the Sun Rasterfile picture */
  39.   fp=fopen(fname,"r");
  40.   if (!fp) return( SunRasError("unable to open file") );
  41.  
  42.   flipit = 0;
  43.   fread(&sunheader,sizeof(struct rasterfile),1,fp);
  44.   if (sunheader.ras_magic != RAS_MAGIC)
  45.   {
  46.     flipl( (byte *) &sunheader.ras_magic);
  47.     if (sunheader.ras_magic == RAS_MAGIC) flipit = 1;
  48.     else flipl( (byte *) &sunheader.ras_magic);
  49.   }
  50.   if (sunheader.ras_magic != RAS_MAGIC) 
  51.     return( SunRasError("not a Sun rasterfile") );
  52.  
  53.   if (flipit) {
  54.     flipl((byte *) &sunheader.ras_width);
  55.     flipl((byte *) &sunheader.ras_height);
  56.     flipl((byte *) &sunheader.ras_depth);
  57.     flipl((byte *) &sunheader.ras_length);
  58.     flipl((byte *) &sunheader.ras_type);
  59.     flipl((byte *) &sunheader.ras_maptype);
  60.     flipl((byte *) &sunheader.ras_maplength);
  61.     }
  62.  
  63.   /* make sure that the input picture can be dealt with */
  64.   if (sunheader.ras_depth != 1 &&
  65.       sunheader.ras_depth != 8 &&
  66.       sunheader.ras_depth != 24 &&
  67.       sunheader.ras_depth != 32) {
  68.     fprintf (stderr, "Sun rasterfile image has depth %d\n", 
  69.          sunheader.ras_depth);
  70.     fprintf (stderr, "Depths supported are 1, 8, 24, and 32\n");
  71.     return 1;
  72.   }
  73.  
  74.   if (sunheader.ras_type != RT_OLD &&
  75.       sunheader.ras_type != RT_STANDARD &&
  76.       sunheader.ras_type != RT_BYTE_ENCODED &&
  77.       sunheader.ras_type != RT_FORMAT_RGB) {
  78.     fprintf (stderr, "Sun rasterfile of unsupported type %d\n",
  79.          sunheader.ras_type);
  80.     return 1;
  81.   }
  82.  
  83.   if (sunheader.ras_maptype != RMT_RAW &&
  84.       sunheader.ras_maptype != RMT_NONE &&
  85.       sunheader.ras_maptype != RMT_EQUAL_RGB) {
  86.     fprintf (stderr, "Sun rasterfile colormap of unsupported type %d\n",
  87.          sunheader.ras_maptype);
  88.     return 1;
  89.   }
  90.  
  91.   w = sunheader.ras_width;
  92.   h = sunheader.ras_height;
  93.   d = sunheader.ras_depth;
  94.   isize = sunheader.ras_length ?
  95.       sunheader.ras_length :
  96.       (w * h * d) / 8;
  97.   csize = (sunheader.ras_maptype == RMT_NONE) ? 0 : sunheader.ras_maplength;
  98.  
  99.   /* compute length of the output (xv-format) image */
  100.   lsize = w * h;     
  101.   if (d == 24 || d == 32) lsize = lsize * 3;
  102.  
  103.   linesize = w * d;
  104.   /* if ((linesize % 48) && d == 24) linesize += (48 - (linesize % 48)); */
  105.   if (linesize % 16) linesize += (16 - (linesize % 16));
  106.   linesize /= 8;
  107.  
  108.   if (DEBUG)
  109.   {
  110.     fprintf(stderr,"%s: LoadSunRas() - loading a %dx%d pic, %d planes\n",
  111.         cmd, w, h,
  112.         d);
  113.     fprintf (stderr, 
  114.        "type %d, maptype %d, isize %d, csize %d, lsize %d, linesize %d\n",
  115.          sunheader.ras_type, sunheader.ras_maptype,
  116.          isize, csize, lsize, linesize);
  117.   }
  118.  
  119.  
  120.   SetDirRButt(F_FORMAT, F_SUNRAS);
  121.   if (d==1) SetDirRButt(F_COLORS, F_BWDITHER);
  122.        else SetDirRButt(F_COLORS, F_FULLCOLOR);
  123.  
  124.   SetISTR(ISTR_FORMAT,"Sun %s rasterfile.  (%d plane%s)  (%d bytes)",
  125.       sunheader.ras_type == RT_BYTE_ENCODED ? "rle" : "standard",
  126.       d,
  127.       d == 1 ? "" : "s",
  128.       sizeof (struct rasterfile) + csize + isize);
  129.  
  130.   sprintf(formatStr, "%dx%d Sun Rasterfile.",w,h);
  131.  
  132.   /* read in the colormap, if any */
  133.   if (sunheader.ras_maptype == RMT_EQUAL_RGB && csize)
  134.   {
  135.     fread (r, sizeof (byte), sunheader.ras_maplength/3, fp);
  136.     fread (g, sizeof (byte), sunheader.ras_maplength/3, fp);
  137.     fread (b, sizeof (byte), sunheader.ras_maplength/3, fp);
  138.  
  139.    /* for (i = 0; i < sunheader.ras_maplength/3; i++)
  140.     {
  141.       r[i] = getc (fp);
  142.       g[i] = getc (fp);
  143.       b[i] = getc (fp);
  144.     } */
  145.   }
  146.   else if (sunheader.ras_maptype == RMT_RAW && csize)
  147.   {
  148.     /* we don't know how to handle raw colormap, ignore */
  149.     fseek (fp, (long) csize, 1);
  150.   }
  151.  
  152.   else {  /* no colormap, make one up */
  153.     if (sunheader.ras_depth == 1) {
  154.       r[0] = g[0] = b[0] = 0;
  155.       r[1] = g[1] = b[1] = 255;
  156.     }
  157.  
  158.     else if (sunheader.ras_depth == 8) {
  159.       for (i = 0; i < 256; i++)
  160.     r[i] = g[i]  = b[i] = i;
  161.     }
  162.   }
  163.  
  164.  
  165.   /* allocate memory for picture and read it in */
  166.   /* note we may slightly overallocate here (if image is padded) */
  167.   image = (byte *) malloc (lsize);
  168.   line = (byte *) malloc (linesize);
  169.   if (image == NULL || line == NULL)
  170.     FatalError("Can't allocate memory for image\n");
  171.  
  172.   for (i = 0; i < h; i++) {
  173.     if ((i&0x1f) == 0) WaitCursor();
  174.     if (sunheader.ras_type == RT_BYTE_ENCODED) {
  175.       if (rle_read (line, 1, linesize, fp, (i==0)) != linesize) break;
  176.     /* return (SunRasError ("rle file read error")); */
  177.     }
  178.  
  179.     else {
  180.       if (fread (line, 1, linesize, fp) != linesize)
  181.     return (SunRasError ("file read error"));
  182.     }
  183.  
  184.     switch (d) {
  185.     case 1:  SunRas1to8 (image + w * i, line, w);    break;
  186.     case 8:  memcpy (image + w * i, line, w);        break;
  187.     case 24: memcpy (image + w * i * 3, line, w * 3); break;
  188.     case 32: {
  189.                int k;
  190.                byte *ip, *op;
  191.            ip = line;
  192.            op = (byte *) (image + w * i * 3);
  193.            for (k = 0; k<w; k++) {
  194.          *ip++;           /* skip 'alpha' */
  195.          *op++ = *ip++;   /* red   */
  196.          *op++ = *ip++;   /* green */
  197.          *op++ = *ip++;   /* blue  */
  198.            }
  199.          }
  200.     }
  201.   }
  202.  
  203.   if (fp != stdin) fclose (fp);
  204.   if (DEBUG) fprintf(stderr,"Sun ras: image loaded!\n");
  205.  
  206.   if (d == 24 || d == 32) {
  207.     if (sunheader.ras_type != RT_FORMAT_RGB) fixBGR(image,w,h);
  208.     rv = Conv24to8 (image, w, h, nc);
  209.     free (image);
  210.     return (rv);
  211.   }
  212.  
  213.   else {
  214.     pic = image;
  215.     pWIDE = w;
  216.     pHIGH = h;
  217.     return (0);
  218.   }
  219. }
  220.  
  221.  
  222. /*****************************/
  223. static int rle_read (ptr, size, nitems, fp, init)
  224. byte *ptr;
  225. int size, nitems,init;
  226. FILE *fp;
  227. {
  228.   static int count, ch;
  229.   int readbytes, c, read;
  230.  
  231.   if (init) { count = ch = 0; }
  232.  
  233.   readbytes = size * nitems;
  234.   for (read = 0; read < readbytes; read++) {
  235.     if (count) {
  236.       *ptr++ = (byte) ch;
  237.       count--;
  238.     }
  239.  
  240.     else {
  241.       c = getc(fp);
  242.       if (c == EOF) break;
  243.  
  244.       if (c == RAS_RLE) {   /* 0x80 */
  245.     count = getc(fp);
  246.     if (count == EOF) break;
  247.  
  248.     if (count < 0) count &= 0xff;
  249.     if (count == 0) *ptr++ = c;
  250.         else {
  251.           if ((ch = getc(fp)) == EOF) break;
  252.           *ptr++ = ch;
  253.         }
  254.       }
  255.       else *ptr++ = c;
  256.     }
  257.   }
  258.  
  259.   return (read/size);
  260. }
  261.  
  262.  
  263. /*****************************/
  264. static int SunRasError(st)
  265. char *st;
  266. {
  267.   SetISTR(ISTR_WARNING,"LoadSunRas() - %s",st);
  268.   Warning();
  269.   return -1;
  270. }
  271.  
  272.  
  273. /*****************************/
  274. static void flipl(p)
  275.      byte *p;
  276. {
  277.   byte t;
  278.   t = p[0];  p[0]=p[3];  p[3] = t;
  279.   t = p[1];  p[1]=p[2];  p[2] = t;
  280. }
  281.  
  282.  
  283. static void SunRas1to8 (dest, src, len)
  284. byte *dest, *src;
  285. int len;
  286. {
  287.   int i, b;
  288.   int c;
  289.  
  290.   for (i = 0, b = -1; i < len; i++) {
  291.     if (b < 0) {
  292.       b = 7;
  293.       c = ~*src++;
  294.     }
  295.     *dest++ = ((c >> (b--)) & 1);
  296.   }
  297. }
  298.  
  299.  
  300.  
  301. static void SunRas8to1 (dest, src, len)
  302. byte *dest, *src;
  303. int len;
  304. {
  305.   int i, b;
  306.   int c;
  307.  
  308.   for (c = b = i = 0; i < len; i++) {
  309.     c <<= 1;
  310.     c |= (*src++ ? 0 : 1);
  311.     if (b++ == 7) {
  312.       *dest++ = c;
  313.       b = c = 0;
  314.     }
  315.   }
  316.   if (b) *dest = c;
  317. }
  318.  
  319.  
  320.  
  321.  
  322. /*******************************************/
  323. int WriteSunRas(fp,pic,w,h,rmap,gmap,bmap,numcols,colorstyle,userle)
  324. FILE *fp;
  325. byte *pic;
  326. int   w,h;
  327. byte *rmap, *gmap, *bmap;
  328. int   numcols, colorstyle, userle;
  329. {
  330.   /* writes a sun rasterfile to the already open stream
  331.      writes either 8-bit or 1-bit (never 24)
  332.      currently will not write rle files
  333.  
  334.      biggest problem w/ rle file: should we compute
  335.      image size first (nicer) or go back and write it
  336.      in when we are done (kludgy)?
  337.    */
  338.  
  339.   struct rasterfile sunheader;
  340.   int linesize, i, color, d, y;
  341.   byte *line;
  342.  
  343.   if (colorstyle != 2 && numcols > 2) d = 8;
  344.   else d = 1;
  345.  
  346.   linesize = w;
  347.   if (d == 1) {
  348.     if (linesize % 8) linesize += (8 - linesize % 8);
  349.     linesize /= 8;
  350.   }
  351.  
  352.   if (linesize % 2) linesize++;
  353.   line = (byte *) malloc (linesize);
  354.   if (!line) {
  355.     SetISTR(ISTR_WARNING, "Can't allocate memory for save!\n");
  356.     return (1);
  357.   }
  358.  
  359.   if (DEBUG)
  360.     fprintf (stderr,
  361.          "WriteSunRas: d %d, linesize %d numcols %d\n",
  362.          d, linesize, numcols);
  363.  
  364.   /* set up the header */
  365.   sunheader.ras_magic      = RAS_MAGIC;
  366.   sunheader.ras_width      = w;
  367.   sunheader.ras_height      = h;
  368.   sunheader.ras_depth      = d;
  369.   sunheader.ras_length      = linesize * h;
  370.   sunheader.ras_type      = RT_STANDARD;
  371.   sunheader.ras_maptype   = (d == 1) ? RMT_NONE : RMT_EQUAL_RGB;
  372.   sunheader.ras_maplength = (d == 1) ? 0 : 3 * numcols;
  373.  
  374.   write_sun_long (sunheader.ras_magic     , fp);
  375.   write_sun_long (sunheader.ras_width     , fp);
  376.   write_sun_long (sunheader.ras_height     , fp);
  377.   write_sun_long (sunheader.ras_depth     , fp);
  378.   write_sun_long (sunheader.ras_length     , fp);
  379.   write_sun_long (sunheader.ras_type     , fp);
  380.   write_sun_long (sunheader.ras_maptype  , fp);
  381.   write_sun_long (sunheader.ras_maplength, fp);
  382.  
  383.   /* write the colormap */
  384.   if (d > 1)
  385.     if (colorstyle == 1)  /* grayscale */
  386.       for (color = 0; color < 3; color++)
  387.     for (i = 0; i < numcols; i++)
  388.       putc (MONO(rmap[i],gmap[i],bmap[i]), fp);
  389.     else {
  390.       fwrite (rmap, sizeof (byte), numcols, fp);
  391.       fwrite (gmap, sizeof (byte), numcols, fp);
  392.       fwrite (bmap, sizeof (byte), numcols, fp);
  393.     }
  394.  
  395.   /* write the image */
  396.   line[linesize-1] = 0;
  397.   for (y = 0; y < h; y++) {
  398.     if ((y&0x1f) == 0) WaitCursor();
  399.  
  400.     if (d > 1)
  401.       memcpy (line, pic + y * w, w);
  402.     else
  403.       SunRas8to1 (line, pic + y * w, w);
  404.  
  405.     if (fwrite (line, sizeof (byte), linesize, fp) != linesize) {
  406.       SetISTR(ISTR_WARNING, "Write failed during save!\n");
  407.       free (line);
  408.       return (2);
  409.     }
  410.   }
  411.  
  412.   free (line);
  413.   return (0);
  414. }
  415.  
  416.  
  417. /* write a long word in sun byte-order
  418.    returns 0 for success, EOF for failure
  419.  */
  420. static int write_sun_long (l, fp)
  421. long l;
  422. FILE *fp;
  423. {
  424.     char c;
  425.  
  426.     c = ((l >> 24) & 0xff);
  427.     if (putc (c, fp) == EOF) return (EOF);
  428.     c = ((l >> 16) & 0xff);
  429.     if (putc (c, fp) == EOF) return (EOF);
  430.     c = ((l >> 8) & 0xff);
  431.     if (putc (c, fp) == EOF) return (EOF);
  432.     c = (l & 0xff);
  433.     if (putc (c, fp) == EOF) return (EOF);
  434.     return (0);
  435. }
  436.  
  437.  
  438.  
  439.  
  440. /* kr3 - fix up BGR order SUN 24-bit rasters to be RGB order */
  441. static void fixBGR(img,w,h)
  442. unsigned char *img;
  443. int w,h;
  444. {
  445.   int i,npixels;
  446.   unsigned char tmp;
  447.  
  448.   npixels = w*h;
  449.   for (i=0; i<npixels; i++) {
  450.     tmp = img[0];                   /* swap red and blue channels */
  451.     img[0] = img[2];
  452.     img[2] = tmp;
  453.     img += 3;                       /* bump to next pixel */
  454.   }
  455. }
  456.  
  457.