home *** CD-ROM | disk | FTP | other *** search
/ Fractal Frenzy 1 / WalnutCreekFractalFrenzy-1.iso / pc / viewers / x11 / xv221.tz / xv221 / xv-2.21 / xvrle.c < prev    next >
C/C++ Source or Header  |  1992-04-06  |  9KB  |  348 lines

  1. /*
  2.  * xvrle.c - load routine for rle (Utah Raster Toolkit) format pictures
  3.  *
  4.  * LoadRLE(fname, numcols)  -  loads an RLE file
  5.  */
  6.  
  7. /*
  8.  * Copyright 1989, 1990, 1991, 1992 by John Bradley and
  9.  *                       The University of Pennsylvania
  10.  *
  11.  * Permission to use, copy, and distribute for non-commercial purposes,
  12.  * is hereby granted without fee, providing that the above copyright
  13.  * notice appear in all copies and that both the copyright notice and this
  14.  * permission notice appear in supporting documentation.
  15.  *
  16.  * The software may be modified for your own purposes, but modified versions
  17.  * may not be distributed.
  18.  *
  19.  * This software is provided "as is" without any expressed or implied warranty.
  20.  *
  21.  * The author may be contacted via:
  22.  *    US Mail:   John Bradley
  23.  *               GRASP Lab, Room 301C
  24.  *               3401 Walnut St.
  25.  *               Philadelphia, PA  19104
  26.  *
  27.  *    Phone:     (215) 898-8813
  28.  *    EMail:     bradley@cis.upenn.edu
  29.  */
  30.  
  31.  
  32. #include "xv.h"
  33.  
  34.  
  35. /* Definitions needed to parse RLE format */
  36. /*   snarfed from rle_code.h, part of the Utah Raster Toolkit */
  37. #define     LONG_OP             0x40
  38. #define     RSkipLinesOp        1
  39. #define     RSetColorOp         2
  40. #define     RSkipPixelsOp       3
  41. #define     RByteDataOp         5
  42. #define     RRunDataOp          6
  43. #define     REOFOp              7
  44.  
  45. #define     H_CLEARFIRST        0x1   /* clear framebuffer flag */
  46. #define     H_NO_BACKGROUND     0x2   /* if set, no bg color supplied */
  47. #define     H_ALPHA             0x4   /* if set, alpha channel (-1) present */
  48. #define     H_COMMENT           0x8   /* if set, comments present */
  49.  
  50.  
  51. #define GETINT(fp) (c=getc(fp), c1=getc(fp), (c1<<8) + c )
  52.  
  53. static void read_rle();
  54. static int RLEerr();
  55.  
  56.  
  57.  
  58. /*******************************************/
  59. int LoadRLE(fname,nc)
  60.      char *fname;
  61.      int   nc;
  62. /*******************************************/
  63. {
  64.   FILE  *fp;
  65.   int    c, c1, i, j, k;
  66.   byte   bgcol[256];
  67.   byte   maps[3][256];
  68.   int    xpos, ypos, w, h, flags, ncolors, pixelbits, ncmap, cmaplen;
  69.   int    cmtlen;
  70.   byte  *img;
  71.   long filesize;
  72.  
  73.  
  74.   /* open the stream */
  75.   fp=fopen(fname,"r");
  76.   if (!fp) return 1;
  77.   
  78.  
  79.   /* figure out the file size */
  80.   fseek(fp, 0L, 2);
  81.   filesize = ftell(fp);
  82.   fseek(fp, 0L, 0);
  83.  
  84.  
  85.   /* read the magic number */
  86.   c = getc(fp);  c1 = getc(fp);
  87.   if ((c != 0x52) || (c1 != 0xcc))
  88.     return(RLEerr("unrecognized magic number"));
  89.  
  90.   xpos       = GETINT(fp);    /* read rest of header info */
  91.   ypos       = GETINT(fp);
  92.   w          = GETINT(fp);
  93.   h          = GETINT(fp);
  94.   flags      = getc(fp);
  95.   ncolors    = getc(fp);
  96.   pixelbits  = getc(fp);
  97.   ncmap      = getc(fp);
  98.   c          = getc(fp);
  99.   cmaplen = (1L << c);
  100.  
  101.   if (DEBUG) {
  102.     fprintf(stderr,"RLE: %dx%d image at %d,%d\n", w, h, xpos, ypos);
  103.     fprintf(stderr,"flags: 0x%02x  (%s%s%s%s)\n",
  104.         flags, 
  105.         (flags & H_CLEARFIRST)    ? "CLEARFIRST " : "",
  106.         (flags & H_NO_BACKGROUND) ? "NO_BG " : "",
  107.         (flags & H_ALPHA)         ? "ALPHA " : "",
  108.         (flags & H_COMMENT)       ? "COMMENT" : "");
  109.  
  110.     fprintf(stderr, "%d bands, %d pixelbits, %d cmap bands, %d cmap entries\n",
  111.         ncolors, pixelbits, ncmap, cmaplen);
  112.   }  
  113.  
  114.   if (DEBUG) fprintf(stderr, "background value: ");
  115.   for (i=0; i<ncolors; i++) {
  116.     bgcol[i] = getc(fp);
  117.     if (DEBUG) fprintf(stderr, "0x%02x ", bgcol[i]);
  118.   }
  119.   if (DEBUG) fprintf(stderr,"\n");
  120.  
  121.   if ((ncolors % 2) == 0) getc(fp);     /* get on a word boundary */
  122.  
  123.   /* read colormap(s) */
  124.   for (i=0; i<ncmap; i++) {
  125.     for (j = 0; j<cmaplen; j++) {
  126.       k = GETINT(fp);
  127.       if (i<3) maps[i][j] = k>>8;
  128.     }
  129.   }
  130.  
  131.   if (DEBUG) {
  132.     if (ncmap) {
  133.       fprintf(stderr, "Colormap:\n");
  134.       for (i=0; i<cmaplen; i++) {
  135.     fprintf(stderr,"(");
  136.     for (j=0; (j<ncmap && j<3); j++) {
  137.       fprintf(stderr, "%02x ", maps[j][i]);
  138.     }
  139.     fprintf(stderr,")  ");
  140.       }
  141.       fprintf(stderr,"\n\n");
  142.     }
  143.     else fprintf(stderr,"No colormap\n");
  144.   }
  145.  
  146.  
  147.   /* read (skip over, actually) the comments, if any */
  148.   if (flags & H_COMMENT) {
  149.     cmtlen = GETINT(fp);
  150.     if (cmtlen) {
  151.       if (DEBUG) fprintf(stderr,"Comment: (%d bytes) '", cmtlen);
  152.       for (i=0; i<cmtlen; i++) {
  153.     c = getc(fp);
  154.     if (DEBUG) fprintf(stderr,"%c",c);
  155.       }
  156.       if (cmtlen % 2) getc(fp);    /* get on a word boundary */
  157.       if (DEBUG) fprintf(stderr,"'\n\n");
  158.     }
  159.   }
  160.  
  161.  
  162.   if (ferror(fp)) 
  163.     return RLEerr("EOF reached while reading RLE header.\n");
  164.  
  165.  
  166.   /*
  167.    * Acceptable cases:
  168.    *   ncolors = 1, 3, or >3 (extra planes ignored)
  169.    *   pixelbits = 8
  170.    *   ncmap = 0    (interpreted as TrueColor/TrueGray)
  171.    *           1    (TrueColor/TrueGray with a gamma curve)
  172.    *    3 | ncolors (TrueColor with three gamma curves)
  173.    */
  174.  
  175.   if (ncolors == 0 || ncolors == 2) 
  176.     return RLEerr("Unsupported number of channels in RLE file.\n");
  177.  
  178.   if (pixelbits != 8)
  179.     return RLEerr("Only 8-bit pixels supported in RLE files.\n");
  180.  
  181.   if (ncmap==0 || ncmap==1 || (ncmap == 3 && ncolors >=3)) { /* ok */ }
  182.   else return RLEerr("Invalid # of colormap channels in RLE file.\n");
  183.  
  184.   if (w<1 || h<1) 
  185.     return RLEerr("Bogus size in RLE header.\n");
  186.  
  187.  
  188.  
  189.   /* allocate image memory */
  190.   if (ncolors == 1) img = (byte *) calloc(w * h, 1);
  191.                else img = (byte *) calloc(w * h * 3, 1);
  192.   if (!img) return RLEerr("LoadRLE(): Unable to allocate image data.\n");
  193.  
  194.  
  195.   /* set background, if necessary */
  196.   if ((flags & H_CLEARFIRST) && ((~flags) & H_NO_BACKGROUND)) {
  197.     byte *ip;
  198.     if (ncolors == 1) {
  199.       for (i=0, ip=img; i<w*h; i++, ip++) *ip = bgcol[0];
  200.     }
  201.     else {
  202.       for (i=0, ip=img; i<w*h; i++) 
  203.     for (j=0; j<3; j++, ip++) *ip = bgcol[j];
  204.     }
  205.   }
  206.  
  207.  
  208.   read_rle(fp, img, w, h, ncolors, ncmap);
  209.  
  210.  
  211.   /* apply colormap transformation to image */
  212.   if (ncmap) {
  213.     byte *ip;
  214.     int   imagelen, cmask;
  215.     imagelen = (ncolors==1) ? w*h : w*h*3;
  216.     cmask = (cmaplen-1);
  217.  
  218.     if (ncmap == 1) {
  219.       for (i=0, ip=img; i<imagelen; i++, ip++) *ip = maps[0][*ip & cmask];
  220.     }
  221.  
  222.     else if (ncmap == 3) {
  223.       for (i=0, ip=img; i<w*h; i++) {
  224.     *ip = maps[0][*ip & cmask];   ip++;
  225.     *ip = maps[1][*ip & cmask];   ip++;
  226.     *ip = maps[2][*ip & cmask];   ip++;
  227.       }
  228.     }
  229.   }
  230.  
  231.  
  232.   /* finally, convert into XV internal format */
  233.   if (ncolors == 1) {     /* grayscale */
  234.     pic = img;  pWIDE = w;  pHIGH = h;
  235.     SetISTR(ISTR_FORMAT, "Greyscale RLE.  (%ld bytes)", filesize);
  236.     sprintf(formatStr, "%dx%d RLE.",w, h);
  237.     SetDirRButt(F_COLORS, F_GREYSCALE);
  238.  
  239.     for (i=0; i<256; i++) r[i] = g[i] = b[i] = i;  /* gray cmap */
  240.   }
  241.  
  242.   else {                  /* true color */
  243.     SetISTR(ISTR_FORMAT, "Color RLE.  (%ld bytes)", filesize);
  244.     sprintf(formatStr, "%dx%d RLE.",w, h);
  245.     SetDirRButt(F_COLORS, F_FULLCOLOR);
  246.  
  247.     i = Conv24to8(img, w, h, nc);
  248.     free(img);
  249.     return i;
  250.   }
  251.  
  252.   return 0;
  253. }
  254.  
  255.  
  256. /*******************************************/
  257. static void read_rle(fp, img, w, h, ncolors, ncmap)
  258.      FILE *fp;
  259.      byte *img;
  260.      int   w, h, ncolors, ncmap;
  261. {
  262.   int posx, posy, plane, bperpix, i, pixval, skipcalls;
  263.   int opcode, operand, done, c, c1;    
  264.   byte *ip;
  265.  
  266.   posx = posy = plane = done = skipcalls = 0;
  267.   if (ncolors == 1) bperpix = 1;
  268.                else bperpix = 3;
  269.  
  270.  
  271.   while (!done && (opcode=getc(fp)) != EOF) {
  272.     switch (opcode & 0x3f) {
  273.     case RSkipLinesOp:
  274.       if (opcode & LONG_OP) { getc(fp);  operand = GETINT(fp); }
  275.       else operand = getc(fp);
  276.       posx = 0;
  277.       posy += operand;
  278.       skipcalls++;
  279.       if ((skipcalls & 0x7f)==0) WaitCursor();
  280.       break;
  281.  
  282.  
  283.     case RSetColorOp:
  284.       operand = getc(fp);
  285.       plane = operand;
  286.       posx = 0;
  287.       break;
  288.  
  289.  
  290.     case RSkipPixelsOp:
  291.       if (opcode & LONG_OP) { getc(fp);  operand = GETINT(fp); }
  292.       else operand = getc(fp);
  293.       
  294.       posx += operand;
  295.       break;
  296.  
  297.  
  298.     case RByteDataOp:
  299.       if (opcode & LONG_OP) { getc(fp);  operand = GETINT(fp); }
  300.       else operand = getc(fp);
  301.  
  302.       ip = img + ((h-posy-1) * w*bperpix) + posx*bperpix + plane;
  303.       operand++;
  304.  
  305.       for (i=0; i<operand; i++, ip+=bperpix) {
  306.     c = getc(fp);
  307.     if (plane<ncolors && posy<h && (posx+i < w)) *ip = c;
  308.       }
  309.       
  310.       if (operand & 1) getc(fp);  /* word boundary */
  311.       posx += operand;
  312.       break;
  313.  
  314.  
  315.     case RRunDataOp:
  316.       if (opcode & LONG_OP) { getc(fp);  operand = GETINT(fp); }
  317.       else operand = getc(fp);
  318.  
  319.       pixval = getc(fp);  getc(fp);
  320.       operand++;
  321.  
  322.       ip = img + ((h-posy-1) * w*bperpix) + posx*bperpix + plane;
  323.  
  324.       for (i=0; i<operand; i++, ip+=bperpix) {
  325.     if (plane<ncolors && posy<h && (posx+i < w)) *ip = pixval;
  326.       }
  327.       
  328.     /*  if (operand & 1) getc(fp);  /* word boundary */
  329.       posx += operand;
  330.       break;
  331.  
  332.     case REOFOp:
  333.       done = 1;
  334.       break;
  335.     }
  336.   }
  337. }
  338.  
  339.  
  340. /*******************************************/
  341. static int RLEerr(st)
  342. char *st;
  343. {
  344.   SetISTR(ISTR_WARNING,st);
  345.   return 1;
  346. }
  347.  
  348.