tkImgGIF.c revision 3f54fd611f536639ec30dd53c48e5ec1897cc7d9
/*
* tkImgGIF.c --
*
* A photo image file handler for GIF files. Reads 87a and 89a GIF files.
* At present there is no write function.
*
* Derived from the giftoppm code found in the pbmplus package
* and tkImgFmtPPM.c in the tk4.0b2 distribution by -
*
* Reed Wade (wade@cs.utk.edu), University of Tennessee
*
* Copyright (c) 1995-1996 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* This file also contains code from the giftoppm program, which is
* copyrighted as follows:
*
* +-------------------------------------------------------------------+
* | 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. |
* +-------------------------------------------------------------------+
*
* SCCS: @(#) tkImgGIF.c 1.9 96/07/19 09:57:18
*/
#include "tkInt.h"
/*
* The format record for the GIF file format:
*/
"GIF", /* name */
FileMatchGIF, /* fileMatchProc */
NULL, /* stringMatchProc */
FileReadGIF, /* fileReadProc */
NULL, /* stringReadProc */
NULL, /* fileWriteProc */
NULL, /* stringWriteProc */
};
#define INTERLACE 0x40
#define LOCALCOLORMAP 0x80
#define MAXCOLORMAPSIZE 256
#define CM_RED 0
#define CM_GREEN 1
#define CM_BLUE 2
#define MAX_LWZ_BITS 12
#define LM_to_uint(a,b) (((b)<<8)|(a))
/*
* Prototypes for local procedures defined in this file:
*/
int *transparent));
int flag));
unsigned char *buf));
int input_code_size));
int *heightPtr));
int interlace, int transparent));
/*
*----------------------------------------------------------------------
*
* FileMatchGIF --
*
* This procedure is invoked by the photo image type to see if
* a file contains image data in GIF format.
*
* Results:
* The return value is 1 if the first characters in file f look
* like GIF data, and 0 otherwise.
*
* Side effects:
* The access position in f may change.
*
*----------------------------------------------------------------------
*/
static int
FILE *f; /* The image file, open for reading. */
char *fileName; /* The name of the image file. */
char *formatString; /* User-specified format string, or NULL. */
* returned here if the file is a valid
* raw GIF file. */
{
}
/*
*----------------------------------------------------------------------
*
* FileReadGIF --
*
* This procedure is called by the photo image type to read
* GIF format data from a file and write it into a given
* photo image.
*
* Results:
* A standard TCL completion code. If TCL_ERROR is returned
* then an error message is left in interp->result.
*
* Side effects:
* The access position in file f is changed, and new data is
* added to the image given by imageHandle.
*
*----------------------------------------------------------------------
*/
static int
FILE *f; /* The image file, open for reading. */
char *fileName; /* The name of the image file. */
char *formatString; /* User-specified format string, or NULL. */
* photo image to be written to. */
* be written to. */
* in image being read. */
{
int fileWidth, fileHeight;
int nBytes;
unsigned char buf[100];
int bitPixel;
int useGlobalColormap;
int transparent = -1;
return TCL_ERROR;
}
if ((fileWidth <= 0) || (fileHeight <= 0)) {
"\" has dimension(s) <= 0", (char *) NULL);
return TCL_ERROR;
}
return TCL_OK;
}
(char *) NULL);
return TCL_ERROR;
}
}
}
}
return TCL_OK;
}
while (1) {
/*
* Premature end of image. We should really notify
* the user, but for now just show garbage.
*/
break;
}
if (buf[0] == ';') {
/*
* GIF terminator.
*/
break;
}
if (buf[0] == '!') {
/*
* This is a GIF extension.
*/
"error reading extension function code in GIF image";
goto error;
}
goto error;
}
continue;
}
if (buf[0] != ',') {
/*
* Not a valid start character; ignore it.
*/
continue;
}
goto error;
}
if (!useGlobalColormap) {
(char *) NULL);
goto error;
}
transparent) != TCL_OK) {
goto error;
}
} else {
transparent) != TCL_OK) {
goto error;
}
}
break;
}
return TCL_OK;
return TCL_ERROR;
}
/*
*----------------------------------------------------------------------
*
* ReadGIFHeader --
*
* This procedure reads the GIF header from the beginning of a
* GIF file and returns the dimensions of the image.
*
* Results:
* The return value is 1 if file "f" appears to start with
* a valid GIF header, 0 otherwise. If the header is valid,
* then *widthPtr and *heightPtr are modified to hold the
* dimensions of the image.
*
* Side effects:
* The access position in f advances.
*
*----------------------------------------------------------------------
*/
static int
FILE *f; /* Image file to read the header from */
* returned here. */
{
unsigned char buf[7];
return 0;
}
return 0;
}
return 1;
}
/*
*-----------------------------------------------------------------
* The code below is copied from the giftoppm program and modified
* just slightly.
*-----------------------------------------------------------------
*/
static int
int number;
{
int i;
unsigned char rgb[3];
for (i = 0; i < number; ++i) {
return 0;
}
return 1;
}
static int
int label;
int *transparent;
{
static unsigned char buf[256];
int count = 0;
switch (label) {
case 0x01: /* Plain Text Extension */
break;
case 0xff: /* Application Extension */
break;
case 0xfe: /* Comment Extension */
do {
} while (count > 0);
return count;
case 0xf9: /* Graphic Control Extension */
if (count < 0) {
return 1;
}
if ((buf[0] & 0x1) != 0) {
}
do {
} while (count > 0);
return count;
}
do {
} while (count > 0);
return count;
}
static int ZeroDataBlock = 0;
static int
unsigned char *buf;
{
unsigned char count;
return -1;
}
ZeroDataBlock = count == 0;
return -1;
}
return count;
}
static int
char *imagePtr;
int interlace;
int transparent;
{
unsigned char c;
int v;
char *colStr;
/*
* Initialize the Compression routines
*/
return TCL_ERROR;
}
return TCL_ERROR;
}
if (transparent != -1) {
if (colorPtr) {
}
}
}
while ((v = LWZReadByte(fd,0,c)) >= 0 ) {
++xpos;
xpos = 0;
if (interlace) {
switch (pass) {
case 0:
case 1:
ypos += 8; break;
case 2:
ypos += 4; break;
case 3:
ypos += 2; break;
}
++pass;
switch (pass) {
case 1:
ypos = 4; break;
case 2:
ypos = 2; break;
case 3:
ypos = 1; break;
default:
return TCL_OK;
}
}
} else {
++ypos;
}
}
break;
}
return TCL_OK;
}
static int
int flag;
int input_code_size;
{
static int fresh = 0;
static int code_size, set_code_size;
static int max_code, max_code_size;
static int clear_code, end_code;
register int i;
if (flag) {
fresh = 1;
for (i = 0; i < clear_code; ++i) {
table[0][i] = 0;
table[1][i] = i;
}
for (; i < (1<<MAX_LWZ_BITS); ++i) {
}
return 0;
} else if (fresh) {
fresh = 0;
do {
} while (firstcode == clear_code);
return firstcode;
}
return *--sp;
if (code == clear_code) {
for (i = 0; i < clear_code; ++i) {
table[0][i] = 0;
table[1][i] = i;
}
for (; i < (1<<MAX_LWZ_BITS); ++i) {
}
return firstcode;
int count;
unsigned char buf[260];
if (ZeroDataBlock)
return -2;
;
if (count != 0)
return -2;
}
}
while (code >= clear_code) {
return -2;
/*
* Used to be this instead, Steve Ball suggested
* the change to just return.
printf("circular table entry BIG ERROR\n");
*/
}
}
++max_code;
max_code_size *= 2;
++code_size;
}
}
return *--sp;
}
return code;
}
static int
int code_size;
int flag;
{
static unsigned char buf[280];
int i, j, ret;
unsigned char count;
if (flag) {
curbit = 0;
lastbit = 0;
done = 0;
return 0;
}
if (done) {
/* ran off the end of my bits */
return -1;
}
done = 1;
}
ret = 0;
return ret;
}