home *** CD-ROM | disk | FTP | other *** search
- /*
-
- GBMGIF.C Graphics Interchange Format support
-
- Input options: index=# to get a given image in the file
-
- */
-
- /*...sincludes:0:*/
- #include <stdio.h>
- #include <ctype.h>
- #include <stddef.h>
- #include <stdlib.h>
- #include <string.h>
- #include <memory.h>
- #include <malloc.h>
- #ifdef AIX
- #include <unistd.h>
- #else
- #include <io.h>
- #endif
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include "standard.h"
- #include "gbm.h"
-
- /*...vgbm\46\h:0:*/
- /*...e*/
-
- /*...suseful:0:*/
- #define low_byte(w) ((byte) ((w)&0x00ff) )
- #define high_byte(w) ((byte) (((w)&0xff00)>>8))
- #define make_word(a,b) (((word)a) + (((word)b) << 8))
- /*...e*/
- /*...ssame:0:*/
- static BOOLEAN same(char *s1, char *s2, int n)
- {
- for ( ; n--; s1++, s2++ )
- if ( tolower(*s1) != tolower(*s2) )
- return ( FALSE );
- return ( TRUE );
- }
- /*...e*/
- /*...sfind_word:0:*/
- static char *find_word(char *str, char *substr)
- {
- char buf [100+1], *s;
- int len = strlen(substr);
-
- for ( s = strtok(strcpy(buf, str), " \t,");
- s != NULL;
- s = strtok(NULL, " \t,") )
- if ( same(s, substr, len) && s [len] == '\0' )
- return ( str + (s - buf) );
- return ( NULL );
- }
- /*...e*/
- /*...sfind_word_prefix:0:*/
- static char *find_word_prefix(char *str, char *substr)
- {
- char buf [100+1], *s;
- int len = strlen(substr);
-
- for ( s = strtok(strcpy(buf, str), " \t,");
- s != NULL;
- s = strtok(NULL, " \t,") )
- if ( same(s, substr, len) )
- return ( str + (s - buf) );
- return ( NULL );
- }
- /*...e*/
-
- static GBMFT gif_gbmft =
- {
- "GIF",
- "CompuServe Graphics Interchange Format",
- "GIF",
- GBM_FT_R1|GBM_FT_R4|GBM_FT_R8|
- GBM_FT_W1|GBM_FT_W4|GBM_FT_W8,
- };
-
- #define GBM_ERR_GIF_BPP ((GBM_ERR) 1100)
- #define GBM_ERR_GIF_TERM ((GBM_ERR) 1101)
- #define GBM_ERR_GIF_CODE_SIZE ((GBM_ERR) 1102)
- #define GBM_ERR_GIF_CORRUPT ((GBM_ERR) 1103)
-
- typedef struct
- {
- BOOLEAN ilace, errok;
- int bpp;
- byte pal [0x100 * 3];
- } GIF_PRIV;
-
- /*...sgif_qft:0:*/
- GBM_ERR gif_qft(GBMFT *gbmft)
- {
- *gbmft = gif_gbmft;
- return ( GBM_ERR_OK );
- }
- /*...e*/
- /*...sgif_rhdr:0:*/
- GBM_ERR gif_rhdr(char *fn, int fd, GBM *gbm, char *opt)
- {
- GIF_PRIV *gif_priv = (GIF_PRIV *) gbm -> priv;
- byte signiture [6], scn_desc [7], image_desc [10];
- char *index;
- int img = 0, img_want = 1;
- int bits_gct;
-
- fn=fn; /* Suppress 'unref arg' compiler warnings */
-
- /* Discover which image in GIF file we want */
-
- if ( (index = find_word_prefix(opt, "index=")) != NULL )
- sscanf(index + 6, "%d", &img_want);
-
- gif_priv -> errok = ( find_word(opt, "errok") != NULL );
-
- /* Read and validate signiture block */
-
- lseek(fd, 0L, SEEK_SET);
- if ( read(fd, signiture, 6) != 6 )
- return ( GBM_ERR_READ );
- if ( memcmp(signiture, "GIF87a", 6) &&
- memcmp(signiture, "GIF89a", 6) )
- return ( GBM_ERR_BAD_MAGIC );
-
- /* Read screen descriptor */
-
- if ( read(fd, scn_desc, 7) != 7 )
- return ( GBM_ERR_READ );
- gif_priv -> bpp = bits_gct = (scn_desc [4] & 7) + 1;
-
- if ( scn_desc [4] & 0x80 )
- /* Global colour table follows screen descriptor */
- {
- if ( read(fd, gif_priv -> pal, 3 << bits_gct) != (3 << bits_gct) )
- return ( GBM_ERR_READ );
- }
- else
- /* Blank out palette, but make entry 1 white */
- {
- memset(gif_priv -> pal, 0, 3 << bits_gct);
- gif_priv -> pal [3] =
- gif_priv -> pal [4] =
- gif_priv -> pal [5] = 0xff;
- }
-
- /* Expected image descriptors / extension blocks / terminator */
-
- while ( img < img_want )
- {
- if ( read(fd, image_desc, 1) != 1 )
- return ( GBM_ERR_READ );
- switch ( image_desc [0] )
- {
- /*...s0x2c \45\ image descriptor:24:*/
- case 0x2c:
- if ( read(fd, image_desc + 1, 9) != 9 )
- return ( GBM_ERR_READ );
- gbm -> w = make_word(image_desc [5], image_desc [6]);
- gbm -> h = make_word(image_desc [7], image_desc [8]);
- gif_priv -> ilace = ( (image_desc [9] & 0x40) != 0 );
-
- if ( image_desc [9] & 0x80 )
- /* Local colour table follows */
- {
- gif_priv -> bpp = (scn_desc [9] & 7) + 1;
- if ( read(fd, gif_priv -> pal, 3 << gif_priv -> bpp) != (3 << gif_priv -> bpp) )
- return ( GBM_ERR_READ );
- }
-
- if ( ++img != img_want )
- /* Skip the image data */
- {
- byte code_size, block_size;
-
- if ( read(fd, &code_size, 1) != 1 )
- return ( GBM_ERR_READ );
- do
- {
- if ( read(fd, &block_size, 1) != 1 )
- return ( GBM_ERR_READ );
- lseek(fd, block_size, SEEK_SET);
- }
- while ( block_size );
- }
-
- break;
- /*...e*/
- /*...s0x21 \45\ extension block:24:*/
- /* Ignore all extension blocks */
-
- case 0x21:
- {
- byte func_code, byte_count;
-
- if ( read(fd, &func_code, 1) != 1 )
- return ( GBM_ERR_READ );
- do
- {
- if ( read(fd, &byte_count, 1) != 1 )
- return ( GBM_ERR_READ );
- lseek(fd, byte_count, SEEK_CUR);
- }
- while ( byte_count );
- }
- break;
- /*...e*/
- /*...s0x3b \45\ terminator:24:*/
- /* Oi, we were hoping to get an image descriptor! */
-
- case 0x3b:
- return ( GBM_ERR_GIF_TERM );
- /*...e*/
- }
- }
-
- switch ( gif_priv -> bpp )
- {
- case 1: gbm -> bpp = 1; break;
- case 2:
- case 3:
- case 4: gbm -> bpp = 4; break;
- case 5:
- case 6:
- case 7:
- case 8: gbm -> bpp = 8; break;
- default: return ( GBM_ERR_GIF_BPP );
- }
-
- return ( GBM_ERR_OK );
- }
- /*...e*/
- /*...sgif_rpal:0:*/
- GBM_ERR gif_rpal(int fd, GBM *gbm, GBMRGB *gbmrgb)
- {
- GIF_PRIV *gif_priv = (GIF_PRIV *) gbm -> priv;
- byte *pal = gif_priv -> pal;
- int i;
-
- fd=fd; /* Suppress 'unref arg' compiler warning */
-
- memset(gbmrgb, 0x80, (sizeof(GBMRGB) << gbm -> bpp));
-
- for ( i = 0; i < (1 << gif_priv -> bpp); i++ )
- {
- gbmrgb [i].r = *pal++;
- gbmrgb [i].g = *pal++;
- gbmrgb [i].b = *pal++;
- }
-
- return ( GBM_ERR_OK );
- }
- /*...e*/
- /*...sgif_rdata:0:*/
- /*...scword \45\ code word:0:*/
- /*
- For some 32 bit systems, eg: Intel 386 processor, it may be quicker to use
- a 32 bit operation, rather than a 16 bit one. Hence the following :-
- */
-
- #ifdef OS2
- typedef dword cword;
- #else
- typedef word cword;
- #endif
- /*...e*/
-
- /*...sread context:0:*/
- typedef struct
- {
- int fd; /* File descriptor to read */
- int inx, size; /* Index and size in bits */
- byte buf [255+3]; /* Buffer holding bits */
- int code_size; /* Number of bits to return at once */
- cword read_mask; /* 2^code_size-1 */
- } READ_CONTEXT;
-
- static cword read_code(READ_CONTEXT *c)
- {
- int raw_code, byte_inx;
-
- if ( c -> inx + c -> code_size > c -> size )
- /*...snot enough bits in buffer\44\ refill it:16:*/
- /* Not very efficient, but infrequently called */
-
- {
- int bytes_to_lose = (c -> inx >> 3);
- byte bytes;
-
- /* Note biggest code size is 12 bits */
- /* And this can at worst span 3 bytes */
- memcpy(c -> buf, c -> buf + bytes_to_lose, 3);
- (c -> inx) &= 7;
- (c -> size) -= (bytes_to_lose << 3);
- if ( read(c -> fd, &bytes, 1) != 1 )
- return ( 0xffff );
- if ( read(c -> fd, c -> buf + (c -> size >> 3), bytes) != bytes )
- return ( 0xffff );
- (c -> size) += (bytes << 3);
- }
- /*...e*/
-
- byte_inx = (c -> inx >> 3);
- raw_code = c -> buf [byte_inx] + ((c -> buf [byte_inx + 1]) << 8);
- if ( c -> code_size > 8 )
- raw_code += ((c -> buf [byte_inx + 2]) << 16);
- raw_code >>= ((c -> inx) & 7);
- (c -> inx) += (byte) (c -> code_size);
-
- return ( (cword) raw_code & c -> read_mask );
- }
- /*...e*/
- /*...soutput context:0:*/
- typedef struct
- {
- int x, y, w, h, bpp, pass;
- BOOLEAN ilace;
- int stride;
- byte *data, *data_this_line;
- } OUTPUT_CONTEXT;
-
- static void output(byte value, OUTPUT_CONTEXT *o)
- {
- if ( o -> y >= o -> h )
- return;
-
- switch ( o -> bpp )
- {
- case 1:
- if ( (o -> x) & 7 )
- o -> data_this_line [(o -> x) >> 3] |= (value << (7 - ((o -> x) & 7)));
- else
- o -> data_this_line [(o -> x) >> 3] = (value << 7);
- break;
- case 4:
- if ( (o -> x) & 1 )
- o -> data_this_line [(o -> x) >> 1] |= value;
- else
- o -> data_this_line [(o -> x) >> 1] = (value << 4);
- break;
- case 8:
- o -> data_this_line [o -> x] = value;
- break;
- }
-
- if ( ++(o -> x) < o -> w )
- return;
-
- o -> x = 0;
- if ( o -> ilace )
- {
- switch ( o -> pass )
- {
- case 0:
- (o -> y) += 8;
- if ( o -> y >= o -> h )
- {
- (o -> pass)++;
- o -> y = 4;
- }
- break;
- case 1:
- (o -> y) += 8;
- if ( o -> y >= o -> h )
- {
- (o -> pass)++;
- o -> y = 2;
- }
- break;
- case 2:
- (o -> y) += 4;
- if ( o -> y >= o -> h )
- {
- (o -> pass)++;
- o -> y = 1;
- }
- break;
- case 3:
- (o -> y) += 2;
- break;
- }
- o -> data_this_line = o -> data + (o -> h - 1 - o -> y) * o -> stride;
- }
- else
- {
- (o -> y)++;
- o -> data_this_line -= (o -> stride);
- }
- }
- /*...e*/
-
- GBM_ERR gif_rdata(int fd, GBM *gbm, byte *data)
- {
- GIF_PRIV *gif_priv = (GIF_PRIV *) gbm -> priv;
- byte min_code_size; /* As read from the file */
- int init_code_size; /* Initial code size */
- cword max_code; /* 1 << code_size */
- cword clear_code; /* Code to clear table */
- cword eoi_code; /* End of information code */
- cword first_free_code; /* First free code */
- cword free_code; /* Next available free code slot */
- word bit_mask; /* Output pixel mask */
- int i, out_count = 0;
- cword code, cur_code, old_code, in_code, fin_char;
- cword *prefix, *suffix, *outcode;
- READ_CONTEXT c;
- OUTPUT_CONTEXT o;
- BOOLEAN table_full = FALSE; /* To help implement deferred clear */
-
- if ( (prefix = (cword *) malloc(4096 * sizeof(cword))) == NULL )
- return ( GBM_ERR_MEM );
- if ( (suffix = (cword *) malloc(4096 * sizeof(cword))) == NULL )
- {
- free(prefix);
- return ( GBM_ERR_MEM );
- }
- if ( (outcode = (cword *) malloc(4097 * sizeof(cword))) == NULL )
- {
- free(suffix);
- free(prefix);
- return ( GBM_ERR_MEM );
- }
-
- if ( read(fd, &min_code_size, 1) != 1 )
- {
- free(outcode);
- free(suffix);
- free(prefix);
- return ( GBM_ERR_READ );
- }
-
- if ( min_code_size < 2 || min_code_size > 9 )
- {
- free(outcode);
- free(suffix);
- free(prefix);
- return ( GBM_ERR_GIF_CODE_SIZE );
- }
-
- /* Initial read context */
-
- c.inx = 0;
- c.size = 0;
- c.fd = fd;
- c.code_size = min_code_size + 1;
- c.read_mask = (cword) (( 1 << c.code_size ) - 1);
-
- /* Initialise pixel-output context */
-
- o.x = 0;
- o.y = 0;
- o.pass = 0;
- o.w = gbm -> w;
- o.h = gbm -> h;
- o.bpp = gbm -> bpp;
- o.ilace = gif_priv -> ilace;
- o.stride = ( (gbm -> w * gbm -> bpp + 31) / 32 ) * 4;
- o.data = data;
- o.data_this_line = data + (gbm -> h - 1) * o.stride;
-
- bit_mask = (word) ((1 << gif_priv -> bpp) - 1);
-
- /* 2^min_code size accounts for all colours in file */
-
- clear_code = (cword) ( 1 << min_code_size );
- eoi_code = (cword) (clear_code + 1);
- free_code = first_free_code = (cword) (clear_code + 2);
-
- /* 2^(min_code_size+1) includes clear and eoi code and space too */
-
- init_code_size = c.code_size;
- max_code = (cword) ( 1 << c.code_size );
-
- while ( (code = read_code(&c)) != eoi_code && code != 0xffff && o.y < o.h )
- {
- if ( code == clear_code )
- {
- c.code_size = init_code_size;
- max_code = (cword) ( 1 << c.code_size );
- c.read_mask = (cword) (max_code - 1);
- free_code = first_free_code;
- cur_code = old_code = code = read_code(&c);
- if ( code == 0xffff )
- break;
- fin_char = (cur_code & bit_mask);
- output(fin_char, &o);
- table_full = FALSE;
- }
- else
- {
- cur_code = in_code = code;
- if ( cur_code >= free_code )
- {
- cur_code = old_code;
- outcode [out_count++] = fin_char;
- }
- while ( cur_code > bit_mask )
- {
- if ( out_count > 4096 )
- {
- free(outcode);
- free(suffix);
- free(prefix);
- return ( gif_priv -> errok ? GBM_ERR_OK : GBM_ERR_GIF_CORRUPT );
- }
- outcode [out_count++] = suffix [cur_code];
- cur_code = prefix [cur_code];
- }
- fin_char = (cur_code & bit_mask);
- outcode [out_count++] = fin_char;
- for ( i = out_count - 1; i >= 0; i-- )
- output(outcode [i], &o);
- out_count = 0;
-
- /* Update dictionary */
-
- if ( !table_full )
- {
- prefix [free_code] = old_code;
- suffix [free_code] = fin_char;
-
- /* Advance to next free slot */
-
- if ( ++free_code >= max_code )
- {
- if ( c.code_size < 12 )
- {
- c.code_size++;
- max_code <<= 1;
- c.read_mask = (cword) (( 1 << c.code_size ) - 1);
- }
- else
- table_full = TRUE;
- }
- }
- old_code = in_code;
- }
- }
-
- free(outcode);
- free(suffix);
- free(prefix);
-
- if ( code == 0xffff )
- return ( gif_priv -> errok ? GBM_ERR_OK : GBM_ERR_READ );
-
- return ( GBM_ERR_OK );
- }
- /*...e*/
- /*...sgif_w:0:*/
- /*
- We won't write any GIF89a or higher extensions into file.
- Write palette as global colour table, not local.
-
- strings holds code strings in the format
- 2 byte code number
- 1 byte length of string of pixels = N
- N bytes of pixels
- hashcode is calculated from a string of pixels cumulatively.
- hashtable is searched starting at index hashcode for to find the entry.
- hashtable is big enough so that 1/2 of size >= max num of strings.
-
- */
-
- #define INIT_HASH(p) (((p)+3)*301)
-
- /*...swrite context:0:*/
- typedef struct
- {
- int fd; /* Open file descriptor to write to */
- int inx; /* Bit index into buf */
- int code_size; /* Code size in bits */
- byte buf [255+2]; /* Biggest block + overflow space */
- } WRITE_CONTEXT;
-
- static BOOLEAN write_code(int code, WRITE_CONTEXT *w)
- {
- byte *buf = w -> buf + (w -> inx >> 3);
-
- code <<= ((w -> inx) & 7);
- *buf++ |= (byte) code ;
- /*...scomment about IBM C\45\Set\47\2 optmiser bug:8:*/
- /* C-Set/2 with CSD0044 optimiser bug shows itself in following code :-
- LEA EDI,[EDX+01H]
- MOV CL,AL
- SAR CL,08H ; What!
- MOV [EDI],CL
- */
- /*...e*/
- *buf++ = (byte) (code >> 8);
- *buf = (byte) (code >> 16);
-
- (w -> inx) += (w -> code_size);
- if ( w -> inx >= 255 * 8 )
- /* Flush out full buffer */
- {
- byte bytes = 255;
-
- if ( write(w -> fd, &bytes, 1) != 1 )
- return ( FALSE );
- if ( write(w -> fd, w -> buf, 255) != 255 )
- return ( FALSE );
-
- memcpy(w -> buf, w -> buf + 255, 2);
- memset(w -> buf + 2, 0, 255);
- (w -> inx) -= (255 * 8);
- }
-
- return ( TRUE );
- }
-
- static BOOLEAN flush_code(WRITE_CONTEXT *w)
- {
- byte bytes = ((w -> inx + 7) >> 3);
-
- if ( bytes )
- {
- if ( write(w -> fd, &bytes, 1) != 1 )
- return ( FALSE );
- if ( write(w -> fd, w -> buf, bytes) != bytes )
- return ( FALSE );
- }
-
- /* Data block terminator - a block of zero size */
-
- bytes = 0;
- return ( write(w -> fd, &bytes, 1) == 1 );
- }
- /*...e*/
-
- #define MAX_STRING 64 /* Just to prevent huge strings */
- #define MAX_STRINGS 64000 /* Small enough for 16 bit */
- #define MAX_HASH 8193 /* Prime, and much > 4096 */
-
- GBM_ERR gif_w(char *fn, int fd, GBM *gbm, GBMRGB *gbmrgb, byte *data, char *opt)
- {
- int xpos = 0, ypos = 0, xscreen = gbm -> w, yscreen = gbm -> h;
- int inx_background = 0;
- byte scn_desc [7], image_desc [10], term;
- int stride = ((gbm -> w * gbm -> bpp + 31) / 32) * 4;
- WRITE_CONTEXT w;
- int init_code_size, x, y, p;
- word clear_code, eoi_code, lastentry;
- int nextstring, numentries, numrealentries;
- unsigned int hashcode, lenstring;
- byte min_code_size;
- byte string [MAX_STRING-2], *strings, **hashtable, *pdata;
- char *s;
-
- fn=fn; /* Suppress 'unref arg' compiler warnings */
-
- if ( gbm -> bpp != 1 && gbm -> bpp != 4 && gbm -> bpp != 8 )
- return ( GBM_ERR_NOT_SUPP );
-
- if ( (s = find_word_prefix(opt, "xscreen=")) != NULL )
- sscanf(s + 8, "%d", &xscreen);
-
- if ( (s = find_word_prefix(opt, "yscreen=")) != NULL )
- sscanf(s + 8, "%d", &yscreen);
-
- if ( (s = find_word_prefix(opt, "background=")) != NULL )
- sscanf(s + 11, "%d", &inx_background);
-
- if ( (s = find_word_prefix(opt, "xpos=")) != NULL )
- sscanf(s + 5, "%d", &xpos);
-
- if ( (s = find_word_prefix(opt, "ypos=")) != NULL )
- sscanf(s + 5, "%d", &ypos);
-
- /* Write signiture */
-
- if ( write(fd, "GIF87a", 6) != 6 )
- return ( GBM_ERR_WRITE );
-
- /* Write screen descriptor */
-
- scn_desc [0] = low_byte(xscreen);
- scn_desc [1] = high_byte(xscreen);
- scn_desc [2] = low_byte(yscreen);
- scn_desc [3] = high_byte(yscreen);
- scn_desc [4] = (0x80 | ((gbm -> bpp - 1) * 0x11));
- /* Global colour table follows */
- /* Quality bpp == gct bpp == gbm -> bpp */
- scn_desc [5] = (byte) inx_background;
- scn_desc [6] = 0;
- if ( write(fd, scn_desc, 7) != 7 )
- return ( GBM_ERR_WRITE );
-
- /* Write global colour table */
-
- for ( p = 0; p < (1 << gbm -> bpp); p++ )
- {
- byte pal [3];
-
- pal [0] = gbmrgb [p].r;
- pal [1] = gbmrgb [p].g;
- pal [2] = gbmrgb [p].b;
- if ( write(fd, pal, 3) != 3 )
- return ( GBM_ERR_WRITE );
- }
-
- /* Do image descriptor block */
-
- image_desc [0] = (byte) 0x2c;
- image_desc [1] = low_byte(xpos);
- image_desc [2] = high_byte(xpos);
- image_desc [3] = low_byte(ypos);
- image_desc [4] = high_byte(ypos);
- image_desc [5] = low_byte(gbm -> w);
- image_desc [6] = high_byte(gbm -> w);
- image_desc [7] = low_byte(gbm -> h);
- image_desc [8] = high_byte(gbm -> h);
- image_desc [9] = gbm -> bpp - 1;
- /* Non-interlaced, no local colour map, no sorted palette */
- if ( write(fd, image_desc, 10) != 10 )
- return ( GBM_ERR_WRITE );
-
- /* Now LZW encode data */
-
- if ( (strings = (byte *) malloc(MAX_STRINGS)) == NULL )
- return ( GBM_ERR_MEM );
-
- if ( (hashtable = (byte **) malloc(MAX_HASH * sizeof(byte *))) == NULL )
- {
- free(strings);
- return ( GBM_ERR_MEM );
- }
-
- /* Initialise encoder variables */
-
- init_code_size = gbm -> bpp + 1;
- if ( init_code_size == 2 )
- /* Room for col0, col1, cc, eoi, but no others! */
- init_code_size++;
-
- min_code_size = init_code_size - 1;
- if ( write(fd, &min_code_size, 1) != 1 )
- {
- free(hashtable);
- free(strings);
- return ( GBM_ERR_WRITE );
- }
-
- clear_code = ( 1 << min_code_size );
- eoi_code = clear_code + 1;
-
- /* Setup write context */
-
- w.fd = fd;
- w.inx = 0;
- w.code_size = init_code_size;
- memset(w.buf, 0, sizeof(w.buf));
-
- if ( !write_code(clear_code, &w) )
- {
- free(hashtable);
- free(strings);
- return ( GBM_ERR_WRITE );
- }
-
- numentries = 0;
- numrealentries = 0;
- nextstring = 0;
- lenstring = 0;
- for ( hashcode = 0; hashcode < MAX_HASH; hashcode++ )
- hashtable [hashcode] = NULL;
-
- data += ( (gbm -> h - 1) * stride );
- for ( y = gbm -> h - 1; y >= 0; y--, data -= stride )
- for ( x = 0, pdata = data; x < gbm -> w; x++ )
- {
- byte col;
-
- /*...sget col:24:*/
- switch ( gbm -> bpp )
- {
- case 8:
- col = *pdata++;
- break;
- case 4:
- if ( x & 1 )
- col = (*pdata++ & 0x0f);
- else
- col = (*pdata >> 4);
- break;
- default: /* must be 1 */
- if ( (x & 7) == 7 )
- col = (*pdata++ & 0x01);
- else
- col = ((*pdata >> (7-(x&7))) & 0x01);
- break;
- }
- /*...e*/
- /*...slzw encode:24:*/
- string [0] = ++lenstring;
- string [lenstring] = col;
- if ( lenstring == 1 )
- {
- lastentry = col;
- hashcode = INIT_HASH(col);
- }
- else
- {
- unsigned int i, j;
-
- /* Find current string within strings, by generating hash of string,
- and looking in strings for it starting at hashcode */
-
- hashcode *= ( col + lenstring );
- j = (hashcode % MAX_HASH);
- for ( i = 0; i < MAX_HASH; i++ )
- {
- if ( ++j >= MAX_HASH )
- j = 0;
- if ( hashtable [j] == NULL )
- break;
- if ( !memcmp(hashtable [j]+2, string, 1 + lenstring) )
- break;
- }
- if ( hashtable [j] != NULL && 2 + 1 + lenstring < MAX_STRING )
- /* Found in the strings table */
- {
- byte *ptr = hashtable [j];
- lastentry = (word) ptr [0] + ((word) ptr [1] << 8);
- }
- else
- /* Not found, or length too long */
- {
- if ( !write_code(lastentry, &w) )
- {
- free(hashtable);
- free(strings);
- return ( GBM_ERR_WRITE );
- }
- numentries++;
- if ( hashtable [j] == NULL )
- /* Add string */
- {
- word entry = (word) (eoi_code + numentries);
- byte *ptr = strings + nextstring;
- hashtable [j] = ptr;
- ptr [0] = (byte) entry;
- ptr [1] = (byte) (entry >> 8);
- memcpy(ptr + 2, string, 1 + lenstring);
- nextstring += (2 + 1 + lenstring);
- numrealentries++;
- }
- lenstring = string [0] = (byte) 1;
- lastentry = string [1] = (byte) col;
- hashcode = INIT_HASH(col);
-
- if ( eoi_code + numentries == (1 << w.code_size) )
- /* Next code will be written longer */
- w.code_size++;
-
- if ( eoi_code + numentries > 4093 ||
- nextstring + MAX_STRING > MAX_STRINGS )
- /* Reset tables */
- {
- if ( !write_code(lastentry, &w) )
- {
- free(hashtable);
- free(strings);
- return ( GBM_ERR_WRITE );
- }
- if ( !write_code(clear_code, &w) )
- {
- free(hashtable);
- free(strings);
- return ( GBM_ERR_WRITE );
- }
- numentries = 0;
- numrealentries = 0;
- nextstring = 0;
- lenstring = 0;
- w.code_size = init_code_size;
- for ( j = 0; j < MAX_HASH; j++ )
- hashtable [j] = NULL;
- }
- }
- }
- /*...e*/
- }
-
- free(hashtable);
- free(strings);
-
- if ( !write_code(lastentry, &w) )
- return ( GBM_ERR_WRITE );
- if ( !write_code(eoi_code, &w) )
- return ( GBM_ERR_WRITE );
- if ( !flush_code(&w) )
- return ( GBM_ERR_WRITE );
-
- /* Now write terminator */
-
- term = (byte) 0x3b;
- if ( write(fd, &term, 1) != 1 )
- return ( GBM_ERR_WRITE );
-
- return ( GBM_ERR_OK );
- }
- /*...e*/
- /*...sgif_err:0:*/
- char *gif_err(GBM_ERR rc)
- {
- switch ( (int) rc )
- {
- case GBM_ERR_GIF_BPP:
- return ( "bad bits per pixel" );
- case GBM_ERR_GIF_TERM:
- return ( "terminator found before requested image descriptor" );
- case GBM_ERR_GIF_CODE_SIZE:
- return ( "code size not in range 2 to 9" );
- case GBM_ERR_GIF_CORRUPT:
- return ( "encoded data is corrupt" );
- }
- return ( NULL );
- }
- /*...e*/
-