earlybrowserreborn - Rev 1

Subversion Repositories:
Rev:
/*
** img.c - load a GEM Bit Image file for use inside xloadimage
**
**      Tim Northrup <tim@BRS.Com>
**
**      Version 0.1 --  4/25/91 -- Initial cut
**
**  Copyright (C) 1991 Tim Northrup
**      (see file "tgncpyrght.h" for complete copyright information)
*/


#include <stdio.h>
#include "tgncpyrght.h"
#include "image.h"
#include "img.h"

static int Debug = 0;                           /* Set to 1 for info */

static unsigned char *BitRow;                   /* working row of bits */
static int RowRepeat;                           /* number of repititons */
static int RowCount;                            /* current row */
static int ColCount;                            /* current column */

static int IMG_ReadHeader();                    /* Read file header */
static void IMG_WriteByte();                    /* Write output byte */

/*
**  imgIdent
**
**      Identify passed file as a GEM Bit Image or not
**
**      Returns 1 if file is a GEM Image, 0 otherwise
*/


unsigned int imgIdent (fullname,name)

    char *fullname, *name;
{
        ZFILE *zf;                              /* Input file */
        IMG_Header header;                      /* GEM Image header info */
        unsigned int ret = 0;                   /* Return value */

        if ( ! (zf = zopen(fullname)))
                return(0);

        if (IMG_ReadHeader(zf,&header) == 0) {
                printf("%s is a %dx%d GEM Bit Image\n", fullname,
                       header.llen, header.lines);
                ret = 1;
              }

        zclose(zf);

        return(ret);
}

/*
**  imgLoad
**
**      Load GEM Image file into an Image structure.
**
**      Returns pointer to allocated struct if successful, NULL otherwise
*/


Image *imgLoad (fullname,name,verbose)

    char *fullname, *name;
    unsigned int verbose;
{
        register int i;                         /* Random index */
        ZFILE *zf;                              /* Input file */
        short creps;                            /* Repetition counter */
        short ictr;                             /* Secondary index counter */
        unsigned int bpl;                       /* Bytes per scanline */
        Image *image;                           /* Allocated image struct */
        IMG_Header header;                      /* GEM Image header */
        unsigned char inbuf[MAX_LITERAL], ichr; /* Input buffer/char */

        if ( ! (zf = zopen(fullname)))
                return((Image *)NULL);

        if ((i = IMG_ReadHeader(zf,&header)) != 0) {
                zclose(zf);
                switch (i) {
                case 1: /* short read in header */
                case 2: /* not a GEM image */
                  break;
                case 3:
                  printf("  Color GEM images are not supported (yet)\n");
                  break;
                case 4:
                  printf("  GEM image is too large\n");
                  break;
                default:
                  printf("  Unsupported GEM image pattern length\n");
                  break;
                }
                return((Image *)NULL);
              }

        if (verbose)
            printf("%s is a %dx%d GEM Image\n",name,header.llen,header.lines);
        znocache(zf);

        image = newBitImage(header.llen,header.lines);

        BitRow = &(image->data[0]);

        bpl = header.llen / 8;                          /* bytes per line */
        ColCount = 0;                                   /* starting column */
        RowCount = 0;                                   /* starting row */
        RowRepeat = 1;                                  /* default repeat */

        while (RowCount < header.lines) {

                /* While the last line has not been reached ... */

                i = zgetc(zf);
                if (i == EOF) {
                        printf("GEM Image Failure: premature EOF\n");
                        break;
                        }

                if (i == BYTE_FLAG) {           /* scanline */
                        i = zgetc(zf);
                        if (i == EOF) {
                                printf("GEM Image Failure: premature EOF\n");
                                break;
                                }
                        if (i == BYTE_SLREPEAT) {       /* repeat scanline */
                                if (ColCount != 0) {
                                    printf("GEM Image Failure: corrupted\n");
                                    break;
                                    }
                                i = zgetc(zf);          /* SLFLAG byte (0xFF) */
                                if (i != BYTE_SLFLAG) {
                                    printf("GEM Image Failure: corrupted\n");
                                    break;
                                    }
                                RowRepeat = zgetc(zf);   /* repeat count */
                                }
                        else {                  /* repeat pattern_len */
                                creps = i;
                                zread(zf,inbuf,header.patlen);
                                for (i = 0 ; i < creps ; i++)
                                    for (ictr = 0 ; ictr < header.patlen ; ictr++)
                                        IMG_WriteByte(inbuf[ictr],header.llen,bpl);
                                }
                        }
                else if (i == BYTE_LITERAL) {   /* literal follows */
                        creps = zgetc(zf);              /* literal length */
                        zread(zf,inbuf,creps);          /* literal */
                        for (ictr = 0 ; ictr < creps ; ictr++)
                                IMG_WriteByte(inbuf[ictr],header.llen,bpl);
                        }
                else {                  /* monochrome mode bits */
                        creps = RUN_LENGTH(i);
                        ichr = (RUN_COLOR(i) == 1) ?
                                        BYTE_BLACK : BYTE_WHITE;
                        for (i = 0 ; i < creps ; i++)
                                IMG_WriteByte(ichr,header.llen,bpl);
                        }
                }

        zclose(zf);

        image->title = dupString(name);

        return(image);
}

/*
**  IMG_ReadHeader
**
**      Read in IMG file header information, skip extras.
**
**      Returns 0 if successful
**              1 if not enough file for header record
**              2 if header data is nonsensical/invalid
**              3 if image is color (unsupported)
**              4 if image is too wide ( > 8K bits!!)
**              5 if pattern length is too big ( > 255)
*/


static int IMG_ReadHeader (zf,h)

    ZFILE      *zf;
    IMG_Header *h;
{
        register int tlen;                      /* total to read in */
        register int rlen;                      /* read lengths */
        unsigned char junkbuffer[MAX_SCANLINE]; /* scrap buffer */

        tlen = zread(zf,junkbuffer,(DEF_HLEN * 2));
        if (tlen != (DEF_HLEN * 2))
                return(1);                      /* not enough data */

        /* convert from big-endian to machine specific */

        h->vers   = junkbuffer[1] + (256 * junkbuffer[0]);
        h->hlen   = junkbuffer[3] + (256 * junkbuffer[2]);
        h->colors = junkbuffer[5] + (256 * junkbuffer[4]);
        h->patlen = junkbuffer[7] + (256 * junkbuffer[6]);
        h->pixw   = junkbuffer[9] + (256 * junkbuffer[8]);
        h->pixh   = junkbuffer[11] + (256 * junkbuffer[10]);
        h->llen   = junkbuffer[13] + (256 * junkbuffer[12]);
        h->lines  = junkbuffer[15] + (256 * junkbuffer[14]);

        /* sanity check; if fields don't look right, it's probably not a GEM
         * image.
         */


        if ((h->vers != DEF_VERSION) ||
            (h->hlen < DEF_HLEN) ||
            (h->colors < 0) || (h->colors > 256) ||
            (h->pixw < 1) ||
            (h->pixh < 1) ||
            (h->llen < 1) || (h->llen > (MAX_SCANLINE * 8)) ||
            (h->lines < 1) || (h->lines > 8192) ||
            (h->patlen < 0) || (h->patlen > MAX_LITERAL))
          return(2);

        if (Debug) {
                fprintf(stderr,"Header Information:\n");
                fprintf(stderr,"\tIMG Version:  %d\n",h->vers);
                fprintf(stderr,"\t Header Len:  %d\n",h->hlen);
                fprintf(stderr,"\t     Colors:  %d\n",h->colors);
                fprintf(stderr,"\tPattern Len:  %d\n",h->patlen);
                fprintf(stderr,"\t Pixel Size:  %d x %d (microns=1000th mm)\n",
                                h->pixw,h->pixh);
                fprintf(stderr,"\t Image Size:  %d x %d (pixels)\n",
                                h->llen,h->lines);
                }

        /* validity check on particular fields
         */


        if (h->colors != 1)
                return(3);
        if (h->llen > (MAX_SCANLINE * 8))
                return(4);
        if (h->patlen > MAX_LITERAL)
                return(5);

        /* make life easier if not on an even boundary */
        if (h->llen % 8) {
                h->llen += (8 - (h->llen % 8));
                if (Debug)
                        fprintf(stderr,"Image expanded to %d pixels wide\n",
                                h->llen);
                }

        /* skip additional header information if present */
        if (h->hlen > DEF_HLEN) {
                tlen = ((h->hlen - DEF_HLEN) * 2);
                if (Debug)
                        fprintf(stderr,"%d bytes of extra header skipped",tlen);
                for ( ; tlen > 0 ; tlen -= rlen) {
                        rlen = (tlen > MAX_SCANLINE) ? MAX_SCANLINE : tlen;
                        zread(zf,junkbuffer,rlen);
                        }
                }

        return(0);
}



/*
**  IMG_WriteByte
**
**      Add byte to image; if end of scanline, may need to replicate it
**
**      Returns no value (void function)
*/


static void IMG_WriteByte (c,cols,bpl)

    unsigned char c;
    register int cols;
    unsigned int bpl;
{
        register int i;
        register unsigned char *ptr;
        register unsigned char *ptr2;

        BitRow[ColCount] = c;

        if (++ColCount >= bpl) {                        /* end of scanline */
                ptr2 = BitRow + bpl;
                RowCount++;                     /* count one already out */
                while (--RowRepeat > 0) {
                        for (ptr = BitRow, i = 0 ; i < bpl ; i++, ptr++)
                                *ptr2++ = *ptr;
                        RowCount++;
                        }
                BitRow = ptr2;
                ColCount = 0;
                RowRepeat = 1;
                }

        return;
}