#ifdef XPMENABLED /* xpmtoppm.c - read an X11 pixmap file and produce a portable pixmap ** ** Copyright (C) 1991 by Jef Poskanzer. ** ** Permission to use, copy, modify, and distribute this software and its ** documentation for any purpose and without fee is hereby granted, provided ** that the above copyright notice appear in all copies and that both that ** copyright notice and this permission notice appear in supporting ** documentation. This software is provided "as is" without express or ** implied warranty. ** ** Upgraded to support XPM version 3 by ** Arnaud Le Hors (lehors@mirsa.inria.fr) ** Tue Apr 9 1991 ** ** Rainer Sinkwitz sinkwitz@ifi.unizh.ch - 21 Nov 91: ** - Bug fix, no advance of read ptr, would not read ** colors like "ac c black" because it would find ** the "c" of "ac" and then had problems with "c" ** as color. ** ** - Now understands multword X11 color names ** ** - Now reads multiple color keys. Takes the color ** of the hightest available key. Lines no longer need ** to begin with key 'c'. ** ** - expanded line buffer to from 500 to 2048 for bigger files */ #include "xgprintgif.h" #include #include #include // Defined macros {{{ #define BITS 12 #define HSIZE 5003 /* 80% occupancy */ #define TRUE 1 #define FALSE 0 #define NKEYS 5 #define MAXCOLORS 256 #define MAX_LINE 2048 #define HASH_SIZE 20023 #define ppm_hashpixel(p) ((((long) PPM_GETR(p) * 33023 + (long) PPM_GETG(p) * 30013 + (long) PPM_GETB(p) * 27011) & 0x7fffffff) % HASH_SIZE) #define ARGVAL() (*++(*argv) || (--argc && *++argv)) #ifdef COMPATIBLE /* But wrong! */ # define MAXCODE(n_bits) ((code_int) 1 << (n_bits) - 1) #else /*COMPATIBLE*/ # define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1) #endif /*COMPATIBLE*/ #define HashTabOf(i) htab[i] #define CodeTabOf(i) codetab[i] #define tab_prefixof(i) CodeTabOf(i) #define tab_suffixof(i) ((char_type*)(htab))[i] #define de_stack ((char_type*)&tab_suffixof((code_int)1<next; free(chl); } free(cht); } } // }}} // Function colorhash_table ppm_alloccolorhash(void) {{{ colorhash_table ppm_alloccolorhash(void) { colorhash_table cht; int i; cht = (colorhash_table) my_malloc(HASH_SIZE * sizeof(colorhist_list)); for (i = 0; i < HASH_SIZE; ++i) cht[i] = (colorhist_list) 0; return cht; } // }}} // Function colorhash_table ppm_computecolorhash(pix, cols, rows, maxcol, colP){{{ colorhash_table ppm_computecolorhash( pixel** pixels, int cols, int rows, int maxcolors, int* colorsP) { colorhash_table cht = NULL; register pixel* pP; colorhist_list chl; int col, row, hash; cht = ppm_alloccolorhash(); *colorsP = 0; /* Go through the entire image, building a hash table of colors. */ for (row = 0; row < rows; ++row) for (col = 0, pP = pixels[row]; col < cols; ++col, ++pP) { hash = ppm_hashpixel(*pP); for (chl = cht[hash]; chl != (colorhist_list) 0; chl = chl->next) if (PPM_EQUAL(chl->ch.color, *pP)) break; if (chl != (colorhist_list) 0) ++(chl->ch.value); else { if (++(*colorsP) > maxcolors) { ppm_freecolorhash(cht); return (colorhash_table) 0; } chl = (colorhist_list) my_malloc(sizeof(struct colorhist_list_item)); chl->ch.color = *pP; chl->ch.value = 1; chl->next = cht[hash]; cht[hash] = chl; } } return cht; } // }}} // Function int ppm_lookupcolor(colorhash_table cht, pixel* colorP) {{{ int ppm_lookupcolor(colorhash_table cht, pixel* colorP) { int hash; colorhist_list chl; hash = ppm_hashpixel(*colorP); for (chl = cht[hash]; chl != (colorhist_list) 0; chl = chl->next) if (PPM_EQUAL(chl->ch.color, *colorP)) return chl->ch.value; return -1; } // }}} // Function colorhash_table ppm_colorhisttocolorhash(chv, colors) {{{ colorhash_table ppm_colorhisttocolorhash(colorhist_vector chv, int colors) { colorhash_table cht; int i, hash; pixel color; colorhist_list chl; cht = ppm_alloccolorhash(); for (i = 0; i < colors; ++i) { color = chv[i].color; hash = ppm_hashpixel(color); chl = (colorhist_list) my_malloc(sizeof(struct colorhist_list_item)); chl->ch.color = color; chl->ch.value = i; chl->next = cht[hash]; cht[hash] = chl; } return cht; } // }}} // Function colorhist_vector ppm_colorhashtocolorhist(cht, maxcol) {{{ colorhist_vector ppm_colorhashtocolorhist(colorhash_table cht, int maxcolors) { colorhist_vector chv; colorhist_list chl; int i, j; /* Now collate the hash table into a simple colorhist array. */ chv = (colorhist_vector) my_malloc(maxcolors * sizeof(struct colorhist_item)); /* Loop through the hash table. */ j = 0; for (i = 0; i < HASH_SIZE; ++i) for (chl = cht[i]; chl != (colorhist_list) 0; chl = chl->next) { /* Add the new entry. */ chv[j] = chl->ch; ++j; } /* All done. */ return chv; } // }}} // Function colorhist_vector ppm_computecolorhist(pix, cols, rows, maxcol,colP){{{ colorhist_vector ppm_computecolorhist(pixel** pixels, int cols, int rows, int maxcolors, int* colorsP) { colorhash_table cht = NULL; colorhist_vector chv; cht = ppm_computecolorhash(pixels, cols, rows, maxcolors, colorsP); if (cht == (colorhash_table) 0) return (colorhist_vector) 0; chv = ppm_colorhashtocolorhist(cht, maxcolors); ppm_freecolorhash(cht); return chv; } // }}} // Function char *ppm_writeppminit(stream, cols, rows, maxval, forceplain) {{{ char *ppm_writeppminit(char *stream, int cols, int rows, pixval maxval, int forceplain) { #define TMP_LEN 80 char temp[TMP_LEN]; if (maxval <= 255 && ! forceplain) { if (snprintf(temp, TMP_LEN, "%c%c\n%d %d\n%d\n", PPM_MAGIC1, RPPM_MAGIC2, cols, rows, maxval) == -1) fprintf(stderr, "Warning: string truncated at %s:%d\n", __FILE__, __LINE__); } else { if (snprintf(temp, TMP_LEN, "%c%c\n%d %d\n%d\n", PPM_MAGIC1, PPM_MAGIC2, cols, rows, maxval) == -1) fprintf(stderr, "Warning: string truncated at %s:%d\n", __FILE__, __LINE__); } #undef TMP_LEN write_index = strlen(temp); stream = (char*)my_malloc(sizeof(char)*(write_index+1)); strcpy(stream, temp); return stream; } // }}} // Function char *pm_allocrow(int cols, int size) {{{ char *pm_allocrow(int cols, int size) { register char* itrow; itrow = (char*) my_malloc(cols * size); return itrow; } // }}} // Function void putus(unsigned short n, char *stream) {{{ void putus(unsigned short n, char *stream) { if (n >= 10) putus(n / 10, stream); stream[write_index++] = n % 10 + '0'; } // }}} // Function void ppm_writeppmrowraw(stream, pixelrow, cols, maxval) {{{ void ppm_writeppmrowraw(char *stream, pixel* pixelrow, int cols, pixval maxval) { register int col; register pixel* pP; register pixval val; for (col = 0, pP = pixelrow; col < cols; ++col, ++pP) { val = PPM_GETR(*pP); stream[write_index++] = val; val = PPM_GETG(*pP); stream[write_index++] = val; val = PPM_GETB(*pP); stream[write_index++] = val; } } // }}} // Function void ppm_writeppmrowplain(stream, pixelrow, cols, maxval) {{{ void ppm_writeppmrowplain(char *stream, pixel* pixelrow, int cols, pixval maxval) { register int col, charcount; register pixel* pP; register pixval val; charcount = 0; for (col = 0, pP = pixelrow; col < cols; ++col, ++pP) { if (charcount >= 65) { stream[write_index++] = '\n'; charcount = 0; } else if (charcount > 0) { stream[write_index++] = ' '; stream[write_index++] = ' '; charcount += 2; } val = PPM_GETR(*pP); putus(val, stream); stream[write_index++] = ' '; val = PPM_GETG(*pP); putus(val, stream); stream[write_index++] = ' '; val = PPM_GETB(*pP); putus(val, stream); charcount += 11; } if (charcount > 0) stream[write_index++] = '\n'; } // }}} // Function void ppm_writeppmrow(stream, pixelrow, cols, maxval, forceplain) {{{ void ppm_writeppmrow(char *stream, pixel* pixelrow, int cols, pixval maxval, int forceplain) { if (maxval <= 255 && ! forceplain) ppm_writeppmrowraw(stream, pixelrow, cols, maxval); else ppm_writeppmrowplain(stream, pixelrow, cols, maxval); } // }}} // Function long rgbnorm(long rgb, long lmaxval, int n, char* colorname) {{{ long rgbnorm(long rgb, long lmaxval, int n, char* colorname) { switch (n) { case 1: if (lmaxval != 15) rgb = rgb * lmaxval / 15; break; case 2: if (lmaxval != 255) rgb = rgb * lmaxval / 255; break; case 3: if (lmaxval != 4095) rgb = rgb * lmaxval / 4095; break; case 4: if (lmaxval != 65535L) rgb = rgb * lmaxval / 65535L; break; } return rgb; } // }}} // Function pixel ppm_parsecolor(char* colorname, pixval maxval) {{{ pixel ppm_parsecolor(char* colorname, pixval maxval) { int hexit[256], i; pixel p; long lmaxval, r = 0, g = 0, b = 0; for (i = 0; i < 256; ++i) hexit[i] = 1234567890; hexit['0'] = 0; hexit['1'] = 1; hexit['2'] = 2; hexit['3'] = 3; hexit['4'] = 4; hexit['5'] = 5; hexit['6'] = 6; hexit['7'] = 7; hexit['8'] = 8; hexit['9'] = 9; hexit['a'] = hexit['A'] = 10; hexit['b'] = hexit['B'] = 11; hexit['c'] = hexit['C'] = 12; hexit['d'] = hexit['D'] = 13; hexit['e'] = hexit['E'] = 14; hexit['f'] = hexit['F'] = 15; lmaxval = maxval; if (strncmp(colorname, "rgb:", 4) == 0) { /* It's a new-X11-style hexadecimal rgb specifier. */ char* cp; cp = colorname + 4; r = g = b = 0; for (i = 0; *cp != '/'; ++i, ++cp) r = r * 16 + hexit[(int)*cp]; r = rgbnorm(r, lmaxval, i, colorname); for (i = 0, ++cp; *cp != '/'; ++i, ++cp) g = g * 16 + hexit[(int)*cp]; g = rgbnorm(g, lmaxval, i, colorname); for (i = 0, ++cp; *cp != '\0'; ++i, ++cp) b = b * 16 + hexit[(int)*cp]; b = rgbnorm(b, lmaxval, i, colorname); } else if (strncmp(colorname, "rgbi:", 5) == 0) { /* It's a new-X11-style decimal/float rgb specifier. */ float fr = 0.0, fg = 0.0, fb = 0.0; r = fr * lmaxval; g = fg * lmaxval; b = fb * lmaxval; } else if (colorname[0] == '#') { /* It's an old-X11-style hexadecimal rgb specifier. */ switch (strlen(colorname)) { case 4: r = hexit[colorname[1]]; g = hexit[colorname[2]]; b = hexit[colorname[3]]; r = rgbnorm(r, lmaxval, 1, colorname); g = rgbnorm(g, lmaxval, 1, colorname); b = rgbnorm(b, lmaxval, 1, colorname); break; case 7: r = (hexit[colorname[1]] << 4) + hexit[colorname[2]]; g = (hexit[colorname[3]] << 4) + hexit[colorname[4]]; b = (hexit[colorname[5]] << 4) + hexit[colorname[6]]; r = rgbnorm(r, lmaxval, 2, colorname); g = rgbnorm(g, lmaxval, 2, colorname); b = rgbnorm(b, lmaxval, 2, colorname); break; case 10: r = (hexit[colorname[1]] << 8) + (hexit[colorname[2]] << 4) + hexit[colorname[3]]; g = (hexit[colorname[4]] << 8) + (hexit[colorname[5]] << 4) + hexit[colorname[6]]; b = (hexit[colorname[7]] << 8) + (hexit[colorname[8]] << 4) + hexit[colorname[9]]; r = rgbnorm(r, lmaxval, 3, colorname); g = rgbnorm(g, lmaxval, 3, colorname); b = rgbnorm(b, lmaxval, 3, colorname); break; case 13: r = (hexit[colorname[1]] << 12) + (hexit[colorname[2]] << 8) + (hexit[colorname[3]] << 4) + hexit[colorname[4]]; g = (hexit[colorname[5]] << 12) + (hexit[colorname[6]] << 8) + (hexit[colorname[7]] << 4) + hexit[colorname[8]]; b = (hexit[colorname[9]] << 12) + (hexit[colorname[10]] << 8) + (hexit[colorname[11]] << 4) + hexit[colorname[12]]; r = rgbnorm(r, lmaxval, 4, colorname); g = rgbnorm(g, lmaxval, 4, colorname); b = rgbnorm(b, lmaxval, 4, colorname); break; } } else if ((colorname[0] >= '0' && colorname[0] <= '9') || colorname[0] == '.') { /* It's an old-style decimal/float rgb specifier. */ float fr = 0.0, fg = 0.0, fb = 0.0; r = fr * lmaxval; g = fg * lmaxval; b = fb * lmaxval; } PPM_ASSIGN(p, r, g, b); return p; } // }}} // Function char **pm_allocarray(int cols, int rows, int size) {{{ char **pm_allocarray(int cols, int rows, int size) { char** its; int i; its = (char**) my_malloc(rows * sizeof(char*)); its[0] = (char*) my_malloc(rows * cols * size); for (i = 1; i < rows; ++i) its[i] = &(its[0][i * cols * size]); return its; } // }}} // Function void ppm_readppminitrest(stream, colsP, rowsP, maxvalP) {{{ void ppm_readppminitrest(char *stream, int* colsP, int* rowsP, pixval* maxvalP) { int maxval; /* Read size. */ *colsP = ppm_getint(stream); *rowsP = ppm_getint(stream); /* Read maxval. */ maxval = ppm_getint(stream); *maxvalP = maxval; } // }}} // Function int ppm_readmagicnumber(char *stream) {{{ int ppm_readmagicnumber(char *stream) { int ich1, ich2; ich1 = stream[read_index++]; ich2 = stream[read_index++]; return ich1 * 256 + ich2; } // }}} // Function int ppm_getint(char *stream) {{{ int ppm_getint(char *stream) { register char ch; register int i; do { ch = stream[read_index++]; } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); i = 0; do { i = i * 10 + ch - '0'; ch = stream[read_index++]; } while (ch >= '0' && ch <= '9'); return i; } // }}} // Function void ppm_readppmrow(stream, pixelrow, cols, maxval, format) {{{ void ppm_readppmrow(char *stream, pixel* pixelrow, int cols, pixval maxval, int format) { register int col; register pixel* pP; register pixval r, g, b; for (col = 0, pP = pixelrow; col < cols; ++col, ++pP) { r = stream[read_index++]; g = stream[read_index++]; b = stream[read_index++]; PPM_ASSIGN(*pP, r, g, b); } } // }}} // Function pixel **ppm_readppm(stream, colsP, rowsP, maxvalP) {{{ pixel **ppm_readppm(char *stream, int* colsP, int* rowsP, pixval* maxvalP) { pixel** pixels; int row; int format = 0; ppm_readppminitrest(stream, colsP, rowsP, maxvalP); pixels = ppm_allocarray(*colsP, *rowsP); for (row = 0; row < *rowsP; ++row) ppm_readppmrow(stream, pixels[row], *colsP, *maxvalP, format); return pixels; } // }}} // Function void XpmToGif(char **xpmData, char *outFile) {{{ void XpmToGif(char **xpmData, char *outFile) { pixel *pixrow = NULL, *colors = NULL; register pixel *pP; int rows, cols, ncolors, chars_per_pixel, row; register int col; register char *ptr; char *stream=NULL; int length; int size=1; read_index=3; write_index=0; ppm_pbmmaxval = 1; maxbits = BITS; maxmaxcode = (code_int)1 << BITS; hsize = HSIZE; free_ent = 0; clear_flg = 0; in_count = 1; out_count = 0; cur_accum = 0; cur_bits = 0; getline_index = 0; pixels = NULL; cht = NULL; ReadXPMFile(xpmData, &cols, &rows, &ncolors, &chars_per_pixel, &colors); stream = ppm_writeppminit(stream, cols, rows, (pixval) PPM_MAXMAXVAL, 0); length = strlen(stream); pixrow = ppm_allocrow(cols); for (row = 0, ptr = xpmData[row+ncolors+1]; row < rows; ++row, ptr = xpmData[row+ncolors+1]) { for (col = 0, pP = pixrow; col < cols; ++col, ++pP, ++ptr) *pP = colors[(int)*ptr]; stream = (char *)my_realloc(stream, size*cols*3*sizeof(char)+length); ppm_writeppmrow(stream, pixrow, cols, (pixval) PPM_MAXMAXVAL, 0); size++; } ToGif(stream, outFile); free(pixrow); free(stream); free(pixels[0]); free(pixels); free(colors); } // }}} // Function void ReadXPMFile(stream,widthP,heightP,ncolP,chars_per_pixP,colP) {{{ void ReadXPMFile(char **stream, int *widthP, int *heightP, int *ncolorsP, int *chars_per_pixelP, pixel **colorsP) { char line[MAX_LINE], str1[MAX_LINE], str2[MAX_LINE]; char *t1; char *t2; int format, v; register int i, j; int flag; unsigned int curkey, key, highkey; /* current color key */ unsigned int lastwaskey; /* key read */ char curbuf[BUFSIZ]; /* current buffer */ *widthP = *heightP = *ncolorsP = *chars_per_pixelP = format = -1; flag = 0; /* to avoid getting twice a line */ /* Read the hints line */ getline(line, sizeof(line), stream); sscanf(line, "%d %d %d %d", widthP, heightP, ncolorsP, chars_per_pixelP); /* Allocate space for color table. */ /* Up to two chars per pixel, we can use an indexed table. */ v = 1; for (i = 0; i < *chars_per_pixelP; ++i) v *= 256; *colorsP = ppm_allocrow(v); /* Read the color table */ for (i = 0; i < *ncolorsP; i++) { getline(line, sizeof(line), stream); t1 = line; strncpy(str1, t1, *chars_per_pixelP); str1[*chars_per_pixelP] = '\0'; t1++; t1++; v = 0; for (j = 0; j < *chars_per_pixelP; ++j) v = (v << 8) + str1[j]; /* * read color keys and values */ curkey = 0; highkey = 1; lastwaskey = 0; t2 = t1; while (1) { for (t1=t2 ;; t1++) if (*t1 != ' ' && *t1 != ' ') break; for (t2 = t1;; t2++) if (*t2 == ' ' || *t2 == ' ' || *t2 == '\0') break; if (t2 == t1) break; strncpy(str2, t1, t2 - t1); str2[t2 - t1] = '\0'; if (!lastwaskey) { for (key = 1; key < NKEYS + 1; key++) if (!strcmp(colorKeys[key - 1], str2)) break; } else key = NKEYS + 1; if (key > NKEYS) { /* append name */ if (!lastwaskey) strcat(curbuf, " "); /* append space */ strcat(curbuf, str2); /* append buf */ lastwaskey = 0; } if (key <= NKEYS) { /* new key */ if (curkey > highkey) { /* flush string */ /* Index into table. */ (*colorsP)[v] = ppm_parsecolor(curbuf, (pixval) PPM_MAXMAXVAL); highkey = curkey; } curkey = key; /* set new key */ curbuf[0] = '\0'; /* reset curbuf */ lastwaskey = 1; } if (*t2 == 0) break; } if (curkey > highkey) { /* Index into table. */ (*colorsP)[v] = ppm_parsecolor(curbuf, (pixval) PPM_MAXMAXVAL); highkey = curkey; } } } // }}} // Function void getline(char *line, int size, char **stream) {{{ void getline(char *line, int size, char **stream) { static int length, i, j, k, l, max; if (getline_index == 0) { sscanf(stream[0], "%d %d %d %d", &i, &j, &k, &l); max = j+k; } if (getline_index <= max) { length = strlen(stream[getline_index]); i = (size > length) ? length : size; strncpy(line, stream[getline_index], i); line[i] = 0; getline_index++; } } // }}} // Function void ToGif(char* stream, char *outFile) {{{ void ToGif(char* stream, char *outFile) { int rows, cols, colors, i, BitsPerPixel; pixval maxval; colorhist_vector chv = NULL; int Red[MAXCOLORS], Green[MAXCOLORS], Blue[MAXCOLORS]; FILE *file; if ((file = fopen(outFile, "wb"))==NULL) { printf("\nError: could not write GIF file, open failed."); return; } pixels = ppm_readppm(stream, &cols, &rows, &maxval); /* Figure out the colormap. */ chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &colors); /* Now turn the ppm colormap into the appropriate GIF colormap. */ for (i = 0; i < colors; ++i) { Red[i] = PPM_GETR(chv[i].color); Green[i] = PPM_GETG(chv[i].color); Blue[i] = PPM_GETB(chv[i].color); } BitsPerPixel = colorstobpp(colors); /* And make a hash table for fast lookup. */ cht = ppm_colorhisttocolorhash(chv, colors); ppm_freecolorhist(chv); /* All set, let's do it. */ GIFEncode(file, cols, rows, 0, 0, BitsPerPixel, Red, Green, Blue, GetPixel); ppm_freecolorhash(cht); fclose(file); } // }}} // Function static int colorstobpp(int colors) {{{ static int colorstobpp(int colors) { int bpp = 0; if (colors <= 2) bpp = 1; else if (colors <= 4) bpp = 2; else if (colors <= 8) bpp = 3; else if (colors <= 16) bpp = 4; else if (colors <= 32) bpp = 5; else if (colors <= 64) bpp = 6; else if (colors <= 128) bpp = 7; else if (colors <= 256) bpp = 8; return bpp; } // }}} // Function static int GetPixel(int x, int y) {{{ static int GetPixel(int x, int y) { int color; color = ppm_lookupcolor(cht, &pixels[y][x]); return color; } // }}} /***************************************************************************** * * GIFENCODE.C - GIF Image compression interface * * GIFEncode(FName, GHeight, GWidth, GInterlace, Background, * BitsPerPixel, Red, Green, Blue, GetPixel) * *****************************************************************************/ // GIFENCODE functions{{{ /* * Bump the 'curx' and 'cury' to point to the next pixel */ // Function static void BumpPixel(void) {{{ static void BumpPixel(void) { /* * Bump the current X position */ ++curx; /* * If we are at the end of a scan line, set curx back to the beginning * If we are interlaced, bump the cury to the appropriate spot, * otherwise, just increment it. */ if (curx == Width) { curx = 0; if (!Interlace) ++cury; else { switch (Pass) { case 0: cury += 8; if (cury >= Height) { ++Pass; cury = 4; } break; case 1: cury += 8; if (cury >= Height) { ++Pass; cury = 2; } break; case 2: cury += 4; if (cury >= Height) { ++Pass; cury = 1; } break; case 3: cury += 2; break; } } } } // }}} /* * Return the next pixel from the image */ // Function static int GIFNextPixel(ifunptr getpixel) {{{ static int GIFNextPixel(ifunptr getpixel) { int r=0; if (CountDown == 0) return EOF; --CountDown; r = (* getpixel)(curx, cury); BumpPixel(); return r; } // }}} /* public */ // Function static void GIFEncode() {{{ static void GIFEncode(FILE* fp, int GWidth, int GHeight, int GInterlace, int Background, int BitsPerPixel, int Red[], int Green[], int Blue[], ifunptr GetPixel) { int B; int RWidth, RHeight; int LeftOfs, TopOfs; int Resolution; int ColorMapSize; int InitCodeSize; int i; Interlace = GInterlace; ColorMapSize = 1 << BitsPerPixel; RWidth = Width = GWidth; RHeight = Height = GHeight; LeftOfs = TopOfs = 0; Resolution = BitsPerPixel; /* * Calculate number of bits we are expecting */ CountDown = (long)Width * (long)Height; /* * Indicate which pass we are on (if interlace) */ Pass = 0; /* * The initial code size */ if (BitsPerPixel <= 1) InitCodeSize = 2; else InitCodeSize = BitsPerPixel; /* * Set up the current x and y position */ curx = cury = 0; /* * Write the Magic header */ fwrite("GIF87a", 1, 6, fp); /* * Write out the screen width and height */ Putword(RWidth, fp); Putword(RHeight, fp); /* * Indicate that there is a global colour map */ B = 0x80; /* Yes, there is a color map */ /* * OR in the resolution */ B |= (Resolution - 1) << 5; /* * OR in the Bits per Pixel */ B |= (BitsPerPixel - 1); /* * Write it out */ fputc(B, fp); /* * Write out the Background colour */ fputc(Background, fp); /* * Byte of 0's (future expansion) */ fputc(0, fp); /* * Write out the Global Colour Map */ for (i=0; i 0) goto probe; nomatch: output ((code_int) ent); ++out_count; ent = c; #ifdef SIGNED_COMPARE_SLOW if ((unsigned) free_ent < (unsigned) maxmaxcode) { #else /*SIGNED_COMPARE_SLOW*/ if (free_ent < maxmaxcode) { /* } */ #endif /*SIGNED_COMPARE_SLOW*/ CodeTabOf (i) = free_ent++; /* code -> hashtable */ HashTabOf (i) = fcode; } else cl_block(); } /* * Put out the final code. */ output((code_int)ent); ++out_count; output((code_int) EOFCode); } // }}} /***************************************************************** * TAG(output) * * Output the given code. * Inputs: * code: A n_bits-bit integer. If == -1, then EOF. This assumes * that n_bits =< (long)wordsize - 1. * Outputs: * Outputs code to the file. * Assumptions: * Chars are 8 bits long. * Algorithm: * Maintain a BITS character long buffer (so that 8 codes will * fit in it exactly). Use the VAX insv instruction to insert each * code in turn. When the buffer fills up empty it and start over. */ // Function static void output(code_int code) {{{ static void output(code_int code) { cur_accum &= masks[ cur_bits ]; if (cur_bits > 0) cur_accum |= ((long)code << cur_bits); else cur_accum = code; cur_bits += n_bits; while (cur_bits >= 8) { char_out((unsigned int)(cur_accum & 0xff)); cur_accum >>= 8; cur_bits -= 8; } /* * If the next entry is going to be too big for the code size, * then increase it, if possible. */ if (free_ent > maxcode || clear_flg) { if (clear_flg) { maxcode = MAXCODE (n_bits = g_init_bits); clear_flg = 0; } else { ++n_bits; if (n_bits == maxbits) maxcode = maxmaxcode; else maxcode = MAXCODE(n_bits); } } if (code == EOFCode) { /* * At EOF, write the rest of the buffer. */ while (cur_bits > 0) { char_out((unsigned int)(cur_accum & 0xff)); cur_accum >>= 8; cur_bits -= 8; } flush_char(); fflush(g_outfile); } } // }}} /* * Clear out the hash table */ // Function static void cl_block (void) {{{ static void cl_block (void) { /* table clear for block compress */ cl_hash ((count_int) hsize); free_ent = ClearCode + 2; clear_flg = 1; output((code_int)ClearCode); } // }}} // Function static void cl_hash(register count_int hsize) {{{ static void cl_hash(register count_int hsize) { /* reset code table */ register count_int *htab_p = htab+hsize; register long i; register long m1 = -1; i = hsize - 16; do { /* might use Sys V memset(3) here */ *(htab_p-16) = m1; *(htab_p-15) = m1; *(htab_p-14) = m1; *(htab_p-13) = m1; *(htab_p-12) = m1; *(htab_p-11) = m1; *(htab_p-10) = m1; *(htab_p-9) = m1; *(htab_p-8) = m1; *(htab_p-7) = m1; *(htab_p-6) = m1; *(htab_p-5) = m1; *(htab_p-4) = m1; *(htab_p-3) = m1; *(htab_p-2) = m1; *(htab_p-1) = m1; htab_p -= 16; } while ((i -= 16) >= 0); for (i += 16; i > 0; --i) *--htab_p = m1; } // }}} /****************************************************************************** * * GIF Specific routines * ******************************************************************************/ /* * Number of characters so far in this 'packet' */ /* * Set up the 'byte output' routine */ // Function static void char_init(void) {{{ static void char_init(void) { a_count = 0; } // }}} /* * Define the storage for the packet accumulator */ /* * Add a character to the end of the current packet, and if it is 254 * characters, flush the packet to disk. */ // Function static void char_out(int c) {{{ static void char_out(int c) { accum[ a_count++ ] = c; if (a_count >= 254) flush_char(); } // }}} /* * Flush the packet to disk, and reset the accumulator */ // Function static void flush_char(void) {{{ static void flush_char(void) { if (a_count > 0) { fputc(a_count, g_outfile); fwrite(accum, 1, a_count, g_outfile); a_count = 0; } } // }}} // }}} // Modeline for ViM {{{1 // vim:set ts=4: // vim600:fdm=marker fdl=0 fdc=3: // 1}}} #endif /* ifdef XPMENABLED */