This is gifbmap.c in view mode; [Download] [Up]
/*
gifbmap.h
gifheader.c, gifbmap.c, and gif.h are based on "giftoppm"
of David Koblas.
They are modified by T. Ogihara. (1995)
*/
/* +-------------------------------------------------------------------+ */
/* | Copyright 1990, David Koblas. | */
/* | 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. | */
/* +-------------------------------------------------------------------+ */
#include <signal.h>
#include <setjmp.h>
#include "gif.h"
#include "strfunc.h"
static int ReadColorMap(FILE *, gifHeader *);
static int DoExtension(FILE *, gifHeader *);
static int ReadImage(FILE *, const gifHeader *, unsigned char **);
static void (*sav_violation)() = NULL;
static void (*sav_buserror)() = NULL;
static jmp_buf sav_env;
static void
catch_violation(int sig)
{
longjmp(sav_env, sig);
}
int gifGetImage(FILE *fp, gifHeader *gh, unsigned char **planes)
{
int c, rtn = 0;
if (gh->colormap) { /* Global Colormap */
if (ReadColorMap(fp, gh) == 0)
return Err_FORMAT;
}
while ((c = getc(fp)) != ',' ) { /* start character */
if (c == EOF || c == ';') /* GIF terminator */
return Err_SHORT;
if (c == '!') { /* Extension */
if (DoExtension(fp, gh) < 0)
return Err_ILLG;
}
/* other chars are illegal... ignore */
}
(void)get_long(fp); /* skip 4 bytes */
gh->width = get_short(fp);
gh->height = get_short(fp);
c = getc(fp);
gh->interlace = BitSet(c, INTERLACE);
if (BitSet(c, LOCALCOLORMAP)) { /* Use Local Color Map */
gh->colors = 2 << (c & 0x07);
if (ReadColorMap(fp, gh) == 0)
return Err_FORMAT;
}
if (gh->transp >= 0) {
unsigned char *p = (unsigned char *)gh->palette[gh->transp];
p[RED] = p[GREEN] = p[BLUE] = 255;
if (gh->colors - 1 == gh->transp)
--gh->colors; /* if last of palette is transp. */
}
gh->bits = howManyBits(gh->palette, gh->colors);
gh->isgray = isGray(gh->palette, gh->colors);
/* Initialize the Compression routines */
if (initGifLZW(fp) == EOF)
return Err_SHORT;
sav_violation = signal(SIGSEGV, catch_violation);
sav_buserror = signal(SIGBUS, catch_violation);
if (setjmp(sav_env) == 0)
rtn = ReadImage(fp, gh, planes);
else /* return from Segmentation Error */
rtn = Err_FORMAT;
(void) signal(SIGSEGV, sav_violation);
(void) signal(SIGBUS, sav_buserror);
return rtn;
}
static int
ReadColorMap(FILE *fd, gifHeader *gh)
{
int i, j, number;
unsigned char *p, *q;
number = gh->colors;
for (i = 0; i < number; ++i) {
p = (unsigned char *)gh->palette[i];
p[RED] = getc(fd);
p[GREEN] = getc(fd);
p[BLUE] = getc(fd);
if (feof(fd))
return 0;
}
for (i = number - 1; i > 0; --i) { /* skip stab */
p = (unsigned char *)gh->palette[i];
q = (unsigned char *)gh->palette[i - 1];
for (j = 0; j < 3; j++)
if (p[j] != q[j]) goto EXIT;
}
EXIT:
gh->colors = i + 1;
return 1;
}
static int
DoExtension(FILE *fd, gifHeader *gh)
{
int cc;
unsigned char buf[256];
switch (cc = getc(fd)) {
case 0x01: /* Plain Text Extension */
case 0x2c: /* Image Descriptor */
case 0x3b: /* Trailer */
case 0xff: /* Application Extension */
break;
case 0xf9: /* Graphic Control Extension */
while (GetDataBlock(fd, buf) != 0) {
if (BitSet(buf[0], TRANSPARENCY))
gh->transp = buf[3]; /* Transparent Index */
}
return cc;
case 0xfe: /* Comment Extension */
while (GetDataBlock(fd, buf) != 0) {
if (gh->memo == NULL)
gh->memo = (unsigned char *)str_dup(buf);
}
return cc;
default:
return -1; /* ERROR */
}
while (GetDataBlock(fd, buf) != 0)
;
return cc;
}
static int
ReadImage(FILE *fd, const gifHeader *gh, unsigned char **planes)
{
int i, xpos, ypos, xbyte, pass, pn, err;
long wd;
unsigned char *map[MAXPLANE];
unsigned char buffer[MAXWidth];
pn = (gh->isgray ? 1:3) + ((gh->transp >= 0) ? 1 : 0);
err = allocImage(planes, gh->width, gh->height, gh->bits, pn);
if (err)
return err;
pass = 0;
xbyte = byte_length(gh->bits, gh->width);
for (ypos = 0; ; ) {
for (xpos = 0; xpos < gh->width; xpos++)
buffer[xpos] = LWZReadByte(fd);
map[0] = planes[0] + (wd = xbyte * ypos);
for (i = 1; i < pn; i++)
map[i] = planes[i] + wd;
expandImage(map, buffer, (const paltype *)gh->palette,
gh->bits, gh->width, gh->isgray, gh->transp);
if (gh->interlace) {
ypos += pass ? (0x10 >> pass) : 0x08;
if (ypos >= gh->height) {
if (++pass > 3)
break;
ypos = 8 >> pass;
}
}else {
if (++ypos >= gh->height)
break;
}
}
return 0;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.