home *** CD-ROM | disk | FTP | other *** search
/ Fractal Frenzy 1 / WalnutCreekFractalFrenzy-1.iso / pc / viewers / x11 / xloadimg.tz / xloadimg / img.c < prev    next >
C/C++ Source or Header  |  1991-05-20  |  7KB  |  304 lines

  1. /*
  2. ** img.c - load a GEM Bit Image file for use inside xloadimage
  3. **
  4. **    Tim Northrup <tim@BRS.Com>
  5. **
  6. **    Version 0.1 --  4/25/91 -- Initial cut
  7. **
  8. **  Copyright (C) 1991 Tim Northrup
  9. **    (see file "tgncpyrght.h" for complete copyright information)
  10. */
  11.  
  12. #include <stdio.h>
  13. #include "tgncpyrght.h"
  14. #include "image.h"
  15. #include "img.h"
  16.  
  17. static int Debug = 0;                /* Set to 1 for info */
  18.  
  19. static unsigned char *BitRow;            /* working row of bits */
  20. static int RowRepeat;                /* number of repititons */
  21. static int RowCount;                /* current row */
  22. static int ColCount;                /* current column */
  23.  
  24. static int IMG_ReadHeader();            /* Read file header */
  25. static void IMG_WriteByte();            /* Write output byte */
  26.  
  27. /*
  28. **  imgIdent
  29. **
  30. **    Identify passed file as a GEM Bit Image or not
  31. **
  32. **    Returns 1 if file is a GEM Image, 0 otherwise
  33. */
  34.  
  35. unsigned int imgIdent (fullname,name)
  36.  
  37.     char *fullname, *name;
  38. {
  39.     ZFILE *zf;                /* Input file */
  40.     IMG_Header header;            /* GEM Image header info */
  41.     unsigned int ret = 0;            /* Return value */
  42.  
  43.     if ( ! (zf = zopen(fullname)))
  44.         return(0);
  45.  
  46.     if (IMG_ReadHeader(zf,&header) == 0) {
  47.         printf("%s is a %dx%d GEM Bit Image\n", fullname,
  48.                header.llen, header.lines);
  49.         ret = 1;
  50.           }
  51.  
  52.     zclose(zf);
  53.  
  54.     return(ret);
  55. }
  56.  
  57. /*
  58. **  imgLoad
  59. **
  60. **    Load GEM Image file into an Image structure.
  61. **
  62. **    Returns pointer to allocated struct if successful, NULL otherwise
  63. */
  64.  
  65. Image *imgLoad (fullname,name,verbose)
  66.  
  67.     char *fullname, *name;
  68.     unsigned int verbose;
  69. {
  70.     register int i;                /* Random index */
  71.     ZFILE *zf;                /* Input file */
  72.     short creps;                /* Repetition counter */
  73.     short ictr;                /* Secondary index counter */
  74.     unsigned int bpl;            /* Bytes per scanline */
  75.     Image *image;                /* Allocated image struct */
  76.     IMG_Header header;            /* GEM Image header */
  77.     unsigned char inbuf[MAX_LITERAL], ichr;    /* Input buffer/char */
  78.  
  79.     if ( ! (zf = zopen(fullname)))
  80.         return((Image *)NULL);
  81.  
  82.     if ((i = IMG_ReadHeader(zf,&header)) != 0) {
  83.         zclose(zf);
  84.         switch (i) {
  85.         case 1: /* short read in header */
  86.         case 2: /* not a GEM image */
  87.           break;
  88.         case 3:
  89.           printf("  Color GEM images are not supported (yet)\n");
  90.           break;
  91.         case 4:
  92.           printf("  GEM image is too large\n");
  93.           break;
  94.         default:
  95.           printf("  Unsupported GEM image pattern length\n");
  96.           break;
  97.         }
  98.         return((Image *)NULL);
  99.           }
  100.  
  101.     if (verbose)
  102.         printf("%s is a %dx%d GEM Image\n",name,header.llen,header.lines);
  103.     znocache(zf);
  104.  
  105.     image = newBitImage(header.llen,header.lines);
  106.  
  107.     BitRow = &(image->data[0]);
  108.  
  109.     bpl = header.llen / 8;                /* bytes per line */
  110.     ColCount = 0;                    /* starting column */
  111.     RowCount = 0;                    /* starting row */
  112.     RowRepeat = 1;                    /* default repeat */
  113.  
  114.     while (RowCount < header.lines) {
  115.  
  116.         /* While the last line has not been reached ... */
  117.  
  118.         i = zgetc(zf);
  119.         if (i == EOF) {
  120.             printf("GEM Image Failure: premature EOF\n");
  121.             break;
  122.             }
  123.  
  124.         if (i == BYTE_FLAG) {        /* scanline */
  125.             i = zgetc(zf);
  126.             if (i == EOF) {
  127.                 printf("GEM Image Failure: premature EOF\n");
  128.                 break;
  129.                 }
  130.             if (i == BYTE_SLREPEAT) {    /* repeat scanline */
  131.                 if (ColCount != 0) {
  132.                     printf("GEM Image Failure: corrupted\n");
  133.                     break;
  134.                     }
  135.                 i = zgetc(zf);        /* SLFLAG byte (0xFF) */
  136.                 if (i != BYTE_SLFLAG) {
  137.                     printf("GEM Image Failure: corrupted\n");
  138.                     break;
  139.                     }
  140.                 RowRepeat = zgetc(zf);   /* repeat count */
  141.                 }
  142.             else {            /* repeat pattern_len */
  143.                 creps = i;
  144.                 zread(zf,inbuf,header.patlen);
  145.                 for (i = 0 ; i < creps ; i++)
  146.                     for (ictr = 0 ; ictr < header.patlen ; ictr++)
  147.                     IMG_WriteByte(inbuf[ictr],header.llen,bpl);
  148.                 }
  149.             }
  150.         else if (i == BYTE_LITERAL) {    /* literal follows */
  151.             creps = zgetc(zf);        /* literal length */
  152.             zread(zf,inbuf,creps);        /* literal */
  153.             for (ictr = 0 ; ictr < creps ; ictr++)
  154.                 IMG_WriteByte(inbuf[ictr],header.llen,bpl);
  155.             }
  156.         else {            /* monochrome mode bits */
  157.             creps = RUN_LENGTH(i);
  158.             ichr = (RUN_COLOR(i) == 1) ?
  159.                     BYTE_BLACK : BYTE_WHITE;
  160.             for (i = 0 ; i < creps ; i++)
  161.                 IMG_WriteByte(ichr,header.llen,bpl);
  162.             }
  163.         }
  164.  
  165.     zclose(zf);
  166.  
  167.     image->title = dupString(name);
  168.  
  169.     return(image);
  170. }
  171.  
  172. /*
  173. **  IMG_ReadHeader
  174. **
  175. **    Read in IMG file header information, skip extras.
  176. **
  177. **    Returns 0 if successful
  178. **        1 if not enough file for header record
  179. **        2 if header data is nonsensical/invalid
  180. **        3 if image is color (unsupported)
  181. **        4 if image is too wide ( > 8K bits!!)
  182. **        5 if pattern length is too big ( > 255)
  183. */
  184.  
  185. static int IMG_ReadHeader (zf,h)
  186.  
  187.     ZFILE      *zf;
  188.     IMG_Header *h;
  189. {
  190.     register int tlen;            /* total to read in */
  191.     register int rlen;            /* read lengths */
  192.     unsigned char junkbuffer[MAX_SCANLINE];    /* scrap buffer */
  193.  
  194.     tlen = zread(zf,junkbuffer,(DEF_HLEN * 2));
  195.     if (tlen != (DEF_HLEN * 2))
  196.         return(1);            /* not enough data */
  197.  
  198.     /* convert from big-endian to machine specific */
  199.  
  200.     h->vers   = junkbuffer[1] + (256 * junkbuffer[0]);
  201.     h->hlen   = junkbuffer[3] + (256 * junkbuffer[2]);
  202.     h->colors = junkbuffer[5] + (256 * junkbuffer[4]);
  203.     h->patlen = junkbuffer[7] + (256 * junkbuffer[6]);
  204.     h->pixw   = junkbuffer[9] + (256 * junkbuffer[8]);
  205.     h->pixh   = junkbuffer[11] + (256 * junkbuffer[10]);
  206.     h->llen   = junkbuffer[13] + (256 * junkbuffer[12]);
  207.     h->lines  = junkbuffer[15] + (256 * junkbuffer[14]);
  208.  
  209.     /* sanity check; if fields don't look right, it's probably not a GEM
  210.      * image.
  211.      */
  212.  
  213.     if ((h->vers != DEF_VERSION) ||
  214.         (h->hlen < DEF_HLEN) ||
  215.         (h->colors < 0) || (h->colors > 256) ||
  216.         (h->pixw < 1) ||
  217.         (h->pixh < 1) ||
  218.         (h->llen < 1) || (h->llen > (MAX_SCANLINE * 8)) ||
  219.         (h->lines < 1) || (h->lines > 8192) ||
  220.         (h->patlen < 0) || (h->patlen > MAX_LITERAL))
  221.       return(2);
  222.  
  223.     if (Debug) {
  224.         fprintf(stderr,"Header Information:\n");
  225.         fprintf(stderr,"\tIMG Version:  %d\n",h->vers);
  226.         fprintf(stderr,"\t Header Len:  %d\n",h->hlen);
  227.         fprintf(stderr,"\t     Colors:  %d\n",h->colors);
  228.         fprintf(stderr,"\tPattern Len:  %d\n",h->patlen);
  229.         fprintf(stderr,"\t Pixel Size:  %d x %d (microns=1000th mm)\n",
  230.                 h->pixw,h->pixh);
  231.         fprintf(stderr,"\t Image Size:  %d x %d (pixels)\n",
  232.                 h->llen,h->lines);
  233.         }
  234.  
  235.     /* validity check on particular fields
  236.      */
  237.  
  238.     if (h->colors != 1)
  239.         return(3);
  240.     if (h->llen > (MAX_SCANLINE * 8))
  241.         return(4);
  242.     if (h->patlen > MAX_LITERAL)
  243.         return(5);
  244.  
  245.     /* make life easier if not on an even boundary */
  246.     if (h->llen % 8) {
  247.         h->llen += (8 - (h->llen % 8));
  248.         if (Debug)
  249.             fprintf(stderr,"Image expanded to %d pixels wide\n",
  250.                 h->llen);
  251.         }
  252.  
  253.     /* skip additional header information if present */
  254.     if (h->hlen > DEF_HLEN) {
  255.         tlen = ((h->hlen - DEF_HLEN) * 2);
  256.         if (Debug)
  257.             fprintf(stderr,"%d bytes of extra header skipped",tlen);
  258.         for ( ; tlen > 0 ; tlen -= rlen) {
  259.             rlen = (tlen > MAX_SCANLINE) ? MAX_SCANLINE : tlen;
  260.             zread(zf,junkbuffer,rlen);
  261.             }
  262.         }
  263.  
  264.     return(0);
  265. }
  266.  
  267.  
  268.  
  269. /*
  270. **  IMG_WriteByte
  271. **
  272. **    Add byte to image; if end of scanline, may need to replicate it
  273. **
  274. **    Returns no value (void function)
  275. */
  276.  
  277. static void IMG_WriteByte (c,cols,bpl)
  278.  
  279.     unsigned char c;
  280.     register int cols;
  281.     unsigned int bpl;
  282. {
  283.     register int i;
  284.     register unsigned char *ptr;
  285.     register unsigned char *ptr2;
  286.  
  287.     BitRow[ColCount] = c;
  288.  
  289.     if (++ColCount >= bpl) {            /* end of scanline */
  290.         ptr2 = BitRow + bpl;
  291.         RowCount++;            /* count one already out */
  292.         while (--RowRepeat > 0) {
  293.             for (ptr = BitRow, i = 0 ; i < bpl ; i++, ptr++)
  294.                 *ptr2++ = *ptr;
  295.             RowCount++;
  296.             }
  297.         BitRow = ptr2;
  298.         ColCount = 0;
  299.         RowRepeat = 1;
  300.         }
  301.  
  302.     return;
  303. }
  304.