summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MANIFEST13
-rw-r--r--RELEASE.txt4
-rw-r--r--all.zipbin203231 -> 205758 bytes
-rw-r--r--all_withf90.zipbin210340 -> 212874 bytes
-rwxr-xr-xconfigure2
-rw-r--r--configure.in1
-rw-r--r--hl/tools/gif2h5/Makefile.in65
-rw-r--r--hl/tools/gif2h5/decompress.c299
-rw-r--r--hl/tools/gif2h5/gif.h179
-rw-r--r--hl/tools/gif2h5/gif2hdf.c114
-rw-r--r--hl/tools/gif2h5/gif2mem.c344
-rw-r--r--hl/tools/gif2h5/gifread.c382
-rw-r--r--hl/tools/gif2h5/hdf2gif.c354
-rw-r--r--hl/tools/gif2h5/hdfgifwr.c516
-rw-r--r--hl/tools/gif2h5/readhdf.c177
-rw-r--r--hl/tools/gif2h5/writehdf.c410
-rw-r--r--tools/Makefile.in2
-rw-r--r--tools/gifconv/Dependencies0
-rw-r--r--tools/gifconv/Makefile.in65
-rw-r--r--tools/gifconv/decompress.c299
-rw-r--r--tools/gifconv/gif.h179
-rw-r--r--tools/gifconv/gif2hdf.c114
-rw-r--r--tools/gifconv/gif2mem.c344
-rw-r--r--tools/gifconv/gifread.c382
-rw-r--r--tools/gifconv/hdf2gif.c354
-rw-r--r--tools/gifconv/hdfgifwr.c516
-rw-r--r--tools/gifconv/readhdf.c177
-rw-r--r--tools/gifconv/writehdf.c410
28 files changed, 5700 insertions, 2 deletions
diff --git a/MANIFEST b/MANIFEST
index f1d322f..5b18da5 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -968,6 +968,19 @@
./tools/Dependencies
./tools/Makefile.in
+./tools/gifconv/Dependencies
+./tools/gifconv/Makefile.in
+./tools/gifconv/decompress.c
+./tools/gifconf/gif.h
+./tools/gifconv/gif2hdf.c
+./tools/gifconv/gif2mem.c
+./tools/gifconv/gifread.c
+./tools/gifconv/hdf2gif.c
+./tools/gifconv/hdfgifwr.c
+./tools/gifconv/readhdf.c
+./tools/gifconv/writehdf.c
+
+
./tools/h4toh5/Dependencies
./tools/h4toh5/Makefile.in
./tools/h4toh5/h4toh5anno.c
diff --git a/RELEASE.txt b/RELEASE.txt
index c223111..e27d159 100644
--- a/RELEASE.txt
+++ b/RELEASE.txt
@@ -92,7 +92,9 @@ New Features
an hdf5 library or hdf5 application binary.
Also added a verification of the consistency between H5_lib_vers_info_g
and other version information in the source code.
-
+ * H5 <-> GIF convertor has been added. This is available under
+ tools/gifconv. The convertor supports the ability to create animated
+ gifs as well.
Platforms Tested
================
diff --git a/all.zip b/all.zip
index 6ed9ce8..fb81493 100644
--- a/all.zip
+++ b/all.zip
Binary files differ
diff --git a/all_withf90.zip b/all_withf90.zip
index eb80abf..8849236 100644
--- a/all_withf90.zip
+++ b/all_withf90.zip
Binary files differ
diff --git a/configure b/configure
index d6a2fdd..4528d4f 100755
--- a/configure
+++ b/configure
@@ -9964,6 +9964,7 @@ trap 'rm -fr `echo "src/libhdf5.settings
tools/h5ls/Makefile
tools/lib/Makefile
tools/misc/Makefile
+ tools/gifconv/Makefile
$EXTRA_H4_MAKEFILES
examples/Makefile
doc/Makefile
@@ -10130,6 +10131,7 @@ CONFIG_FILES=\${CONFIG_FILES-"src/libhdf5.settings
tools/h5ls/Makefile
tools/lib/Makefile
tools/misc/Makefile
+ tools/gifconv/Makefile
$EXTRA_H4_MAKEFILES
examples/Makefile
doc/Makefile
diff --git a/configure.in b/configure.in
index 1937629..a2e49a5 100644
--- a/configure.in
+++ b/configure.in
@@ -1617,6 +1617,7 @@ AC_OUTPUT(src/libhdf5.settings
tools/h5ls/Makefile
tools/lib/Makefile
tools/misc/Makefile
+ tools/gifconv/Makefile
$EXTRA_H4_MAKEFILES
examples/Makefile
doc/Makefile
diff --git a/hl/tools/gif2h5/Makefile.in b/hl/tools/gif2h5/Makefile.in
new file mode 100644
index 0000000..effeada
--- /dev/null
+++ b/hl/tools/gif2h5/Makefile.in
@@ -0,0 +1,65 @@
+## HDF5 Library Makefile(.in)
+##
+## Copyright (C) 2001 National Center for Supercomputing Applications.
+## All rights reserved.
+##
+##
+top_srcdir=@top_srcdir@
+top_builddir=../..
+srcdir=@srcdir@
+SUBDIRS=
+@COMMENCE@
+
+## Add include directory to the C preprocessor flags, add -lh5tools and
+## -lhdf5 to the list of libraries.
+##
+CPPFLAGS=-I. -I$(srcdir) -I$(top_builddir)/src -I$(top_srcdir)/src \
+ -I$(top_srcdir)/tools/lib @CPPFLAGS@
+
+## Test programs and scripts.
+##
+TEST_PROGS=
+TEST_SCRIPTS=
+
+## These are our main targets: library and tools.
+##
+LIBTOOLS=../lib/libh5tools.la
+LIBHDF5=$(top_builddir)/src/libhdf5.la
+
+PUB_PROGS= gif2h5 h52gif
+PROGS=$(PUB_PROGS) $(TEST_PROGS)
+
+## Source and object files for the library; do not install
+##
+LIB_SRC=
+LIB_OBJ=$(LIB_SRC:.c=.lo)
+PUB_LIB=
+
+## Source and object files for programs...
+##
+PROG_SRC=decompress.c gif2hdf.c gif2mem.c gifread.c hdf2gif.c hdfgifwr.c readhdf.c writehdf.c
+PROG_OBJ=$(PROG_SRC:.c=.lo)
+
+PRIVATE_HDR=gif.h
+
+## Source and object files for the tests
+##
+TEST_SRC=
+TEST_OBJ=$(TEST_SRC:.c=.lo)
+
+## Programs have to be built before they can be tested!
+##
+check test _test: $(PROGS)
+
+## How to build the programs...They all depend on the hdf5 library and
+## the tools library compiled in this directory.
+##
+$(PROGS): $(LIBTOOLS) $(LIBHDF5)
+
+gif2h5: gif2hdf.lo gif2mem.lo decompress.lo gifread.lo writehdf.lo
+ @$(LT_LINK_EXE) $(CFLAGS) -o $@ gif2hdf.lo gif2mem.lo decompress.lo gifread.lo writehdf.lo $(LIBTOOLS) $(LIBHDF5) $(LDFLAGS) $(LIBS)
+
+h52gif: hdf2gif.lo hdfgifwr.lo readhdf.lo
+ @$(LT_LINK_EXE) $(CFLAGS) -o $@ hdf2gif.lo hdfgifwr.lo readhdf.lo $(LIBTOOLS) $(LIBHDF5) $(LDFLAGS) $(LIBS)
+
+@CONCLUDE@
diff --git a/hl/tools/gif2h5/decompress.c b/hl/tools/gif2h5/decompress.c
new file mode 100644
index 0000000..18dbb3e
--- /dev/null
+++ b/hl/tools/gif2h5/decompress.c
@@ -0,0 +1,299 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "gif.h"
+
+#define NEXTBYTE (*ptr++)
+#define IMAGESEP 0x2c
+#define INTERLACEMASK 0x40
+#define COLORMAPMASK 0x80
+#define False 0
+#define True 1
+
+WORD iWIDE,iHIGH,eWIDE,eHIGH,expand,numcols,strip,nostrip;
+unsigned long cols[256];
+char *cmd;
+
+FILE *fp;
+
+static int BitOffset = 0, /* Bit Offset of next code */
+XC = 0, YC = 0, /* Output X and Y coords of current pixel */
+Pass = 0, /* Used by output routine if WORDerlaced pic */
+OutCount = 0, /* Decompressor output 'stack count' */
+RWidth, RHeight, /* screen dimensions */
+IWidth, IHeight, /* image dimensions */
+LeftOfs, TopOfs, /* image offset */
+BitsPerPixel, /* Bits per pixel, read from GIF header */
+BytesPerScanline, /* Bytes per scanline in output raster */
+ColorMapSize, /* number of colors */
+Background, /* background color */
+CodeSize, /* Code size, read from GIF header */
+InitCodeSize, /* Starting code size, used during Clear */
+Code, /* Value returned by ReadCode */
+MaxCode, /* limiting value for current code size */
+ClearCode, /* GIF clear code */
+EOFCode, /* GIF end-of-information code */
+CurCode, OldCode, InCode, /* Decompressor variables */
+FirstFree, /* First free code, generated per GIF spec */
+FreeCode, /* Decompressor, next free slot in hash table */
+FinChar, /* Decompressor variable */
+DataMask, /* AND mask for data size */
+ReadMask; /* Code AND mask for current code size */
+
+/*MODIFICATIONS*/
+BYTE tempbyte[10];
+BYTE * tempBYTEptr[10];
+WORD tempint[10];
+WORD ImageCount = 0;
+/*END MODIFICATION*/
+
+boolean Interlace, HasColormap;
+
+
+BYTE *Image; /* The result array */
+BYTE *RawGIF; /* The heap array to hold it, raw */
+BYTE *Raster; /* The raster data stream, unblocked */
+
+/* The hash table used by the decompressor */
+
+int Prefix[4096];
+int Suffix[4096];
+
+/* An output array used by the decompressor */
+
+int OutCode[1025];
+
+/* The color map, read from the GIF header */
+
+int numused;
+
+/* Fetch the next code from the raster data stream. The codes can be
+* any length from 3 to 12 bits, packed WORDo 8-bit BYTEs, so we have to
+* maWORDain our location in the Raster array as a BIT Offset. We compute
+* the BYTE Offset WORDo the raster array by dividing this by 8, pick up
+* three BYTEs, compute the bit Offset WORDo our 24-bit chunk, shift to
+* bring the desired code to the bottom, then mask it off and return it.
+*/
+ReadCode()
+{
+ int RawCode, ByteOffset;
+
+ ByteOffset = BitOffset / 8;
+ RawCode = Raster[ByteOffset] + (0x100 * Raster[ByteOffset + 1]);
+ if (CodeSize >= 8)
+ RawCode += (0x10000 * Raster[ByteOffset + 2]);
+ RawCode >>= (BitOffset % 8);
+ BitOffset += CodeSize;
+ return(RawCode & ReadMask);
+}
+
+
+AddToPixel(Index)
+BYTE Index;
+{
+ if (YC<IHeight)
+ *(Image + YC * BytesPerScanline + XC) = Index;
+
+
+
+ /* Update the X-coordinate, and if it overflows, update the Y-coordinate */
+ if (++XC == IWidth) {
+
+ /* If a non-WORDerlaced picture, just increment YC to the next scan line.
+ * If it's WORDerlaced, deal with the WORDerlace as described in the GIF
+ * spec. Put the decoded scan line out to the screen if we haven't gone
+ * past the bottom of it.
+ */
+
+ XC = 0;
+ if (!Interlace) YC++;
+ else {
+ switch (Pass) {
+ case 0:
+ YC += 8;
+ if (YC >= IHeight) {
+ Pass++;
+ YC = 4;
+ }
+ break;
+ case 1:
+ YC += 8;
+ if (YC >= IHeight) {
+ Pass++;
+ YC = 2;
+ }
+ break;
+
+ case 2:
+ YC += 4;
+ if (YC >= IHeight) {
+ Pass++;
+ YC = 1;
+ }
+ break;
+ case 3:
+ YC += 2;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+/* Main routine. Convert a GIF image to an HDF image */
+
+BYTE* Decompress(GifImageDesc , GifHead)
+GIFIMAGEDESC *GifImageDesc;
+GIFHEAD *GifHead;
+{
+ int i;
+
+ XC = 0;
+ YC = 0;
+ Pass = 0;
+ OutCount = 0;
+ BitOffset = 0;
+
+ DataMask = (WORD)((1L << ((GifHead->PackedField & 0x07) +1)) -1);
+ Raster = GifImageDesc->GIFImage;
+
+
+ /* Check for image seperator */
+
+ /* Now read in values from the image descriptor */
+ IWidth = GifImageDesc->ImageWidth;
+ IHeight = GifImageDesc->ImageHeight;
+ Interlace = GifImageDesc->PackedField & 0x40;
+
+ /* Note that I ignore the possible existence of a local color map.
+ * I'm told there aren't many files around that use them, and the spec
+ * says it's defined for future use. This could lead to an error
+ * reading some files.
+ */
+
+ /* Start reading the raster data. First we get the WORDial code size
+ * and compute decompressor constant values, based on this code size.
+ */
+
+ CodeSize = GifImageDesc->CodeSize;
+ ClearCode = (1 << CodeSize);
+ EOFCode = ClearCode + 1;
+ FreeCode = FirstFree = ClearCode + 2;
+
+ /* The GIF spec has it that the code size is the code size used to
+ * compute the above values is the code size given in the file, but the
+ * code size used in compression/decompression is the code size given in
+ * the file plus one. (thus the ++).
+ */
+
+ CodeSize++;
+ InitCodeSize = CodeSize;
+ MaxCode = (1 << CodeSize);
+ ReadMask = MaxCode - 1;
+
+ /* Read the raster data. Here we just transpose it from the GIF array
+ * to the Raster array, turning it from a series of blocks WORDo one long
+ * data stream, which makes life much easier for ReadCode().
+ */
+
+
+
+ /* free(RawGIF); We're not done just yet - change made */
+
+ /* Allocate the Image */
+
+ if (!(Image = (BYTE *)malloc(IWidth*IHeight))) {
+ printf("Out of memory");
+ exit(-1);
+ }
+
+ BytesPerScanline = IWidth;
+
+ /* Decompress the file, continuing until you see the GIF EOF code.
+ * One obvious enhancement is to add checking for corrupt files here.
+ */
+
+ Code = ReadCode();
+ while (Code != EOFCode) {
+
+ /* Clear code sets everything back to its initial value, then reads the
+ * immediately subsequent code as uncompressed data.
+ */
+
+ if (Code == ClearCode) {
+ CodeSize = InitCodeSize;
+ MaxCode = (1 << CodeSize);
+ ReadMask = MaxCode - 1;
+ FreeCode = FirstFree;
+ CurCode = OldCode = Code = ReadCode();
+ FinChar = CurCode & DataMask;
+ AddToPixel(FinChar);
+ }
+ else {
+
+ /* If not a clear code, then must be data: save same as CurCode and InCode */
+
+ CurCode = InCode = Code;
+
+ /* If greater or equal to FreeCode, not in the hash table yet;
+ * repeat the last character decoded
+ */
+
+ if (CurCode >= FreeCode) {
+ CurCode = OldCode;
+ OutCode[OutCount++] = FinChar;
+ }
+
+ /* Unless this code is raw data, pursue the chain poWORDed to by CurCode
+ * through the hash table to its end; each code in the chain puts its
+ * associated output code on the output queue.
+ */
+
+ while (CurCode > DataMask) {
+ if (OutCount > 1024) {
+ /*return error message*/
+ }
+ OutCode[OutCount++] = Suffix[CurCode];
+ CurCode = Prefix[CurCode];
+ }
+
+ /* The last code in the chain is treated as raw data. */
+
+ FinChar = CurCode & DataMask;
+ OutCode[OutCount++] = FinChar;
+
+ /* Now we put the data out to the Output routine.
+ * It's been stacked LIFO, so deal with it that way...
+ */
+
+ for (i = OutCount - 1; i >= 0; i--)
+ AddToPixel(OutCode[i]);
+ OutCount = 0;
+
+ /* Build the hash table on-the-fly. No table is stored in the file. */
+
+ Prefix[FreeCode] = OldCode;
+ Suffix[FreeCode] = FinChar;
+ OldCode = InCode;
+
+ /* PoWORD to the next slot in the table. If we exceed the current
+ * MaxCode value, increment the code size unless it's already 12. If it
+ * is, do nothing: the next code decompressed better be CLEAR
+ */
+
+ FreeCode++;
+ if (FreeCode >= MaxCode) {
+ if (CodeSize < 12) {
+ CodeSize++;
+ MaxCode *= 2;
+ ReadMask = (1 << CodeSize) - 1;
+ }
+ }
+ }
+ Code = ReadCode();
+ }
+
+ return Image;
+}
+
+
diff --git a/hl/tools/gif2h5/gif.h b/hl/tools/gif2h5/gif.h
new file mode 100644
index 0000000..f697881
--- /dev/null
+++ b/hl/tools/gif2h5/gif.h
@@ -0,0 +1,179 @@
+/****************************************************************************\
+** Title: GIF.H **
+** Purpose: GIF Header file **
+\****************************************************************************/
+
+#ifndef GIF_H
+#define GIF_H 1
+
+#include <hdf5.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define MAX_PAL 768
+
+/*#include "datatype.h" Data type definitions */
+
+/* set the name length restriction to 64 charachters */
+#define VSNAMELENMAX 64 /* this is a carryover from HDF4 */
+
+/* typedef H5T_NATIVE_UINT8 BYTE; */
+typedef unsigned char BYTE;
+
+/* typedef H5T_NATIVE_UINT16 WORD; */
+typedef unsigned long WORD;
+
+typedef char CHAR;
+typedef unsigned char boolean;
+
+#define false 0;
+#define true 1;
+
+/* Set the EndianOrder.
+** The GIF Reader file should do this.
+** Set EndianOrder = 0 if machine is little endian
+** EndianOrder = 1 if machine is big endian.
+*/
+extern int EndianOrder;
+
+/*
+** The GIF header format.
+**
+** This structure actually contains the header, logical screen
+** descriptor, and the global color table for the GIF image.
+*/
+typedef struct _GifHeader /* Offset Description */
+{
+ BYTE PackedField; /* 0Ah Color Information */
+ WORD TableSize;
+ BYTE ImageCount; /* Keep a count of the number of images */
+ BYTE CommentCount;
+ BYTE ApplicationCount;
+ BYTE PlainTextCount;
+ BYTE HDFPalette[256][3];
+ BYTE HeaderDump[6]; /* BYTE array to dump header contents */
+ BYTE LSDDump[7]; /* Logical Screen Descriptor dump */
+} GIFHEAD;
+
+
+/*
+** The GIF Image Descriptor.
+*/
+typedef struct _GifImageDescriptor
+{
+ WORD ImageWidth; /* Width of the image in pixels */
+ WORD ImageHeight; /* Height of the image in pixels */
+ BYTE PackedField; /* Image and Color Table Data Information */
+ WORD TableSize;
+ WORD CodeSize; /* Minimum LZW CodeSize for image data */
+ BYTE HDFPalette[256][3];
+ BYTE GIDDump[9]; /* GifImageDescriptor dump */
+
+ BYTE *Image; /* Decompressed Raster Image */
+ BYTE *GIFImage;
+} GIFIMAGEDESC;
+
+
+/*
+** GIF 89a Graphic Control Extension Block
+*/
+typedef struct _GifGraphicControlExtension
+{
+ BYTE GCEDump[5]; /* Graphic Control Extension Dump */
+} GIFGRAPHICCONTROL;
+
+
+/*
+** GIF 89a Plain Text Extension Block
+*/
+typedef struct _GifPlainTextExtension
+{
+ BYTE PTEDump[15]; /* Plain Text Extension Dump */
+ BYTE *PlainTextData; /* Plain Text data sub-blocks */
+ WORD DataSize;
+} GIFPLAINTEXT;
+
+
+/*
+** GIF 89a Application Extension Block
+*/
+typedef struct _GifApplicationExtension
+{
+ BYTE AEDump[14]; /* Application Extension Dump */
+ BYTE *ApplicationData; /* Application data sub-blocks */
+ WORD DataSize;
+} GIFAPPLICATION;
+
+/*
+** GIF 89a Comment Extension Block
+*/
+typedef struct _GifCommentExtension
+{
+ BYTE CEDump[2]; /* Comment Extension Dump */
+ BYTE *CommentData; /* Comment data sub-blocks */
+ WORD DataSize;
+ BYTE Terminator; /* Block Terminator (always 0) */
+} GIFCOMMENT;
+
+/*
+** GIF to HDF Memory Struct
+** Purpose : The gif to hdf structure is used to pass all the
+** gif data to the memory, which gets caught by the hdf driver
+** Its the drivers job to put the data in the appropriate places
+** in the HDF file.
+** I have assumed that the ImageDescriptors and GraphicControls follow
+** one another, ie. I have not associated them with each other. The driver
+** must assume a 1-1 correspondance. The same discussion with plain text
+** extension.
+*/
+typedef struct _GifToMem
+{
+ GIFHEAD *GifHeader;
+ GIFIMAGEDESC **GifImageDesc;
+ GIFGRAPHICCONTROL **GifGraphicControlExtension;
+ GIFPLAINTEXT **GifPlainTextExtension;
+ GIFAPPLICATION **GifApplicationExtension;
+ GIFCOMMENT **GifCommentExtension;
+} GIFTOMEM;
+
+
+/*
+** Function Prototypes
+*/
+/* GIF2MEM.C */
+GIFTOMEM Gif2Mem(BYTE *);
+
+/* GIFREAD.C */
+int ReadGifHeader(GIFHEAD *, BYTE **);
+int ReadGifImageDesc(GIFIMAGEDESC *, BYTE **);
+int ReadGifGraphicControl(GIFGRAPHICCONTROL *, BYTE **);
+int ReadGifPlainText(GIFPLAINTEXT *, BYTE **);
+int ReadGifApplication(GIFAPPLICATION *, BYTE **);
+int ReadGifComment(GIFCOMMENT *, BYTE **);
+
+/* WRITEHDF.C */
+int WriteHDF(GIFTOMEM , CHAR * , CHAR *);
+
+/* Function : ReadHDF
+** Return: 0 on completion without error, -1 on error
+** Input: CHAR *h5_file - HDF file name
+** CHAR *dset_name - Name of the HDF Image dataset
+** CHAR *pal_name - Name of the HDF palette
+** Output : BYTE* data - the HDF Image to be converted
+** BYTE palette[256][3] - the corresponding palette
+** hsize_t* image_size - the size of each dimension of the image
+**
+*/
+int ReadHDF(BYTE** data , BYTE palette[256][3] , hsize_t *image_size , CHAR *h5_file , CHAR *dset_name , CHAR *pal_name);
+
+BYTE *ReadDataSubBlocks(BYTE ** , WORD *);
+BYTE *Decompress (GIFIMAGEDESC * , GIFHEAD *);
+BYTE GetByte(BYTE *);
+WORD GetWord(BYTE *);
+
+void cleanup(BYTE*);
+#endif /* GIF_H */
+
diff --git a/hl/tools/gif2h5/gif2hdf.c b/hl/tools/gif2h5/gif2hdf.c
new file mode 100644
index 0000000..0211143
--- /dev/null
+++ b/hl/tools/gif2h5/gif2hdf.c
@@ -0,0 +1,114 @@
+/* #include <hdf.h> */
+#include "gif.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+int
+main(argv , argc)
+int argv;
+char *argc[];
+{
+
+ GIFTOMEM GifMemoryStruct;
+ GIFIMAGEDESC gifImageDesc;
+
+ FILE *fpGif;
+
+ /* replacing int32 with long */
+ long i,ImageCount;
+ long filesize;
+
+ BYTE *MemGif;
+ BYTE *StartPos;
+
+ /* VSNAMELENMAX is a carryover from HDF4 and is #defined to 256 in gif.h */
+ char GIFFileName[VSNAMELENMAX];
+ char HDFFileName[VSNAMELENMAX];
+
+ /* Initialize all GifMemoryStruct pointers to null
+ ** to prevent hassles later on
+ */
+ GifMemoryStruct.GifHeader = NULL;
+ GifMemoryStruct.GifImageDesc = NULL;
+ GifMemoryStruct.GifGraphicControlExtension = NULL;
+ GifMemoryStruct.GifPlainTextExtension = NULL;
+ GifMemoryStruct.GifApplicationExtension = NULL;
+ GifMemoryStruct.GifCommentExtension = NULL;
+
+
+ if (argv<3)
+ {
+ printf("\n\nWrong Usage. Use:\ngif2hdf <GIFFILE> <HDFFILE>\n\n");
+ return(-1);
+ }
+
+
+
+ strncpy(GIFFileName , argc[1] , VSNAMELENMAX - 1);
+ strncpy(HDFFileName , argc[2] , VSNAMELENMAX - 1);
+ GIFFileName[VSNAMELENMAX - 1] = '\0';
+ HDFFileName[VSNAMELENMAX - 1] = '\0';
+
+ if (!(fpGif = fopen(GIFFileName,"rb"))) {
+ printf("Unable to open GIF file for reading.\n");
+ printf("Filename (including path) must be less than %d charachters in length\n",VSNAMELENMAX);
+ exit(-1);
+ }
+
+ /* Get the whole file into memory. Mem's much faster than I/O */
+ fseek(fpGif, 0L , 2);
+ filesize = ftell(fpGif);
+ fseek(fpGif, 0L , 0);
+ if (filesize == 0) printf("File Size Zero");
+ if (!(MemGif = StartPos = (BYTE *)malloc(filesize))) {
+ printf("Out of memory");
+ exit (-1);
+ }
+ if (fread(MemGif,filesize,1,fpGif) != 1) {
+ printf("Corrupted Input File");
+ exit(-1);
+ }
+
+ fseek(fpGif,0L,0);
+
+ /*
+ ** Call Gif2Mem and break the whole file into parts.
+ ** Gif2Mem also calls decompresses the images so we don't
+ ** have to worry about that
+ */
+ GifMemoryStruct = Gif2Mem(MemGif);
+ if (ferror(fpGif)) {
+ printf("File Stream Error\n\n");
+ exit(-1);
+ }
+ fclose(fpGif);
+
+ /* Call WriteHDF from here. Go ahead and change WriteHDF to write
+ ** whatever format you want
+ */
+ if (WriteHDF(GifMemoryStruct , argc[2] , argc[1]))
+ printf("HDF Write Error\n\n");
+
+ /* Free all buffers */
+ /* replacing int32 with long */
+ ImageCount = (long)((GifMemoryStruct.GifHeader)->ImageCount);
+
+ for(i = 0 ; i < ImageCount ; i++)
+ {
+ gifImageDesc = *(GifMemoryStruct.GifImageDesc[i]);
+ if (gifImageDesc.Image != NULL)
+ free(gifImageDesc.Image);
+
+ if (GifMemoryStruct.GifGraphicControlExtension[i] != NULL)
+ free(GifMemoryStruct.GifGraphicControlExtension[i]);
+
+ }
+ free(StartPos);
+
+ free (GifMemoryStruct.GifHeader);
+
+ if (GifMemoryStruct.GifApplicationExtension != NULL)
+ free (GifMemoryStruct.GifApplicationExtension);
+
+ return (0);
+}
diff --git a/hl/tools/gif2h5/gif2mem.c b/hl/tools/gif2h5/gif2mem.c
new file mode 100644
index 0000000..92ca8e5
--- /dev/null
+++ b/hl/tools/gif2h5/gif2mem.c
@@ -0,0 +1,344 @@
+/*
+** This file contains snippets of code from James Murray's original file
+** to display the GIF header information, but most of it has been modified to
+** suit gif2hdf
+*/
+
+
+
+/****************************************************************************\
+** Title: GIFHEAD.C **
+** Purpose: Display the data in a GIF image file. **
+** Version: 1.0 **
+** Date: March 1992 **
+** Author: James D. Murray, Anaheim, CA, USA **
+** C Compilers: Borland C++ v2.0, Microsoft C v6.00a **
+** **
+** GIFHEAD displays all real information contained within a GIF image **
+** file, including all color tables and extension block information. **
+** GIFHEAD reads both GIF 87a abd 89a-format files. **
+** **
+** Copyright (C) 1991-92 by Graphics Software Labs. All rights reserved. **
+\****************************************************************************/
+#include <stdio.h>
+#include "gif.h"
+/* #include <hdf.h> */
+
+#define VERSION "1.00"
+extern int EndianOrder;
+
+GIFTOMEM
+Gif2Mem(MemGif)
+BYTE *MemGif;
+{
+ /*
+ ** The gif structure outline for passing data to memory
+ ** is given in gif.h
+ ** These pointers are redunant, should take them out in ver. 2
+ */
+ GIFHEAD *gifHead; /* GIF Header structure */
+ GIFIMAGEDESC **gifImageDesc; /* Logical Image Descriptor struct */
+ GIFPLAINTEXT **gifPlainText; /* Plain Text Extension structure */
+ GIFAPPLICATION **gifApplication; /* Application Extension structure */
+ GIFCOMMENT **gifComment; /* Comment Extension structure */
+ GIFGRAPHICCONTROL **gifGraphicControl; /* Graphic Control Extension strct */
+
+ GIFTOMEM GifMemoryStruct;
+
+
+
+ register WORD i; /* Loop counter */
+ BYTE Identifier; /* Extension block identifier holder */
+ BYTE Label; /* Extension block label holder */
+ BYTE ImageCount; /* Count of the number of images in the file */
+ BYTE ImageArray; /* Keep the size of the array to store Images */
+ BYTE CommentCount;
+ BYTE CommentArray;
+ BYTE ApplicationCount;
+ BYTE ApplicationArray;
+ BYTE PlainTextCount;
+ BYTE PlainTextArray;
+ BYTE GCEflag;
+ BYTE aTemp;
+ BYTE j;
+
+ BYTE w; /* Two more variables needed only while testing */
+ BYTE *b; /* Endian Ordering */
+
+ /* Allocate memory for the GIF structures */
+ /* Plug the structs into GifMemoryStruct at the end */
+ /****************************************************/
+ if (!(gifHead = (GIFHEAD *)malloc(sizeof(GIFHEAD))))
+ {
+ printf("Could not allocate memory for gifHead\n");
+ exit(-1);
+ }
+
+ /*
+ ** The next three have to grow dynamically so we leave them
+ ** for now and let realloc handle it later on.
+ */
+ gifImageDesc = NULL;
+ gifPlainText = NULL;
+ gifGraphicControl = NULL;
+ gifComment = NULL;
+ gifApplication = NULL;
+
+ /******************************/
+ /* Memory allocation complete */
+
+
+ /* Carry out Endian Testing and set Endian Order */
+ w = 0x0001;
+ b = (BYTE *) &w;
+ EndianOrder = (b[0] ? 1 : 0);
+
+ /* Read the GIF image file header information */
+ ReadGifHeader(gifHead, &MemGif);
+
+ /* Check for FILE stream error */
+ /*
+ if (ferror(fpGif))
+ {
+ fputs("GIFHEAD: Error reading header information!\n", stderr);
+ exit(-3);
+ }
+ */
+
+ /*
+ ** Identify, read, and display block information.
+ */
+ ImageCount = ImageArray = 0;
+ CommentCount = CommentArray = 0;
+ ApplicationCount = ApplicationArray = 0;
+ PlainTextCount = PlainTextArray = 0;
+ GCEflag = 0;
+
+ for (;;)
+ {
+ Identifier = *MemGif++;
+
+ switch (Identifier)
+ {
+ case 0x3B: /* Trailer */
+ /* The counts are stored to make it easier while
+ ** putting stuff into the HDF file and then
+ ** deallocating space.
+ */
+ gifHead->ImageCount = ImageCount;
+ gifHead->CommentCount = CommentCount;
+ gifHead->ApplicationCount = ApplicationCount;
+ gifHead->PlainTextCount = PlainTextCount;
+
+ /* putting stuff into the gif2mem structure */
+ GifMemoryStruct.GifHeader = gifHead;
+ GifMemoryStruct.GifImageDesc = gifImageDesc;
+ GifMemoryStruct.GifPlainTextExtension = gifPlainText;
+ GifMemoryStruct.GifApplicationExtension = gifApplication;
+ GifMemoryStruct.GifCommentExtension = gifComment;
+ GifMemoryStruct.GifGraphicControlExtension = gifGraphicControl;
+
+ /* return the struct */
+ return GifMemoryStruct;
+
+
+
+ case 0x2C: /* Image Descriptor */
+ /* If there was no image descriptor before this increase image count.
+ ** If an imagedescriptor was present, reset GCEflag
+ */
+ if (GCEflag == 0)
+ ImageCount++;
+ else
+ GCEflag = 0;
+
+ if (ImageCount > ImageArray) {
+ aTemp = ImageArray;
+ ImageArray = (ImageArray << 1) + 1;
+ if (!(gifImageDesc = (GIFIMAGEDESC **)realloc(gifImageDesc , sizeof(GIFIMAGEDESC *) * ImageArray)))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+ if (!(gifGraphicControl = (GIFGRAPHICCONTROL **)realloc(gifGraphicControl , sizeof(GIFGRAPHICCONTROL *) * ImageArray)))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+
+ for (j = aTemp ; j < ImageArray ; j++) {
+ gifGraphicControl[j] = NULL;
+ gifImageDesc[j] = NULL;
+ }
+ }
+
+ if(!(gifImageDesc[ImageCount-1] = (GIFIMAGEDESC*)malloc(sizeof(GIFIMAGEDESC))))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+
+
+ if (ReadGifImageDesc(gifImageDesc[ImageCount-1], &MemGif) == -1)
+ fputs("Error reading Image Descriptor information\n", stderr);
+
+ /*
+ ** Decompress the Image
+ */
+ gifImageDesc[ImageCount-1]->Image = Decompress(gifImageDesc[ImageCount-1] , gifHead);
+ free(gifImageDesc[ImageCount-1]->GIFImage);
+
+ /*
+ ** Convert the local palette into an HDF compatible palette
+ ** In case the local color table is present, it is written out as the HDFPalette
+ ** If it is absent the global table is written as the HDFPalette.
+ */
+ if (!((gifImageDesc[ImageCount-1]->PackedField) & 0x80))
+ {
+ /* Check to see if the global color table exists.... */
+ if (gifHead->PackedField & 0x80) {
+ for (i=0 ; i<gifHead->TableSize ; i++)
+ {
+ gifImageDesc[ImageCount-1]->HDFPalette[i][0] = gifHead->HDFPalette[i][0];
+ gifImageDesc[ImageCount-1]->HDFPalette[i][1] = gifHead->HDFPalette[i][1];
+ gifImageDesc[ImageCount-1]->HDFPalette[i][2] = gifHead->HDFPalette[i][2];
+ }
+ }
+ gifImageDesc[ImageCount-1]->TableSize = gifHead->TableSize;
+ }
+
+ break;
+
+ case 0x21: /* Extension Block */
+ Label = *MemGif++;
+ switch (Label)
+ {
+ case 0x01: /* Plain Text Extension */
+ puts("Plain Text Extension\n");
+
+ PlainTextCount++;
+ if (PlainTextCount > PlainTextArray)
+ PlainTextArray = (PlainTextArray << 1) + 1;
+
+ if (!(gifPlainText = (GIFPLAINTEXT **)realloc(gifPlainText , sizeof(GIFPLAINTEXT *) * PlainTextArray)))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+
+ if(!(gifPlainText[PlainTextCount - 1] = (GIFPLAINTEXT*)malloc(sizeof(GIFPLAINTEXT))))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+
+
+
+ if (ReadGifPlainText(gifPlainText[PlainTextCount - 1], &MemGif))
+ fprintf(stderr,
+ "Error reading Plain Text Extension information.\n");
+
+ break;
+
+ case 0xFE: /* Comment Extension */
+ CommentCount++;
+ if (CommentCount > CommentArray)
+ CommentArray = (CommentArray << 1) + 1;
+
+ if (!(gifComment = (GIFCOMMENT **)realloc(gifComment , sizeof(GIFCOMMENT *) * CommentArray)))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+
+ if(!(gifComment[CommentCount - 1] = (GIFCOMMENT *)malloc(sizeof(GIFCOMMENT))))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+
+
+ if (ReadGifComment(gifComment[CommentCount - 1], &MemGif))
+ fprintf(stderr,
+ "Error reading Comment Extension information\n");
+ break;
+
+ case 0xF9: /* Graphic Control Extension */
+ if (GCEflag == 0 )
+ ImageCount++;
+
+ GCEflag = 1;
+
+ if (ImageCount > ImageArray) {
+ aTemp = ImageArray;
+ ImageArray = (ImageArray << 1) + 1;
+ if (!(gifGraphicControl = (GIFGRAPHICCONTROL **)realloc(gifGraphicControl , sizeof(GIFGRAPHICCONTROL *) * ImageArray)))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+ if (!(gifImageDesc = (GIFIMAGEDESC **)realloc(gifImageDesc , sizeof(GIFIMAGEDESC *) * ImageArray)))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+ for (j = aTemp ; j < ImageArray ; j++) {
+ gifGraphicControl[j] = NULL;
+ gifImageDesc[j] = NULL;
+ }
+ }
+
+ if(!(gifGraphicControl[ImageCount-1] = (GIFGRAPHICCONTROL*)malloc(sizeof(GIFGRAPHICCONTROL))))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+
+
+ if (ReadGifGraphicControl(gifGraphicControl[ImageCount-1], &MemGif))
+ fprintf(stderr,
+ "Error reading Graphic Control Extension information\n");
+
+ if (!*MemGif++ == 0)
+ fprintf(stderr,
+ "Error reading Graphic Control Extension\n");
+
+ break;
+
+ case 0xFF: /* Application Extension */
+ ApplicationCount++;
+ if (ApplicationCount > ApplicationArray)
+ ApplicationArray = (ApplicationArray << 1) + 1;
+
+ if (!(gifApplication = (GIFAPPLICATION **)realloc(gifApplication , sizeof(GIFAPPLICATION *) * ApplicationArray)))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+
+ if(!(gifApplication[ApplicationCount - 1] = (GIFAPPLICATION *)malloc(sizeof(GIFAPPLICATION))))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+
+
+ if (ReadGifApplication(gifApplication[ApplicationCount - 1], &MemGif))
+ fprintf(stderr,
+ "Error reading Application Extension information\n");
+ break;
+
+ default:
+
+ printf("Unknown Extension Label: 0x%02x\n", Label);
+ break;
+ }
+ break;
+ default:
+ fprintf(stderr, "Unknown Block Separator Character: 0x%02x\n",
+ Identifier);
+ }
+ }
+
+
+}
diff --git a/hl/tools/gif2h5/gifread.c b/hl/tools/gif2h5/gifread.c
new file mode 100644
index 0000000..1196241
--- /dev/null
+++ b/hl/tools/gif2h5/gifread.c
@@ -0,0 +1,382 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "gif.h"
+
+int EndianOrder;
+int i;
+
+
+WORD
+GetWord (MemGif)
+BYTE *MemGif;
+{
+ register WORD w;
+ if (EndianOrder == 1) /* LittleEndian */
+ {
+ w = (WORD) (*MemGif++ & 0xFF);
+ w |= (WORD) ((*MemGif++ & 0xFF) << 0x08);
+ }
+ else
+ {
+ w = (WORD) (*MemGif++ & 0xFF);
+ w = ((WORD) (*MemGif++ & 0xFF)) | (w << 0x08);
+ }
+ return w;
+}
+
+BYTE
+GetByte (MemGif)
+BYTE *MemGif;
+{
+ return *MemGif;
+}
+
+/*
+** Read a GIF image BYTE Header.
+**
+** This function reads the Header, Logical Screen Descriptor, and
+** Global Color Table (if any) from a GIF image file. The information
+** is stored in a GIFHEAD structure.
+**
+** Returns: -1 if a FILE stream error occured during the read,
+** otherwise 0 if no error occured.
+*/
+int
+ReadGifHeader(GifHead, MemGif2)
+GIFHEAD *GifHead; /* Pointer to GIF header structure */
+BYTE **MemGif2; /* GIF image file input FILE stream */
+{
+ register WORD i; /* Loop counter */
+ WORD tableSize; /* Number of entires in the Global Color Table */
+
+ GifHead->TableSize = 0;
+ for (i = 0 ; i < 6 ; i++) {
+ GifHead->HeaderDump[i] = *(*MemGif2)++;
+ }
+ if (strncmp(GifHead->HeaderDump , "GIF" , 3)) {
+ printf("The file does not appear to be a valid GIF file.\n");
+ exit(-1);
+ }
+
+ for (i = 0 ; i < 7 ; i++) {
+ GifHead->LSDDump[i] = *(*MemGif2)++;
+ }
+
+ GifHead->PackedField = GifHead->LSDDump[4];
+ /* Check if a Global Color Table is present */
+ if (GifHead->PackedField & 0x80)
+ {
+ /* Read number of color table entries */
+ tableSize = (WORD) (1L << ((GifHead->PackedField & 0x07) + 1));
+ GifHead->TableSize = tableSize;
+ /* Read the Global Color Table */
+ /*
+ ** There are some changes made here apart from just
+ ** reading in the global color table as would
+ ** seem intuitively obvious.
+ ** The colors are stored in the bottom part of the
+ ** palette as opposed to the top
+ */
+
+ for (i = 0; i < tableSize; i++)
+ {
+ GifHead->HDFPalette[i][0] = *(*MemGif2)++;
+ GifHead->HDFPalette[i][1] = *(*MemGif2)++;
+ GifHead->HDFPalette[i][2] = *(*MemGif2)++;
+ }
+ }
+
+ /* Check for a FILE stream error */
+ /*
+ if (ferror(FpGif))
+ return(-1);
+ */
+
+ return(0); /* No FILE stream error occured */
+}
+
+
+/*
+** Read a GIF Local Image Descriptor.
+**
+** This function reads the Local Image Descriptor, and Local Color
+** Table (if any) from a GIF image file. The information is stored
+** in a GIFIMAGEDESC structure.
+**
+** Note that the ImageSeparator field value in the GIFIMAGEDESC
+** structure is assigned by the function calling ReadGifImageDesc().
+**
+** Returns: -1 if a FILE stream error occured during the read,
+** otherwise 0 if no error occured.
+*/
+int
+ReadGifImageDesc(GifImageDesc, MemGif2)
+GIFIMAGEDESC *GifImageDesc; /* Pointer to GIF image descriptor structure */
+BYTE **MemGif2; /* GIF image file input FILE stream */
+{
+ register WORD i; /* Loop counter */
+ WORD tableSize; /* Number of entries in the Local Color Table */
+ BYTE Interlace; /* PackedField & 0x20 gives information on interlacing */
+ BYTE *TempPtr;
+ int ch , ch1;
+
+ GifImageDesc->TableSize = 0;
+ for (i = 0 ; i < 9 ; i++) {
+ GifImageDesc->GIDDump[i] = *(*MemGif2)++;
+ }
+
+ /*
+ ** Get the relevant fields. I need ImageWidth and Height actively hence I have
+ ** taken information from those fields. I intend to keep the GifImageDesc data
+ ** structure as it is so that anyone needing the rest of the fields can do so
+ ** quickly.
+ */
+
+ if (EndianOrder == 1) /* LittleEndian */
+ {
+ GifImageDesc->ImageWidth = (WORD) (GifImageDesc->GIDDump[4] & 0xFF);
+ GifImageDesc->ImageWidth |= (WORD) ((GifImageDesc->GIDDump[5] & 0xFF) << 0x08);
+
+ GifImageDesc->ImageHeight = (WORD) (GifImageDesc->GIDDump[6] & 0xFF);
+ GifImageDesc->ImageHeight |= (WORD) ((GifImageDesc->GIDDump[7] & 0xFF) << 0x08);
+
+ }
+ else
+ {
+ GifImageDesc->ImageWidth = (WORD) (GifImageDesc->GIDDump[4] & 0xFF);
+ GifImageDesc->ImageWidth = ((WORD) (GifImageDesc->GIDDump[5] & 0xFF)) | (GifImageDesc->ImageWidth << 0x08);
+
+ GifImageDesc->ImageHeight = (WORD) (GifImageDesc->GIDDump[6] & 0xFF);
+ GifImageDesc->ImageHeight = ((WORD) (GifImageDesc->GIDDump[7] & 0xFF)) | (GifImageDesc->ImageWidth << 0x08);
+
+
+ }
+
+ GifImageDesc->PackedField = GifImageDesc->GIDDump[8];
+
+ /* Interlace = GifImageDesc->PackedField & 0x20; */
+
+ /* Check if a Local Color Table is present */
+ if (GifImageDesc->PackedField & 0x80)
+ {
+ /* Read number of color table entries */
+ tableSize = (WORD) (1L << ((GifImageDesc->PackedField & 0x07) + 1));
+ GifImageDesc->TableSize = tableSize;
+ /* Read the Local Color Table */
+ for (i = 0; i < tableSize; i++)
+ {
+ GifImageDesc->HDFPalette[i][0] = *(*MemGif2)++;
+ GifImageDesc->HDFPalette[i][1] = *(*MemGif2)++;
+ GifImageDesc->HDFPalette[i][2] = *(*MemGif2)++;
+ }
+ }
+
+ /*
+ ** Get LZW minimum Code Size
+ */
+ GifImageDesc->CodeSize = (WORD)*(*MemGif2)++;
+
+ /*GifImageDesc->GIFImage = ReadDataSubBlocks(FpGif);*/
+ if (!(GifImageDesc->GIFImage = (BYTE *)malloc((GifImageDesc->ImageWidth) * (GifImageDesc->ImageHeight)))) {
+ printf("Out of memory");
+ exit(-1);
+ }
+
+
+ TempPtr = GifImageDesc->GIFImage;
+ do
+ {
+ ch = ch1 = (int)*(*MemGif2)++;
+ while (ch--) *TempPtr++ = *(*MemGif2)++;
+ }
+ while (ch1);
+
+
+ return(0); /* No FILE stream error occured */
+}
+
+
+/*
+** Read a GIF Graphic Control Extension block.
+**
+** Note that the Introducer and Label field values in the GIFGRAPHICCONTROL
+** structure are assigned by the function calling ReadGifGraphicControl().
+**
+** Returns: -1 if a FILE stream error occured during the read,
+** otherwise 0 if no error occured.
+*/
+int
+ReadGifGraphicControl(GifGraphicControl, MemGif2)
+GIFGRAPHICCONTROL *GifGraphicControl; /* Pointer to GC Extension structure */
+BYTE **MemGif2; /* GIF image file input FILE stream */
+{
+
+
+ for (i = 0 ; i < 5 ; i++) {
+ GifGraphicControl->GCEDump[i] = *(*MemGif2)++;
+ }
+
+ return(0); /* No FILE stream error occured */
+}
+
+
+/*
+** Read a GIF Plain Text Extension block.
+**
+** Note that the Introducer and Label field values in the GIFLPLAINTEXT
+** structure are assigned by the function calling ReadGifPlainText().
+**
+** Returns: -1 if a FILE stream error occured during the read,
+** otherwise 0 if no error occured.
+*/
+int
+ReadGifPlainText(GifPlainText, MemGif2)
+GIFPLAINTEXT *GifPlainText; /* Pointer to Plain Text Extension structure */
+BYTE **MemGif2; /* GIF image file input FILE stream */
+{
+ for (i = 0 ; i < 13 ; i++) {
+ GifPlainText->PTEDump[i] = *(*MemGif2)++;
+ }
+
+ /* Read in the Plain Text data sub-blocks */
+ if (!(GifPlainText->PlainTextData = ReadDataSubBlocks(MemGif2 , &(GifPlainText->DataSize))))
+ return(1);
+
+ /*
+ GifPlainText->Terminator = 0;
+ */
+
+ /* Check for a FILE stream error */
+ /*
+ if (ferror(FpGif))
+ return(-1);
+ */
+
+ return(0); /* No FILE stream error occured */
+}
+
+
+/*
+** Read a GIF Application Extension block.
+**
+** Note that the Introducer and Label field values in the GIFAPPLICATION
+** structure are assigned by the function calling ReadGifApplication().
+**
+** Returns: -1 if a FILE stream error occured during the read,
+** otherwise 0 if no error occured.
+*/
+int
+ReadGifApplication(GifApplication, MemGif2)
+GIFAPPLICATION *GifApplication; /* Pointer to Application Extension structure */
+BYTE **MemGif2; /* GIF image file input FILE stream */
+{
+ for (i = 0 ; i < 12 ; i++) {
+ GifApplication->AEDump[i] = *(*MemGif2)++;
+ }
+
+ /* Read in the Plain Text data sub-blocks */
+ if (!(GifApplication->ApplicationData = ReadDataSubBlocks(MemGif2 , &(GifApplication->DataSize))))
+ return(1);
+ /*
+ GifApplication->Terminator = 0;
+ */
+
+ /* Check for a FILE stream error */
+ /*
+ if (ferror(FpGif))
+ return(-1);
+ */
+
+ return(0); /* No FILE stream error occured */
+}
+
+
+/*
+** Read a GIF Comment Extension block.
+**
+** Note that the Introducer and Label field values in the GIFCOMMENT
+** structure are assigned by the function calling ReadGifComment().
+**
+** Returns: -1 if a FILE stream error occured during the read,
+** otherwise 0 if no error occured.
+*/
+int
+ReadGifComment(GifComment, MemGif2)
+GIFCOMMENT *GifComment; /* Pointer to GIF Comment Extension structure */
+BYTE **MemGif2; /* GIF image file input FILE stream */
+{
+
+ /* Read in the Plain Text data sub-blocks */
+ if (!(GifComment->CommentData = ReadDataSubBlocks(MemGif2 , &(GifComment->DataSize))))
+ return(1);
+
+ GifComment->Terminator = 0;
+
+ return(0); /* No FILE stream error occured */
+}
+
+
+/*
+** Read one or more GIF data sub-blocks and write the information
+** to a buffer.
+**
+** A GIF "sub-block" is a single count byte followed by 1 to 255
+** additional data bytes.
+**
+** Returns: A NULL pointer if a memory allocation error occured,
+** otherwise a valid pointer if no error occured.
+*/
+static BYTE *
+ReadDataSubBlocks(MemGif2 , DSize)
+BYTE **MemGif2; /* GIF image file input FILE stream */
+WORD *DSize;
+{
+ BYTE *ptr1; /* Pointer used to "walk the heap" */
+ BYTE *ptr2; /* Pointer used to mark the top of the heap */
+ BYTE dataSize; /* Size of the current data sub-block being read */
+ WORD bufSize; /* Total size of the Plain Text data buffer */
+ int tempcount = 0;
+
+ bufSize = 0; /* The output buffer is empty */
+
+ dataSize = *(*MemGif2)++; /* Get the size of the first sub-block */
+
+ /* Allocate initial data buffer */
+ if (!(ptr1 = ptr2 = (BYTE *) malloc(dataSize + 1))) {
+ printf("Out of memory. Allocation of memory for data sub-blocks for\neither Comment, Plain Text or Application Extensions failed");
+ return((BYTE *) NULL);
+ }
+ for (;;)
+ {
+ tempcount++;
+ bufSize += (dataSize); /* Running total of the buffer size */
+ *DSize = bufSize;
+
+ /* *ptr1++ = dataSize; /* Write the data count */
+ while (dataSize--) /* Read/write the Plain Text data */
+ *ptr1++ = *(*MemGif2)++;
+
+ /* Check if there is another data sub-block */
+ if ((dataSize = *(*MemGif2)++) == 0)
+ break; /* Block Terminator encountered */
+
+ /* Increase the buffer size to accomodate the next sub-block */
+ if (!(ptr1 = ptr2 = (BYTE *) realloc(ptr2, bufSize + dataSize + 1)))
+ return((BYTE *) NULL);
+
+
+ ptr1 += bufSize; /* Move pointer to the end of the data */
+
+
+ }
+
+ /**ptr1++ = (BYTE) NULL; /* Add NULL to simulate Terminator value */
+ *ptr1++ = '\0';
+
+ return(ptr2); /* Return a pointer to the sub-block data */
+}
+
+
+
+
+
diff --git a/hl/tools/gif2h5/hdf2gif.c b/hl/tools/gif2h5/hdf2gif.c
new file mode 100644
index 0000000..9c4133e
--- /dev/null
+++ b/hl/tools/gif2h5/hdf2gif.c
@@ -0,0 +1,354 @@
+/* NOTES:
+** 04/01 - 04/10: been working on it a lot. I think it does gif89 images just fine with
+** palettes. So that's cool. Putting in multiple images and animation support right now
+** 03/29: For some reason I can write .GIF files which IE will open and see but
+** kodak imaging does not like. I'm sure its a problem with the GIF file,
+** I can't figure out what.
+** 03/17: Explicitely deallocate the GIFTOMEM* struct in the main loop.
+** Check for both success and failure conditions
+*/
+
+#include "gif.h"
+#include <stdio.h>
+
+#define MAX_FILE_LEN 256
+#define MAX_NUMBER_IMAGES 50
+
+extern int hdfWriteGIF(FILE *fp, BYTE *pic, int ptype, int w, int h, BYTE *rmap,
+ BYTE *gmap, BYTE *bmap, BYTE *pc2ncmap, int numcols, int colorstyle, int BitsPerPixel);
+
+int EndianOrder;
+
+void PutByte(BYTE b , FILE *fpGif)
+{
+ if (fputc(b , fpGif) == EOF) {
+ printf("File Writing Error, cannot continue");
+ exit(-1);
+ }
+}
+
+
+void putword(int w, FILE *fp)
+{
+ /* writes a 16-bit integer in GIF order (LSB first) */
+
+ fputc(w &0xff, fp);
+
+ fputc((w>>8)&0xff,fp);
+}
+
+void usage() {
+ printf("Usage: h52gif <h5_file> <gif_file> -i <h5_image> [-p <h5_palette>]\n");
+ printf("h52gif expects *at least* one h5_image. You may repeat -i <h5_image> [-p <h5_palette>] at most 50 times (maximum of 50 images).\n");
+}
+
+int main(int argc , char **argv) {
+
+ FILE *fpGif;
+
+ hsize_t dim_sizes[2];
+
+ BYTE *Image;
+ /* compression structs */
+
+ CHAR *HDFName = NULL;
+ CHAR *GIFName = NULL;
+ CHAR *image_path = NULL;
+ CHAR *pal_path = NULL;
+ /* reference variables */
+
+ int has_local_palette; /* treated as a flag */
+ int loop_times; /* number of times to loop, i'm going to treat it as a yes or no */
+
+ BYTE* b;
+
+ BYTE GlobalPalette[256][3];
+ BYTE Red[256];
+ BYTE Green[256];
+ BYTE Blue[256];
+
+ int RWidth, RHeight;
+ int LeftOfs, TopOfs;
+ int ColorMapSize, InitCodeSize, Background, BitsPerPixel;
+ int j,nc;
+ int w,h,i;
+ int numcols = 256;
+ int CountDown;
+ int curx , cury;
+ int time_out = 0; /* time between two images in the animation */
+ int n_images , index;
+
+ BYTE pc2nc[256] , r1[256] , g1[256] , b1[256];
+
+ /* initial stuff */
+ int number_of_images = 0;
+ int arg_index = 2;
+ int bool_is_image = 0; /* 0 = false , 1 = true */
+ int bool_is_palette = 0;
+ CHAR* image_name_arr[MAX_NUMBER_IMAGES];
+ CHAR* pal_name_arr[MAX_NUMBER_IMAGES];
+
+ if (argc < 5) {
+ /* they didn't supply at least one image -- bail */
+ usage();
+ return 0;
+ }
+
+ memset(image_name_arr , NULL , MAX_NUMBER_IMAGES);
+ memset(pal_name_arr , NULL , MAX_NUMBER_IMAGES);
+
+ HDFName = (CHAR*) malloc (strlen(argv[1]) + 1);
+ GIFName = (CHAR*) malloc (strlen(argv[2]) + 1);
+
+ if (strlen(argv[1] + 1) > MAX_FILE_LEN || strlen(argv[2] + 1) > MAX_FILE_LEN) {
+ /* supplied file names are too long. bail. */
+ usage();
+ printf("Supplied filenames exceed maximum length of 256 bytes\n");
+ }
+
+ strcpy(HDFName , argv[1]);
+ strcpy(GIFName , argv[2]);
+
+ /* get the options */
+ while (arg_index++ < argc - 1 && number_of_images < MAX_NUMBER_IMAGES) {
+ if (!strcmp(argv[arg_index] , "-i")) {
+ bool_is_image = 1;
+ continue;
+ }
+ if (!strcmp(argv[arg_index] , "-p")) {
+ bool_is_palette = 1;
+ continue;
+ }
+ if (!strcmp(argv[arg_index] , "-a")) {
+ time_out = 10;
+ continue;
+ }
+ if (bool_is_image) {
+ /* this is an image */
+ /* allocate space to store the image name */
+ image_name_arr[number_of_images] = (CHAR*) malloc(strlen(argv[arg_index] + 1));
+ strcpy(image_name_arr[number_of_images] , argv[arg_index]);
+ /* make the palette array for this NULL */
+ pal_name_arr[number_of_images] = NULL;
+ number_of_images++;
+ bool_is_image = 0;
+ continue;
+ }
+ if (bool_is_palette) {
+ /* this is a palette */
+ /* allocate space to store the pal name */
+ /* the palette was probably allocated for a previous image */
+ pal_name_arr[number_of_images-1] = (CHAR*) malloc(strlen(argv[arg_index] + 1));
+ strcpy(pal_name_arr[number_of_images - 1] , argv[arg_index]);
+ bool_is_palette = 0;
+ continue;
+ }
+ /* oops. This was not meant to happen */
+ usage();
+ /*
+ while (number_of_images--) {
+ cleanup(image_name_arr[number_of_images]);
+ cleanup(pal_name_arr[number_of_images]);
+ }
+ */
+ return -1;
+
+ }
+
+ /* we shall always have a palette - read hdf will see to that */
+ has_local_palette = true;
+
+ /* Do Endian Order testing and set Endian Order */
+ w = 0x0001;
+ b = (BYTE *) &w;
+ EndianOrder = (b[0] ? 1:0);
+
+ if (!(fpGif = fopen(GIFName , "wb"))) {
+ printf("Error opening gif file for output. Aborting.\n");
+ return -1;
+ }
+
+ /* hardwire n_images to 1 for now. */
+ n_images = number_of_images;
+
+ Background = 0;
+ for (index = 0 ; index < n_images ; index++) {
+
+ /* try to read the image and the palette */
+ /* Lots of funky stuff to support multiple images has been taken off.
+ ** Just in case you're extending code, here's what you need to do in short:
+ ** figure out if there is a global palette or not, if there is one store that one
+ ** only.
+ ** If they are all local or a combination of local and global palettes, you will have
+ ** to write the global palette out and then independantly write the smaller local
+ ** palettes
+ */
+ if (ReadHDF(&Image , GlobalPalette , dim_sizes , HDFName , image_name_arr[index] , pal_name_arr[index]) < 0) {
+ fprintf(stderr , "Unable to read HDF file\n");
+ return -1;
+ }
+
+ w = dim_sizes[1];
+ h = dim_sizes[0];
+
+ RWidth = dim_sizes[1];
+ RHeight = dim_sizes[0];
+ LeftOfs = TopOfs = 0;
+
+
+ /* If the first image does not have a palette, I make my own global color table
+ ** Obviously this is not the best thing to do, better steps would be:
+ ** 1. Check for either a global palette or a global attribute called palette
+ ** 2. Check for palettes in any of the other images.
+ */
+ if (!has_local_palette) {
+ for (i = 0 ; i < 256 ; i++) {
+ Red[i] = 255 - i;
+ Green[i] = 255 - i;
+ Blue[i] = 255 - i;
+ }
+ }
+ else {
+ for (i = 0 ; i < 256 ; i++){
+ Red[i] = GlobalPalette[i][0];
+ Green[i] = GlobalPalette[i][1];
+ Blue[i] = GlobalPalette[i][2];
+ }
+ }
+
+ for (i=0; i<256; i++) { pc2nc[i] = r1[i] = g1[i] = b1[i] = 0; }
+ /* compute number of unique colors */
+ nc = 0;
+ for (i=0; i<numcols; i++) {
+ /* see if color #i is already used */
+ for (j=0; j<i; j++) {
+ if (Red[i] == Red[j] && Green[i] == Green[j] &&
+ Blue[i] == Blue[j]) break;
+ }
+ if (j==i) { /* wasn't found */
+ pc2nc[i] = nc;
+ r1[nc] = Red[i];
+ g1[nc] = Green[i];
+ b1[nc] = Blue[i];
+ nc++;
+ }
+ else pc2nc[i] = pc2nc[j];
+ }
+ /* figure out 'BitsPerPixel' */
+ for (i=1; i<8; i++) {
+ if ( (1<<i) >= nc) break;
+ }
+ BitsPerPixel = i;
+ ColorMapSize = 1 << BitsPerPixel;
+
+
+ CountDown = w * h; /* # of pixels we'll be doing */
+
+ if (BitsPerPixel <= 1) InitCodeSize = 2;
+ else InitCodeSize = BitsPerPixel;
+
+ curx = cury = 0;
+
+ if (!fpGif) {
+ fprintf(stderr, "WriteGIF: file not open for writing\n" );
+ return (1);
+ }
+
+ /* If it is the first image we do all the header stuff that isn't required for the
+ ** rest of the images.
+ */
+ if (index == 0) {
+ /* Write out the GIF header and logical screen descriptor */
+ if (n_images > 1) {
+ fwrite("GIF89a", 1, 6, fpGif); /* the GIF magic number */
+ loop_times = 0;
+ }
+ else {
+ fwrite("GIF87a", 1, 6, fpGif); /* the GIF magic number */
+ loop_times = 1;
+ }
+
+ putword(RWidth, fpGif); /* screen descriptor */
+ putword(RHeight, fpGif);
+
+ i = 0x00; /* No, there is no color map */
+ i |= (8-1)<<4; /* OR in the color resolution (hardwired 8) */
+ i |= (BitsPerPixel - 1); /* OR in the # of bits per pixel */
+ fputc(i,fpGif);
+
+ fputc(Background,fpGif); /* background color */
+
+ fputc(0, fpGif); /* future expansion byte */
+
+
+ /* If loop_times is 0 , put in the application extension to make the gif anime loop
+ ** indefinitely
+ */
+ if (time_out > 0) {
+ fputc(0x21 , fpGif);
+ fputc(0xFF , fpGif);
+ fputc(11 , fpGif);
+ fwrite("NETSCAPE2.0" , 1 , 11 , fpGif);
+ fputc(3 , fpGif);
+ fputc(1 , fpGif);
+ fputc(0 , fpGif);
+ fputc(0 , fpGif);
+ fputc(0 , fpGif);
+
+ }
+
+
+ }
+
+ if (n_images > 1) {
+ /* write a graphic control block */
+ fputc(0x21 , fpGif);
+ fputc(0xF9 , fpGif);
+ fputc(4 , fpGif);
+ fputc(4 , fpGif);
+ putword(time_out , fpGif);
+ fputc(255, fpGif);
+ fputc(0 , fpGif);
+ }
+
+ /* Put Image Descriptor
+ ** Hardwiring Left Offset and Top Offset to 0x00
+ */
+
+ fputc (0x2c , fpGif);
+ putword (0x00 , fpGif);
+ putword (0x00 , fpGif);
+ putword (RWidth , fpGif);
+ putword (RHeight , fpGif);
+
+ /* since we always have a local color palette ... */
+ fputc ((0x80 | (BitsPerPixel - 1)) , fpGif);
+ for (i=0; i<ColorMapSize; i++) { /* write out Global colormap */
+ fputc(r1[i], fpGif);
+ fputc(g1[i], fpGif);
+ fputc(b1[i], fpGif);
+ }
+
+ fputc (InitCodeSize , fpGif);
+
+ i = hdfWriteGIF(fpGif , Image , 0 , dim_sizes[0] , dim_sizes[1] , r1, g1 , b1 , pc2nc , 256 , 8 , BitsPerPixel);
+ fputc(0x00 , fpGif);
+ free (Image);
+ }
+
+ if (fputc(';',fpGif) == EOF) { /* Write GIF file terminator */
+ fprintf(stderr , "Error!");
+ return -1;
+ }
+
+ fclose (fpGif);
+
+ while (number_of_images--) {
+ /*if (image_name_arr[number_of_images])
+ free(image_name_arr[number_of_images]);*/
+ /*if (pal_name_arr[number_of_images])
+ free(pal_name_arr[number_of_images]);*/
+ }
+
+ return(0);
+}
diff --git a/hl/tools/gif2h5/hdfgifwr.c b/hl/tools/gif2h5/hdfgifwr.c
new file mode 100644
index 0000000..28d556e
--- /dev/null
+++ b/hl/tools/gif2h5/hdfgifwr.c
@@ -0,0 +1,516 @@
+/*
+ * hdfgifwr.c - handles writing of GIF files.
+ *
+ * Contains:
+ * hdfWriteGIF(fp, pic, ptype, w, h, rmap, gmap, bmap, numcols, colorstyle,
+ * comment)
+ *
+ * Note: slightly brain-damaged, in that it'll only write non-interlaced
+ * GIF files (in the interests of speed, or something)
+ *
+ */
+
+
+
+/*****************************************************************
+ * Portions of this code Copyright (C) 1989 by Michael Mauldin.
+ * Permission is granted to use this file in whole or in
+ * part for any purpose, educational, recreational or commercial,
+ * provided that this copyright notice is retained unchanged.
+ * This software is available to all free of charge by anonymous
+ * FTP and in the UUNET archives.
+ *
+ *
+ * Authors: Michael Mauldin (mlm@cs.cmu.edu)
+ * David Rowley (mgardi@watdcsu.waterloo.edu)
+ *
+ * Based on: compress.c - File compression ala IEEE Computer, June 1984.
+ *
+ * Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
+ * Jim McKie (decvax!mcvax!jim)
+ * Steve Davies (decvax!vax135!petsd!peora!srd)
+ * Ken Turkowski (decvax!decwrl!turtlevax!ken)
+ * James A. Woods (decvax!ihnp4!ames!jaw)
+ * Joe Orost (decvax!vax135!petsd!joe)
+ *****************************************************************/
+
+
+#include <stdio.h>
+#include "gif.h"
+#include <stdlib.h>
+#include <string.h>
+
+typedef BYTE byte;
+typedef long int count_int;
+
+/* indicies into conv24MB */
+#define CONV24_8BIT 0
+#define CONV24_24BIT 1
+#define CONV24_SEP1 2
+#define CONV24_LOCK 3
+#define CONV24_SEP2 4
+#define CONV24_FAST 5
+#define CONV24_SLOW 6
+#define CONV24_BEST 7
+#define CONV24_MAX 8
+
+/* values 'picType' can take */
+#define PIC8 CONV24_8BIT
+#define PIC24 CONV24_24BIT
+
+/* MONO returns total intensity of r,g,b components */
+#define MONO(rd,gn,bl) (((rd)*11 + (gn)*16 + (bl)*5) >> 5) /*.33R+ .5G+ .17B*/
+
+static int Width, Height;
+static int curx, cury;
+static long CountDown;
+static int Interlace;
+
+#ifdef __STDC__
+static void putword(int, FILE *);
+static void compress(int, FILE *, byte *, int);
+static void output(int);
+static void cl_block(void);
+static void cl_hash(count_int);
+static void char_init(void);
+static void char_out(int);
+static void flush_char(void);
+#else
+static void putword(), compress(), output(), cl_block(), cl_hash();
+static void char_init(), char_out(), flush_char();
+#endif
+
+static byte pc2nc[256],r1[256],g1[256],b1[256];
+
+void xvbzero(s, len)
+ char *s;
+ int len;
+{
+ for ( ; len>0; len--) *s++ = 0;
+}
+
+/*************************************************************/
+int hdfWriteGIF(fp, pic, ptype, w, h, rmap, gmap, bmap, pc2ncmap, numcols, colorstyle, BitsPerPixel)
+ FILE *fp;
+ byte *pic;
+ int ptype, w,h;
+ byte *rmap, *gmap, *bmap , *pc2ncmap;
+ int numcols, colorstyle;
+ int BitsPerPixel;
+{
+ int RWidth, RHeight;
+ int LeftOfs, TopOfs;
+ int ColorMapSize, InitCodeSize, Background;
+ int i;
+ byte *pic8;
+ pic8 = pic;
+
+ Interlace = 0;
+ Background = 0;
+
+ for (i=0; i<256; i++) {
+ pc2nc[i] = pc2ncmap[i];
+ r1[i] = rmap[i];
+ g1[i] = gmap[i];
+ b1[i] = bmap[i];
+ }
+
+ ColorMapSize = 1 << BitsPerPixel;
+
+ RWidth = Width = w;
+ RHeight = Height = h;
+ LeftOfs = TopOfs = 0;
+
+ CountDown = w * h; /* # of pixels we'll be doing */
+
+ if (BitsPerPixel <= 1) InitCodeSize = 2;
+ else InitCodeSize = BitsPerPixel;
+
+ curx = cury = 0;
+
+ if (!fp) {
+ fprintf(stderr, "WriteGIF: file not open for writing\n" );
+ return (1);
+ }
+
+ compress(InitCodeSize+1, fp, pic8, w*h);
+
+
+ if (ferror(fp)) return -1;
+ return (0);
+}
+
+
+
+
+/******************************/
+static void putword(w, fp)
+int w;
+FILE *fp;
+{
+ /* writes a 16-bit integer in GIF order (LSB first) */
+
+ fputc(w &0xff, fp);
+
+ fputc((w>>8)&0xff,fp);
+}
+
+
+
+
+/***********************************************************************/
+static unsigned long cur_accum = 0;
+static int cur_bits = 0;
+
+#define MAXCODE(n_bits) ( (1 << (n_bits)) - 1)
+#define min(a,b) ((a>b) ? b : a)
+#define XV_BITS 12 /* BITS was already defined on some systems */
+#define MSDOS 1
+#define HSIZE 5003 /* 80% occupancy */
+
+typedef unsigned char char_type;
+static int n_bits; /* number of bits/code */
+static int maxbits = XV_BITS; /* user settable max # bits/code */
+static int maxcode; /* maximum code, given n_bits */
+static int maxmaxcode = 1 << XV_BITS; /* NEVER generate this */
+
+static count_int htab [HSIZE];
+static unsigned short codetab [HSIZE];
+#define HashTabOf(i) htab[i]
+#define CodeTabOf(i) codetab[i]
+
+static int hsize = HSIZE; /* for dynamic table sizing */
+
+/*
+ * To save much memory, we overlay the table used by compress() with those
+ * used by decompress(). The tab_prefix table is the same size and type
+ * as the codetab. The tab_suffix table needs 2**BITS characters. We
+ * get this from the beginning of htab. The output stack uses the rest
+ * of htab, and contains characters. There is plenty of room for any
+ * possible stack (stack used to be 8000 characters).
+ */
+
+#define tab_prefixof(i) CodeTabOf(i)
+#define tab_suffixof(i) ((char_type *)(htab))[i]
+#define de_stack ((char_type *)&tab_suffixof(1<<XV_BITS))
+
+static int free_ent = 0; /* first unused entry */
+
+/*
+ * block compression parameters -- after all codes are used up,
+ * and compression rate changes, start over.
+ */
+static int clear_flg = 0;
+
+static long int in_count = 1; /* length of input */
+static long int out_count = 0; /* # of codes output (for debugging) */
+
+/*
+ * compress stdin to stdout
+ *
+ * Algorithm: use open addressing double hashing (no chaining) on the
+ * prefix code / next character combination. We do a variant of Knuth's
+ * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
+ * secondary probe. Here, the modular division first probe is gives way
+ * to a faster exclusive-or manipulation. Also do block compression with
+ * an adaptive reset, whereby the code table is cleared when the compression
+ * ratio decreases, but after the table fills. The variable-length output
+ * codes are re-sized at this point, and a special CLEAR code is generated
+ * for the decompressor. Late addition: construct the table according to
+ * file size for noticeable speed improvement on small files. Please direct
+ * questions about this implementation to ames!jaw.
+ */
+
+static int g_init_bits;
+static FILE *g_outfile;
+
+static int ClearCode;
+static int EOFCode;
+
+/********************************************************/
+static void compress(init_bits, outfile, data, len)
+int init_bits;
+FILE *outfile;
+byte *data;
+int len;
+{
+ register long fcode;
+ register int i = 0;
+ register int c;
+ register int ent;
+ register int disp;
+ register int hsize_reg;
+ register int hshift;
+
+ /*
+ * Set up the globals: g_init_bits - initial number of bits
+ * g_outfile - pointer to output file
+ */
+ g_init_bits = init_bits;
+ g_outfile = outfile;
+
+ /* initialize 'compress' globals */
+ maxbits = XV_BITS;
+ maxmaxcode = 1<<XV_BITS;
+ xvbzero((char *) htab, sizeof(htab));
+ xvbzero((char *) codetab, sizeof(codetab));
+ hsize = HSIZE;
+ free_ent = 0;
+ clear_flg = 0;
+ in_count = 1;
+ out_count = 0;
+ cur_accum = 0;
+ cur_bits = 0;
+
+
+ /*
+ * Set up the necessary values
+ */
+ out_count = 0;
+ clear_flg = 0;
+ in_count = 1;
+ maxcode = MAXCODE(n_bits = g_init_bits);
+
+ ClearCode = (1 << (init_bits - 1));
+ EOFCode = ClearCode + 1;
+ free_ent = ClearCode + 2;
+
+ char_init();
+ ent = pc2nc[*data++]; len--;
+
+ hshift = 0;
+ for ( fcode = (long) hsize; fcode < 65536L; fcode *= 2L )
+ hshift++;
+ hshift = 8 - hshift; /* set hash code range bound */
+
+ hsize_reg = hsize;
+ cl_hash( (count_int) hsize_reg); /* clear hash table */
+
+ output(ClearCode);
+
+ while (len) {
+ c = pc2nc[*data++]; len--;
+ in_count++;
+
+ fcode = (long) ( ( (long) c << maxbits) + ent);
+ i = (((int) c << hshift) ^ ent); /* xor hashing */
+
+ if ( HashTabOf (i) == fcode ) {
+ ent = CodeTabOf (i);
+ continue;
+ }
+
+ else if ( (long)HashTabOf (i) < 0 ) /* empty slot */
+ goto nomatch;
+
+ disp = hsize_reg - i; /* secondary hash (after G. Knott) */
+ if ( i == 0 )
+ disp = 1;
+
+probe:
+ if ( (i -= disp) < 0 )
+ i += hsize_reg;
+
+ if ( HashTabOf (i) == fcode ) {
+ ent = CodeTabOf (i);
+ continue;
+ }
+
+ if ( (long)HashTabOf (i) >= 0 )
+ goto probe;
+
+nomatch:
+ output(ent);
+ out_count++;
+ ent = c;
+
+ if ( free_ent < maxmaxcode ) {
+ CodeTabOf (i) = free_ent++; /* code -> hashtable */
+ HashTabOf (i) = fcode;
+ }
+ else
+ cl_block();
+ }
+
+ /* Put out the final code */
+ output(ent);
+ out_count++;
+ output(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.
+ */
+
+static
+unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
+ 0x001F, 0x003F, 0x007F, 0x00FF,
+ 0x01FF, 0x03FF, 0x07FF, 0x0FFF,
+ 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
+
+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 );
+
+#ifdef FOO
+ if( ferror( g_outfile ) )
+ FatalError("unable to write GIF file");
+#endif
+ }
+}
+
+
+/********************************/
+static void cl_block () /* table clear for block compress */
+{
+ /* Clear out the hash table */
+
+ cl_hash ( (count_int) hsize );
+ free_ent = ClearCode + 2;
+ clear_flg = 1;
+
+ output(ClearCode);
+}
+
+
+/********************************/
+static void cl_hash(hsize) /* reset code table */
+register count_int hsize;
+{
+ 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'
+ */
+static int a_count;
+
+/*
+ * Set up the 'byte output' routine
+ */
+static void char_init()
+{
+ a_count = 0;
+}
+
+/*
+ * Define the storage for the packet accumulator
+ */
+static char accum[ 256 ];
+
+/*
+ * Add a character to the end of the current packet, and if it is 254
+ * characters, flush the packet to disk.
+ */
+static void char_out(c)
+int c;
+{
+ accum[ a_count++ ] = c;
+ if( a_count >= 254 )
+ flush_char();
+}
+
+/*
+ * Flush the packet to disk, and reset the accumulator
+ */
+static void flush_char()
+{
+ if( a_count > 0 ) {
+ fputc( a_count, g_outfile );
+ fwrite( accum, 1, a_count, g_outfile );
+ a_count = 0;
+ }
+}
diff --git a/hl/tools/gif2h5/readhdf.c b/hl/tools/gif2h5/readhdf.c
new file mode 100644
index 0000000..a7101c9
--- /dev/null
+++ b/hl/tools/gif2h5/readhdf.c
@@ -0,0 +1,177 @@
+#include "gif.h"
+
+/* just a small cleanup routine before we leave */
+void cleanup(BYTE *ptr) {
+ if (ptr)
+ free(ptr);
+}
+
+/* Function : ReadHDF
+** Return: 0 on completion without error, -1 on error
+** Input: CHAR *h5_file - HDF file name
+** CHAR *dset_name - Name of the HDF Image dataset
+** CHAR *pal_name - Name of the HDF palette
+** Output : BYTE** data - the HDF Image to be converted
+** BYTE palette[256][3] - the corresponding palette
+** hsize_t* image_size - the size of each dimension of the image
+**
+** Future Notes:
+** The way readHDF works right now is that it expects the user
+** to know the exact path to the HDF image. Thus it does not
+** parse the HDF file looking for image datasets and corresponding
+** palettes. Also it takes in the default palette for the image
+** specified, if the palette is missing, it makes a default greyscale
+** palette and throws it in.
+**
+*/
+int ReadHDF(BYTE** data ,
+ BYTE palette[256][3] ,
+ hsize_t *image_size ,
+ CHAR *h5_file ,
+ CHAR *dset_name ,
+ CHAR *pal_name)
+{
+ hid_t fHfile; /* H5 file to open */
+ herr_t status; /* status variable */
+ hid_t dspace; /* dataspace identifier for the the dataset */
+ hid_t dset; /* dataset identifier */
+
+ hid_t pal_set; /* dataset for palette */
+ hid_t pal_space;/* dataspace for palette */
+ hsize_t pal_size; /* size of the palette */
+
+ hsize_t datasize; /* size of the image */
+ hsize_t maxdims; /* dummy */
+
+ int pal_exist = 0; /* do we have a palette? */
+
+ /* check stuff */
+ if (!h5_file || !dset_name || !image_size) {
+ fprintf(stderr , "NULL is not an acceptable input for HDFread. Aborting.\n");
+ return -1;
+ }
+
+ /* do we have a palette ? */
+ if (pal_name) {
+ pal_exist = 1;
+ }
+
+ /* try opening the file */
+ /* H5 file open calls */
+ if ((fHfile = H5Fopen(h5_file , H5F_ACC_RDONLY , H5P_DEFAULT)) < 0) {
+ fprintf(stderr , "Unable to open HDF file for input. Aborting.\n");
+ return -1;
+ }
+
+ /* open the dataset for reading */
+ if ((dset = H5Dopen(fHfile , dset_name)) < 0) {
+ fprintf(stderr , "Unable to open dataset\n");
+ return -1;
+ }
+
+ /* get the dataspace */
+ if ((dspace = H5Dget_space(dset)) < 0) {
+ fprintf(stderr , "Unable to get dataspace\n");
+ return -1;
+ }
+
+ /* get the dimension size of the image */
+ if (H5Sget_simple_extent_dims(dspace , image_size , &maxdims) !=2 ) {
+ fprintf(stderr , "Unable to get dimension info\n");
+ return -1;
+ }
+
+ /* size needed to store the image */
+ datasize = image_size[0] * image_size[1];
+
+ /* allocate memory to store the image */
+ if ((*data = (BYTE*) malloc(datasize)) == NULL) {
+ fprintf(stderr , "Out of memory, exiting");
+ return -1;
+ }
+
+ /* get the actual image */
+ if ((status = H5Dread(dset , H5Dget_type(dset) , H5S_ALL , H5S_ALL , H5P_DEFAULT , *data)) < 0) {
+ fprintf(stderr , "Unable to read data \n");
+ cleanup(*data);
+ return -1;
+ }
+
+ if (pal_exist) {
+ hsize_t pal_size[2];
+ hsize_t max_pal_dims[2];
+ hsize_t pal_datasize;
+ CHAR *pal_path;
+
+ BYTE *temp_buf;
+ hsize_t temp_size;
+
+ /* get the palette dataset */
+ if ((pal_set = H5Dopen(fHfile , pal_name)) < 0) {
+ fprintf(stderr , "Unable to open dataset\n");
+ pal_exist = 0;
+ return -1;
+ }
+
+ /* get the dataspace */
+ if ((pal_space = H5Dget_space(pal_set)) < 0) {
+ fprintf(stderr , "Unable to get dataspace\n");
+ pal_exist = 0;
+ return -1;
+ }
+
+ /* get the dimension size of the palette. */
+ if (H5Sget_simple_extent_dims(pal_space , pal_size , &max_pal_dims) !=2 ) {
+ fprintf(stderr , "Unable to get dimension info\n");
+ pal_exist = 0;
+ return -1;
+ }
+
+ /* size needed to store the image */
+ pal_datasize = pal_size[0] * pal_size[1];
+
+ /* copy stuff into a temp buffer and then copy 256*3 elements to palette */
+ temp_size = H5Dget_storage_size(pal_set);
+
+ temp_buf = (BYTE*) malloc (temp_size * sizeof(BYTE));
+
+ /* make sure that the palette is actually 256 X 3 so that we don't create overflows */
+ if (pal_datasize > 256 * 3)
+ {
+ fprintf(stderr , "Palette seems to be more than 256X3 bytes\n");
+ fprintf(stderr , "Truncating palette to 256 colors. This might cause a problem with the final image\n");
+ pal_datasize = 256 * 3;
+ }
+
+ /* get the actual palette */
+ if ((status = H5Dread(pal_set , H5Dget_type(pal_set) , H5S_ALL , H5S_ALL , H5P_DEFAULT , temp_buf)) < 0) {
+ fprintf(stderr , "Unable to read data \n");
+ cleanup(*data);
+ cleanup(temp_buf);
+ return -1;
+ }
+
+ /* copy stuff into the actual palette */
+ memcpy(palette , temp_buf , pal_datasize);
+
+ /* get rid of the temp memory */
+ cleanup(temp_buf);
+ /* end of if (pal_exist) */
+
+ } else {
+ int i;
+ /* if palette does not exist we just go ahead and create a uniform greyscale palette */
+ for (i = 0 ; i < 256 ; i++) {
+ palette[i][0] = 255 - i;
+ palette[i][1] = 255 - i;
+ palette[i][2] = 255 - i;
+ }
+ }
+
+ /* close everything */
+ status = H5Dclose(dset);
+ status = H5Sclose(dspace);
+ status = H5Fclose(fHfile);
+
+ return 0;
+}
diff --git a/hl/tools/gif2h5/writehdf.c b/hl/tools/gif2h5/writehdf.c
new file mode 100644
index 0000000..7afccdf
--- /dev/null
+++ b/hl/tools/gif2h5/writehdf.c
@@ -0,0 +1,410 @@
+#include "gif.h"
+#include <string.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*******************************************************************
+** Function: write_text_attribute
+** Use: Just a small wrapper to write text attributes easily
+********************************************************************/
+int write_text_attribute(hid_t dataset_id , char *attr_name , char *attr_value) {
+
+ /* variables for the attributes */
+ hsize_t attr_dims_size; /* dimensions for the attribute */
+ hid_t attr_dataspace_id; /* dataspaces needed for the various attributes */
+ hid_t attr_attr_id; /* attribute id */
+ herr_t status; /* check return status */
+ hid_t attr_type_id;
+
+
+ /* check strings */
+ if (!attr_name || !attr_value)
+ return -1;
+
+ /* figure out size of the data */
+ attr_dims_size = strlen(attr_value) + 1;
+
+ /* set the type to string */
+ attr_type_id = H5Tcopy(H5T_C_S1);
+ H5Tset_size(attr_type_id , attr_dims_size);
+
+ /* create the dataspace for the attribute */
+ attr_dataspace_id = H5Screate_simple(1 , &attr_dims_size , NULL);
+
+ /* create the attribute */
+ attr_attr_id = H5Acreate(dataset_id , attr_name , attr_type_id , attr_dataspace_id , H5P_DEFAULT);
+
+ /* write out the attribute data */
+ if ((status = H5Awrite(attr_attr_id , attr_type_id , attr_value)) < 0)
+ return -1;
+
+ /* close the attribute */
+ if ((status = H5Aclose(attr_attr_id)) < 0)
+ return -1;
+
+ /* close the dataspace */
+ if ((status = H5Sclose(attr_dataspace_id)) < 0) {
+ fprintf(stderr , "Unable to close attribute dataspace. Aborting \n");
+ return -1;
+ }
+
+ return 0;
+
+}
+
+int
+WriteHDF(GifMemoryStruct, HDFName , GIFFileName)
+GIFTOMEM GifMemoryStruct;
+char *HDFName;
+char *GIFFileName;
+{
+ GIFHEAD gifHead; /* GIF Header structure */
+ GIFIMAGEDESC* gifImageDesc; /* Logical Image Descriptor struct */
+
+ long ImageCount , /* number of images */
+ CommentCount, /* number of comments */
+ ApplicationCount , /* number of application extensions */
+ PlainTextCount; /* number of plain text extensions */
+
+ char ImageName[256], /* Image name for the GR Image */
+ CommentName[256],
+ ApplicationName[256],
+ PlainTextName[256];
+
+ char GroupName[VSNAMELENMAX]; /* so that we can name the subgroups appropriately */
+
+ /* H5 variables */
+ hid_t file_id; /* H5 file id */
+ hid_t image_id; /* H5 id for the whole image */
+ hid_t pal_id; /* H5 id for the palette */
+ herr_t status; /* status variable */
+ hobj_ref_t pal_ref; /* Create a reference for the palette */
+
+ /* temp counter */
+ int i;
+
+
+
+
+
+
+ /* get the GIFMem stuff */
+ gifHead = *(GifMemoryStruct.GifHeader);
+
+ /* get some data from gifHead */
+ ImageCount = (WORD)gifHead.ImageCount;
+ CommentCount = (WORD)gifHead.CommentCount;
+ ApplicationCount = (WORD)gifHead.ApplicationCount;
+ PlainTextCount = (WORD)gifHead.PlainTextCount;
+
+ /* get the main group name from GIFFileName */
+ GroupName[0]= '/';
+ if (strncpy(GroupName , GIFFileName , VSNAMELENMAX-2) == NULL) {
+ fprintf(stderr , "strncpy failed\n");
+ exit(1);
+ }
+ GroupName[VSNAMELENMAX] = '\0';
+
+
+ if ((file_id = H5Fcreate(HDFName , H5F_ACC_TRUNC , H5P_DEFAULT , H5P_DEFAULT)) < 0) {
+ /* error occured opening the HDF File for write */
+ fprintf(stderr , "HDF file could not be opened for writing\n");
+ fprintf(stderr , "NOTE: GIF file must be present in the same directory as the binary on UNIX systems.\n");
+ exit(1);
+ }
+
+ /* create a group within the root group to hold the gif image */
+ /* might want to make a different naming style out here */
+ image_id = H5Gcreate(file_id, GroupName , 0);
+
+ /* first create the global palette if there is one */
+ if (gifHead.PackedField & 0x80) { /* global palette exists */
+ hid_t dataspace_id; /* identifier for dataspace */
+ hsize_t dims[2]; /* specify the dimensions of the palette */
+
+ hsize_t dimsr[1] = {1}; /* needed to store reference */
+ hid_t ref_dataspace_id; /* dataspace id for references */
+ hid_t ref_dataset_id; /* dataset id for references */
+
+ /* size of the palette is tablesize (rows) X 3 (columns) */
+ dims[0] = gifHead.TableSize;
+ dims[1] = 3;
+
+ /* create the dataspace */
+ if ((dataspace_id = H5Screate_simple(2 , dims , NULL)) < 0) {
+ fprintf(stderr , "Could not create dataspace for palette. Aborting...\n");
+ return -1;
+ }
+
+ /* create the palette dataset */
+ if ((pal_id = H5Dcreate(image_id , "Global Palette" , H5T_NATIVE_UINT8 , dataspace_id , H5P_DEFAULT )) < 0) {
+ fprintf(stderr , "Could not create palette dataset. Aborting...\n");
+ return -1;
+ }
+
+ /* write the palette data out */
+ /****** Ask Elena about VOIDP ******/
+ if ((status = H5Dwrite(pal_id , H5T_NATIVE_UINT8 , H5S_ALL , H5S_ALL , H5P_DEFAULT , (void *)gifHead.HDFPalette)) < 0) {
+ fprintf(stderr , "Error writing dataset. Aborting...\n");
+ return -1;
+ }
+
+ /* set palette attributes */
+
+ /* attribute CLASS = PALETTE */
+ if ((write_text_attribute(pal_id , "CLASS" , "PALETTE")) < 0) {
+ fprintf(stderr , "Unable to write palette attributes. Aborting\n");
+ return -1;
+ }
+
+ /* attribute PAL_COLORMODEL = RGB */
+ if ((write_text_attribute(pal_id , "PAL_COLORMODEL" , "RGB")) < 0) {
+ fprintf(stderr , "Unable to write palette attributes. Aborting\n");
+ return -1;
+ }
+
+ /* attribute PAL_TYPE = STANDARD8 */
+ if ((write_text_attribute(pal_id , "PAL_TYPE" , "STANDARD8")) < 0) {
+ fprintf(stderr , "Unable to write palette attributes. Aborting\n");
+ return -1;
+ }
+
+ /* attribute PAL_VERSION = 1.0 */
+ if ((write_text_attribute(pal_id , "PAL_VERSION" , "1.0")) < 0) {
+ fprintf(stderr , "Unable to write palette attributes. Aborting\n");
+ return -1;
+ }
+
+ /* create dataspace for the dataset to store references */
+ ref_dataspace_id = H5Screate_simple(1 , dimsr , NULL);
+
+ /* create a dataset to store the references */
+ ref_dataset_id = H5Dcreate(image_id , "Palette Reference" , H5T_STD_REF_OBJ , ref_dataspace_id , H5P_DEFAULT);
+
+ /* create a reference to the palette */
+ if ((status = H5Rcreate(&pal_ref , image_id , "Global Palette" , H5R_OBJECT , -1)) < 0) {
+ fprintf(stderr , "Unable to create palette reference\n");
+ return -1;
+ }
+
+ /* write the reference out */
+ if ((status = H5Dwrite(ref_dataset_id , H5T_STD_REF_OBJ, H5S_ALL, H5S_ALL , H5P_DEFAULT, &pal_ref)) < 0) {
+ fprintf(stderr , "Unable to write Palette Reference");
+ return -1;
+ }
+
+ /* close dataset */
+ if ((status = H5Dclose(ref_dataset_id)) < 0) {
+ fprintf(stderr , "Unable to close palette dataset.\n");
+ return -1;
+ }
+
+ /* close dataspace */
+ if ((status = H5Sclose(ref_dataspace_id)) < 0) {
+ fprintf(stderr , "Unable to close palette dataspace.\n");
+ return -1;
+ }
+
+ /* close everything */
+ if ((status = H5Dclose(pal_id)) < 0) {
+ fprintf(stderr , "Unable to close palette dataset. Aborting.\n");
+ return -1;
+ }
+
+ if ((status = H5Sclose(dataspace_id)) < 0) {
+ fprintf(stderr , "Unable to close palette dataspace. Aborting.\n");
+ return -1;
+ }
+
+ }
+
+ for(i=0 ; i < ImageCount ; i++) {
+ /* variables for the images */
+ hsize_t dims[2]; /* dimensions for the dataset */
+ hid_t dataspace_id; /* identifier for the dataspace */
+ hid_t sub_image_id; /* wierd name to distinguish from the group_id */
+
+ /* variables for the attributes */
+ hsize_t attr_dims[2]; /* dimensions for the attribute */
+ hid_t attr_dataspace_id; /* dataspaces needed for the various attributes */
+ hid_t attr_attr_id; /* attribute id */
+ BYTE minmax[2]; /* lower and upper minmax values */
+
+ /* initialise minmax */
+ minmax[0] = 0 ; minmax[1] = 255;
+
+ /* get the gifImageDesc */
+ gifImageDesc = GifMemoryStruct.GifImageDesc[i];
+
+ /* set the dimensions */
+ dims[0] = gifImageDesc->ImageHeight;
+ dims[1] = gifImageDesc->ImageWidth;
+
+ /* create the empty dataspace */
+ if ((dataspace_id = H5Screate_simple(2 , dims , NULL)) < 0) {
+ fprintf(stderr , "Could not create image dataspace. Aborting\n");
+ return -1;
+ }
+
+ /* create the image name */
+ sprintf(ImageName , "Image%d" , i);
+
+ /* create the image data set */
+ if ((sub_image_id = H5Dcreate(image_id , ImageName , H5T_NATIVE_UINT8 , dataspace_id , H5P_DEFAULT)) < 0) {
+ fprintf(stderr , "Could not create dataset for image. Aborting... \n");
+ return -1;
+ }
+
+ /* write out the image */
+ /****** Ask Elena about VOIDP ******/
+ if ((status = H5Dwrite(sub_image_id , H5T_NATIVE_UINT8 , H5S_ALL , H5S_ALL , H5P_DEFAULT , (void *)(gifImageDesc->Image))) < 0) {
+ fprintf(stderr , "Error writing image. Aborting... \n");
+ return -1;
+ }
+
+ /* set the attributes */
+ /* This info is available at http://hdf.ncsa.uiuc.edu/HDF5/doc/ImageSpec.html */
+ /* The following attributes must be set for each image:
+ ** ---------------------------------------
+ ** Attribute Name Value
+ ** CLASS IMAGE
+ ** IMAGE_VERSION 1.0
+ ** IMAGE_SUBCLASS IMAGE_BITMAP
+ ** PALETTE ref. to palette datasets
+ ** IMAGE_MINMAXRANGE [0,255]
+ ** ---------------------------------------
+ */
+
+ /****************************************
+ ** Attribute: CLASS
+ ** Value : IMAGE
+ *****************************************/
+
+ if (write_text_attribute(sub_image_id , "CLASS" , "IMAGE") < 0) {
+ fprintf(stderr , "Unable to write CLASS = IMAGE attribute\n");
+ return -1;
+ }
+
+ /****************************************
+ ** Attribute: IMAGE_VERSION
+ ** Value : 1.0
+ *****************************************/
+
+ if (write_text_attribute(sub_image_id , "IMAGE_VERSION" , "1.0") < 0) {
+ fprintf(stderr , "Unable to write IMAGE_VERSION attribute\n");
+ return -1;
+ }
+
+ /****************************************
+ ** Attribute: IMAGE_SUBCLASS
+ ** Value : IMAGE_BITMAP
+ *****************************************/
+
+ if (write_text_attribute(sub_image_id , "IMAGE_SUBCLASS" , "IMAGE_BITMAP") < 0) {
+ fprintf(stderr , "Unable to write IMAGE_SUBCLASS attribute\n");
+ return -1;
+ }
+
+ /****************************************
+ ** Attribute: IMAGE_COLORMODEL
+ ** Value : RGB
+ *****************************************/
+
+ if (write_text_attribute(sub_image_id , "IMAGE_COLORMODEL" , "RGB") < 0) {
+ fprintf(stderr , "Unable to write IMAGE_SUBCLASS attribute\n");
+ return -1;
+ }
+
+ /****************************************
+ ** Attribute: PALETTE
+ ** Value : Reference to Palette
+ *****************************************/
+
+ /**** MAKE SURE PALETTE EXISTS!!! ****/
+ if (gifHead.PackedField & 0x80) { /* global palette exists */
+
+ attr_dims[0] = 1;
+
+ /* create the dataspace for the attribute */
+ attr_dataspace_id = H5Screate_simple(1 , attr_dims , NULL);
+
+ /* create the attribute */
+ attr_attr_id = H5Acreate(sub_image_id , "PALETTE" , H5T_STD_REF_OBJ , attr_dataspace_id , H5P_DEFAULT);
+
+ if ((status = H5Awrite(attr_attr_id , H5T_STD_REF_OBJ , &pal_ref)) < 0) {
+ fprintf(stderr , "Unable to write attribute. Aborting \n");
+ return -1;
+ }
+
+ /* close the attribute */
+ if ((status = H5Aclose(attr_attr_id)) < 0) {
+ fprintf(stderr , "Unable to close CLASS IMAGE attribute. Aborting.\n");
+ return -1;
+ }
+
+ /* close the dataspace */
+ if ((status = H5Sclose(attr_dataspace_id)) < 0) {
+ fprintf(stderr , "Unable to close attribute dataspace. Aborting \n");
+ return -1;
+ }
+
+ }
+
+ /****************************************
+ ** Attribute: IMAGE_MINMAXRANGE
+ ** Value : minmax
+ *****************************************/
+
+ attr_dims[0] = 2;
+
+ /* create the dataspace for the attribute */
+ attr_dataspace_id = H5Screate_simple(1 , attr_dims , NULL);
+
+ /* create the attribute */
+ attr_attr_id = H5Acreate(sub_image_id , "IMAGE_MINMAXRANGE" , H5T_NATIVE_UINT8 , attr_dataspace_id , H5P_DEFAULT);
+
+ if ((status = H5Awrite(attr_attr_id , H5T_NATIVE_UINT8 , minmax)) < 0) {
+ fprintf(stderr , "Unable to write attribute. Aborting \n");
+ return -1;
+ }
+
+ /* close the attribute */
+ if ((status = H5Aclose(attr_attr_id)) < 0) {
+ fprintf(stderr , "Unable to close CLASS IMAGE attribute. Aborting.\n");
+ return -1;
+ }
+
+ /* close the dataspace */
+ if ((status = H5Sclose(attr_dataspace_id)) < 0) {
+ fprintf(stderr , "Unable to close attribute dataspace. Aborting \n");
+ return -1;
+ }
+
+
+ /* close everything */
+ if ((status = H5Dclose(sub_image_id)) < 0) {
+ fprintf(stderr , "Unable to close image dataset. Aborting \n");
+ return -1;
+ }
+
+ if ((status = H5Sclose(dataspace_id)) < 0) {
+ fprintf(stderr , "Unable to close image dataspace. Aborting \n");
+ return -1;
+ }
+
+ }
+
+ /* close the main image group */
+ if ((status = H5Gclose(image_id)) < 0) {
+ fprintf(stderr , "Could not close the image group. Aborting...\n");
+ return -1;
+ }
+
+ /* close the H5 file */
+ if ((status = H5Fclose(file_id)) < 0) {
+ fprintf(stderr , "Could not close HDF5 file. Aborting...\n");
+ return -1;
+ }
+
+ return(0);
+}
diff --git a/tools/Makefile.in b/tools/Makefile.in
index 5369e87..64653a6 100644
--- a/tools/Makefile.in
+++ b/tools/Makefile.in
@@ -9,7 +9,7 @@ srcdir=@srcdir@
## All subdirectories except for the ``lib'' subdirectory.
##
-SUBDIRS=h5dump h5ls misc @H5TOH4@ @H4TOH5@
+SUBDIRS=h5dump h5ls misc gifconv @H5TOH4@ @H4TOH5@
@COMMENCE@
diff --git a/tools/gifconv/Dependencies b/tools/gifconv/Dependencies
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/gifconv/Dependencies
diff --git a/tools/gifconv/Makefile.in b/tools/gifconv/Makefile.in
new file mode 100644
index 0000000..effeada
--- /dev/null
+++ b/tools/gifconv/Makefile.in
@@ -0,0 +1,65 @@
+## HDF5 Library Makefile(.in)
+##
+## Copyright (C) 2001 National Center for Supercomputing Applications.
+## All rights reserved.
+##
+##
+top_srcdir=@top_srcdir@
+top_builddir=../..
+srcdir=@srcdir@
+SUBDIRS=
+@COMMENCE@
+
+## Add include directory to the C preprocessor flags, add -lh5tools and
+## -lhdf5 to the list of libraries.
+##
+CPPFLAGS=-I. -I$(srcdir) -I$(top_builddir)/src -I$(top_srcdir)/src \
+ -I$(top_srcdir)/tools/lib @CPPFLAGS@
+
+## Test programs and scripts.
+##
+TEST_PROGS=
+TEST_SCRIPTS=
+
+## These are our main targets: library and tools.
+##
+LIBTOOLS=../lib/libh5tools.la
+LIBHDF5=$(top_builddir)/src/libhdf5.la
+
+PUB_PROGS= gif2h5 h52gif
+PROGS=$(PUB_PROGS) $(TEST_PROGS)
+
+## Source and object files for the library; do not install
+##
+LIB_SRC=
+LIB_OBJ=$(LIB_SRC:.c=.lo)
+PUB_LIB=
+
+## Source and object files for programs...
+##
+PROG_SRC=decompress.c gif2hdf.c gif2mem.c gifread.c hdf2gif.c hdfgifwr.c readhdf.c writehdf.c
+PROG_OBJ=$(PROG_SRC:.c=.lo)
+
+PRIVATE_HDR=gif.h
+
+## Source and object files for the tests
+##
+TEST_SRC=
+TEST_OBJ=$(TEST_SRC:.c=.lo)
+
+## Programs have to be built before they can be tested!
+##
+check test _test: $(PROGS)
+
+## How to build the programs...They all depend on the hdf5 library and
+## the tools library compiled in this directory.
+##
+$(PROGS): $(LIBTOOLS) $(LIBHDF5)
+
+gif2h5: gif2hdf.lo gif2mem.lo decompress.lo gifread.lo writehdf.lo
+ @$(LT_LINK_EXE) $(CFLAGS) -o $@ gif2hdf.lo gif2mem.lo decompress.lo gifread.lo writehdf.lo $(LIBTOOLS) $(LIBHDF5) $(LDFLAGS) $(LIBS)
+
+h52gif: hdf2gif.lo hdfgifwr.lo readhdf.lo
+ @$(LT_LINK_EXE) $(CFLAGS) -o $@ hdf2gif.lo hdfgifwr.lo readhdf.lo $(LIBTOOLS) $(LIBHDF5) $(LDFLAGS) $(LIBS)
+
+@CONCLUDE@
diff --git a/tools/gifconv/decompress.c b/tools/gifconv/decompress.c
new file mode 100644
index 0000000..18dbb3e
--- /dev/null
+++ b/tools/gifconv/decompress.c
@@ -0,0 +1,299 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "gif.h"
+
+#define NEXTBYTE (*ptr++)
+#define IMAGESEP 0x2c
+#define INTERLACEMASK 0x40
+#define COLORMAPMASK 0x80
+#define False 0
+#define True 1
+
+WORD iWIDE,iHIGH,eWIDE,eHIGH,expand,numcols,strip,nostrip;
+unsigned long cols[256];
+char *cmd;
+
+FILE *fp;
+
+static int BitOffset = 0, /* Bit Offset of next code */
+XC = 0, YC = 0, /* Output X and Y coords of current pixel */
+Pass = 0, /* Used by output routine if WORDerlaced pic */
+OutCount = 0, /* Decompressor output 'stack count' */
+RWidth, RHeight, /* screen dimensions */
+IWidth, IHeight, /* image dimensions */
+LeftOfs, TopOfs, /* image offset */
+BitsPerPixel, /* Bits per pixel, read from GIF header */
+BytesPerScanline, /* Bytes per scanline in output raster */
+ColorMapSize, /* number of colors */
+Background, /* background color */
+CodeSize, /* Code size, read from GIF header */
+InitCodeSize, /* Starting code size, used during Clear */
+Code, /* Value returned by ReadCode */
+MaxCode, /* limiting value for current code size */
+ClearCode, /* GIF clear code */
+EOFCode, /* GIF end-of-information code */
+CurCode, OldCode, InCode, /* Decompressor variables */
+FirstFree, /* First free code, generated per GIF spec */
+FreeCode, /* Decompressor, next free slot in hash table */
+FinChar, /* Decompressor variable */
+DataMask, /* AND mask for data size */
+ReadMask; /* Code AND mask for current code size */
+
+/*MODIFICATIONS*/
+BYTE tempbyte[10];
+BYTE * tempBYTEptr[10];
+WORD tempint[10];
+WORD ImageCount = 0;
+/*END MODIFICATION*/
+
+boolean Interlace, HasColormap;
+
+
+BYTE *Image; /* The result array */
+BYTE *RawGIF; /* The heap array to hold it, raw */
+BYTE *Raster; /* The raster data stream, unblocked */
+
+/* The hash table used by the decompressor */
+
+int Prefix[4096];
+int Suffix[4096];
+
+/* An output array used by the decompressor */
+
+int OutCode[1025];
+
+/* The color map, read from the GIF header */
+
+int numused;
+
+/* Fetch the next code from the raster data stream. The codes can be
+* any length from 3 to 12 bits, packed WORDo 8-bit BYTEs, so we have to
+* maWORDain our location in the Raster array as a BIT Offset. We compute
+* the BYTE Offset WORDo the raster array by dividing this by 8, pick up
+* three BYTEs, compute the bit Offset WORDo our 24-bit chunk, shift to
+* bring the desired code to the bottom, then mask it off and return it.
+*/
+ReadCode()
+{
+ int RawCode, ByteOffset;
+
+ ByteOffset = BitOffset / 8;
+ RawCode = Raster[ByteOffset] + (0x100 * Raster[ByteOffset + 1]);
+ if (CodeSize >= 8)
+ RawCode += (0x10000 * Raster[ByteOffset + 2]);
+ RawCode >>= (BitOffset % 8);
+ BitOffset += CodeSize;
+ return(RawCode & ReadMask);
+}
+
+
+AddToPixel(Index)
+BYTE Index;
+{
+ if (YC<IHeight)
+ *(Image + YC * BytesPerScanline + XC) = Index;
+
+
+
+ /* Update the X-coordinate, and if it overflows, update the Y-coordinate */
+ if (++XC == IWidth) {
+
+ /* If a non-WORDerlaced picture, just increment YC to the next scan line.
+ * If it's WORDerlaced, deal with the WORDerlace as described in the GIF
+ * spec. Put the decoded scan line out to the screen if we haven't gone
+ * past the bottom of it.
+ */
+
+ XC = 0;
+ if (!Interlace) YC++;
+ else {
+ switch (Pass) {
+ case 0:
+ YC += 8;
+ if (YC >= IHeight) {
+ Pass++;
+ YC = 4;
+ }
+ break;
+ case 1:
+ YC += 8;
+ if (YC >= IHeight) {
+ Pass++;
+ YC = 2;
+ }
+ break;
+
+ case 2:
+ YC += 4;
+ if (YC >= IHeight) {
+ Pass++;
+ YC = 1;
+ }
+ break;
+ case 3:
+ YC += 2;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+/* Main routine. Convert a GIF image to an HDF image */
+
+BYTE* Decompress(GifImageDesc , GifHead)
+GIFIMAGEDESC *GifImageDesc;
+GIFHEAD *GifHead;
+{
+ int i;
+
+ XC = 0;
+ YC = 0;
+ Pass = 0;
+ OutCount = 0;
+ BitOffset = 0;
+
+ DataMask = (WORD)((1L << ((GifHead->PackedField & 0x07) +1)) -1);
+ Raster = GifImageDesc->GIFImage;
+
+
+ /* Check for image seperator */
+
+ /* Now read in values from the image descriptor */
+ IWidth = GifImageDesc->ImageWidth;
+ IHeight = GifImageDesc->ImageHeight;
+ Interlace = GifImageDesc->PackedField & 0x40;
+
+ /* Note that I ignore the possible existence of a local color map.
+ * I'm told there aren't many files around that use them, and the spec
+ * says it's defined for future use. This could lead to an error
+ * reading some files.
+ */
+
+ /* Start reading the raster data. First we get the WORDial code size
+ * and compute decompressor constant values, based on this code size.
+ */
+
+ CodeSize = GifImageDesc->CodeSize;
+ ClearCode = (1 << CodeSize);
+ EOFCode = ClearCode + 1;
+ FreeCode = FirstFree = ClearCode + 2;
+
+ /* The GIF spec has it that the code size is the code size used to
+ * compute the above values is the code size given in the file, but the
+ * code size used in compression/decompression is the code size given in
+ * the file plus one. (thus the ++).
+ */
+
+ CodeSize++;
+ InitCodeSize = CodeSize;
+ MaxCode = (1 << CodeSize);
+ ReadMask = MaxCode - 1;
+
+ /* Read the raster data. Here we just transpose it from the GIF array
+ * to the Raster array, turning it from a series of blocks WORDo one long
+ * data stream, which makes life much easier for ReadCode().
+ */
+
+
+
+ /* free(RawGIF); We're not done just yet - change made */
+
+ /* Allocate the Image */
+
+ if (!(Image = (BYTE *)malloc(IWidth*IHeight))) {
+ printf("Out of memory");
+ exit(-1);
+ }
+
+ BytesPerScanline = IWidth;
+
+ /* Decompress the file, continuing until you see the GIF EOF code.
+ * One obvious enhancement is to add checking for corrupt files here.
+ */
+
+ Code = ReadCode();
+ while (Code != EOFCode) {
+
+ /* Clear code sets everything back to its initial value, then reads the
+ * immediately subsequent code as uncompressed data.
+ */
+
+ if (Code == ClearCode) {
+ CodeSize = InitCodeSize;
+ MaxCode = (1 << CodeSize);
+ ReadMask = MaxCode - 1;
+ FreeCode = FirstFree;
+ CurCode = OldCode = Code = ReadCode();
+ FinChar = CurCode & DataMask;
+ AddToPixel(FinChar);
+ }
+ else {
+
+ /* If not a clear code, then must be data: save same as CurCode and InCode */
+
+ CurCode = InCode = Code;
+
+ /* If greater or equal to FreeCode, not in the hash table yet;
+ * repeat the last character decoded
+ */
+
+ if (CurCode >= FreeCode) {
+ CurCode = OldCode;
+ OutCode[OutCount++] = FinChar;
+ }
+
+ /* Unless this code is raw data, pursue the chain poWORDed to by CurCode
+ * through the hash table to its end; each code in the chain puts its
+ * associated output code on the output queue.
+ */
+
+ while (CurCode > DataMask) {
+ if (OutCount > 1024) {
+ /*return error message*/
+ }
+ OutCode[OutCount++] = Suffix[CurCode];
+ CurCode = Prefix[CurCode];
+ }
+
+ /* The last code in the chain is treated as raw data. */
+
+ FinChar = CurCode & DataMask;
+ OutCode[OutCount++] = FinChar;
+
+ /* Now we put the data out to the Output routine.
+ * It's been stacked LIFO, so deal with it that way...
+ */
+
+ for (i = OutCount - 1; i >= 0; i--)
+ AddToPixel(OutCode[i]);
+ OutCount = 0;
+
+ /* Build the hash table on-the-fly. No table is stored in the file. */
+
+ Prefix[FreeCode] = OldCode;
+ Suffix[FreeCode] = FinChar;
+ OldCode = InCode;
+
+ /* PoWORD to the next slot in the table. If we exceed the current
+ * MaxCode value, increment the code size unless it's already 12. If it
+ * is, do nothing: the next code decompressed better be CLEAR
+ */
+
+ FreeCode++;
+ if (FreeCode >= MaxCode) {
+ if (CodeSize < 12) {
+ CodeSize++;
+ MaxCode *= 2;
+ ReadMask = (1 << CodeSize) - 1;
+ }
+ }
+ }
+ Code = ReadCode();
+ }
+
+ return Image;
+}
+
+
diff --git a/tools/gifconv/gif.h b/tools/gifconv/gif.h
new file mode 100644
index 0000000..f697881
--- /dev/null
+++ b/tools/gifconv/gif.h
@@ -0,0 +1,179 @@
+/****************************************************************************\
+** Title: GIF.H **
+** Purpose: GIF Header file **
+\****************************************************************************/
+
+#ifndef GIF_H
+#define GIF_H 1
+
+#include <hdf5.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define MAX_PAL 768
+
+/*#include "datatype.h" Data type definitions */
+
+/* set the name length restriction to 64 charachters */
+#define VSNAMELENMAX 64 /* this is a carryover from HDF4 */
+
+/* typedef H5T_NATIVE_UINT8 BYTE; */
+typedef unsigned char BYTE;
+
+/* typedef H5T_NATIVE_UINT16 WORD; */
+typedef unsigned long WORD;
+
+typedef char CHAR;
+typedef unsigned char boolean;
+
+#define false 0;
+#define true 1;
+
+/* Set the EndianOrder.
+** The GIF Reader file should do this.
+** Set EndianOrder = 0 if machine is little endian
+** EndianOrder = 1 if machine is big endian.
+*/
+extern int EndianOrder;
+
+/*
+** The GIF header format.
+**
+** This structure actually contains the header, logical screen
+** descriptor, and the global color table for the GIF image.
+*/
+typedef struct _GifHeader /* Offset Description */
+{
+ BYTE PackedField; /* 0Ah Color Information */
+ WORD TableSize;
+ BYTE ImageCount; /* Keep a count of the number of images */
+ BYTE CommentCount;
+ BYTE ApplicationCount;
+ BYTE PlainTextCount;
+ BYTE HDFPalette[256][3];
+ BYTE HeaderDump[6]; /* BYTE array to dump header contents */
+ BYTE LSDDump[7]; /* Logical Screen Descriptor dump */
+} GIFHEAD;
+
+
+/*
+** The GIF Image Descriptor.
+*/
+typedef struct _GifImageDescriptor
+{
+ WORD ImageWidth; /* Width of the image in pixels */
+ WORD ImageHeight; /* Height of the image in pixels */
+ BYTE PackedField; /* Image and Color Table Data Information */
+ WORD TableSize;
+ WORD CodeSize; /* Minimum LZW CodeSize for image data */
+ BYTE HDFPalette[256][3];
+ BYTE GIDDump[9]; /* GifImageDescriptor dump */
+
+ BYTE *Image; /* Decompressed Raster Image */
+ BYTE *GIFImage;
+} GIFIMAGEDESC;
+
+
+/*
+** GIF 89a Graphic Control Extension Block
+*/
+typedef struct _GifGraphicControlExtension
+{
+ BYTE GCEDump[5]; /* Graphic Control Extension Dump */
+} GIFGRAPHICCONTROL;
+
+
+/*
+** GIF 89a Plain Text Extension Block
+*/
+typedef struct _GifPlainTextExtension
+{
+ BYTE PTEDump[15]; /* Plain Text Extension Dump */
+ BYTE *PlainTextData; /* Plain Text data sub-blocks */
+ WORD DataSize;
+} GIFPLAINTEXT;
+
+
+/*
+** GIF 89a Application Extension Block
+*/
+typedef struct _GifApplicationExtension
+{
+ BYTE AEDump[14]; /* Application Extension Dump */
+ BYTE *ApplicationData; /* Application data sub-blocks */
+ WORD DataSize;
+} GIFAPPLICATION;
+
+/*
+** GIF 89a Comment Extension Block
+*/
+typedef struct _GifCommentExtension
+{
+ BYTE CEDump[2]; /* Comment Extension Dump */
+ BYTE *CommentData; /* Comment data sub-blocks */
+ WORD DataSize;
+ BYTE Terminator; /* Block Terminator (always 0) */
+} GIFCOMMENT;
+
+/*
+** GIF to HDF Memory Struct
+** Purpose : The gif to hdf structure is used to pass all the
+** gif data to the memory, which gets caught by the hdf driver
+** Its the drivers job to put the data in the appropriate places
+** in the HDF file.
+** I have assumed that the ImageDescriptors and GraphicControls follow
+** one another, ie. I have not associated them with each other. The driver
+** must assume a 1-1 correspondance. The same discussion with plain text
+** extension.
+*/
+typedef struct _GifToMem
+{
+ GIFHEAD *GifHeader;
+ GIFIMAGEDESC **GifImageDesc;
+ GIFGRAPHICCONTROL **GifGraphicControlExtension;
+ GIFPLAINTEXT **GifPlainTextExtension;
+ GIFAPPLICATION **GifApplicationExtension;
+ GIFCOMMENT **GifCommentExtension;
+} GIFTOMEM;
+
+
+/*
+** Function Prototypes
+*/
+/* GIF2MEM.C */
+GIFTOMEM Gif2Mem(BYTE *);
+
+/* GIFREAD.C */
+int ReadGifHeader(GIFHEAD *, BYTE **);
+int ReadGifImageDesc(GIFIMAGEDESC *, BYTE **);
+int ReadGifGraphicControl(GIFGRAPHICCONTROL *, BYTE **);
+int ReadGifPlainText(GIFPLAINTEXT *, BYTE **);
+int ReadGifApplication(GIFAPPLICATION *, BYTE **);
+int ReadGifComment(GIFCOMMENT *, BYTE **);
+
+/* WRITEHDF.C */
+int WriteHDF(GIFTOMEM , CHAR * , CHAR *);
+
+/* Function : ReadHDF
+** Return: 0 on completion without error, -1 on error
+** Input: CHAR *h5_file - HDF file name
+** CHAR *dset_name - Name of the HDF Image dataset
+** CHAR *pal_name - Name of the HDF palette
+** Output : BYTE* data - the HDF Image to be converted
+** BYTE palette[256][3] - the corresponding palette
+** hsize_t* image_size - the size of each dimension of the image
+**
+*/
+int ReadHDF(BYTE** data , BYTE palette[256][3] , hsize_t *image_size , CHAR *h5_file , CHAR *dset_name , CHAR *pal_name);
+
+BYTE *ReadDataSubBlocks(BYTE ** , WORD *);
+BYTE *Decompress (GIFIMAGEDESC * , GIFHEAD *);
+BYTE GetByte(BYTE *);
+WORD GetWord(BYTE *);
+
+void cleanup(BYTE*);
+#endif /* GIF_H */
+
diff --git a/tools/gifconv/gif2hdf.c b/tools/gifconv/gif2hdf.c
new file mode 100644
index 0000000..0211143
--- /dev/null
+++ b/tools/gifconv/gif2hdf.c
@@ -0,0 +1,114 @@
+/* #include <hdf.h> */
+#include "gif.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+int
+main(argv , argc)
+int argv;
+char *argc[];
+{
+
+ GIFTOMEM GifMemoryStruct;
+ GIFIMAGEDESC gifImageDesc;
+
+ FILE *fpGif;
+
+ /* replacing int32 with long */
+ long i,ImageCount;
+ long filesize;
+
+ BYTE *MemGif;
+ BYTE *StartPos;
+
+ /* VSNAMELENMAX is a carryover from HDF4 and is #defined to 256 in gif.h */
+ char GIFFileName[VSNAMELENMAX];
+ char HDFFileName[VSNAMELENMAX];
+
+ /* Initialize all GifMemoryStruct pointers to null
+ ** to prevent hassles later on
+ */
+ GifMemoryStruct.GifHeader = NULL;
+ GifMemoryStruct.GifImageDesc = NULL;
+ GifMemoryStruct.GifGraphicControlExtension = NULL;
+ GifMemoryStruct.GifPlainTextExtension = NULL;
+ GifMemoryStruct.GifApplicationExtension = NULL;
+ GifMemoryStruct.GifCommentExtension = NULL;
+
+
+ if (argv<3)
+ {
+ printf("\n\nWrong Usage. Use:\ngif2hdf <GIFFILE> <HDFFILE>\n\n");
+ return(-1);
+ }
+
+
+
+ strncpy(GIFFileName , argc[1] , VSNAMELENMAX - 1);
+ strncpy(HDFFileName , argc[2] , VSNAMELENMAX - 1);
+ GIFFileName[VSNAMELENMAX - 1] = '\0';
+ HDFFileName[VSNAMELENMAX - 1] = '\0';
+
+ if (!(fpGif = fopen(GIFFileName,"rb"))) {
+ printf("Unable to open GIF file for reading.\n");
+ printf("Filename (including path) must be less than %d charachters in length\n",VSNAMELENMAX);
+ exit(-1);
+ }
+
+ /* Get the whole file into memory. Mem's much faster than I/O */
+ fseek(fpGif, 0L , 2);
+ filesize = ftell(fpGif);
+ fseek(fpGif, 0L , 0);
+ if (filesize == 0) printf("File Size Zero");
+ if (!(MemGif = StartPos = (BYTE *)malloc(filesize))) {
+ printf("Out of memory");
+ exit (-1);
+ }
+ if (fread(MemGif,filesize,1,fpGif) != 1) {
+ printf("Corrupted Input File");
+ exit(-1);
+ }
+
+ fseek(fpGif,0L,0);
+
+ /*
+ ** Call Gif2Mem and break the whole file into parts.
+ ** Gif2Mem also calls decompresses the images so we don't
+ ** have to worry about that
+ */
+ GifMemoryStruct = Gif2Mem(MemGif);
+ if (ferror(fpGif)) {
+ printf("File Stream Error\n\n");
+ exit(-1);
+ }
+ fclose(fpGif);
+
+ /* Call WriteHDF from here. Go ahead and change WriteHDF to write
+ ** whatever format you want
+ */
+ if (WriteHDF(GifMemoryStruct , argc[2] , argc[1]))
+ printf("HDF Write Error\n\n");
+
+ /* Free all buffers */
+ /* replacing int32 with long */
+ ImageCount = (long)((GifMemoryStruct.GifHeader)->ImageCount);
+
+ for(i = 0 ; i < ImageCount ; i++)
+ {
+ gifImageDesc = *(GifMemoryStruct.GifImageDesc[i]);
+ if (gifImageDesc.Image != NULL)
+ free(gifImageDesc.Image);
+
+ if (GifMemoryStruct.GifGraphicControlExtension[i] != NULL)
+ free(GifMemoryStruct.GifGraphicControlExtension[i]);
+
+ }
+ free(StartPos);
+
+ free (GifMemoryStruct.GifHeader);
+
+ if (GifMemoryStruct.GifApplicationExtension != NULL)
+ free (GifMemoryStruct.GifApplicationExtension);
+
+ return (0);
+}
diff --git a/tools/gifconv/gif2mem.c b/tools/gifconv/gif2mem.c
new file mode 100644
index 0000000..92ca8e5
--- /dev/null
+++ b/tools/gifconv/gif2mem.c
@@ -0,0 +1,344 @@
+/*
+** This file contains snippets of code from James Murray's original file
+** to display the GIF header information, but most of it has been modified to
+** suit gif2hdf
+*/
+
+
+
+/****************************************************************************\
+** Title: GIFHEAD.C **
+** Purpose: Display the data in a GIF image file. **
+** Version: 1.0 **
+** Date: March 1992 **
+** Author: James D. Murray, Anaheim, CA, USA **
+** C Compilers: Borland C++ v2.0, Microsoft C v6.00a **
+** **
+** GIFHEAD displays all real information contained within a GIF image **
+** file, including all color tables and extension block information. **
+** GIFHEAD reads both GIF 87a abd 89a-format files. **
+** **
+** Copyright (C) 1991-92 by Graphics Software Labs. All rights reserved. **
+\****************************************************************************/
+#include <stdio.h>
+#include "gif.h"
+/* #include <hdf.h> */
+
+#define VERSION "1.00"
+extern int EndianOrder;
+
+GIFTOMEM
+Gif2Mem(MemGif)
+BYTE *MemGif;
+{
+ /*
+ ** The gif structure outline for passing data to memory
+ ** is given in gif.h
+ ** These pointers are redunant, should take them out in ver. 2
+ */
+ GIFHEAD *gifHead; /* GIF Header structure */
+ GIFIMAGEDESC **gifImageDesc; /* Logical Image Descriptor struct */
+ GIFPLAINTEXT **gifPlainText; /* Plain Text Extension structure */
+ GIFAPPLICATION **gifApplication; /* Application Extension structure */
+ GIFCOMMENT **gifComment; /* Comment Extension structure */
+ GIFGRAPHICCONTROL **gifGraphicControl; /* Graphic Control Extension strct */
+
+ GIFTOMEM GifMemoryStruct;
+
+
+
+ register WORD i; /* Loop counter */
+ BYTE Identifier; /* Extension block identifier holder */
+ BYTE Label; /* Extension block label holder */
+ BYTE ImageCount; /* Count of the number of images in the file */
+ BYTE ImageArray; /* Keep the size of the array to store Images */
+ BYTE CommentCount;
+ BYTE CommentArray;
+ BYTE ApplicationCount;
+ BYTE ApplicationArray;
+ BYTE PlainTextCount;
+ BYTE PlainTextArray;
+ BYTE GCEflag;
+ BYTE aTemp;
+ BYTE j;
+
+ BYTE w; /* Two more variables needed only while testing */
+ BYTE *b; /* Endian Ordering */
+
+ /* Allocate memory for the GIF structures */
+ /* Plug the structs into GifMemoryStruct at the end */
+ /****************************************************/
+ if (!(gifHead = (GIFHEAD *)malloc(sizeof(GIFHEAD))))
+ {
+ printf("Could not allocate memory for gifHead\n");
+ exit(-1);
+ }
+
+ /*
+ ** The next three have to grow dynamically so we leave them
+ ** for now and let realloc handle it later on.
+ */
+ gifImageDesc = NULL;
+ gifPlainText = NULL;
+ gifGraphicControl = NULL;
+ gifComment = NULL;
+ gifApplication = NULL;
+
+ /******************************/
+ /* Memory allocation complete */
+
+
+ /* Carry out Endian Testing and set Endian Order */
+ w = 0x0001;
+ b = (BYTE *) &w;
+ EndianOrder = (b[0] ? 1 : 0);
+
+ /* Read the GIF image file header information */
+ ReadGifHeader(gifHead, &MemGif);
+
+ /* Check for FILE stream error */
+ /*
+ if (ferror(fpGif))
+ {
+ fputs("GIFHEAD: Error reading header information!\n", stderr);
+ exit(-3);
+ }
+ */
+
+ /*
+ ** Identify, read, and display block information.
+ */
+ ImageCount = ImageArray = 0;
+ CommentCount = CommentArray = 0;
+ ApplicationCount = ApplicationArray = 0;
+ PlainTextCount = PlainTextArray = 0;
+ GCEflag = 0;
+
+ for (;;)
+ {
+ Identifier = *MemGif++;
+
+ switch (Identifier)
+ {
+ case 0x3B: /* Trailer */
+ /* The counts are stored to make it easier while
+ ** putting stuff into the HDF file and then
+ ** deallocating space.
+ */
+ gifHead->ImageCount = ImageCount;
+ gifHead->CommentCount = CommentCount;
+ gifHead->ApplicationCount = ApplicationCount;
+ gifHead->PlainTextCount = PlainTextCount;
+
+ /* putting stuff into the gif2mem structure */
+ GifMemoryStruct.GifHeader = gifHead;
+ GifMemoryStruct.GifImageDesc = gifImageDesc;
+ GifMemoryStruct.GifPlainTextExtension = gifPlainText;
+ GifMemoryStruct.GifApplicationExtension = gifApplication;
+ GifMemoryStruct.GifCommentExtension = gifComment;
+ GifMemoryStruct.GifGraphicControlExtension = gifGraphicControl;
+
+ /* return the struct */
+ return GifMemoryStruct;
+
+
+
+ case 0x2C: /* Image Descriptor */
+ /* If there was no image descriptor before this increase image count.
+ ** If an imagedescriptor was present, reset GCEflag
+ */
+ if (GCEflag == 0)
+ ImageCount++;
+ else
+ GCEflag = 0;
+
+ if (ImageCount > ImageArray) {
+ aTemp = ImageArray;
+ ImageArray = (ImageArray << 1) + 1;
+ if (!(gifImageDesc = (GIFIMAGEDESC **)realloc(gifImageDesc , sizeof(GIFIMAGEDESC *) * ImageArray)))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+ if (!(gifGraphicControl = (GIFGRAPHICCONTROL **)realloc(gifGraphicControl , sizeof(GIFGRAPHICCONTROL *) * ImageArray)))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+
+ for (j = aTemp ; j < ImageArray ; j++) {
+ gifGraphicControl[j] = NULL;
+ gifImageDesc[j] = NULL;
+ }
+ }
+
+ if(!(gifImageDesc[ImageCount-1] = (GIFIMAGEDESC*)malloc(sizeof(GIFIMAGEDESC))))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+
+
+ if (ReadGifImageDesc(gifImageDesc[ImageCount-1], &MemGif) == -1)
+ fputs("Error reading Image Descriptor information\n", stderr);
+
+ /*
+ ** Decompress the Image
+ */
+ gifImageDesc[ImageCount-1]->Image = Decompress(gifImageDesc[ImageCount-1] , gifHead);
+ free(gifImageDesc[ImageCount-1]->GIFImage);
+
+ /*
+ ** Convert the local palette into an HDF compatible palette
+ ** In case the local color table is present, it is written out as the HDFPalette
+ ** If it is absent the global table is written as the HDFPalette.
+ */
+ if (!((gifImageDesc[ImageCount-1]->PackedField) & 0x80))
+ {
+ /* Check to see if the global color table exists.... */
+ if (gifHead->PackedField & 0x80) {
+ for (i=0 ; i<gifHead->TableSize ; i++)
+ {
+ gifImageDesc[ImageCount-1]->HDFPalette[i][0] = gifHead->HDFPalette[i][0];
+ gifImageDesc[ImageCount-1]->HDFPalette[i][1] = gifHead->HDFPalette[i][1];
+ gifImageDesc[ImageCount-1]->HDFPalette[i][2] = gifHead->HDFPalette[i][2];
+ }
+ }
+ gifImageDesc[ImageCount-1]->TableSize = gifHead->TableSize;
+ }
+
+ break;
+
+ case 0x21: /* Extension Block */
+ Label = *MemGif++;
+ switch (Label)
+ {
+ case 0x01: /* Plain Text Extension */
+ puts("Plain Text Extension\n");
+
+ PlainTextCount++;
+ if (PlainTextCount > PlainTextArray)
+ PlainTextArray = (PlainTextArray << 1) + 1;
+
+ if (!(gifPlainText = (GIFPLAINTEXT **)realloc(gifPlainText , sizeof(GIFPLAINTEXT *) * PlainTextArray)))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+
+ if(!(gifPlainText[PlainTextCount - 1] = (GIFPLAINTEXT*)malloc(sizeof(GIFPLAINTEXT))))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+
+
+
+ if (ReadGifPlainText(gifPlainText[PlainTextCount - 1], &MemGif))
+ fprintf(stderr,
+ "Error reading Plain Text Extension information.\n");
+
+ break;
+
+ case 0xFE: /* Comment Extension */
+ CommentCount++;
+ if (CommentCount > CommentArray)
+ CommentArray = (CommentArray << 1) + 1;
+
+ if (!(gifComment = (GIFCOMMENT **)realloc(gifComment , sizeof(GIFCOMMENT *) * CommentArray)))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+
+ if(!(gifComment[CommentCount - 1] = (GIFCOMMENT *)malloc(sizeof(GIFCOMMENT))))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+
+
+ if (ReadGifComment(gifComment[CommentCount - 1], &MemGif))
+ fprintf(stderr,
+ "Error reading Comment Extension information\n");
+ break;
+
+ case 0xF9: /* Graphic Control Extension */
+ if (GCEflag == 0 )
+ ImageCount++;
+
+ GCEflag = 1;
+
+ if (ImageCount > ImageArray) {
+ aTemp = ImageArray;
+ ImageArray = (ImageArray << 1) + 1;
+ if (!(gifGraphicControl = (GIFGRAPHICCONTROL **)realloc(gifGraphicControl , sizeof(GIFGRAPHICCONTROL *) * ImageArray)))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+ if (!(gifImageDesc = (GIFIMAGEDESC **)realloc(gifImageDesc , sizeof(GIFIMAGEDESC *) * ImageArray)))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+ for (j = aTemp ; j < ImageArray ; j++) {
+ gifGraphicControl[j] = NULL;
+ gifImageDesc[j] = NULL;
+ }
+ }
+
+ if(!(gifGraphicControl[ImageCount-1] = (GIFGRAPHICCONTROL*)malloc(sizeof(GIFGRAPHICCONTROL))))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+
+
+ if (ReadGifGraphicControl(gifGraphicControl[ImageCount-1], &MemGif))
+ fprintf(stderr,
+ "Error reading Graphic Control Extension information\n");
+
+ if (!*MemGif++ == 0)
+ fprintf(stderr,
+ "Error reading Graphic Control Extension\n");
+
+ break;
+
+ case 0xFF: /* Application Extension */
+ ApplicationCount++;
+ if (ApplicationCount > ApplicationArray)
+ ApplicationArray = (ApplicationArray << 1) + 1;
+
+ if (!(gifApplication = (GIFAPPLICATION **)realloc(gifApplication , sizeof(GIFAPPLICATION *) * ApplicationArray)))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+
+ if(!(gifApplication[ApplicationCount - 1] = (GIFAPPLICATION *)malloc(sizeof(GIFAPPLICATION))))
+ {
+ printf("Out of memory!");
+ exit(-1);
+ }
+
+
+ if (ReadGifApplication(gifApplication[ApplicationCount - 1], &MemGif))
+ fprintf(stderr,
+ "Error reading Application Extension information\n");
+ break;
+
+ default:
+
+ printf("Unknown Extension Label: 0x%02x\n", Label);
+ break;
+ }
+ break;
+ default:
+ fprintf(stderr, "Unknown Block Separator Character: 0x%02x\n",
+ Identifier);
+ }
+ }
+
+
+}
diff --git a/tools/gifconv/gifread.c b/tools/gifconv/gifread.c
new file mode 100644
index 0000000..1196241
--- /dev/null
+++ b/tools/gifconv/gifread.c
@@ -0,0 +1,382 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "gif.h"
+
+int EndianOrder;
+int i;
+
+
+WORD
+GetWord (MemGif)
+BYTE *MemGif;
+{
+ register WORD w;
+ if (EndianOrder == 1) /* LittleEndian */
+ {
+ w = (WORD) (*MemGif++ & 0xFF);
+ w |= (WORD) ((*MemGif++ & 0xFF) << 0x08);
+ }
+ else
+ {
+ w = (WORD) (*MemGif++ & 0xFF);
+ w = ((WORD) (*MemGif++ & 0xFF)) | (w << 0x08);
+ }
+ return w;
+}
+
+BYTE
+GetByte (MemGif)
+BYTE *MemGif;
+{
+ return *MemGif;
+}
+
+/*
+** Read a GIF image BYTE Header.
+**
+** This function reads the Header, Logical Screen Descriptor, and
+** Global Color Table (if any) from a GIF image file. The information
+** is stored in a GIFHEAD structure.
+**
+** Returns: -1 if a FILE stream error occured during the read,
+** otherwise 0 if no error occured.
+*/
+int
+ReadGifHeader(GifHead, MemGif2)
+GIFHEAD *GifHead; /* Pointer to GIF header structure */
+BYTE **MemGif2; /* GIF image file input FILE stream */
+{
+ register WORD i; /* Loop counter */
+ WORD tableSize; /* Number of entires in the Global Color Table */
+
+ GifHead->TableSize = 0;
+ for (i = 0 ; i < 6 ; i++) {
+ GifHead->HeaderDump[i] = *(*MemGif2)++;
+ }
+ if (strncmp(GifHead->HeaderDump , "GIF" , 3)) {
+ printf("The file does not appear to be a valid GIF file.\n");
+ exit(-1);
+ }
+
+ for (i = 0 ; i < 7 ; i++) {
+ GifHead->LSDDump[i] = *(*MemGif2)++;
+ }
+
+ GifHead->PackedField = GifHead->LSDDump[4];
+ /* Check if a Global Color Table is present */
+ if (GifHead->PackedField & 0x80)
+ {
+ /* Read number of color table entries */
+ tableSize = (WORD) (1L << ((GifHead->PackedField & 0x07) + 1));
+ GifHead->TableSize = tableSize;
+ /* Read the Global Color Table */
+ /*
+ ** There are some changes made here apart from just
+ ** reading in the global color table as would
+ ** seem intuitively obvious.
+ ** The colors are stored in the bottom part of the
+ ** palette as opposed to the top
+ */
+
+ for (i = 0; i < tableSize; i++)
+ {
+ GifHead->HDFPalette[i][0] = *(*MemGif2)++;
+ GifHead->HDFPalette[i][1] = *(*MemGif2)++;
+ GifHead->HDFPalette[i][2] = *(*MemGif2)++;
+ }
+ }
+
+ /* Check for a FILE stream error */
+ /*
+ if (ferror(FpGif))
+ return(-1);
+ */
+
+ return(0); /* No FILE stream error occured */
+}
+
+
+/*
+** Read a GIF Local Image Descriptor.
+**
+** This function reads the Local Image Descriptor, and Local Color
+** Table (if any) from a GIF image file. The information is stored
+** in a GIFIMAGEDESC structure.
+**
+** Note that the ImageSeparator field value in the GIFIMAGEDESC
+** structure is assigned by the function calling ReadGifImageDesc().
+**
+** Returns: -1 if a FILE stream error occured during the read,
+** otherwise 0 if no error occured.
+*/
+int
+ReadGifImageDesc(GifImageDesc, MemGif2)
+GIFIMAGEDESC *GifImageDesc; /* Pointer to GIF image descriptor structure */
+BYTE **MemGif2; /* GIF image file input FILE stream */
+{
+ register WORD i; /* Loop counter */
+ WORD tableSize; /* Number of entries in the Local Color Table */
+ BYTE Interlace; /* PackedField & 0x20 gives information on interlacing */
+ BYTE *TempPtr;
+ int ch , ch1;
+
+ GifImageDesc->TableSize = 0;
+ for (i = 0 ; i < 9 ; i++) {
+ GifImageDesc->GIDDump[i] = *(*MemGif2)++;
+ }
+
+ /*
+ ** Get the relevant fields. I need ImageWidth and Height actively hence I have
+ ** taken information from those fields. I intend to keep the GifImageDesc data
+ ** structure as it is so that anyone needing the rest of the fields can do so
+ ** quickly.
+ */
+
+ if (EndianOrder == 1) /* LittleEndian */
+ {
+ GifImageDesc->ImageWidth = (WORD) (GifImageDesc->GIDDump[4] & 0xFF);
+ GifImageDesc->ImageWidth |= (WORD) ((GifImageDesc->GIDDump[5] & 0xFF) << 0x08);
+
+ GifImageDesc->ImageHeight = (WORD) (GifImageDesc->GIDDump[6] & 0xFF);
+ GifImageDesc->ImageHeight |= (WORD) ((GifImageDesc->GIDDump[7] & 0xFF) << 0x08);
+
+ }
+ else
+ {
+ GifImageDesc->ImageWidth = (WORD) (GifImageDesc->GIDDump[4] & 0xFF);
+ GifImageDesc->ImageWidth = ((WORD) (GifImageDesc->GIDDump[5] & 0xFF)) | (GifImageDesc->ImageWidth << 0x08);
+
+ GifImageDesc->ImageHeight = (WORD) (GifImageDesc->GIDDump[6] & 0xFF);
+ GifImageDesc->ImageHeight = ((WORD) (GifImageDesc->GIDDump[7] & 0xFF)) | (GifImageDesc->ImageWidth << 0x08);
+
+
+ }
+
+ GifImageDesc->PackedField = GifImageDesc->GIDDump[8];
+
+ /* Interlace = GifImageDesc->PackedField & 0x20; */
+
+ /* Check if a Local Color Table is present */
+ if (GifImageDesc->PackedField & 0x80)
+ {
+ /* Read number of color table entries */
+ tableSize = (WORD) (1L << ((GifImageDesc->PackedField & 0x07) + 1));
+ GifImageDesc->TableSize = tableSize;
+ /* Read the Local Color Table */
+ for (i = 0; i < tableSize; i++)
+ {
+ GifImageDesc->HDFPalette[i][0] = *(*MemGif2)++;
+ GifImageDesc->HDFPalette[i][1] = *(*MemGif2)++;
+ GifImageDesc->HDFPalette[i][2] = *(*MemGif2)++;
+ }
+ }
+
+ /*
+ ** Get LZW minimum Code Size
+ */
+ GifImageDesc->CodeSize = (WORD)*(*MemGif2)++;
+
+ /*GifImageDesc->GIFImage = ReadDataSubBlocks(FpGif);*/
+ if (!(GifImageDesc->GIFImage = (BYTE *)malloc((GifImageDesc->ImageWidth) * (GifImageDesc->ImageHeight)))) {
+ printf("Out of memory");
+ exit(-1);
+ }
+
+
+ TempPtr = GifImageDesc->GIFImage;
+ do
+ {
+ ch = ch1 = (int)*(*MemGif2)++;
+ while (ch--) *TempPtr++ = *(*MemGif2)++;
+ }
+ while (ch1);
+
+
+ return(0); /* No FILE stream error occured */
+}
+
+
+/*
+** Read a GIF Graphic Control Extension block.
+**
+** Note that the Introducer and Label field values in the GIFGRAPHICCONTROL
+** structure are assigned by the function calling ReadGifGraphicControl().
+**
+** Returns: -1 if a FILE stream error occured during the read,
+** otherwise 0 if no error occured.
+*/
+int
+ReadGifGraphicControl(GifGraphicControl, MemGif2)
+GIFGRAPHICCONTROL *GifGraphicControl; /* Pointer to GC Extension structure */
+BYTE **MemGif2; /* GIF image file input FILE stream */
+{
+
+
+ for (i = 0 ; i < 5 ; i++) {
+ GifGraphicControl->GCEDump[i] = *(*MemGif2)++;
+ }
+
+ return(0); /* No FILE stream error occured */
+}
+
+
+/*
+** Read a GIF Plain Text Extension block.
+**
+** Note that the Introducer and Label field values in the GIFLPLAINTEXT
+** structure are assigned by the function calling ReadGifPlainText().
+**
+** Returns: -1 if a FILE stream error occured during the read,
+** otherwise 0 if no error occured.
+*/
+int
+ReadGifPlainText(GifPlainText, MemGif2)
+GIFPLAINTEXT *GifPlainText; /* Pointer to Plain Text Extension structure */
+BYTE **MemGif2; /* GIF image file input FILE stream */
+{
+ for (i = 0 ; i < 13 ; i++) {
+ GifPlainText->PTEDump[i] = *(*MemGif2)++;
+ }
+
+ /* Read in the Plain Text data sub-blocks */
+ if (!(GifPlainText->PlainTextData = ReadDataSubBlocks(MemGif2 , &(GifPlainText->DataSize))))
+ return(1);
+
+ /*
+ GifPlainText->Terminator = 0;
+ */
+
+ /* Check for a FILE stream error */
+ /*
+ if (ferror(FpGif))
+ return(-1);
+ */
+
+ return(0); /* No FILE stream error occured */
+}
+
+
+/*
+** Read a GIF Application Extension block.
+**
+** Note that the Introducer and Label field values in the GIFAPPLICATION
+** structure are assigned by the function calling ReadGifApplication().
+**
+** Returns: -1 if a FILE stream error occured during the read,
+** otherwise 0 if no error occured.
+*/
+int
+ReadGifApplication(GifApplication, MemGif2)
+GIFAPPLICATION *GifApplication; /* Pointer to Application Extension structure */
+BYTE **MemGif2; /* GIF image file input FILE stream */
+{
+ for (i = 0 ; i < 12 ; i++) {
+ GifApplication->AEDump[i] = *(*MemGif2)++;
+ }
+
+ /* Read in the Plain Text data sub-blocks */
+ if (!(GifApplication->ApplicationData = ReadDataSubBlocks(MemGif2 , &(GifApplication->DataSize))))
+ return(1);
+ /*
+ GifApplication->Terminator = 0;
+ */
+
+ /* Check for a FILE stream error */
+ /*
+ if (ferror(FpGif))
+ return(-1);
+ */
+
+ return(0); /* No FILE stream error occured */
+}
+
+
+/*
+** Read a GIF Comment Extension block.
+**
+** Note that the Introducer and Label field values in the GIFCOMMENT
+** structure are assigned by the function calling ReadGifComment().
+**
+** Returns: -1 if a FILE stream error occured during the read,
+** otherwise 0 if no error occured.
+*/
+int
+ReadGifComment(GifComment, MemGif2)
+GIFCOMMENT *GifComment; /* Pointer to GIF Comment Extension structure */
+BYTE **MemGif2; /* GIF image file input FILE stream */
+{
+
+ /* Read in the Plain Text data sub-blocks */
+ if (!(GifComment->CommentData = ReadDataSubBlocks(MemGif2 , &(GifComment->DataSize))))
+ return(1);
+
+ GifComment->Terminator = 0;
+
+ return(0); /* No FILE stream error occured */
+}
+
+
+/*
+** Read one or more GIF data sub-blocks and write the information
+** to a buffer.
+**
+** A GIF "sub-block" is a single count byte followed by 1 to 255
+** additional data bytes.
+**
+** Returns: A NULL pointer if a memory allocation error occured,
+** otherwise a valid pointer if no error occured.
+*/
+static BYTE *
+ReadDataSubBlocks(MemGif2 , DSize)
+BYTE **MemGif2; /* GIF image file input FILE stream */
+WORD *DSize;
+{
+ BYTE *ptr1; /* Pointer used to "walk the heap" */
+ BYTE *ptr2; /* Pointer used to mark the top of the heap */
+ BYTE dataSize; /* Size of the current data sub-block being read */
+ WORD bufSize; /* Total size of the Plain Text data buffer */
+ int tempcount = 0;
+
+ bufSize = 0; /* The output buffer is empty */
+
+ dataSize = *(*MemGif2)++; /* Get the size of the first sub-block */
+
+ /* Allocate initial data buffer */
+ if (!(ptr1 = ptr2 = (BYTE *) malloc(dataSize + 1))) {
+ printf("Out of memory. Allocation of memory for data sub-blocks for\neither Comment, Plain Text or Application Extensions failed");
+ return((BYTE *) NULL);
+ }
+ for (;;)
+ {
+ tempcount++;
+ bufSize += (dataSize); /* Running total of the buffer size */
+ *DSize = bufSize;
+
+ /* *ptr1++ = dataSize; /* Write the data count */
+ while (dataSize--) /* Read/write the Plain Text data */
+ *ptr1++ = *(*MemGif2)++;
+
+ /* Check if there is another data sub-block */
+ if ((dataSize = *(*MemGif2)++) == 0)
+ break; /* Block Terminator encountered */
+
+ /* Increase the buffer size to accomodate the next sub-block */
+ if (!(ptr1 = ptr2 = (BYTE *) realloc(ptr2, bufSize + dataSize + 1)))
+ return((BYTE *) NULL);
+
+
+ ptr1 += bufSize; /* Move pointer to the end of the data */
+
+
+ }
+
+ /**ptr1++ = (BYTE) NULL; /* Add NULL to simulate Terminator value */
+ *ptr1++ = '\0';
+
+ return(ptr2); /* Return a pointer to the sub-block data */
+}
+
+
+
+
+
diff --git a/tools/gifconv/hdf2gif.c b/tools/gifconv/hdf2gif.c
new file mode 100644
index 0000000..9c4133e
--- /dev/null
+++ b/tools/gifconv/hdf2gif.c
@@ -0,0 +1,354 @@
+/* NOTES:
+** 04/01 - 04/10: been working on it a lot. I think it does gif89 images just fine with
+** palettes. So that's cool. Putting in multiple images and animation support right now
+** 03/29: For some reason I can write .GIF files which IE will open and see but
+** kodak imaging does not like. I'm sure its a problem with the GIF file,
+** I can't figure out what.
+** 03/17: Explicitely deallocate the GIFTOMEM* struct in the main loop.
+** Check for both success and failure conditions
+*/
+
+#include "gif.h"
+#include <stdio.h>
+
+#define MAX_FILE_LEN 256
+#define MAX_NUMBER_IMAGES 50
+
+extern int hdfWriteGIF(FILE *fp, BYTE *pic, int ptype, int w, int h, BYTE *rmap,
+ BYTE *gmap, BYTE *bmap, BYTE *pc2ncmap, int numcols, int colorstyle, int BitsPerPixel);
+
+int EndianOrder;
+
+void PutByte(BYTE b , FILE *fpGif)
+{
+ if (fputc(b , fpGif) == EOF) {
+ printf("File Writing Error, cannot continue");
+ exit(-1);
+ }
+}
+
+
+void putword(int w, FILE *fp)
+{
+ /* writes a 16-bit integer in GIF order (LSB first) */
+
+ fputc(w &0xff, fp);
+
+ fputc((w>>8)&0xff,fp);
+}
+
+void usage() {
+ printf("Usage: h52gif <h5_file> <gif_file> -i <h5_image> [-p <h5_palette>]\n");
+ printf("h52gif expects *at least* one h5_image. You may repeat -i <h5_image> [-p <h5_palette>] at most 50 times (maximum of 50 images).\n");
+}
+
+int main(int argc , char **argv) {
+
+ FILE *fpGif;
+
+ hsize_t dim_sizes[2];
+
+ BYTE *Image;
+ /* compression structs */
+
+ CHAR *HDFName = NULL;
+ CHAR *GIFName = NULL;
+ CHAR *image_path = NULL;
+ CHAR *pal_path = NULL;
+ /* reference variables */
+
+ int has_local_palette; /* treated as a flag */
+ int loop_times; /* number of times to loop, i'm going to treat it as a yes or no */
+
+ BYTE* b;
+
+ BYTE GlobalPalette[256][3];
+ BYTE Red[256];
+ BYTE Green[256];
+ BYTE Blue[256];
+
+ int RWidth, RHeight;
+ int LeftOfs, TopOfs;
+ int ColorMapSize, InitCodeSize, Background, BitsPerPixel;
+ int j,nc;
+ int w,h,i;
+ int numcols = 256;
+ int CountDown;
+ int curx , cury;
+ int time_out = 0; /* time between two images in the animation */
+ int n_images , index;
+
+ BYTE pc2nc[256] , r1[256] , g1[256] , b1[256];
+
+ /* initial stuff */
+ int number_of_images = 0;
+ int arg_index = 2;
+ int bool_is_image = 0; /* 0 = false , 1 = true */
+ int bool_is_palette = 0;
+ CHAR* image_name_arr[MAX_NUMBER_IMAGES];
+ CHAR* pal_name_arr[MAX_NUMBER_IMAGES];
+
+ if (argc < 5) {
+ /* they didn't supply at least one image -- bail */
+ usage();
+ return 0;
+ }
+
+ memset(image_name_arr , NULL , MAX_NUMBER_IMAGES);
+ memset(pal_name_arr , NULL , MAX_NUMBER_IMAGES);
+
+ HDFName = (CHAR*) malloc (strlen(argv[1]) + 1);
+ GIFName = (CHAR*) malloc (strlen(argv[2]) + 1);
+
+ if (strlen(argv[1] + 1) > MAX_FILE_LEN || strlen(argv[2] + 1) > MAX_FILE_LEN) {
+ /* supplied file names are too long. bail. */
+ usage();
+ printf("Supplied filenames exceed maximum length of 256 bytes\n");
+ }
+
+ strcpy(HDFName , argv[1]);
+ strcpy(GIFName , argv[2]);
+
+ /* get the options */
+ while (arg_index++ < argc - 1 && number_of_images < MAX_NUMBER_IMAGES) {
+ if (!strcmp(argv[arg_index] , "-i")) {
+ bool_is_image = 1;
+ continue;
+ }
+ if (!strcmp(argv[arg_index] , "-p")) {
+ bool_is_palette = 1;
+ continue;
+ }
+ if (!strcmp(argv[arg_index] , "-a")) {
+ time_out = 10;
+ continue;
+ }
+ if (bool_is_image) {
+ /* this is an image */
+ /* allocate space to store the image name */
+ image_name_arr[number_of_images] = (CHAR*) malloc(strlen(argv[arg_index] + 1));
+ strcpy(image_name_arr[number_of_images] , argv[arg_index]);
+ /* make the palette array for this NULL */
+ pal_name_arr[number_of_images] = NULL;
+ number_of_images++;
+ bool_is_image = 0;
+ continue;
+ }
+ if (bool_is_palette) {
+ /* this is a palette */
+ /* allocate space to store the pal name */
+ /* the palette was probably allocated for a previous image */
+ pal_name_arr[number_of_images-1] = (CHAR*) malloc(strlen(argv[arg_index] + 1));
+ strcpy(pal_name_arr[number_of_images - 1] , argv[arg_index]);
+ bool_is_palette = 0;
+ continue;
+ }
+ /* oops. This was not meant to happen */
+ usage();
+ /*
+ while (number_of_images--) {
+ cleanup(image_name_arr[number_of_images]);
+ cleanup(pal_name_arr[number_of_images]);
+ }
+ */
+ return -1;
+
+ }
+
+ /* we shall always have a palette - read hdf will see to that */
+ has_local_palette = true;
+
+ /* Do Endian Order testing and set Endian Order */
+ w = 0x0001;
+ b = (BYTE *) &w;
+ EndianOrder = (b[0] ? 1:0);
+
+ if (!(fpGif = fopen(GIFName , "wb"))) {
+ printf("Error opening gif file for output. Aborting.\n");
+ return -1;
+ }
+
+ /* hardwire n_images to 1 for now. */
+ n_images = number_of_images;
+
+ Background = 0;
+ for (index = 0 ; index < n_images ; index++) {
+
+ /* try to read the image and the palette */
+ /* Lots of funky stuff to support multiple images has been taken off.
+ ** Just in case you're extending code, here's what you need to do in short:
+ ** figure out if there is a global palette or not, if there is one store that one
+ ** only.
+ ** If they are all local or a combination of local and global palettes, you will have
+ ** to write the global palette out and then independantly write the smaller local
+ ** palettes
+ */
+ if (ReadHDF(&Image , GlobalPalette , dim_sizes , HDFName , image_name_arr[index] , pal_name_arr[index]) < 0) {
+ fprintf(stderr , "Unable to read HDF file\n");
+ return -1;
+ }
+
+ w = dim_sizes[1];
+ h = dim_sizes[0];
+
+ RWidth = dim_sizes[1];
+ RHeight = dim_sizes[0];
+ LeftOfs = TopOfs = 0;
+
+
+ /* If the first image does not have a palette, I make my own global color table
+ ** Obviously this is not the best thing to do, better steps would be:
+ ** 1. Check for either a global palette or a global attribute called palette
+ ** 2. Check for palettes in any of the other images.
+ */
+ if (!has_local_palette) {
+ for (i = 0 ; i < 256 ; i++) {
+ Red[i] = 255 - i;
+ Green[i] = 255 - i;
+ Blue[i] = 255 - i;
+ }
+ }
+ else {
+ for (i = 0 ; i < 256 ; i++){
+ Red[i] = GlobalPalette[i][0];
+ Green[i] = GlobalPalette[i][1];
+ Blue[i] = GlobalPalette[i][2];
+ }
+ }
+
+ for (i=0; i<256; i++) { pc2nc[i] = r1[i] = g1[i] = b1[i] = 0; }
+ /* compute number of unique colors */
+ nc = 0;
+ for (i=0; i<numcols; i++) {
+ /* see if color #i is already used */
+ for (j=0; j<i; j++) {
+ if (Red[i] == Red[j] && Green[i] == Green[j] &&
+ Blue[i] == Blue[j]) break;
+ }
+ if (j==i) { /* wasn't found */
+ pc2nc[i] = nc;
+ r1[nc] = Red[i];
+ g1[nc] = Green[i];
+ b1[nc] = Blue[i];
+ nc++;
+ }
+ else pc2nc[i] = pc2nc[j];
+ }
+ /* figure out 'BitsPerPixel' */
+ for (i=1; i<8; i++) {
+ if ( (1<<i) >= nc) break;
+ }
+ BitsPerPixel = i;
+ ColorMapSize = 1 << BitsPerPixel;
+
+
+ CountDown = w * h; /* # of pixels we'll be doing */
+
+ if (BitsPerPixel <= 1) InitCodeSize = 2;
+ else InitCodeSize = BitsPerPixel;
+
+ curx = cury = 0;
+
+ if (!fpGif) {
+ fprintf(stderr, "WriteGIF: file not open for writing\n" );
+ return (1);
+ }
+
+ /* If it is the first image we do all the header stuff that isn't required for the
+ ** rest of the images.
+ */
+ if (index == 0) {
+ /* Write out the GIF header and logical screen descriptor */
+ if (n_images > 1) {
+ fwrite("GIF89a", 1, 6, fpGif); /* the GIF magic number */
+ loop_times = 0;
+ }
+ else {
+ fwrite("GIF87a", 1, 6, fpGif); /* the GIF magic number */
+ loop_times = 1;
+ }
+
+ putword(RWidth, fpGif); /* screen descriptor */
+ putword(RHeight, fpGif);
+
+ i = 0x00; /* No, there is no color map */
+ i |= (8-1)<<4; /* OR in the color resolution (hardwired 8) */
+ i |= (BitsPerPixel - 1); /* OR in the # of bits per pixel */
+ fputc(i,fpGif);
+
+ fputc(Background,fpGif); /* background color */
+
+ fputc(0, fpGif); /* future expansion byte */
+
+
+ /* If loop_times is 0 , put in the application extension to make the gif anime loop
+ ** indefinitely
+ */
+ if (time_out > 0) {
+ fputc(0x21 , fpGif);
+ fputc(0xFF , fpGif);
+ fputc(11 , fpGif);
+ fwrite("NETSCAPE2.0" , 1 , 11 , fpGif);
+ fputc(3 , fpGif);
+ fputc(1 , fpGif);
+ fputc(0 , fpGif);
+ fputc(0 , fpGif);
+ fputc(0 , fpGif);
+
+ }
+
+
+ }
+
+ if (n_images > 1) {
+ /* write a graphic control block */
+ fputc(0x21 , fpGif);
+ fputc(0xF9 , fpGif);
+ fputc(4 , fpGif);
+ fputc(4 , fpGif);
+ putword(time_out , fpGif);
+ fputc(255, fpGif);
+ fputc(0 , fpGif);
+ }
+
+ /* Put Image Descriptor
+ ** Hardwiring Left Offset and Top Offset to 0x00
+ */
+
+ fputc (0x2c , fpGif);
+ putword (0x00 , fpGif);
+ putword (0x00 , fpGif);
+ putword (RWidth , fpGif);
+ putword (RHeight , fpGif);
+
+ /* since we always have a local color palette ... */
+ fputc ((0x80 | (BitsPerPixel - 1)) , fpGif);
+ for (i=0; i<ColorMapSize; i++) { /* write out Global colormap */
+ fputc(r1[i], fpGif);
+ fputc(g1[i], fpGif);
+ fputc(b1[i], fpGif);
+ }
+
+ fputc (InitCodeSize , fpGif);
+
+ i = hdfWriteGIF(fpGif , Image , 0 , dim_sizes[0] , dim_sizes[1] , r1, g1 , b1 , pc2nc , 256 , 8 , BitsPerPixel);
+ fputc(0x00 , fpGif);
+ free (Image);
+ }
+
+ if (fputc(';',fpGif) == EOF) { /* Write GIF file terminator */
+ fprintf(stderr , "Error!");
+ return -1;
+ }
+
+ fclose (fpGif);
+
+ while (number_of_images--) {
+ /*if (image_name_arr[number_of_images])
+ free(image_name_arr[number_of_images]);*/
+ /*if (pal_name_arr[number_of_images])
+ free(pal_name_arr[number_of_images]);*/
+ }
+
+ return(0);
+}
diff --git a/tools/gifconv/hdfgifwr.c b/tools/gifconv/hdfgifwr.c
new file mode 100644
index 0000000..28d556e
--- /dev/null
+++ b/tools/gifconv/hdfgifwr.c
@@ -0,0 +1,516 @@
+/*
+ * hdfgifwr.c - handles writing of GIF files.
+ *
+ * Contains:
+ * hdfWriteGIF(fp, pic, ptype, w, h, rmap, gmap, bmap, numcols, colorstyle,
+ * comment)
+ *
+ * Note: slightly brain-damaged, in that it'll only write non-interlaced
+ * GIF files (in the interests of speed, or something)
+ *
+ */
+
+
+
+/*****************************************************************
+ * Portions of this code Copyright (C) 1989 by Michael Mauldin.
+ * Permission is granted to use this file in whole or in
+ * part for any purpose, educational, recreational or commercial,
+ * provided that this copyright notice is retained unchanged.
+ * This software is available to all free of charge by anonymous
+ * FTP and in the UUNET archives.
+ *
+ *
+ * Authors: Michael Mauldin (mlm@cs.cmu.edu)
+ * David Rowley (mgardi@watdcsu.waterloo.edu)
+ *
+ * Based on: compress.c - File compression ala IEEE Computer, June 1984.
+ *
+ * Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
+ * Jim McKie (decvax!mcvax!jim)
+ * Steve Davies (decvax!vax135!petsd!peora!srd)
+ * Ken Turkowski (decvax!decwrl!turtlevax!ken)
+ * James A. Woods (decvax!ihnp4!ames!jaw)
+ * Joe Orost (decvax!vax135!petsd!joe)
+ *****************************************************************/
+
+
+#include <stdio.h>
+#include "gif.h"
+#include <stdlib.h>
+#include <string.h>
+
+typedef BYTE byte;
+typedef long int count_int;
+
+/* indicies into conv24MB */
+#define CONV24_8BIT 0
+#define CONV24_24BIT 1
+#define CONV24_SEP1 2
+#define CONV24_LOCK 3
+#define CONV24_SEP2 4
+#define CONV24_FAST 5
+#define CONV24_SLOW 6
+#define CONV24_BEST 7
+#define CONV24_MAX 8
+
+/* values 'picType' can take */
+#define PIC8 CONV24_8BIT
+#define PIC24 CONV24_24BIT
+
+/* MONO returns total intensity of r,g,b components */
+#define MONO(rd,gn,bl) (((rd)*11 + (gn)*16 + (bl)*5) >> 5) /*.33R+ .5G+ .17B*/
+
+static int Width, Height;
+static int curx, cury;
+static long CountDown;
+static int Interlace;
+
+#ifdef __STDC__
+static void putword(int, FILE *);
+static void compress(int, FILE *, byte *, int);
+static void output(int);
+static void cl_block(void);
+static void cl_hash(count_int);
+static void char_init(void);
+static void char_out(int);
+static void flush_char(void);
+#else
+static void putword(), compress(), output(), cl_block(), cl_hash();
+static void char_init(), char_out(), flush_char();
+#endif
+
+static byte pc2nc[256],r1[256],g1[256],b1[256];
+
+void xvbzero(s, len)
+ char *s;
+ int len;
+{
+ for ( ; len>0; len--) *s++ = 0;
+}
+
+/*************************************************************/
+int hdfWriteGIF(fp, pic, ptype, w, h, rmap, gmap, bmap, pc2ncmap, numcols, colorstyle, BitsPerPixel)
+ FILE *fp;
+ byte *pic;
+ int ptype, w,h;
+ byte *rmap, *gmap, *bmap , *pc2ncmap;
+ int numcols, colorstyle;
+ int BitsPerPixel;
+{
+ int RWidth, RHeight;
+ int LeftOfs, TopOfs;
+ int ColorMapSize, InitCodeSize, Background;
+ int i;
+ byte *pic8;
+ pic8 = pic;
+
+ Interlace = 0;
+ Background = 0;
+
+ for (i=0; i<256; i++) {
+ pc2nc[i] = pc2ncmap[i];
+ r1[i] = rmap[i];
+ g1[i] = gmap[i];
+ b1[i] = bmap[i];
+ }
+
+ ColorMapSize = 1 << BitsPerPixel;
+
+ RWidth = Width = w;
+ RHeight = Height = h;
+ LeftOfs = TopOfs = 0;
+
+ CountDown = w * h; /* # of pixels we'll be doing */
+
+ if (BitsPerPixel <= 1) InitCodeSize = 2;
+ else InitCodeSize = BitsPerPixel;
+
+ curx = cury = 0;
+
+ if (!fp) {
+ fprintf(stderr, "WriteGIF: file not open for writing\n" );
+ return (1);
+ }
+
+ compress(InitCodeSize+1, fp, pic8, w*h);
+
+
+ if (ferror(fp)) return -1;
+ return (0);
+}
+
+
+
+
+/******************************/
+static void putword(w, fp)
+int w;
+FILE *fp;
+{
+ /* writes a 16-bit integer in GIF order (LSB first) */
+
+ fputc(w &0xff, fp);
+
+ fputc((w>>8)&0xff,fp);
+}
+
+
+
+
+/***********************************************************************/
+static unsigned long cur_accum = 0;
+static int cur_bits = 0;
+
+#define MAXCODE(n_bits) ( (1 << (n_bits)) - 1)
+#define min(a,b) ((a>b) ? b : a)
+#define XV_BITS 12 /* BITS was already defined on some systems */
+#define MSDOS 1
+#define HSIZE 5003 /* 80% occupancy */
+
+typedef unsigned char char_type;
+static int n_bits; /* number of bits/code */
+static int maxbits = XV_BITS; /* user settable max # bits/code */
+static int maxcode; /* maximum code, given n_bits */
+static int maxmaxcode = 1 << XV_BITS; /* NEVER generate this */
+
+static count_int htab [HSIZE];
+static unsigned short codetab [HSIZE];
+#define HashTabOf(i) htab[i]
+#define CodeTabOf(i) codetab[i]
+
+static int hsize = HSIZE; /* for dynamic table sizing */
+
+/*
+ * To save much memory, we overlay the table used by compress() with those
+ * used by decompress(). The tab_prefix table is the same size and type
+ * as the codetab. The tab_suffix table needs 2**BITS characters. We
+ * get this from the beginning of htab. The output stack uses the rest
+ * of htab, and contains characters. There is plenty of room for any
+ * possible stack (stack used to be 8000 characters).
+ */
+
+#define tab_prefixof(i) CodeTabOf(i)
+#define tab_suffixof(i) ((char_type *)(htab))[i]
+#define de_stack ((char_type *)&tab_suffixof(1<<XV_BITS))
+
+static int free_ent = 0; /* first unused entry */
+
+/*
+ * block compression parameters -- after all codes are used up,
+ * and compression rate changes, start over.
+ */
+static int clear_flg = 0;
+
+static long int in_count = 1; /* length of input */
+static long int out_count = 0; /* # of codes output (for debugging) */
+
+/*
+ * compress stdin to stdout
+ *
+ * Algorithm: use open addressing double hashing (no chaining) on the
+ * prefix code / next character combination. We do a variant of Knuth's
+ * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
+ * secondary probe. Here, the modular division first probe is gives way
+ * to a faster exclusive-or manipulation. Also do block compression with
+ * an adaptive reset, whereby the code table is cleared when the compression
+ * ratio decreases, but after the table fills. The variable-length output
+ * codes are re-sized at this point, and a special CLEAR code is generated
+ * for the decompressor. Late addition: construct the table according to
+ * file size for noticeable speed improvement on small files. Please direct
+ * questions about this implementation to ames!jaw.
+ */
+
+static int g_init_bits;
+static FILE *g_outfile;
+
+static int ClearCode;
+static int EOFCode;
+
+/********************************************************/
+static void compress(init_bits, outfile, data, len)
+int init_bits;
+FILE *outfile;
+byte *data;
+int len;
+{
+ register long fcode;
+ register int i = 0;
+ register int c;
+ register int ent;
+ register int disp;
+ register int hsize_reg;
+ register int hshift;
+
+ /*
+ * Set up the globals: g_init_bits - initial number of bits
+ * g_outfile - pointer to output file
+ */
+ g_init_bits = init_bits;
+ g_outfile = outfile;
+
+ /* initialize 'compress' globals */
+ maxbits = XV_BITS;
+ maxmaxcode = 1<<XV_BITS;
+ xvbzero((char *) htab, sizeof(htab));
+ xvbzero((char *) codetab, sizeof(codetab));
+ hsize = HSIZE;
+ free_ent = 0;
+ clear_flg = 0;
+ in_count = 1;
+ out_count = 0;
+ cur_accum = 0;
+ cur_bits = 0;
+
+
+ /*
+ * Set up the necessary values
+ */
+ out_count = 0;
+ clear_flg = 0;
+ in_count = 1;
+ maxcode = MAXCODE(n_bits = g_init_bits);
+
+ ClearCode = (1 << (init_bits - 1));
+ EOFCode = ClearCode + 1;
+ free_ent = ClearCode + 2;
+
+ char_init();
+ ent = pc2nc[*data++]; len--;
+
+ hshift = 0;
+ for ( fcode = (long) hsize; fcode < 65536L; fcode *= 2L )
+ hshift++;
+ hshift = 8 - hshift; /* set hash code range bound */
+
+ hsize_reg = hsize;
+ cl_hash( (count_int) hsize_reg); /* clear hash table */
+
+ output(ClearCode);
+
+ while (len) {
+ c = pc2nc[*data++]; len--;
+ in_count++;
+
+ fcode = (long) ( ( (long) c << maxbits) + ent);
+ i = (((int) c << hshift) ^ ent); /* xor hashing */
+
+ if ( HashTabOf (i) == fcode ) {
+ ent = CodeTabOf (i);
+ continue;
+ }
+
+ else if ( (long)HashTabOf (i) < 0 ) /* empty slot */
+ goto nomatch;
+
+ disp = hsize_reg - i; /* secondary hash (after G. Knott) */
+ if ( i == 0 )
+ disp = 1;
+
+probe:
+ if ( (i -= disp) < 0 )
+ i += hsize_reg;
+
+ if ( HashTabOf (i) == fcode ) {
+ ent = CodeTabOf (i);
+ continue;
+ }
+
+ if ( (long)HashTabOf (i) >= 0 )
+ goto probe;
+
+nomatch:
+ output(ent);
+ out_count++;
+ ent = c;
+
+ if ( free_ent < maxmaxcode ) {
+ CodeTabOf (i) = free_ent++; /* code -> hashtable */
+ HashTabOf (i) = fcode;
+ }
+ else
+ cl_block();
+ }
+
+ /* Put out the final code */
+ output(ent);
+ out_count++;
+ output(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.
+ */
+
+static
+unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
+ 0x001F, 0x003F, 0x007F, 0x00FF,
+ 0x01FF, 0x03FF, 0x07FF, 0x0FFF,
+ 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
+
+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 );
+
+#ifdef FOO
+ if( ferror( g_outfile ) )
+ FatalError("unable to write GIF file");
+#endif
+ }
+}
+
+
+/********************************/
+static void cl_block () /* table clear for block compress */
+{
+ /* Clear out the hash table */
+
+ cl_hash ( (count_int) hsize );
+ free_ent = ClearCode + 2;
+ clear_flg = 1;
+
+ output(ClearCode);
+}
+
+
+/********************************/
+static void cl_hash(hsize) /* reset code table */
+register count_int hsize;
+{
+ 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'
+ */
+static int a_count;
+
+/*
+ * Set up the 'byte output' routine
+ */
+static void char_init()
+{
+ a_count = 0;
+}
+
+/*
+ * Define the storage for the packet accumulator
+ */
+static char accum[ 256 ];
+
+/*
+ * Add a character to the end of the current packet, and if it is 254
+ * characters, flush the packet to disk.
+ */
+static void char_out(c)
+int c;
+{
+ accum[ a_count++ ] = c;
+ if( a_count >= 254 )
+ flush_char();
+}
+
+/*
+ * Flush the packet to disk, and reset the accumulator
+ */
+static void flush_char()
+{
+ if( a_count > 0 ) {
+ fputc( a_count, g_outfile );
+ fwrite( accum, 1, a_count, g_outfile );
+ a_count = 0;
+ }
+}
diff --git a/tools/gifconv/readhdf.c b/tools/gifconv/readhdf.c
new file mode 100644
index 0000000..a7101c9
--- /dev/null
+++ b/tools/gifconv/readhdf.c
@@ -0,0 +1,177 @@
+#include "gif.h"
+
+/* just a small cleanup routine before we leave */
+void cleanup(BYTE *ptr) {
+ if (ptr)
+ free(ptr);
+}
+
+/* Function : ReadHDF
+** Return: 0 on completion without error, -1 on error
+** Input: CHAR *h5_file - HDF file name
+** CHAR *dset_name - Name of the HDF Image dataset
+** CHAR *pal_name - Name of the HDF palette
+** Output : BYTE** data - the HDF Image to be converted
+** BYTE palette[256][3] - the corresponding palette
+** hsize_t* image_size - the size of each dimension of the image
+**
+** Future Notes:
+** The way readHDF works right now is that it expects the user
+** to know the exact path to the HDF image. Thus it does not
+** parse the HDF file looking for image datasets and corresponding
+** palettes. Also it takes in the default palette for the image
+** specified, if the palette is missing, it makes a default greyscale
+** palette and throws it in.
+**
+*/
+int ReadHDF(BYTE** data ,
+ BYTE palette[256][3] ,
+ hsize_t *image_size ,
+ CHAR *h5_file ,
+ CHAR *dset_name ,
+ CHAR *pal_name)
+{
+ hid_t fHfile; /* H5 file to open */
+ herr_t status; /* status variable */
+ hid_t dspace; /* dataspace identifier for the the dataset */
+ hid_t dset; /* dataset identifier */
+
+ hid_t pal_set; /* dataset for palette */
+ hid_t pal_space;/* dataspace for palette */
+ hsize_t pal_size; /* size of the palette */
+
+ hsize_t datasize; /* size of the image */
+ hsize_t maxdims; /* dummy */
+
+ int pal_exist = 0; /* do we have a palette? */
+
+ /* check stuff */
+ if (!h5_file || !dset_name || !image_size) {
+ fprintf(stderr , "NULL is not an acceptable input for HDFread. Aborting.\n");
+ return -1;
+ }
+
+ /* do we have a palette ? */
+ if (pal_name) {
+ pal_exist = 1;
+ }
+
+ /* try opening the file */
+ /* H5 file open calls */
+ if ((fHfile = H5Fopen(h5_file , H5F_ACC_RDONLY , H5P_DEFAULT)) < 0) {
+ fprintf(stderr , "Unable to open HDF file for input. Aborting.\n");
+ return -1;
+ }
+
+ /* open the dataset for reading */
+ if ((dset = H5Dopen(fHfile , dset_name)) < 0) {
+ fprintf(stderr , "Unable to open dataset\n");
+ return -1;
+ }
+
+ /* get the dataspace */
+ if ((dspace = H5Dget_space(dset)) < 0) {
+ fprintf(stderr , "Unable to get dataspace\n");
+ return -1;
+ }
+
+ /* get the dimension size of the image */
+ if (H5Sget_simple_extent_dims(dspace , image_size , &maxdims) !=2 ) {
+ fprintf(stderr , "Unable to get dimension info\n");
+ return -1;
+ }
+
+ /* size needed to store the image */
+ datasize = image_size[0] * image_size[1];
+
+ /* allocate memory to store the image */
+ if ((*data = (BYTE*) malloc(datasize)) == NULL) {
+ fprintf(stderr , "Out of memory, exiting");
+ return -1;
+ }
+
+ /* get the actual image */
+ if ((status = H5Dread(dset , H5Dget_type(dset) , H5S_ALL , H5S_ALL , H5P_DEFAULT , *data)) < 0) {
+ fprintf(stderr , "Unable to read data \n");
+ cleanup(*data);
+ return -1;
+ }
+
+ if (pal_exist) {
+ hsize_t pal_size[2];
+ hsize_t max_pal_dims[2];
+ hsize_t pal_datasize;
+ CHAR *pal_path;
+
+ BYTE *temp_buf;
+ hsize_t temp_size;
+
+ /* get the palette dataset */
+ if ((pal_set = H5Dopen(fHfile , pal_name)) < 0) {
+ fprintf(stderr , "Unable to open dataset\n");
+ pal_exist = 0;
+ return -1;
+ }
+
+ /* get the dataspace */
+ if ((pal_space = H5Dget_space(pal_set)) < 0) {
+ fprintf(stderr , "Unable to get dataspace\n");
+ pal_exist = 0;
+ return -1;
+ }
+
+ /* get the dimension size of the palette. */
+ if (H5Sget_simple_extent_dims(pal_space , pal_size , &max_pal_dims) !=2 ) {
+ fprintf(stderr , "Unable to get dimension info\n");
+ pal_exist = 0;
+ return -1;
+ }
+
+ /* size needed to store the image */
+ pal_datasize = pal_size[0] * pal_size[1];
+
+ /* copy stuff into a temp buffer and then copy 256*3 elements to palette */
+ temp_size = H5Dget_storage_size(pal_set);
+
+ temp_buf = (BYTE*) malloc (temp_size * sizeof(BYTE));
+
+ /* make sure that the palette is actually 256 X 3 so that we don't create overflows */
+ if (pal_datasize > 256 * 3)
+ {
+ fprintf(stderr , "Palette seems to be more than 256X3 bytes\n");
+ fprintf(stderr , "Truncating palette to 256 colors. This might cause a problem with the final image\n");
+ pal_datasize = 256 * 3;
+ }
+
+ /* get the actual palette */
+ if ((status = H5Dread(pal_set , H5Dget_type(pal_set) , H5S_ALL , H5S_ALL , H5P_DEFAULT , temp_buf)) < 0) {
+ fprintf(stderr , "Unable to read data \n");
+ cleanup(*data);
+ cleanup(temp_buf);
+ return -1;
+ }
+
+ /* copy stuff into the actual palette */
+ memcpy(palette , temp_buf , pal_datasize);
+
+ /* get rid of the temp memory */
+ cleanup(temp_buf);
+ /* end of if (pal_exist) */
+
+ } else {
+ int i;
+ /* if palette does not exist we just go ahead and create a uniform greyscale palette */
+ for (i = 0 ; i < 256 ; i++) {
+ palette[i][0] = 255 - i;
+ palette[i][1] = 255 - i;
+ palette[i][2] = 255 - i;
+ }
+ }
+
+ /* close everything */
+ status = H5Dclose(dset);
+ status = H5Sclose(dspace);
+ status = H5Fclose(fHfile);
+
+ return 0;
+}
diff --git a/tools/gifconv/writehdf.c b/tools/gifconv/writehdf.c
new file mode 100644
index 0000000..7afccdf
--- /dev/null
+++ b/tools/gifconv/writehdf.c
@@ -0,0 +1,410 @@
+#include "gif.h"
+#include <string.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*******************************************************************
+** Function: write_text_attribute
+** Use: Just a small wrapper to write text attributes easily
+********************************************************************/
+int write_text_attribute(hid_t dataset_id , char *attr_name , char *attr_value) {
+
+ /* variables for the attributes */
+ hsize_t attr_dims_size; /* dimensions for the attribute */
+ hid_t attr_dataspace_id; /* dataspaces needed for the various attributes */
+ hid_t attr_attr_id; /* attribute id */
+ herr_t status; /* check return status */
+ hid_t attr_type_id;
+
+
+ /* check strings */
+ if (!attr_name || !attr_value)
+ return -1;
+
+ /* figure out size of the data */
+ attr_dims_size = strlen(attr_value) + 1;
+
+ /* set the type to string */
+ attr_type_id = H5Tcopy(H5T_C_S1);
+ H5Tset_size(attr_type_id , attr_dims_size);
+
+ /* create the dataspace for the attribute */
+ attr_dataspace_id = H5Screate_simple(1 , &attr_dims_size , NULL);
+
+ /* create the attribute */
+ attr_attr_id = H5Acreate(dataset_id , attr_name , attr_type_id , attr_dataspace_id , H5P_DEFAULT);
+
+ /* write out the attribute data */
+ if ((status = H5Awrite(attr_attr_id , attr_type_id , attr_value)) < 0)
+ return -1;
+
+ /* close the attribute */
+ if ((status = H5Aclose(attr_attr_id)) < 0)
+ return -1;
+
+ /* close the dataspace */
+ if ((status = H5Sclose(attr_dataspace_id)) < 0) {
+ fprintf(stderr , "Unable to close attribute dataspace. Aborting \n");
+ return -1;
+ }
+
+ return 0;
+
+}
+
+int
+WriteHDF(GifMemoryStruct, HDFName , GIFFileName)
+GIFTOMEM GifMemoryStruct;
+char *HDFName;
+char *GIFFileName;
+{
+ GIFHEAD gifHead; /* GIF Header structure */
+ GIFIMAGEDESC* gifImageDesc; /* Logical Image Descriptor struct */
+
+ long ImageCount , /* number of images */
+ CommentCount, /* number of comments */
+ ApplicationCount , /* number of application extensions */
+ PlainTextCount; /* number of plain text extensions */
+
+ char ImageName[256], /* Image name for the GR Image */
+ CommentName[256],
+ ApplicationName[256],
+ PlainTextName[256];
+
+ char GroupName[VSNAMELENMAX]; /* so that we can name the subgroups appropriately */
+
+ /* H5 variables */
+ hid_t file_id; /* H5 file id */
+ hid_t image_id; /* H5 id for the whole image */
+ hid_t pal_id; /* H5 id for the palette */
+ herr_t status; /* status variable */
+ hobj_ref_t pal_ref; /* Create a reference for the palette */
+
+ /* temp counter */
+ int i;
+
+
+
+
+
+
+ /* get the GIFMem stuff */
+ gifHead = *(GifMemoryStruct.GifHeader);
+
+ /* get some data from gifHead */
+ ImageCount = (WORD)gifHead.ImageCount;
+ CommentCount = (WORD)gifHead.CommentCount;
+ ApplicationCount = (WORD)gifHead.ApplicationCount;
+ PlainTextCount = (WORD)gifHead.PlainTextCount;
+
+ /* get the main group name from GIFFileName */
+ GroupName[0]= '/';
+ if (strncpy(GroupName , GIFFileName , VSNAMELENMAX-2) == NULL) {
+ fprintf(stderr , "strncpy failed\n");
+ exit(1);
+ }
+ GroupName[VSNAMELENMAX] = '\0';
+
+
+ if ((file_id = H5Fcreate(HDFName , H5F_ACC_TRUNC , H5P_DEFAULT , H5P_DEFAULT)) < 0) {
+ /* error occured opening the HDF File for write */
+ fprintf(stderr , "HDF file could not be opened for writing\n");
+ fprintf(stderr , "NOTE: GIF file must be present in the same directory as the binary on UNIX systems.\n");
+ exit(1);
+ }
+
+ /* create a group within the root group to hold the gif image */
+ /* might want to make a different naming style out here */
+ image_id = H5Gcreate(file_id, GroupName , 0);
+
+ /* first create the global palette if there is one */
+ if (gifHead.PackedField & 0x80) { /* global palette exists */
+ hid_t dataspace_id; /* identifier for dataspace */
+ hsize_t dims[2]; /* specify the dimensions of the palette */
+
+ hsize_t dimsr[1] = {1}; /* needed to store reference */
+ hid_t ref_dataspace_id; /* dataspace id for references */
+ hid_t ref_dataset_id; /* dataset id for references */
+
+ /* size of the palette is tablesize (rows) X 3 (columns) */
+ dims[0] = gifHead.TableSize;
+ dims[1] = 3;
+
+ /* create the dataspace */
+ if ((dataspace_id = H5Screate_simple(2 , dims , NULL)) < 0) {
+ fprintf(stderr , "Could not create dataspace for palette. Aborting...\n");
+ return -1;
+ }
+
+ /* create the palette dataset */
+ if ((pal_id = H5Dcreate(image_id , "Global Palette" , H5T_NATIVE_UINT8 , dataspace_id , H5P_DEFAULT )) < 0) {
+ fprintf(stderr , "Could not create palette dataset. Aborting...\n");
+ return -1;
+ }
+
+ /* write the palette data out */
+ /****** Ask Elena about VOIDP ******/
+ if ((status = H5Dwrite(pal_id , H5T_NATIVE_UINT8 , H5S_ALL , H5S_ALL , H5P_DEFAULT , (void *)gifHead.HDFPalette)) < 0) {
+ fprintf(stderr , "Error writing dataset. Aborting...\n");
+ return -1;
+ }
+
+ /* set palette attributes */
+
+ /* attribute CLASS = PALETTE */
+ if ((write_text_attribute(pal_id , "CLASS" , "PALETTE")) < 0) {
+ fprintf(stderr , "Unable to write palette attributes. Aborting\n");
+ return -1;
+ }
+
+ /* attribute PAL_COLORMODEL = RGB */
+ if ((write_text_attribute(pal_id , "PAL_COLORMODEL" , "RGB")) < 0) {
+ fprintf(stderr , "Unable to write palette attributes. Aborting\n");
+ return -1;
+ }
+
+ /* attribute PAL_TYPE = STANDARD8 */
+ if ((write_text_attribute(pal_id , "PAL_TYPE" , "STANDARD8")) < 0) {
+ fprintf(stderr , "Unable to write palette attributes. Aborting\n");
+ return -1;
+ }
+
+ /* attribute PAL_VERSION = 1.0 */
+ if ((write_text_attribute(pal_id , "PAL_VERSION" , "1.0")) < 0) {
+ fprintf(stderr , "Unable to write palette attributes. Aborting\n");
+ return -1;
+ }
+
+ /* create dataspace for the dataset to store references */
+ ref_dataspace_id = H5Screate_simple(1 , dimsr , NULL);
+
+ /* create a dataset to store the references */
+ ref_dataset_id = H5Dcreate(image_id , "Palette Reference" , H5T_STD_REF_OBJ , ref_dataspace_id , H5P_DEFAULT);
+
+ /* create a reference to the palette */
+ if ((status = H5Rcreate(&pal_ref , image_id , "Global Palette" , H5R_OBJECT , -1)) < 0) {
+ fprintf(stderr , "Unable to create palette reference\n");
+ return -1;
+ }
+
+ /* write the reference out */
+ if ((status = H5Dwrite(ref_dataset_id , H5T_STD_REF_OBJ, H5S_ALL, H5S_ALL , H5P_DEFAULT, &pal_ref)) < 0) {
+ fprintf(stderr , "Unable to write Palette Reference");
+ return -1;
+ }
+
+ /* close dataset */
+ if ((status = H5Dclose(ref_dataset_id)) < 0) {
+ fprintf(stderr , "Unable to close palette dataset.\n");
+ return -1;
+ }
+
+ /* close dataspace */
+ if ((status = H5Sclose(ref_dataspace_id)) < 0) {
+ fprintf(stderr , "Unable to close palette dataspace.\n");
+ return -1;
+ }
+
+ /* close everything */
+ if ((status = H5Dclose(pal_id)) < 0) {
+ fprintf(stderr , "Unable to close palette dataset. Aborting.\n");
+ return -1;
+ }
+
+ if ((status = H5Sclose(dataspace_id)) < 0) {
+ fprintf(stderr , "Unable to close palette dataspace. Aborting.\n");
+ return -1;
+ }
+
+ }
+
+ for(i=0 ; i < ImageCount ; i++) {
+ /* variables for the images */
+ hsize_t dims[2]; /* dimensions for the dataset */
+ hid_t dataspace_id; /* identifier for the dataspace */
+ hid_t sub_image_id; /* wierd name to distinguish from the group_id */
+
+ /* variables for the attributes */
+ hsize_t attr_dims[2]; /* dimensions for the attribute */
+ hid_t attr_dataspace_id; /* dataspaces needed for the various attributes */
+ hid_t attr_attr_id; /* attribute id */
+ BYTE minmax[2]; /* lower and upper minmax values */
+
+ /* initialise minmax */
+ minmax[0] = 0 ; minmax[1] = 255;
+
+ /* get the gifImageDesc */
+ gifImageDesc = GifMemoryStruct.GifImageDesc[i];
+
+ /* set the dimensions */
+ dims[0] = gifImageDesc->ImageHeight;
+ dims[1] = gifImageDesc->ImageWidth;
+
+ /* create the empty dataspace */
+ if ((dataspace_id = H5Screate_simple(2 , dims , NULL)) < 0) {
+ fprintf(stderr , "Could not create image dataspace. Aborting\n");
+ return -1;
+ }
+
+ /* create the image name */
+ sprintf(ImageName , "Image%d" , i);
+
+ /* create the image data set */
+ if ((sub_image_id = H5Dcreate(image_id , ImageName , H5T_NATIVE_UINT8 , dataspace_id , H5P_DEFAULT)) < 0) {
+ fprintf(stderr , "Could not create dataset for image. Aborting... \n");
+ return -1;
+ }
+
+ /* write out the image */
+ /****** Ask Elena about VOIDP ******/
+ if ((status = H5Dwrite(sub_image_id , H5T_NATIVE_UINT8 , H5S_ALL , H5S_ALL , H5P_DEFAULT , (void *)(gifImageDesc->Image))) < 0) {
+ fprintf(stderr , "Error writing image. Aborting... \n");
+ return -1;
+ }
+
+ /* set the attributes */
+ /* This info is available at http://hdf.ncsa.uiuc.edu/HDF5/doc/ImageSpec.html */
+ /* The following attributes must be set for each image:
+ ** ---------------------------------------
+ ** Attribute Name Value
+ ** CLASS IMAGE
+ ** IMAGE_VERSION 1.0
+ ** IMAGE_SUBCLASS IMAGE_BITMAP
+ ** PALETTE ref. to palette datasets
+ ** IMAGE_MINMAXRANGE [0,255]
+ ** ---------------------------------------
+ */
+
+ /****************************************
+ ** Attribute: CLASS
+ ** Value : IMAGE
+ *****************************************/
+
+ if (write_text_attribute(sub_image_id , "CLASS" , "IMAGE") < 0) {
+ fprintf(stderr , "Unable to write CLASS = IMAGE attribute\n");
+ return -1;
+ }
+
+ /****************************************
+ ** Attribute: IMAGE_VERSION
+ ** Value : 1.0
+ *****************************************/
+
+ if (write_text_attribute(sub_image_id , "IMAGE_VERSION" , "1.0") < 0) {
+ fprintf(stderr , "Unable to write IMAGE_VERSION attribute\n");
+ return -1;
+ }
+
+ /****************************************
+ ** Attribute: IMAGE_SUBCLASS
+ ** Value : IMAGE_BITMAP
+ *****************************************/
+
+ if (write_text_attribute(sub_image_id , "IMAGE_SUBCLASS" , "IMAGE_BITMAP") < 0) {
+ fprintf(stderr , "Unable to write IMAGE_SUBCLASS attribute\n");
+ return -1;
+ }
+
+ /****************************************
+ ** Attribute: IMAGE_COLORMODEL
+ ** Value : RGB
+ *****************************************/
+
+ if (write_text_attribute(sub_image_id , "IMAGE_COLORMODEL" , "RGB") < 0) {
+ fprintf(stderr , "Unable to write IMAGE_SUBCLASS attribute\n");
+ return -1;
+ }
+
+ /****************************************
+ ** Attribute: PALETTE
+ ** Value : Reference to Palette
+ *****************************************/
+
+ /**** MAKE SURE PALETTE EXISTS!!! ****/
+ if (gifHead.PackedField & 0x80) { /* global palette exists */
+
+ attr_dims[0] = 1;
+
+ /* create the dataspace for the attribute */
+ attr_dataspace_id = H5Screate_simple(1 , attr_dims , NULL);
+
+ /* create the attribute */
+ attr_attr_id = H5Acreate(sub_image_id , "PALETTE" , H5T_STD_REF_OBJ , attr_dataspace_id , H5P_DEFAULT);
+
+ if ((status = H5Awrite(attr_attr_id , H5T_STD_REF_OBJ , &pal_ref)) < 0) {
+ fprintf(stderr , "Unable to write attribute. Aborting \n");
+ return -1;
+ }
+
+ /* close the attribute */
+ if ((status = H5Aclose(attr_attr_id)) < 0) {
+ fprintf(stderr , "Unable to close CLASS IMAGE attribute. Aborting.\n");
+ return -1;
+ }
+
+ /* close the dataspace */
+ if ((status = H5Sclose(attr_dataspace_id)) < 0) {
+ fprintf(stderr , "Unable to close attribute dataspace. Aborting \n");
+ return -1;
+ }
+
+ }
+
+ /****************************************
+ ** Attribute: IMAGE_MINMAXRANGE
+ ** Value : minmax
+ *****************************************/
+
+ attr_dims[0] = 2;
+
+ /* create the dataspace for the attribute */
+ attr_dataspace_id = H5Screate_simple(1 , attr_dims , NULL);
+
+ /* create the attribute */
+ attr_attr_id = H5Acreate(sub_image_id , "IMAGE_MINMAXRANGE" , H5T_NATIVE_UINT8 , attr_dataspace_id , H5P_DEFAULT);
+
+ if ((status = H5Awrite(attr_attr_id , H5T_NATIVE_UINT8 , minmax)) < 0) {
+ fprintf(stderr , "Unable to write attribute. Aborting \n");
+ return -1;
+ }
+
+ /* close the attribute */
+ if ((status = H5Aclose(attr_attr_id)) < 0) {
+ fprintf(stderr , "Unable to close CLASS IMAGE attribute. Aborting.\n");
+ return -1;
+ }
+
+ /* close the dataspace */
+ if ((status = H5Sclose(attr_dataspace_id)) < 0) {
+ fprintf(stderr , "Unable to close attribute dataspace. Aborting \n");
+ return -1;
+ }
+
+
+ /* close everything */
+ if ((status = H5Dclose(sub_image_id)) < 0) {
+ fprintf(stderr , "Unable to close image dataset. Aborting \n");
+ return -1;
+ }
+
+ if ((status = H5Sclose(dataspace_id)) < 0) {
+ fprintf(stderr , "Unable to close image dataspace. Aborting \n");
+ return -1;
+ }
+
+ }
+
+ /* close the main image group */
+ if ((status = H5Gclose(image_id)) < 0) {
+ fprintf(stderr , "Could not close the image group. Aborting...\n");
+ return -1;
+ }
+
+ /* close the H5 file */
+ if ((status = H5Fclose(file_id)) < 0) {
+ fprintf(stderr , "Could not close HDF5 file. Aborting...\n");
+ return -1;
+ }
+
+ return(0);
+}