jedioutcast/utils/roq2/libim/imhdfread.c

2633 lines
80 KiB
C
Raw Normal View History

2013-04-04 18:02:27 +00:00
/**
** $Header: /roq/libim/imhdfread.c 1 11/02/99 4:38p Zaphod $
** Copyright (c) 1989-1995 San Diego Supercomputer Center (SDSC)
** a division of General Atomics, San Diego, California, USA
**
** Users and possessors of this source code are hereby granted a
** nonexclusive, royalty-free copyright and design patent license to
** use this code in individual software. License is not granted for
** commercial resale, in whole or in part, without prior written
** permission from SDSC. This source is provided "AS IS" without express
** or implied warranty of any kind.
**
** For further information contact:
** E-Mail: info@sds.sdsc.edu
**
** Surface Mail: Information Center
** San Diego Supercomputer Center
** P.O. Box 85608
** San Diego, CA 92138-5608
** (619) 534-5000
**/
#define HEADER " $Header: /roq/libim/imhdfread.c 1 11/02/99 4:38p Zaphod $"
/**
** FILE
** imhdfread.c - HDF image file read
**
** PROJECT
** libim - SDSC image manipulation library
**
** DESCRIPTION
** imhdf.c contains routines to read HDF image files for
** the image manipulation library. Raster data read in is stored
** in a VFB and optional CLT in a tag table.
**
** PUBLIC CONTENTS
** d =defined constant
** f =function
** m =defined macro
** t =typedef/struct/union
** v =variable
** ? =other
**
** none
**
** PRIVATE CONTENTS
** ImHdfRead f read an HDF file
**
** imHdfDDList v list of DDs
** imHdfDDListEnd v pointer to end of DD list
** imHdfDDCount v # of entries in DD list
**
** imHdfDDEmpty f empty the DD list
** imHdfDDAppend f append to the DD list
** imHdfDDFind f search the DD list
**
** imHdfCltList v list of CLT's being written out
** imHdfCltListEnd v end of the CLT list
**
** imHdfCltEmpty f empty the Clt list
** imHdfCltAppend f append to the Clt list
** imHdfCltFind f find entry based on its CLT pointer
** imHdfCltFindRef f find entry based on its LUT reference number
**
** imHdfByteOrder v data byte order
** imHdfFloatFormat v data float format
** imHdfRef v current reference number
**
** imHdfDimRead f read dimensions
** imHdfCltRead f read in a CLT
** imHdfVfbRead f read in a VFB
**
** imHdfVfbRead8 f read 8-bit uncomp. VFB
** imHdfVfbReadRLE8 f read 8-bit RLE comp. VFB
** imHdfVfbRead32 f read 32-bit uncomp. VFB
** imHdfVfbReadRGB f read 24-bit uncomp. uninterleaved VFB
** imHdfVfbReadRGBLine f read 24-bit uncomp. line interleaved VFB
** imHdfVfbReadRGBPlane f read 24-bit uncomp. plane interleaved VFB
** imHdfVfbReadRLERGB f read 24-bit RLE comp. uninterleaved VFB
** imHdfVfbReadRLERGBLine f read 24-bit RLE comp. line interleaved VFB
** imHdfVfbReadRLERGBPlane f read 24-bit RLE comp. plane interleaved VFB
**
** HISTORY
** $Log: /roq/libim/imhdfread.c $
*
* 1 11/02/99 4:38p Zaphod
** Revision 1.20 1995/06/30 22:00:40 bduggan
** changed comparison, since we got stuck in a
** loop with c++ on decalpha's
**
** Revision 1.19 1995/06/29 00:28:04 bduggan
** updated copyright year
**
** Revision 1.18 1995/06/15 20:23:28 bduggan
** Added an include, a prototype, and a return.
** removed an unused variable or two.
**
** Revision 1.17 1995/04/03 21:25:23 bduggan
** took out #ifdef NEWMAGIC
**
** Revision 1.16 1995/01/10 23:26:36 bduggan
** Put in IMMULTI/IMPIPE instead of TRUE/FALSE,
** Made read/write routines static
**
** Revision 1.15 94/10/03 11:30:09 nadeau
** Updated to ANSI C and C++ compatibility.
** Removed all use of register keyword.
** Minimized use of custom SDSC types (e.g., uchar vs. unsigned char)
** Changed all float arguments to double.
** Added forward declarations.
** Added misc. casts to passify SGI and DEC compilers.
** Changed all macros and defined constants to have names
** starting with IM.
** Rearranged magic number structures for format handlers.
** Made format handler routines static (i.e., local to file).
** Updated comments, adding format descriptions and references.
** Updated indenting on some code.
** Updated copyright message.
**
** Revision 1.14 92/12/03 01:48:26 nadeau
** Corrected info messages.
**
** Revision 1.13 92/12/01 17:28:48 nadeau
** Updated write map and corrected info messages.
**
** Revision 1.12 92/11/23 18:42:26 nadeau
** Removed use of IMINFOMSG.
**
** Revision 1.11 92/11/04 11:49:36 groening
** put ImFIleFormat info and magic number info
** from imfmt.c into this file.
**
** Revision 1.10 92/10/19 14:14:29 groening
** added ImInfo statements
**
** Revision 1.9 92/08/31 17:24:52 vle
** Updated copyright notice.
**
** Revision 1.8 92/04/09 09:34:23 groening
** To make the compiler happy added extern statements.
**
** Revision 1.7 91/10/03 09:04:17 nadeau
** Changed 'interlace' to 'interleave'. Moved write
** support to imhdfwrite.c so that the file was smaller
** and would compile easier on small systems. Moved
** opcode and flag #defines to imhdfinternal.h. Various
** cosmetic changes.
**
** Revision 1.6 91/02/12 10:51:18 nadeau
** Removed the tag table checking, temp file creation, and
** VFB conversion now handled by ImFileRead and ImFileWrite.
**
** Revision 1.5 91/01/30 18:06:29 nadeau
** Changed a bit of obscure C trickery to something more
** acceptable to the Alliant FX2800 C compiler.
**
** Revision 1.4 91/01/09 13:38:32 nadeau
** Fixed malloc sizes for RLE buffers. They didn't handle the worst
** case expansion factor on the HDF RLE scheme.
**
** Revision 1.3 90/12/12 20:09:21 rama
** Added function declarations for imHdfVfbWrite functions
** since they return a long value rather than an int.
**
** Revision 1.2 90/07/25 16:23:57 nadeau
** Updated comments.
**
** Revision 1.1 90/07/23 13:47:31 nadeau
** Initial revision
**
**/
//#include <unistd.h>
#include "iminternal.h"
#include "imhdfinternal.h"
/*
** FORMAT
** HDF - Hierarchical Data Format
**
** AKA
** df, ncsa
**
** FORMAT REFERENCES
** NCSA HDF Specifications, NCSA
**
** CODE CREDITS
** Custom development, Dave Nadeau, San Diego Supercomputer Center, 1990.
**
** DESCRIPTION
** An HDF (Hierarchical Data Format) file is a "tagged" data format.
** This means that each piece of information in the file is labeled
** in a standard way. These labels are called "Tags".
**
** An HDF file starts with a magic number and a "DD Block". A DD block
** is a block of space filled with DD's. A DD is a "Data Descriptor"
** and is just a group of tags (and related information). A DD block
** starts with a DDH (DD Header) that tells how many DD's there are in
** the block, and a file byte offset to the next DD block in the file.
** If there are no more DD blocks, this offset is a 0.
**
** A DD contains the tag (a 16-bit unsigned integer), a reference
** number (just a 16-bit unsigned occurrence number for that type of
** tag), a file byte offset to the tag's data, and the number of bytes
** of data at that location.
**
** There are lots of different tags. Tags are informally grouped by
** functionalilty into "sets". HDF currently defines the "utility set"
** of miscellaneous tags, the "raster-8 set" of 8-bit raster image
** tags (now out of date, but still supported), the "raster image set"
** for generic raster images, the "composite set" for describing the
** compositing of images, the "vector set" for Tektronix command streams,
** and the "scientific data set" for scientific data (huge arrays of
** floating point numbers, usually).
**
** This code supports some of the utility tags and all of the raster
** image set tags. The raster-8 set tags are considered redundant and
** are ignored in preference to the generic raster image set tags.
** Vector, composite, and scientific data set tags are ignored.
**
** The raster image set defines a special tag, called the "raster image
** group" that just lists other tags (and their reference numbers) that
** together describe an image. A typical raster image group would list
** a tag describing the image's dimensions (the ID tag), the raster
** image (the RI tag), and possibly a CLT dimension tag (the LD tag)
** and the CLT (the LUT tag).
**
** FORMAT HISTORY
** HDF was developed by NCSA (National Center for Supercomputing
** Applications), one of four national supercomputer centers funded
** by the National Science Foundation. SDSC (San Diego Supercomputer
** Center) is another of the four centers.
**
** NCSA supplies a C and FORTRAN callable routine library for read and
** writing HDF files.
**
** We do not use the NCSA HDF library for a variety of reasons:
**
** 1. NCSA's HDF library is not structured to be easily portable.
** A great many of the byte order and floating point format
** oddities in the world are exposed to the HDF library user.
**
** We have opted to use the portable binary I/O library
** developed at SDSC to portably cover up this stuff as it
** is being read in.
**
** 2. NCSA's HDF library does not handle pipes. It does the
** opening itself and thus requires a file name. The image
** library has been structured more generically. Input might
** not be a file. In any case, the file's name is not always
** available at this level.
**
** 3. NCSA's HDF library only supports one open HDF file at a
** time (as of version 2.37). The application may be using
** the HDF library to manage a scientific data set file when
** it calls the image library. If we usurp the HDF library
** for reading in the image, we have messed up the application.
**
** 4. If we use the NCSA HDF library, then all applications that
** link with the image library must also linked with an HDF
** library, whether they make HDF calls themselves or not.
** This is awkward. Inclusion of the HDF code within the
** image library is equally awkward and slightly immoral.
**
** Additionally, because the rest of the image library is
** more portable than NCSA's code, there will be cases
** where the image library can function on a new machine,
** but NCSA hasn't ported the HDF library to it yet. We
** will be stuck waiting on NCSA.
**
** So, we read in the HDF files directly, without use of NCSA's library.
** We use the portable binary I/O library and none of NCSA's source,
** and none of their include files.
**
** FORMAT PROBLEMS
** HDF excels as a flexible file format.... at the cost of increased
** complexity. That complexity makes it difficult to make a generic
** access library that covers up byte order and floating point formats.
**
** HDF tags come in three flavors:
**
** 1. Self-contained tags. These tags give the names of things,
** attributes of a type (int, float, etc), or attributes of
** something else (image aspect ratio).
**
** 2. Tags that reference other tags. These tags include
** within their data the tag number and reference number of
** one or more other tags. The raster image group is just
** a list of such tag/ref pairs. The image dimension tag (ID)
** indicates a tag/ref describing a pixel channel (red, green,
** whatever), and another tag/ref giving the compression
** scheme used.
**
** 3. Tags that require other tags in order to be read in.
** A raster image requires info in an image dimension tag
** in order to be read in. Similarly with CLT's.
**
** Because of this high degree of interconnectivity, a generic package
** design is tough. There is no obvious place at which to begin to
** modularize... except at the "read it all in and give me a list of
** images" level represented by this source.
**
** NCSA's HDF library modularizes by having calls to read in a tag and
** its byte stream of data. It is then up to the caller to figure out
** byte order and floating point format oddities.
**
** The upshot of all this is that we are using a monolithic coding style
** to read in the HDF file. Modularization is purely for the convenience
** of this code and does not constitute any kind of generic HDF file
** read/write package. It's not clear a good design for such a package
** is even possible.
**
** Nevertheless, SDSC does support and applaud HDF. It is an excellent,
** generic, and portable file format that completely describes its own
** contents. Good work NCSA!
**
** FORMAT VARIATIONS SUPPORTED
** The following image forms are read and written:
**
** Chan. # of Inter- Comp-
** Size Chan. lace ress. Meaning
** ------- ------- ------- ------- ---------------------------------------
** 1 byte 1 none none 8-bit index
** RLE 8-bit index, compressed
**
** 2 byte 1 none none 16-bit index
**
** 3 byte 1 none none 24-bit index
**
** 4 byte 1 none none 32-bit index
**
** 1 byte 3 none none 24-bit RGB
** RLE 24-bit RGB, compressed
** line none 24-bit RGB, scanline interleave
** RLE 24-bit RGB, scanline interleave, comp.
** plane none 24-bit RGB, plane interleave
** RLE 24-bit RGB, plane interleave, compressed
**
** RLE compression is not supported on 2, 3, and 4 byte indexes because
** of the poor choice of RLE definition used by the HDF spec. RLE
** is defined to be byte-wise. On multiple-byte-per-channel data, this
** would try to find runs between bytes, rather than between full channel
** integers. A run would only occur when consequitive bytes of the same
** channel's integer happened to have the same bit pattern. Very rare and
** very stupid. It also prevents the hiding of byte-order nonsense
** below the level of format knowledge (such as in the binary I/O package
** used by this code). So, RLE is not supported for multi-byte-per-channel
** data.
**
** NCSA's IMCOMP compression scheme is not supported.
**
** The following CLT forms are read and written:
**
** Chan. # of Inter- Comp-
** Size Chan. lace ress. Meaning
** ------- ------- ------- ------- ---------------------------------------
** 1 byte 3 none none 8-bit per primary
** line 8-bit per primary, line interleaved
**
** Plane interleave has no meaning on CLT's.
**
** RLE and IMCOMP compressions are not supported on CLT's.
**
** Only 1-byte-per-primary and 3-primary CLT's are handled, ie. RGB CLT's.
** The Image library doesn't currently support CLT's with larger
** primaries or more than 3 primaries.
**
** CLT's may be of any length, including longer than is indexable by
** a pixel in the CLT.
**
** The following tags are read and written:
**
** Tag Set Meaning
** ------- --------------- ------------------------------------------------
** NT Utility Number type
** MT Utility Machine type
** RLE Utility RLE compression
**
** ID8 Raster-8 8-bit image dimensions
** IP8 Raster-8 8-bit CLT
** RI8 Raster-8 8-bit image
** CI8 Raster-8 8-bit compressed image
**
** RIG Raster Raster image group
** ID Raster Image dimensions
** LD Raster CLT dimensions
** RI Raster Raster image
** CI Raster Compressed image
** LUT Raster CLT
** CFM Raster Color format
**
** The CCN (Color correction) and AR (aspect ratio) tags of the general
** raster set are not supported.
**
** Matte channels are not yet supported.
**
** Composition, vector, and scientific data set tags are not supported.
**/
#ifdef __STDC__
static int imHdfDimRead( int ioType, int fd, FILE *fp, imHdfDim **pDim );
static int imHdfCltRead( int ioType, int fd, FILE *fp, imHdfRIG *pRIG, ImClt **pClt );
static int imHdfVfbRead(int ioType, int fd, FILE *fp, imHdfRIG *pRIG, ImVfb **pVfb );
static int imHdfVfbRead8( int ioType, int fd, FILE *fp, imHdfRIG *pRIG, ImVfb **pVfb);
static int imHdfVfbReadRLE8( int ioType, int fd, FILE *fp, imHdfRIG *pRIG, ImVfb **pVfb);
static int imHdfVfbRead32( int ioType, int fd, FILE *fp, imHdfRIG *pRIG, ImVfb **pVfb);
static int imHdfVfbReadRGB( int ioType, int fd, FILE *fp, imHdfRIG *pRIG, ImVfb **pVfb);
static int imHdfVfbReadRGBLine( int ioType, int fd, FILE *fp, imHdfRIG *pRIG, ImVfb **pVfb);
static int imHdfVfbReadRGBPlane( int ioType, int fd, FILE *fp, imHdfRIG *pRIG, ImVfb **pVfb);
static int imHdfVfbReadRLERGB( int ioType, int fd, FILE *fp, imHdfRIG *pRIG, ImVfb **pVfb);
static int imHdfVfbReadRLERGBLine( int ioType, int fd, FILE *fp, imHdfRIG *pRIG, ImVfb **pVfb);
static int imHdfVfbReadRLERGBPlane( int ioType, int fd, FILE *fp, imHdfRIG *pRIG, ImVfb **pVfb);
static int ImHdfRead( int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable );
extern int ImHdfWrite( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp, TagTable *flagsTable,
TagTable *tagTable );
#else
static int imHdfDimRead();
static int imHdfCltRead();
static int imHdfVfbRead();
static int imHdfVfbRead8();
static int imHdfVfbReadRLE8();
static int imHdfVfbRead32( );
static int imHdfVfbReadRGB();
static int imHdfVfbReadRGBLine();
static int imHdfVfbReadRGBPlane();
static int imHdfVfbReadRLERGB() ;
static int imHdfVfbReadRLERGBLine();
static int ImHdfRead( );
extern int ImHdfWrite( );
#endif
/*
* HDF - Hierarchical Data Format
* For information on these structures, how to use them, etc. please
* see imfmt.c.
*/
static char *imHdfNames[ ] = { "hdf", "df", "ncsa", NULL };
static unsigned char imHdfMagicNumber[ ] = { 0x0E, 0x03, 0x13, 0x01 };
static ImFileMagic imFileHdfMagic []=
{
{ 0, 4, imHdfMagicNumber},
{ 0, 0, NULL },
NULL
};
static ImFileFormatReadMap imHdfReadMap[ ] =
{
/* in out */
/* type,ch,dep, attr. VFB type attr. */
{ IN,1,8, 0, IMVFBINDEX8, 0 },
{ IN,1,8, C, IMVFBINDEX8, C },
{ IN,1,16, 0, IMVFBINDEX16, 0 },
{ IN,1,16, C, IMVFBINDEX16, C },
{ IN,1,24, 0, IMVFBINDEX16, 0 },
{ IN,1,24, C, IMVFBINDEX16, C },
{ IN,1,32, 0, IMVFBINDEX16, 0 },
{ IN,1,32, C, IMVFBINDEX16, C },
{ RGB,3,8, 0, IMVFBRGB, 0 },
{ RGB,3,8, LI, IMVFBRGB, 0 },
{ RGB,3,8, PI, IMVFBRGB, 0 },
{ IN,1,8, RLE, IMVFBINDEX8, 0 },
{ IN,1,8, RLE | C,IMVFBINDEX8, C },
{ RGB,3,8, RLE, IMVFBRGB, 0 },
{ RGB,3,8, RLE |LI,IMVFBRGB, 0 },
{ RGB,3,8, RLE |PI,IMVFBRGB, 0 },
{ -1, 0, -1, 0 },
};
static ImFileFormatWriteMap imHdfWriteMap[ ] =
{
/*
* For HDF, all image types vector thru to the same ImHdfWrite()
* routine. This is necessary because a tagTable may be passed in
* that contains multiple VFB's, each with different depth, CLT
* and alpha attributes. The write map primarily serves as a
* filter to make sure all such incomming VFB's are in one of the
* supported formats.
*/
/* in out */
/* VFB type, attr., type,ch,dep, attr., func */
{ IMVFBINDEX8, C, IN,1,8, C, ImHdfWrite },
{ IMVFBINDEX8, 0, IN,1,8, 0, ImHdfWrite },
{ IMVFBINDEX8, C, IN,1,8, RLE|C, ImHdfWrite },
{ IMVFBINDEX8, 0, IN,1,8, RLE, ImHdfWrite },
/* No RLE index 16 because HDF's RLE definition is braindamaged */
{ IMVFBINDEX16, C, IN,1,16, C, ImHdfWrite },
{ IMVFBINDEX16, 0, IN,1,16, 0, ImHdfWrite },
#ifdef hdf_24_compressed
/*
* NCSA's HDF tools don't fully support 24-bit images:
* NCSA Image 2.0 tries to read in 24-bit images, but bombs.
* NCSA Image 3.0 rejects 24-bit images with a cryptic message.
* SypGlass View 1.0 rejects 24-bit images with a message.
*
* hdf24hdf8 accepts uncompressed 24-bit images, rejects
* compressed interleaved 24-bit images, and incorrectly grabs
* only the 1st third of the data for compressed uninterleaved
* 24-bit images.
*
* Until NCSA's library fully supports compressed 24-bit images,
* our support will be disabled. Note that we will continue to
* read compressed 24-bit images.
*/
{ IMVFBRGB, 0, RGB,3,8, RLE|PI, ImHdfWrite },
{ IMVFBRGB, 0, RGB,3,8, RLE|LI, ImHdfWrite },
{ IMVFBRGB, 0, RGB,3,8, RLE, ImHdfWrite },
#endif
{ IMVFBRGB, 0, RGB,3,8, 0, ImHdfWrite },
{ IMVFBRGB, 0, RGB,3,8, LI, ImHdfWrite },
{ IMVFBRGB, 0, RGB,3,8, PI, ImHdfWrite },
{ -1, 0, -1, 0, NULL },
};
ImFileFormat ImFileHdfFormat =
{
imHdfNames, "Hierarchical Data File",
"NCSA",
"8-bit color index images, un- and RLE-compressed. 16-, 24-, and\n\
2-bit color index images, un-compressed. 24-bit RGB, un- and RLE-\n\
ompressed, un-, scanline- and plane-interleaved. Raster image\n\
roups as well as older Raster-8 files.",
"8-bit color index images, un- and RLE-compressed. 16-bit color\n\
ndex images, un-compressed. 24-bit RGB, uncompressed, un-,\n\
canline- and plane-interleaved. Raster image group and older\n\
aster-8 tags included.",
imFileHdfMagic,
IMMULTI, IMNOPIPE, /* Read */
IMMULTI, IMNOPIPE, /* Write */
ImHdfRead, imHdfReadMap, imHdfWriteMap
};
/*
* DD List Management
*/
/*
* GLOBALS
* imHdfDDList - list of DDs
* imHdfDDListEnd - pointer to end of DD list
* imHdfDDCount - # of entries in DD list
*/
imHdfDD *imHdfDDList = NULL; /* List of DD's */
imHdfDD *imHdfDDListEnd = NULL;/* Pointer to end of DD list */
int imHdfDDCount = 0; /* # of DD's in list */
/*
* FUNCTION
* imHdfDDEmpty - empty the DD list
* imHdfDDAppend - append to the DD list
* imHdfDDFind - search the DD list
*
* DESCRIPTION
* A DD list of tag/ref values is created and maintained.
*/
void /* Returns nothing */
imHdfDDEmpty( )
{
imHdfDD *pDD; /* DD list pointer */
imHdfDD *pDD2; /* 2nd DD list pointer */
for ( pDD = imHdfDDList; pDD; )
{
pDD2 = pDD;
pDD = pDD->dd_next;
free( (char *)pDD2 );
}
imHdfDDList = imHdfDDListEnd = NULL;
imHdfDDCount = 0;
}
imHdfDD * /* Returns new DD pointer */
#ifdef __STDC__
imHdfDDAppend( unsigned int tag, unsigned int ref, long dataOffset, long dataLength )
#else
imHdfDDAppend( tag, ref, dataOffset, dataLength )
unsigned int tag; /* Tag number */
unsigned int ref; /* Reference number */
long dataOffset; /* File offset */
long dataLength; /* Number of bytes */
#endif
{
imHdfDD *pDD; /* New DD */
if ( (pDD = (imHdfDD *)malloc( sizeof( imHdfDD ) )) == NULL )
{
ImErrNo = IMEMALLOC;
ImErrorFatal( ImQError(), NULL, ImErrNo );
}
pDD->dd_tag = tag;
pDD->dd_ref = ref;
pDD->dd_dataOffset = dataOffset;
pDD->dd_dataLength = dataLength;
if ( imHdfDDList == NULL )
imHdfDDList = pDD;
else
imHdfDDListEnd->dd_next = pDD;
pDD->dd_next = NULL;
imHdfDDListEnd = pDD;
imHdfDDCount++;
return ( pDD );
}
imHdfDD * /* Returns found DD pointer */
#ifdef __STDC__
imHdfDDFind( unsigned int tag, unsigned int ref )
#else
imHdfDDFind( tag, ref )
unsigned int tag; /* Tag number */
unsigned int ref; /* Reference number */
#endif
{
imHdfDD *pDD; /* DD list pointer */
for ( pDD = imHdfDDList; pDD; pDD = pDD->dd_next )
if ( pDD->dd_tag == tag && pDD->dd_ref == ref )
break;
return ( pDD ); /* Could be NULL */
}
/*
* CLT List Management
*/
/*
* GLOBALS
* imHdfCltList - list of CLT's being written out
* imHdfCltListEnd - end of the CLT list
*/
imHdfClt *imHdfCltList = NULL;
imHdfClt *imHdfCltListEnd = NULL;
/*
* FUNCTION
* imHdfCltEmpty - empty the Clt list
* imHdfCltAppend - append to the Clt list
* imHdfCltFind - find entry based on its CLT pointer
* imHdfCltFindRef - find entry based on its LUT reference number
*
* DESCRIPTION
* A Clt list of tag/ref values is created and maintained.
*/
void /* Returns nothing */
imHdfCltEmpty( )
{
imHdfClt *pClt; /* Clt list pointer */
imHdfClt *pClt2; /* 2nd Clt list pointer */
for ( pClt = imHdfCltList; pClt; )
{
pClt2 = pClt;
pClt = pClt->clt_next;
free( (char *)pClt2 );
}
imHdfCltList = imHdfCltListEnd = NULL;
}
imHdfClt * /* Returns new Clt pointer */
#ifdef __STDC__
imHdfCltAppend( ImClt* clt, unsigned int refLUT, unsigned int refLD )
#else
imHdfCltAppend( clt, refLUT, refLD )
ImClt *clt; /* CLT to add to list */
unsigned int refLUT; /* It's LUT tag reference # */
unsigned int refLD; /* It's LD tag reference # */
#endif
{
imHdfClt *pClt; /* New Clt list entry */
if ( (pClt = (imHdfClt *)malloc( sizeof( imHdfClt ) )) == NULL )
{
ImErrNo = IMEMALLOC;
ImErrorFatal( ImQError(), NULL, ImErrNo );
}
pClt->clt_clt = clt;
pClt->clt_refLUT = refLUT;
pClt->clt_refLD = refLD;
if ( imHdfCltList == NULL )
imHdfCltList = pClt;
else
imHdfCltListEnd->clt_next = pClt;
pClt->clt_next = NULL;
imHdfCltListEnd = pClt;
return ( pClt );
}
imHdfClt * /* Returns found Clt pointer */
#ifdef __STDC__
imHdfCltFind(ImClt * clt )
#else
imHdfCltFind( clt )
ImClt *clt; /* CLT to look for */
#endif
{
imHdfClt *pClt; /* Clt list pointer */
for ( pClt = imHdfCltList; pClt; pClt = pClt->clt_next )
if ( pClt->clt_clt == clt )
break;
return ( pClt ); /* Could be NULL */
}
imHdfClt * /* Returns found Clt pointer */
#ifdef __STDC__
imHdfCltFindRef( unsigned int ref )
#else
imHdfCltFindRef( ref )
unsigned int ref; /* Reference number to look for */
#endif
{
imHdfClt *pClt; /* Clt list pointer */
for ( pClt = imHdfCltList; pClt; pClt = pClt->clt_next )
if ( pClt->clt_refLUT == ref )
break;
return ( pClt ); /* Could be NULL */
}
/*
* GLOBALS
* imHdfByteOrder - data byte order
* imHdfFloatFormat - data float format
* imHdfRef - current reference number
*/
int imHdfByteOrder; /* Default byte order */
int imHdfFloatFormat; /* Default float format */
sdsc_uint16 imHdfRef = 100; /* Current reference number */
/*
* FUNCTION
* ImHdfRead - read an HDF file
*
* DESCRIPTION
* ImHdfRead() reads in an HDF file and adds all images and CLTs to
* the tag table.
*
* HDF files are structured such that we have to do multiple passes on
* the file, and then on the data we read in in order to get things
* done...
*
* 1. Read in all of the Data Descriptors (DDs), each one describing
* one tag in the file. A DD includes the file byte offset to get
* to the actual data for the tag.
*
* We can't immediately go out and get the data when we read in a
* DD because we don't know what to do with it yet. All raster
* image set tags are used by one or more raster image groups (RIGs)
* and we don't know what to do with, say, an ID (image dimension)
* tag until we've read in the RIG(s) that reference it.
*
* While reading in DD's, we toss ones for tags we don't handle.
* We also build up a linked list of RIG tags that we've found. The
* RIG tags are sorted by reference count, which may be (but usually
* isn't) different from the order found in the file.
*
* 2. Read in all the RIGs. Each RIG is a list of tag/ref values
* that refer to tags that in turn refer to data relevant for this
* image. The order of tags listed in a RIG is undefined. We'd
* like to just read in the data for each of the RIG's tags,
* but we can't always. For instance, to read in an image,
* we have to first know how big it is. That's told by an ID tag.
* But we might not have read in the ID tag for the RIG yet. Sigh.
*
* 3. Read in each RIG's CLT, image, and matte data based upon the
* ID, etc, tag information we read in in (2). Now we can process
* the file's CLT into an ImCLT, and uncompress the file's image
* into an ImVfb. As we finish each RIG, we add the ImClt and ImVfb
* to the tag table.
*/
static int /* Returns status */
#ifdef __STDC__
ImHdfRead( int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable )
#else
ImHdfRead( ioType, fd, fp, flagsTable, tagTable )
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
TagTable *flagsTable; /* Format flags */
TagTable *tagTable; /* Tag list to add to */
#endif
{
int i; /* Counter */
ImVfb *vfb; /* virtual frame buffer */
ImClt *clt; /* color lookup table */
unsigned char magic[4]; /* Magic number */
char message[1024]; /* Error message holder */
unsigned int nDD; /* # of DD's in block */
long offset; /* Offset to next DD block */
imHdfDD *pDD; /* DD pointer */
imHdfDD *pDD2; /* 2nd DD pointer */
imHdfDD *pPrevDD; /* Previous DD pointer */
imHdfClt *pClt; /* Clt information */
imHdfRIG *rigList; /* List of RIG's */
imHdfRIG *rigListEnd; /* Pointer to end of RIG list */
imHdfRIG *pRIG; /* RIG pointer */
imHdfRIG *pRIG2; /* 2nd RIG pointer */
imHdfRIG *pPrevRIG; /* Previous RIG pointer */
int nTag; /* # of tags in a RIG */
unsigned int tagList[50]; /* List of tags in a RIG */
unsigned int refList[50]; /* and their ref numbers */
unsigned int tag; /* DD tag */
unsigned int ref; /* DD reference number */
long dataOffset; /* Offset to data */
long dataLength; /* Length of data */
int imageNum; /* number of images in a rig list */
int imageNumII; /* number of images in a rig list */
/*
* All administrative stuff (tags, reference counts, file offsets)
* are in MBF byte order.
*/
BinByteOrder( BINMBF );
ImInfo ("Byte Order (header)",
"Most Significant Byte First");
/*
* Read in the magic number.
*/
Read( magic, UCHAR, 1, 4 );
if ( magic[0] != 0x0E || magic[1] != 0x03 || magic[2] != 0x13 ||
magic[3] != 0x01 )
{
ImErrNo = IMEMAGIC;
ImErrorFatal( ImQError( ), -1, ImErrNo );
}
/*
* Read in the Data Descriptor Header (DDH) and each of the
* Data Descriptors (DDs) in the block. Create a linked list of
* the DDs, then advance to the next DDH.
*/
imHdfByteOrder = BINMBF;
imHdfFloatFormat = BINIEEE;
imHdfDDEmpty( );
rigList = rigListEnd = NULL;
for ( ; ; )
{
Read( &nDD, UINT, 2, 1 );
Read( &offset, LONG, 4, 1 );
for ( i = 0; i < nDD; i++ )
{
Read( &tag, UINT, 2, 1 );
Read( &ref, UINT, 2, 1 );
Read( &dataOffset, LONG, 4, 1 );
Read( &dataLength, LONG, 4, 1 );
/*
* Toss tags we don't care about and process those
* we do.
*/
switch ( tag )
{
/* Keep number type tags */
case IMHDFTNT: /* Number type */
if ( imHdfDDAppend( tag, ref, dataOffset,
dataLength ) == NULL )
return( -1 ); /* Error handled*/
break;
/* Keep raster image set tags */
case IMHDFTCFM: /* Color format */
case IMHDFTID: /* Image dimension */
case IMHDFTLD: /* Lookup table dimension */
case IMHDFTMD: /* Matte dimension */
case IMHDFTMA: /* Matte */
case IMHDFTCCN: /* Color correction */
case IMHDFTAR: /* Aspect ratio */
case IMHDFTRI: /* Raster image */
case IMHDFTCI: /* Compressed raster image */
case IMHDFTLUT: /* Lookup table */
case IMHDFTMTO: /* Machine-Type Override */
if ( imHdfDDAppend( tag, ref, dataOffset,
dataLength ) == NULL )
return( -1 ); /* Error handled*/
break;
/* Add RIG's to a list, in ref number order */
case IMHDFTRIG: /* Raster image group */
if ( (pDD = imHdfDDAppend( tag, ref, dataOffset,
dataLength ) ) == NULL )
return( -1 ); /* Error handled*/
ImMalloc( pRIG, imHdfRIG *, sizeof( imHdfRIG ) );
pRIG->rig_dd = pDD;
/* Set defaults for RIGs. */
pRIG->rig_imageDim = NULL;
pRIG->rig_imageDD = NULL;
pRIG->rig_cltDim = NULL;
pRIG->rig_cltDD = NULL;
pRIG->rig_matteDim = NULL;
pRIG->rig_matteDD = NULL;
pRIG->rig_ccnGiven = FALSE;
pRIG->rig_colorFormat = IMHDFCVALUE;
pRIG->rig_aspectRatio = 1.0;
/* If list is empty, make it start of list*/
if ( rigList == NULL )
{
rigList = rigListEnd = pRIG;
pRIG->rig_next = NULL;
break;
}
/* If ref > last in list, append to list*/
if ( imHdfDDQRef( pDD ) > imHdfDDQRef( rigListEnd->rig_dd ) )
{
rigListEnd->rig_next = pRIG;
pRIG->rig_next = NULL;
rigListEnd = pRIG;
break;
}
/* If ref < first in list, start list */
if ( imHdfDDQRef( pDD ) < imHdfDDQRef( rigList->rig_dd ) )
{
pRIG->rig_next = rigList;
rigList = pRIG;
break;
}
/* Search list for proper position */
pPrevRIG = rigList;
pRIG2 = rigList->rig_next;
while ( pRIG2 )
{
if ( imHdfDDQRef( pDD ) > imHdfDDQRef( pRIG2->rig_dd ) )
{
pPrevRIG = pRIG2;
pRIG2 = pRIG2->rig_next;
continue;
}
pRIG->rig_next = pRIG2;
pPrevRIG->rig_next = pRIG;
break;
}
break;
/* Immediately process machine type tags */
case IMHDFTMT: /* Machine type */
switch ( (ref>>12)&0xF )
{
case IMHDFINTMBO: /* Motorola byte order (MBF)*/
ImInfo ("Byte Order (RIG)",
"Most Significant Byte First");
imHdfByteOrder = BINMBF;
break;
case IMHDFINTVBO: /* Vax byte order (LBF) */
case IMHDFINTIBO: /* Intel byte order (LBF)*/
ImInfo ("Byte Order (RIG)",
"Least Significant Byte First");
imHdfByteOrder = BINLBF;
break;
}
switch ( (ref>>8)&0xF )
{
case IMHDFFLOATIEEE:/* IEEE */
imHdfFloatFormat = BINIEEE;
break;
case IMHDFFLOATVAX:/* VAX */
imHdfFloatFormat = BINVAX;
break;
case IMHDFFLOATCRAY:/* Cray */
imHdfFloatFormat = BINCRAYMP;
break;
case IMHDFFLOATPC:/* PC? */
imHdfFloatFormat = BINIEEE;/* unknown!*/
break;
}
continue;
/* Skip null tags */
case IMHDFTNULL: /* No data */
continue;
/* Skip generic compression description tags */
case IMHDFTRLE: /* Run length encoded data */
case IMHDFTIMC: /* IMCOMP compressed data */
continue;
/* Skip file, tag, and data identifiers */
case IMHDFTFID: /* File identifier */
case IMHDFTFD: /* File descriptor */
case IMHDFTTID: /* Tag identifier */
case IMHDFTTD: /* Tag descriptor */
case IMHDFTDIL: /* Data identifier label */
case IMHDFTDIA: /* Data identifier annotation */
continue;
/* Skip redundant raster-8 tags */
case IMHDFTID8: /* Image dimension-8 */
case IMHDFTIP8: /* Image palette-8 */
case IMHDFTRI8: /* Raster image-8 */
case IMHDFTCI8: /* Compressed image-8 */
case IMHDFTII8: /* IMCOMP image-8 */
continue;
/* Skip composition tags */
case IMHDFTDRAW: /* Draw */
case IMHDFTRUN: /* Run */
case IMHDFTXYP: /* XY position */
continue;
/* Skip vector set tags */
case IMHDFTT14: /* Tektronix 4014 */
case IMHDFTT105: /* Tektronix 4105 */
continue;
/* Skip scientific data set tags */
case IMHDFTSDG: /* Scientific data group */
case IMHDFTSDD: /* Scientific data dimension record*/
case IMHDFTSD: /* Scientific data */
case IMHDFTSDS: /* Scientific data scales */
case IMHDFTSDL: /* Scientific data labels */
case IMHDFTSDU: /* Scientific data units */
case IMHDFTSDF: /* Scientific data format */
case IMHDFTSDC: /* Scientific data coordinates */
case IMHDFTSDM: /* Scientific data max/min */
case IMHDFTSDT: /* Scientific data transpose */
continue;
/* Skip all unknown tags */
default:
continue;
}
}
if ( offset <= 0 )
break;
Seek( offset );
}
/*
* Walk the RIG list. For each RIG, read in its list of tags and
* reference numbers, find each one, read it in, and add data to
* the RIG structure.
*
* We have to postpone reading in the actual CLT, image, and matte
* data until the rest of the RIG tags have been read in and processed.
* For instance, to read in an image we have to have the ID tag's
* info at hand. But that tag may be listed after the tag pointing
* to the image data. Sigh.
*/
BinByteOrder( imHdfByteOrder ); /* Data byte order */
BinFloatFormat( imHdfFloatFormat ); /* Data float format */
for ( pRIG = rigList; pRIG; pRIG = pRIG->rig_next )
{
pDD = pRIG->rig_dd;
Seek( imHdfDDQDataOffset( pDD ) );
nTag = imHdfDDQDataLength( pDD ) / 4;/* 4 bytes per tag/ref*/
for ( i = 0; i < nTag; i++ )
{
Read( &tagList[i], UINT, 2, 1 );
Read( &refList[i], UINT, 2, 1 );
}
/*
* For each tag/ref in the RIG, search the DD list, then
* read in its data (if possible).
*/
for ( i = 0; i < nTag; i++ )
{
if ( (pDD = imHdfDDFind( tagList[i], refList[i] )) == NULL)
{
sprintf( message, "RIG %d references non-existant tag %d/%d",
imHdfDDQRef( pRIG->rig_dd ),
tagList[i], refList[i] );
ImErrorFatal( message, -1, IMESYNTAX );
}
switch ( tagList[i] )
{
case IMHDFTRI: /* Raster image */
case IMHDFTCI: /* Compressed raster image */
pRIG->rig_imageDD = pDD;
break;
case IMHDFTLUT: /* CLT */
pRIG->rig_cltDD = pDD;
break;
case IMHDFTMA: /* Matte channel */
pRIG->rig_matteDD = pDD;
break;
case IMHDFTAR: /* Aspect ratio */
Seek( imHdfDDQDataOffset( pDD ) );
Read( &pRIG->rig_aspectRatio, FLOAT, 4, 1 );
break;
case IMHDFTCCN: /* Color correction */
pRIG->rig_ccnGiven = TRUE;
Seek( imHdfDDQDataOffset( pDD ) );
Read( &pRIG->rig_gamma, FLOAT, 4, 1 );
Read( pRIG->rig_red, FLOAT, 4, 3 );
Read( pRIG->rig_green, FLOAT, 4, 3 );
Read( pRIG->rig_blue, FLOAT, 4, 3 );
Read( pRIG->rig_white, FLOAT, 4, 3 );
break;
case IMHDFTCFM: /* Color format */
{
char *buffer;
ImMalloc( buffer, char *, sizeof( char ) *
(imHdfDDQDataLength( pDD ) + 1) );
Seek( imHdfDDQDataOffset( pDD ) );
Read( buffer, CHAR, 1, imHdfDDQDataLength( pDD ) );
buffer[imHdfDDQDataLength( pDD )] = '\0';
if ( strcmp( "VALUE", buffer ) == 0 )
pRIG->rig_colorFormat = IMHDFCVALUE;
else if ( strcmp( "RGB", buffer ) == 0 )
pRIG->rig_colorFormat = IMHDFCRGB;
else if ( strcmp( "XYZ", buffer ) == 0 )
pRIG->rig_colorFormat = IMHDFCXYZ;
else if ( strcmp( "HSV", buffer ) == 0 )
pRIG->rig_colorFormat = IMHDFCHSV;
else if ( strcmp( "HSI", buffer ) == 0 )
pRIG->rig_colorFormat = IMHDFCHSI;
else if ( strcmp( "SPECTRAL", buffer ) == 0 )
pRIG->rig_colorFormat = IMHDFCSPECTRAL;
else
{
sprintf( message, "Unknown color format '%s'", buffer );
ImErrorFatal( message, -1, IMESYNTAX );
}
free( (char *)buffer );
break;
}
case IMHDFTID: /* Image dimension */
Seek( imHdfDDQDataOffset( pDD ) );
if ( imHdfDimRead( ioType, fd, fp,
&pRIG->rig_imageDim ) == -1 )
return ( -1 ); /* Error stuff done*/
break;
case IMHDFTLD: /* Lookup table dimension */
Seek( imHdfDDQDataOffset( pDD ) );
if ( imHdfDimRead( ioType, fd, fp,
&pRIG->rig_cltDim ) == -1 )
return ( -1 ); /* Error stuff done*/
break;
case IMHDFTMD: /* Matte dimension */
Seek( imHdfDDQDataOffset( pDD ) );
if ( imHdfDimRead( ioType, fd, fp,
&pRIG->rig_matteDim ) == -1 )
return ( -1 ); /* Error stuff done*/
break;
}
}
/*
* There may or may not be an LD tag giving the dimensions of
* the lookup table. SDSC tools always add the LD tag.
* NCSA tools apparently do not.
*
* Without an explicit LD, we create one:
* width = 256
* height = 1
* channel type = UCHAR
* channel size = 1
* channel byte order = BINMBF (unneeded)
* channel float format = BINIEEE (unneeded)
* pixel size = 3
* interleave = 0 (RGB, RGB, RGB, ...)
* compression = 0 (none)
*
* These attributes match those of the IP8 pallette most
* commonly used in cases where the LD tag is "forgotten".
*/
if ( pRIG->rig_cltDD != NULL && pRIG->rig_cltDim == NULL )
{
ImMalloc( pRIG->rig_cltDim, imHdfDim *, sizeof( imHdfDim ) );
pRIG->rig_cltDim->dim_width = 256;
pRIG->rig_cltDim->dim_height = 1;
pRIG->rig_cltDim->dim_channelType = UCHAR;
pRIG->rig_cltDim->dim_channelSize = 1;
pRIG->rig_cltDim->dim_channelByteOrder = BINMBF;
pRIG->rig_cltDim->dim_channelFloatFormat = BINIEEE;
pRIG->rig_cltDim->dim_pixelSize = 3;
pRIG->rig_cltDim->dim_interleave = 0;
pRIG->rig_cltDim->dim_compression = 0;
}
/*
* Confirm that we got all that we needed.
*/
if ( pRIG->rig_imageDD != NULL && pRIG->rig_imageDim == NULL )
ImErrorFatal( "Missing image dimension tag for raster image",
-1, IMESYNTAX );
if ( pRIG->rig_matteDD != NULL && pRIG->rig_matteDim == NULL )
ImErrorFatal( "Missing matte dimension tag for matte",
-1, IMESYNTAX );
}
/*
* Walk the RIG list and read in each RIG's CLT (if any) and image
* (if any).
*
* We don't keep track of multiple RIG's pointing to the same VFB.
* We do keep track of multiple RIG's using the same CLT.
*/
nTag = 0;
imHdfCltEmpty( );
/* Count the number of images */
imageNum=0;
imageNumII=0;
for ( pRIG = rigList; pRIG; pRIG = pRIG->rig_next )
if ( pRIG->rig_imageDD ) imageNum++;
for ( pRIG = rigList; pRIG; pRIG = pRIG->rig_next )
{
if ( pRIG->rig_imageDD )
{
imageNumII++;
sprintf (message, "%d of %d",imageNumII, imageNum);
ImInfo ("Image",message);
}
/*
* Read in the CLT.
*/
clt = IMCLTNULL;
if ( pRIG->rig_cltDD )
{
/*
* Check if CLT has already been read in for another
* image.
*/
if ( (pClt = imHdfCltFindRef( imHdfDDQRef( pRIG->rig_cltDD ) )) == NULL )
{
/* Nope. Read it in and add it to our list.*/
if ( imHdfCltRead( ioType, fd, fp, pRIG, &clt ) == -1 )
return ( -1 ); /* Error stuff done already*/
imHdfCltAppend( clt, imHdfDDQRef( pRIG->rig_cltDD ),
0 );
TagTableAppend( tagTable,
TagEntryAlloc( "image clt", POINTER, &clt ) );
}
else
clt = imHdfCltQClt( pClt );
nTag++;
}
/*
* Read in the image.
*/
vfb = IMVFBNULL;
if ( pRIG->rig_imageDD )
{
if ( imHdfVfbRead( ioType, fd, fp, pRIG, &vfb ) == -1 )
return ( -1 ); /* Error stuff done already*/
ImVfbSClt( vfb, clt ); /* Could be NULL clt */
TagTableAppend( tagTable,
TagEntryAlloc( "image vfb", POINTER, &vfb ) );
nTag++;
}
}
imHdfDDEmpty( );
imHdfCltEmpty( );
return ( nTag );
}
/*
* FUNCTION
* imHdfDimRead - read dimensions
*
* DESCRIPTION
* The ID, LD, and MD tags all share the same structuring of their
* data. imHdfDimRead() reads in this set of dimension information and
* returns it in a new imHdfDim structure.
*
* A dimension tag also references an NT tag (for the size of a pixel
* channel), and an optional compression tag. These tags are searched
* for in the DD list and their information incorporated into the imHdfDim
* structure.
*/
static int /* Returns status */
#ifdef __STDC__
imHdfDimRead( int ioType, int fd, FILE *fp, imHdfDim **pDim )
#else
imHdfDimRead( ioType, fd, fp, pDim )
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
imHdfDim **pDim; /* Returned dimensions */
#endif
{
unsigned int tagNT, refNT; /* NT tag and reference number */
unsigned int tagComp, refComp; /* Compression tag and ref number*/
unsigned char nt[4]; /* NT information */
imHdfDD *pDD2; /* 2nd DD pointer */
imHdfDim *dim; /* New dimension information */
char message[1024]; /* Tmp error message text */
/*
* Create a new dimension description and read in the basic info.
*/
ImMalloc( dim, imHdfDim *, sizeof( imHdfDim ) );
Read( &dim->dim_width, INT, 4, 1 );
Read( &dim->dim_height, INT, 4, 1 );
Read( &tagNT, UINT, 2, 1 );
Read( &refNT, UINT, 2, 1 );
Read( &dim->dim_pixelSize, INT, 2, 1 );
Read( &dim->dim_interleave, INT, 2, 1 );
Read( &tagComp, UINT, 2, 1 );
Read( &refComp, UINT, 2, 1 );
/*
* Search the DD list for the NT tag.
*/
if ( (pDD2 = imHdfDDFind( tagNT, refNT )) == NULL )
ImErrorFatal( "Dimension tag references nonexistant NT tag",
-1, IMESYNTAX );
/*
* Read in the NT tag and decode it.
*
* The NT tag's data is 4 1-byte quantities:
*
* 0 version number of NT tag (version 1 supported here)
* 1 type code
* 2 width of type, in bits
* 3 class code (byte order, float format, etc)
*/
Seek( imHdfDDQDataOffset( pDD2 ) );
Read( nt, UCHAR, 1, 4 );
dim->dim_channelSize = ((nt[2] + 7) / 8);
dim->dim_channelByteOrder = imHdfByteOrder; /* Default */
dim->dim_channelFloatFormat = imHdfFloatFormat; /* Default */
switch ( nt[1] )
{
case IMHDFNTUINT: /* unsigned int */
case IMHDFNTINT: /* int */
dim->dim_channelType = (nt[1] == IMHDFNTUINT) ? UINT : INT ;
switch ( nt[3] )
{
default:
case IMHDFINTMBO:
dim->dim_channelByteOrder = BINMBF;
ImInfo ("Byte Order (data)",
"Most Significant Byte First");
break;
case IMHDFINTVBO:
case IMHDFINTIBO:
ImInfo ("Byte Order (data)",
"Least Significant Byte First");
dim->dim_channelByteOrder = BINLBF;
break;
}
break;
case IMHDFNTUCHAR:/* unsigned char */
/* Ignore nt[3] = ASCII or bitwise-numeric. */
dim->dim_channelType = UCHAR;
break;
case IMHDFNTCHAR: /* char */
/* Ignore nt[3] = ASCII or bitwise-numeric. */
dim->dim_channelType = CHAR;
break;
case IMHDFNTFLOAT:/* float */
dim->dim_channelType = FLOAT;
case IMHDFNTDOUBLE:/* double */
dim->dim_channelType = (nt[1] == IMHDFNTFLOAT) ? FLOAT : DOUBLE ;
switch ( nt[3] )
{
default:
case IMHDFFLOATPC:
case IMHDFFLOATIEEE:
dim->dim_channelFloatFormat = BINIEEE;
break;
case IMHDFFLOATVAX:
dim->dim_channelFloatFormat = BINVAX;
break;
case IMHDFFLOATCRAY:
dim->dim_channelFloatFormat = BINCRAYMP;
break;
}
break;
default:
sprintf( message, "Unknown NT type code '%d'", nt[1] );
ImErrorFatal( message, -1, IMESYNTAX );
}
/*
* Check the compression tag type.
*
* As of this version, 3 types of compression are defined:
*
* 0 none
* RLE run-length encode
* IMCOMP special compression
*
* The later two have tags, but those tags don't actually point
* to any data, so we don't bother reading them in. If, someday,
* other compression types exist, those types may have data and
* we'd have to seek and read them in.
*
* Note: in practice, NCSA tools appear to simply skip adding the
* compression tags, since they have no data. Mentioning their
* tag number is enough. SDSC tools more closely follow the HDF
* spec and do add the no-data compression tags.
*/
switch ( tagComp )
{
case 0: /* No compression used */
case IMHDFTRLE: /* RLE used */
case IMHDFTIMC: /* IMCOMP used */
dim->dim_compression = tagComp;
break;
default:
sprintf( message, "Unknown image compression tag '%d'",
tagComp );
ImErrorFatal( message, -1, IMESYNTAX );
}
*pDim = dim;
return ( 0 );
}
/*
* FUNCTION
* imHdfCltRead - read in a CLT
*
* DESCRIPTION
* HDF files support lots of variations on the traditional CLT.
* Fortunately, virtually all HDF files use the same small subset of
* the possibilities. We restrict ourselves to this same subset by
* ruling out the following possibilities:
*
* 2D CLT's
* CLT's are expected to have a width that is the number of
* colors in the CLT, and a height of 1. Height values other
* than 1 are rejected.
*
* Non-RGB CLT's (CLT's that aren't 3 8-bit chars)
* A channel (red, green, whatever) has a type, a size, a
* byte order and/or a floating point format. A number of
* these channels together form a pixel value.
*
* HDF allows one to describe obscure CLT's that have, say,
* 10 channels, each one a 3 byte IEEE (no such thing) floating
* point number. Woa! This is too much. We restrict ourselves
* to the traditional 3 channel, 1 char each CLT.
*
* Compressed CLT's
* The LD tag can give a compression mode. However, there are
* no compression modes currently defined for CLT's. Its
* unclear why one would bother.
*/
static int /* Returns status */
#ifdef __STDC__
imHdfCltRead( int ioType, int fd, FILE *fp, imHdfRIG *pRIG, ImClt **pClt )
#else
imHdfCltRead( ioType, fd, fp, pRIG, pClt )
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
imHdfRIG *pRIG; /* Image group description */
ImClt **pClt; /* Returned CLT */
#endif
{
int n; /* Number of CLT entries */
int i; /* Counter */
ImClt *clt; /* New clt */
ImCltPtr pColor; /* CLT entry "pointer" */
char message[1024]; /* Error message buffer */
imHdfDim *pDim; /* CLT dimension information */
unsigned char *buffer; /* Temp CLT buffer */
/*
* Check for strange CLT specifications.
*/
pDim = pRIG->rig_cltDim;
if ( pDim->dim_height != 1 )
{
sprintf( message, "Unsupported CLT height '%d' (should be 1)",
pDim->dim_height );
ImErrorFatal( message, -1, IMESYNTAX );
}
if ( pDim->dim_channelType != UCHAR || pDim->dim_channelSize != 1 ||
pDim->dim_pixelSize != 3 )
ImErrorFatal( "Non-RGB (24-bit) CLT's not supported",
-1, IMESYNTAX );
if ( pDim->dim_compression != 0 )
{
sprintf( message, "Unsupported CLT compression scheme '%d' (should be 0)",
pDim->dim_compression );
ImErrorFatal( message, -1, IMESYNTAX );
}
/*
* Allocate a new CLT.
*/
n = pDim->dim_width;
if ( (clt = ImCltAlloc( n )) == IMCLTNULL )
ImErrorFatal( ImQError( ), -1, ImErrNo );
sprintf (message, "%d Entries",pDim->dim_width);
ImInfo ("Color Table",message);
/*
* Read it in, based on the interleave mode.
*/
Seek( imHdfDDQDataOffset( pRIG->rig_cltDD ) );
switch ( pDim->dim_interleave )
{
case 0: /* RGB, RGB, RGB, ... */
ImMalloc( buffer, unsigned char *, sizeof( unsigned char ) * n * 3 );
pColor = ImCltQFirst( clt );
Read( buffer, UCHAR, 1, n * 3 );
n *= 3;
for ( i = 0; i < n; i+=3 )
{
ImCltSRed( pColor, buffer[i] );
ImCltSGreen( pColor, buffer[i+1] );
ImCltSBlue( pColor, buffer[i+2] );
ImCltSInc( clt, pColor );
}
free( (char *)buffer );
break;
case 1: /* RRRR..., GGGG..., BBBB... */
ImMalloc( buffer, unsigned char *, sizeof( unsigned char ) * n );
pColor = ImCltQFirst( clt );
Read( buffer, UCHAR, 1, n );
for ( i = 0; i < n; i++ )
{
ImCltSRed( pColor, buffer[i] );
ImCltSInc( clt, pColor );
}
pColor = ImCltQFirst( clt );
Read( buffer, UCHAR, 1, n );
for ( i = 0; i < n; i++ )
{
ImCltSGreen( pColor, buffer[i] );
ImCltSInc( clt, pColor );
}
pColor = ImCltQFirst( clt );
Read( buffer, UCHAR, 1, n );
for ( i = 0; i < n; i++ )
{
ImCltSBlue( pColor, buffer[i] );
ImCltSInc( clt, pColor );
}
free( (char *)buffer );
break;
default:
sprintf( message, "Unsupported CLT interleave scheme '%d'",
pDim->dim_interleave );
ImErrorFatal( message, -1, IMESYNTAX );
}
*pClt = clt;
return ( 0 );
}
/*
* FUNCTION
* imHdfVfbRead - read in a VFB
*
* DESCRIPTION
* HDF files represent images using one of three "interleave" methods:
*
* #0: RGB per pixel per scanline.
* #1: Red scanline, then Green, then Blue.
* #2: Red plane, then Green, then Blue.
*
* Each of these three methods may be optionally compressed:
*
* None: Values are not compressed.
*
* RLE: Bytewise run-length encoded:
*
* <count> <value> ...
*
* if <count> < 0, repeate <value> -<count> times
* else, include next <count> values as is
*
* Note: worst case encoding: ABBABBABB... where A and
* B are different <value>'s. Encoded result is:
* 1A-2BB1A-2BB1A-2BB..., giving a 33% expansion.
*
* IMCOMP: Color sampling.
*
* HDF allows one to describe bizarre image storage configurations that
* have, for instance, 7 channels per pixel, each represented by a
* 13-byte VAX float (no such thing) in the CIE XYZ color space (but
* with 7 channels?). Yeah, right. We restrict ourselves to the more
* traditional configurations:
*
* 1 8-bit channel: 8-bit color index + CLT
* 1 16-bit channel: 16-bit color index + CLT
* 1 24-bit channel: 24-bit color index + CLT
* 1 32-bit channel: 32-bit color index + CLT
*
* 3 8-bit channels: 24-bit RGB color
*
* All other variations cause errors.
*
* Note that for 16-, 24-, and 32-bit index configurations we do not
* support encoding. HDF defines their RLE encoding as being byte-wise,
* even on multi-byte integer values. This is nonsense. Encoding would
* only do anything if each byte in the integer had the same bit-pattern!
* Very dumb. It also makes it impossible to hide byte order stuff
* beneath the encoding scheme (and in the Binary I/O package).
*
* HDF supports a variety of color formats for pixel storage, including
* RGB, CIE, HSI, HSV, and spectral samples. We only support RGB and
* pseudo-color (VALUE).
*/
static int /* Returns status */
#ifdef __STDC__
imHdfVfbRead( int ioType, int fd, FILE *fp, imHdfRIG *pRIG, ImVfb **pVfb )
#else
imHdfVfbRead( ioType, fd, fp, pRIG, pVfb )
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
imHdfRIG *pRIG; /* Image group description */
ImVfb **pVfb; /* Returned VFB */
#endif
{
imHdfDim *pDim; /* Image dimension information */
char message[1024]; /* Error message buffer */
/*
* Check for unsupported image specifications and vector off to
* the appropriate read routine.
*/
pDim = pRIG->rig_imageDim;
if ( pRIG->rig_ccnGiven )
ImErrorInfo( "Color correction specifications ignored",
-1, IMESYNTAX );
/*
* NCSA tools fail to add the color format tag, so we have to assume
* it is either a value (for 8- and 16-bit images) or an RGB color (for
* 24-bit images). SDSC tools always add the color format tag.
*/
if ( pRIG->rig_colorFormat != IMHDFCRGB &&
pRIG->rig_colorFormat != IMHDFCVALUE )
ImErrorFatal( "Non-RGB color formats not supported",
-1, IMESYNTAX );
/*
* Check for illegal combinations.
*/
if ( pDim->dim_pixelSize == 1 )
{
/* 1 channel. We support 1, 2, 3 and 4 byte channels. */
if ( pDim->dim_channelSize < 1 || pDim->dim_channelSize > 4 )
{
sprintf( message, "Unsupported channel size: '%d' bytes\n",
pDim->dim_channelSize );
ImErrorFatal( message, -1, IMESYNTAX );
}
if ( pDim->dim_channelSize != 1 && pDim->dim_compression != 0 )
ImErrorFatal( "RLE image compression not supported on channels larger than 1 byte",
-1, IMESYNTAX );
if ( pDim->dim_interleave != 0 )
{
sprintf( message, "Interleave '%d' meaningless on single-channel images",
pDim->dim_interleave );
ImErrorInfo( message, -1, IMESYNTAX );
}
}
else if ( pDim->dim_pixelSize != 3 )
{
sprintf( message, "Unsupported number of channels per pixel: '%d'",
pDim->dim_pixelSize );
ImErrorFatal( message, -1, IMESYNTAX );
}
if ( pDim->dim_channelType == FLOAT || pDim->dim_channelType == DOUBLE )
ImErrorFatal( "Floating point channels not supported",
-1, IMESYNTAX );
if ( pDim->dim_compression != 0 && pDim->dim_compression != IMHDFTRLE )
{
sprintf( message, "Unsupported image compression scheme '%d'",
pDim->dim_compression );
ImErrorFatal( message, -1, IMESYNTAX );
}
if ( pDim->dim_interleave < 0 || pDim->dim_interleave > 3 )
{
sprintf( message, "Unknown interleave scheme '%d'",
pDim->dim_interleave );
ImErrorFatal( message, -1, IMESYNTAX );
}
sprintf (message, "%d x %d",pDim->dim_width, pDim->dim_height);
ImInfo("Resolution",message);
/*
* Call the appropriate VFB read routine.
*/
if ( pDim->dim_pixelSize == 1 )
{
switch ( pDim->dim_channelSize )
{
case 1: /* 8-bit, single channel per pixel image. */
ImInfo ("Type","8-bit Color Indexed");
switch ( pDim->dim_compression )
{
case 0: /* Uncompressed */
ImInfo ("Compression Type","None");
return ( imHdfVfbRead8( ioType, fd, fp,
pRIG, pVfb ) );
case IMHDFTRLE:/* Run-length encoded */
ImInfo ("Compression Type","Run Length Encoded (RLE)");
return ( imHdfVfbReadRLE8( ioType, fd, fp,
pRIG, pVfb ) );
}
case 2: /* 16-bit, single channel per pixel image. */
case 3: /* 24-bit, single channel per pixel image. */
case 4: /* 32-bit, single channel per pixel image. */
/* Uncompressed */
ImInfo ("Type","32-bit Color Indexed");
ImInfo ("Compression Type","None");
return ( imHdfVfbRead32( ioType, fd, fp,
pRIG, pVfb ) );
}
}
/* RGB image */
ImInfo ("Type","24-bit RGB");
switch ( pDim->dim_compression )
{
case 0: /* Uncompressed */
ImInfo ("Compression Type","None");
switch ( pDim->dim_interleave )
{
case 0: /* Uninterleaved */
ImInfo ("Interleave Type","None (Non-interleaved)");
return ( imHdfVfbReadRGB( ioType, fd, fp,
pRIG, pVfb ) );
case 1: /* Scanline interleaved */
ImInfo ("Interleave Type","Scanline");
return ( imHdfVfbReadRGBLine( ioType, fd, fp,
pRIG, pVfb ));
case 2: /* Plane interleaved */
ImInfo ("Interleave Type","Plane");
return ( imHdfVfbReadRGBPlane( ioType, fd, fp,
pRIG, pVfb));
}
case IMHDFTRLE:/* Run-length encoded */
ImInfo ("Compression Type","Run Length Encoded (RLE)");
switch ( pDim->dim_interleave )
{
case 0: /* Uninterleaved */
ImInfo ("Interleave Type","None (Non-inteleaved)");
return ( imHdfVfbReadRLERGB( ioType, fd, fp,
pRIG, pVfb ) );
case 1: /* Scanline interleaved */
ImInfo ("Interleave Type","Scanline");
return ( imHdfVfbReadRLERGBLine( ioType, fd, fp,
pRIG, pVfb ));
case 2: /* Plane interleaved */
ImInfo ("Interleave Type","Plane");
return ( imHdfVfbReadRLERGBPlane( ioType, fd, fp,
pRIG, pVfb));
}
}
/*NOT REACHED*/
return 0;
}
/*
* FUNCTION
* imHdfVfbRead8 - read 8-bit uncomp. VFB
* imHdfVfbReadRLE8 - read 8-bit RLE comp. VFB
*
* imHdfVfbRead32 - read 32-bit uncomp. VFB
*
* imHdfVfbReadRGB - read 24-bit uncomp. uninterleaved VFB
* imHdfVfbReadRGBLine - read 24-bit uncomp. line interleaved VFB
* imHdfVfbReadRGBPlane - read 24-bit uncomp. plane interleaved VFB
*
* imHdfVfbReadRLERGB - read 24-bit RLE comp. uninterleaved VFB
* imHdfVfbReadRLERGBLine - read 24-bit RLE comp. line interleaved VFB
* imHdfVfbReadRLERGBPlane - read 24-bit RLE comp. plane interleaved VFB
*
* DESCRIPTION
* Each of these routines allocate a new VFB, then read in the image
* data from the file. If RLE compression is in use, runs are decoded.
*/
static int /* Returns status */
#ifdef __STDC__
imHdfVfbRead8( int ioType, int fd, FILE *fp, imHdfRIG *pRIG, ImVfb **pVfb )
#else
imHdfVfbRead8( ioType, fd, fp, pRIG, pVfb )
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
imHdfRIG *pRIG; /* Image group description */
ImVfb **pVfb; /* Returned VFB */
#endif
{
imHdfDim *pDim; /* Image dimension information */
ImVfb *vfb; /* New VFB */
ImVfbPtr pPixel; /* Pixel pointer */
unsigned char *buffer; /* Input buffer */
unsigned char *pBuffer; /* Pointer into input buffer */
int i, j; /* Counters */
/*
* Allocate a new 8-bit index VFB.
*/
pDim = pRIG->rig_imageDim;
if ( (vfb = ImVfbAlloc( pDim->dim_width, pDim->dim_height, IMVFBINDEX8))
== IMVFBNULL )
ImErrorFatal( ImQError( ), -1, ImErrNo );
/*
* Allocate a buffer that is big enough for one scanline. Read in
* the image one scanline at a time.
*/
ImMalloc( buffer, unsigned char *, sizeof( unsigned char ) * pDim->dim_width );
pPixel = ImVfbQFirst( vfb );
Seek( imHdfDDQDataOffset( pRIG->rig_imageDD ) );
for ( i = 0; i < pDim->dim_height; i++ )
{
Read( buffer, UCHAR, 1, pDim->dim_width );
pBuffer = buffer;
for ( j = 0; j < pDim->dim_width; j++ )
{
ImVfbSIndex8( vfb, pPixel, *pBuffer++ );
ImVfbSInc( vfb, pPixel );
}
}
free( (char *)buffer );
*pVfb = vfb;
return ( 0 );
}
static int /* Returns status */
#ifdef __STDC__
imHdfVfbReadRLE8( int ioType, int fd, FILE *fp, imHdfRIG *pRIG, ImVfb **pVfb )
#else
imHdfVfbReadRLE8( ioType, fd, fp, pRIG, pVfb )
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
imHdfRIG *pRIG; /* Image group description */
ImVfb **pVfb; /* Returned VFB */
#endif
{
imHdfDim *pDim; /* Image dimension information */
ImVfb *vfb; /* New VFB */
ImVfbPtr pPixel; /* Pixel pointer */
unsigned char *buffer; /* Input buffer */
unsigned char *pBuffer; /* Pointer into input buffer */
unsigned char *pBufferEnd; /* Pointer to end of buffer */
unsigned char count; /* Run length count */
/*
* Allocate a new 8-bit index VFB.
*/
pDim = pRIG->rig_imageDim;
if ( (vfb = ImVfbAlloc( pDim->dim_width, pDim->dim_height, IMVFBINDEX8))
== IMVFBNULL )
ImErrorFatal( ImQError( ), -1, ImErrNo );
/*
* Allocate a buffer big enough for the whole image, read it in,
* then process the whole thing. This takes more memory, but we
* have no othe rway of alloating space sufficient for just one
* scanline, then reading in only that scanline.
*/
Seek( imHdfDDQDataOffset( pRIG->rig_imageDD ) );
pPixel = ImVfbQFirst( vfb );
ImMalloc( buffer, unsigned char *, sizeof( unsigned char ) * imHdfDDQDataLength( pRIG->rig_imageDD ) );
pBuffer = buffer;
pBufferEnd = buffer + imHdfDDQDataLength( pRIG->rig_imageDD );
Read( buffer, UCHAR, 1, imHdfDDQDataLength( pRIG->rig_imageDD ) );
while ( pBuffer < pBufferEnd )
{
count = *pBuffer++;
if ( !(count & 0x80) )
{
/* Take next 'count' bytes as literal. */
while ( count-- )
{
ImVfbSIndex8( vfb, pPixel, *pBuffer++ );
ImVfbSInc( vfb, pPixel );
}
continue;
}
/* Repeat next byte 'count' times. */
count &= 0x7F;
while ( count-- )
{
ImVfbSIndex8( vfb, pPixel, *pBuffer );
ImVfbSInc( vfb, pPixel );
}
pBuffer++;
}
free( (char *)buffer );
*pVfb = vfb;
return ( 0 );
}
static int /* Returns status */
#ifdef __STDC__
imHdfVfbRead32( int ioType, int fd, FILE *fp, imHdfRIG *pRIG, ImVfb **pVfb )
#else
imHdfVfbRead32( ioType, fd, fp, pRIG, pVfb )
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
imHdfRIG *pRIG; /* Image group description */
ImVfb **pVfb; /* Returned VFB */
#endif
{
imHdfDim *pDim; /* Image dimension information */
ImVfb *vfb; /* New VFB */
ImVfbPtr pPixel; /* Pixel pointer */
sdsc_uint32 *buffer; /* Input buffer */
sdsc_uint32 *pBuffer; /* Pointer into input buffer */
int i, j; /* Counters */
/*
* Allocate a new 16-bit index VFB.
*/
pDim = pRIG->rig_imageDim;
if ( (vfb = ImVfbAlloc( pDim->dim_width, pDim->dim_height,IMVFBINDEX16))
== IMVFBNULL )
ImErrorFatal( ImQError( ), -1, ImErrNo );
/*
* Allocate a buffer that is big enough for one scanline. Read in
* the image one scanline at a time.
*/
ImMalloc( buffer, sdsc_uint32 *, sizeof( sdsc_uint32 ) * pDim->dim_width );
pPixel = ImVfbQFirst( vfb );
Seek( imHdfDDQDataOffset( pRIG->rig_imageDD ) );
for ( i = 0; i < pDim->dim_height; i++ )
{
Read( buffer, UINT32, pDim->dim_channelSize, pDim->dim_width );
pBuffer = buffer;
for ( j = 0; j < pDim->dim_width; j++ )
{
/* Truncate upper bits. */
ImVfbSIndex16( vfb, pPixel, *pBuffer++ );
ImVfbSInc( vfb, pPixel );
}
}
free( (char *)buffer );
*pVfb = vfb;
return ( 0 );
}
static int /* Returns status */
#ifdef __STDC__
imHdfVfbReadRGB( int ioType, int fd, FILE *fp, imHdfRIG *pRIG, ImVfb **pVfb )
#else
imHdfVfbReadRGB( ioType, fd, fp, pRIG, pVfb )
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
imHdfRIG *pRIG; /* Image group description */
ImVfb **pVfb; /* Returned VFB */
#endif
{
imHdfDim *pDim; /* Image dimension information */
ImVfb *vfb; /* New VFB */
ImVfbPtr pPixel; /* Pixel pointer */
unsigned char *buffer; /* Input buffer */
unsigned char *pBuffer; /* Pointer into input buffer */
int i, j; /* Counters */
/*
* Allocate a new 24-bit index VFB.
*/
pDim = pRIG->rig_imageDim;
if ( (vfb = ImVfbAlloc( pDim->dim_width, pDim->dim_height, IMVFBRGB ))
== IMVFBNULL )
ImErrorFatal( ImQError( ), -1, ImErrNo );
/*
* Allocate a buffer that is big enough for one scanline. Read in
* the image one scanline at a time.
*/
pPixel = ImVfbQFirst( vfb );
Seek( imHdfDDQDataOffset( pRIG->rig_imageDD ) );
ImMalloc( buffer, unsigned char *, sizeof( unsigned char )* pDim->dim_width*3 );
for ( i = 0; i < pDim->dim_height; i++ )
{
Read( buffer, UCHAR, 1, pDim->dim_width * 3 );
pBuffer = buffer;
for ( j = 0; j < pDim->dim_width; j++ )
{
ImVfbSRed( vfb, pPixel, *pBuffer++ );
ImVfbSGreen( vfb, pPixel, *pBuffer++ );
ImVfbSBlue( vfb, pPixel, *pBuffer++ );
ImVfbSInc( vfb, pPixel );
}
}
free( (char *)buffer );
*pVfb = vfb;
return ( 0 );
}
static int /* Returns status */
#ifdef __STDC__
imHdfVfbReadRGBLine( int ioType, int fd, FILE *fp, imHdfRIG *pRIG, ImVfb **pVfb )
#else
imHdfVfbReadRGBLine( ioType, fd, fp, pRIG, pVfb )
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
imHdfRIG *pRIG; /* Image group description */
ImVfb **pVfb; /* Returned VFB */
#endif
{
imHdfDim *pDim; /* Image dimension information */
ImVfb *vfb; /* New VFB */
ImVfbPtr pPixel; /* Pixel pointer */
unsigned char *buffer; /* Input buffer */
unsigned char *pBuffer1; /* Pointer into input buffer */
unsigned char *pBuffer2; /* Pointer into input buffer */
unsigned char *pBuffer3; /* Pointer into input buffer */
int i, j; /* Counters */
/*
* Allocate a new 24-bit index VFB.
*/
pDim = pRIG->rig_imageDim;
if ( (vfb = ImVfbAlloc( pDim->dim_width, pDim->dim_height, IMVFBRGB ))
== IMVFBNULL )
ImErrorFatal( ImQError( ), -1, ImErrNo );
/*
* Allocate a buffer that is big enough for one scanline. Read in
* the image one scanline at a time.
*/
pPixel = ImVfbQFirst( vfb );
Seek( imHdfDDQDataOffset( pRIG->rig_imageDD ) );
ImMalloc( buffer, unsigned char *, sizeof( unsigned char )* pDim->dim_width*3 );
for ( i = 0; i < pDim->dim_height; i++ )
{
Read( buffer, UCHAR, 1, pDim->dim_width * 3 );
pBuffer1 = buffer;
pBuffer2 = buffer + pDim->dim_width;
pBuffer3 = pBuffer2 + pDim->dim_width;
for ( j = 0; j < pDim->dim_width; j++ )
{
ImVfbSRed( vfb, pPixel, *pBuffer1++ );
ImVfbSGreen( vfb, pPixel, *pBuffer2++ );
ImVfbSBlue( vfb, pPixel, *pBuffer3++ );
ImVfbSInc( vfb, pPixel );
}
}
free( (char *)buffer );
*pVfb = vfb;
return ( 0 );
}
static int /* Returns status */
#ifdef __STDC__
imHdfVfbReadRGBPlane( int ioType, int fd, FILE *fp, imHdfRIG *pRIG, ImVfb **pVfb )
#else
imHdfVfbReadRGBPlane( ioType, fd, fp, pRIG, pVfb )
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
imHdfRIG *pRIG; /* Image group description */
ImVfb **pVfb; /* Returned VFB */
#endif
{
imHdfDim *pDim; /* Image dimension information */
ImVfb *vfb; /* New VFB */
ImVfbPtr pPixel; /* Pixel pointer */
unsigned char *buffer; /* Input buffer */
unsigned char *pBuffer; /* Pointer into input buffer */
int i, j; /* Counters */
/*
* Allocate a new 24-bit index VFB.
*/
pDim = pRIG->rig_imageDim;
if ( (vfb = ImVfbAlloc( pDim->dim_width, pDim->dim_height, IMVFBRGB ))
== IMVFBNULL )
ImErrorFatal( ImQError( ), -1, ImErrNo );
/*
* Allocate a buffer that is big enough for one scanline. Read in
* the image one scanline at a time.
*/
Seek( imHdfDDQDataOffset( pRIG->rig_imageDD ) );
ImMalloc( buffer, unsigned char *, sizeof( unsigned char ) * pDim->dim_width );
pPixel = ImVfbQFirst( vfb );
for ( i = 0; i < pDim->dim_height; i++ )
{
Read( buffer, UCHAR, 1, pDim->dim_width );
pBuffer = buffer;
for ( j = 0; j < pDim->dim_width; j++ )
{
ImVfbSRed( vfb, pPixel, *pBuffer++ );
ImVfbSInc( vfb, pPixel );
}
}
pPixel = ImVfbQFirst( vfb );
for ( i = 0; i < pDim->dim_height; i++ )
{
Read( buffer, UCHAR, 1, pDim->dim_width );
pBuffer = buffer;
for ( j = 0; j < pDim->dim_width; j++ )
{
ImVfbSGreen( vfb, pPixel, *pBuffer++ );
ImVfbSInc( vfb, pPixel );
}
}
pPixel = ImVfbQFirst( vfb );
for ( i = 0; i < pDim->dim_height; i++ )
{
Read( buffer, UCHAR, 1, pDim->dim_width );
pBuffer = buffer;
for ( j = 0; j < pDim->dim_width; j++ )
{
ImVfbSBlue( vfb, pPixel, *pBuffer++ );
ImVfbSInc( vfb, pPixel );
}
}
free( (char *)buffer );
*pVfb = vfb;
return ( 0 );
}
static int /* Returns status */
#ifdef __STDC__
imHdfVfbReadRLERGB( int ioType, int fd, FILE *fp, imHdfRIG *pRIG, ImVfb **pVfb )
#else
imHdfVfbReadRLERGB( ioType, fd, fp, pRIG, pVfb )
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
imHdfRIG *pRIG; /* Image group description */
ImVfb **pVfb; /* Returned VFB */
#endif
{
imHdfDim *pDim; /* Image dimension information */
ImVfb *vfb; /* New VFB */
ImVfbPtr pPixel; /* Pixel pointer */
unsigned char *buffer; /* Input buffer */
unsigned char *pBufferEnd; /* Pointer to end of buffer */
unsigned char *pBuffer; /* Pointer into input buffer */
unsigned char count; /* Run length count */
int onRGB; /* Which channel are we on? */
/*
* Allocate a new 24-bit index VFB.
*/
pDim = pRIG->rig_imageDim;
if ( (vfb = ImVfbAlloc( pDim->dim_width, pDim->dim_height, IMVFBRGB ))
== IMVFBNULL )
ImErrorFatal( ImQError( ), -1, ImErrNo );
/*
* Allocate a buffer big enough for the whole image, read it in,
* then process the whole thing. This takes more memory, but we
* have no othe rway of alloating space sufficient for just one
* scanline, then reading in only that scanline.
*/
Seek( imHdfDDQDataOffset( pRIG->rig_imageDD ) );
pPixel = ImVfbQFirst( vfb );
ImMalloc( buffer, unsigned char *, sizeof( unsigned char ) *
imHdfDDQDataLength( pRIG->rig_imageDD ) );
pBuffer = buffer;
pBufferEnd = buffer + imHdfDDQDataLength( pRIG->rig_imageDD );
Read( buffer, UCHAR, 1, imHdfDDQDataLength( pRIG->rig_imageDD ) );
onRGB = RED;
while ( pBuffer < pBufferEnd )
{
count = *pBuffer++;
if ( !(count & 0x80) )
{
/* Take next 'count' bytes as literal. */
while ( count-- )
{
switch ( onRGB )
{
case RED:
ImVfbSRed( vfb, pPixel, *pBuffer++ );
onRGB = GREEN;
continue;
case GREEN:
ImVfbSGreen( vfb, pPixel, *pBuffer++ );
onRGB = BLUE;
continue;
case BLUE:
ImVfbSBlue( vfb, pPixel, *pBuffer++ );
ImVfbSInc( vfb, pPixel );
onRGB = RED;
continue;
}
}
continue;
}
/* Repeat next byte 'count' times. */
count &= 0x7F;
while ( count-- )
{
switch ( onRGB )
{
case RED:
ImVfbSRed( vfb, pPixel, *pBuffer );
onRGB = GREEN;
continue;
case GREEN:
ImVfbSGreen( vfb, pPixel, *pBuffer );
onRGB = BLUE;
continue;
case BLUE:
ImVfbSBlue( vfb, pPixel, *pBuffer );
ImVfbSInc( vfb, pPixel );
onRGB = RED;
continue;
}
}
pBuffer++;
}
free( (char *)buffer );
*pVfb = vfb;
return ( 0 );
}
static int /* Returns status */
#ifdef __STDC__
imHdfVfbReadRLERGBLine( int ioType, int fd, FILE *fp, imHdfRIG *pRIG, ImVfb **pVfb )
#else
imHdfVfbReadRLERGBLine( ioType, fd, fp, pRIG, pVfb )
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
imHdfRIG *pRIG; /* Image group description */
ImVfb **pVfb; /* Returned VFB */
#endif
{
imHdfDim *pDim; /* Image dimension information */
ImVfb *vfb; /* New VFB */
ImVfbPtr pPixel; /* Pixel pointer */
ImVfbPtr pPixelStart; /* Start of scanline */
unsigned char *buffer; /* Input buffer */
unsigned char *pBufferEnd; /* Pointer to end of buffer */
unsigned char *pBuffer; /* Pointer into input buffer */
unsigned char count; /* Run length count */
int onRGB; /* Which channel are we on? */
int i, j; /* Counters */
/*
* Allocate a new 24-bit index VFB.
*/
pDim = pRIG->rig_imageDim;
if ( (vfb = ImVfbAlloc( pDim->dim_width, pDim->dim_height, IMVFBRGB ))
== IMVFBNULL )
ImErrorFatal( ImQError( ), -1, ImErrNo );
/*
* Allocate a buffer big enough for the whole image, read it in,
* then process the whole thing. This takes more memory, but we
* have no othe rway of alloating space sufficient for just one
* scanline, then reading in only that scanline.
*/
Seek( imHdfDDQDataOffset( pRIG->rig_imageDD ) );
pPixel = ImVfbQFirst( vfb );
ImMalloc( buffer, unsigned char *, sizeof( unsigned char ) *
imHdfDDQDataLength( pRIG->rig_imageDD ) );
pBuffer = buffer;
pBufferEnd = buffer + imHdfDDQDataLength( pRIG->rig_imageDD );
Read( buffer, UCHAR, 1, imHdfDDQDataLength( pRIG->rig_imageDD ) );
/*
* This algorithm is made slower by the possibility that a run
* from one scanline extends into the next one (ie, a run at the
* end of the RED channel flows into the GREEN channel). SDSC
* tools end scanline interleaved runs at the end of a channel's
* scanline. The HDF spec, however, makes no such guarantee.
*/
onRGB = RED;
i = 0;
pPixelStart = pPixel;
while ( pBuffer < pBufferEnd )
{
count = *pBuffer++;
if ( !(count & 0x80) )
{
/* Take next 'count' bytes as literal. */
while ( count-- )
{
switch ( onRGB )
{
case RED:
ImVfbSRed( vfb, pPixel, *pBuffer++ );
ImVfbSInc( vfb, pPixel );
if ( ++i >= pDim->dim_width )
{
onRGB = GREEN;
i = 0;
pPixel = pPixelStart;
}
continue;
case GREEN:
ImVfbSGreen( vfb, pPixel, *pBuffer++ );
ImVfbSInc( vfb, pPixel );
if ( ++i >= pDim->dim_width )
{
onRGB = BLUE;
i = 0;
pPixel = pPixelStart;
}
continue;
case BLUE:
ImVfbSBlue( vfb, pPixel, *pBuffer++ );
ImVfbSInc( vfb, pPixel );
if ( ++i >= pDim->dim_width )
{
onRGB = RED;
i = 0;
pPixelStart = pPixel;
}
continue;
}
}
continue;
}
/* Repeat next byte 'count' times. */
count &= 0x7F;
while ( count-- )
{
switch ( onRGB )
{
case RED:
ImVfbSRed( vfb, pPixel, *pBuffer );
ImVfbSInc( vfb, pPixel );
if ( ++i >= pDim->dim_width )
{
onRGB = GREEN;
i = 0;
pPixel = pPixelStart;
}
continue;
case GREEN:
ImVfbSGreen( vfb, pPixel, *pBuffer );
ImVfbSInc( vfb, pPixel );
if ( ++i >= pDim->dim_width )
{
onRGB = BLUE;
i = 0;
pPixel = pPixelStart;
}
continue;
case BLUE:
ImVfbSBlue( vfb, pPixel, *pBuffer );
ImVfbSInc( vfb, pPixel );
if ( ++i >= pDim->dim_width )
{
onRGB = RED;
i = 0;
pPixelStart = pPixel;
}
continue;
}
}
pBuffer++;
}
free( (char *)buffer );
*pVfb = vfb;
return ( 0 );
}
static int /* Returns status */
#ifdef __STDC__
imHdfVfbReadRLERGBPlane( int ioType, int fd, FILE *fp, imHdfRIG *pRIG, ImVfb **pVfb )
#else
imHdfVfbReadRLERGBPlane( ioType, fd, fp, pRIG, pVfb )
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
imHdfRIG *pRIG; /* Image group description */
ImVfb **pVfb; /* Returned VFB */
#endif
{
imHdfDim *pDim; /* Image dimension information */
ImVfb *vfb; /* New VFB */
ImVfbPtr pPixel; /* Pixel pointer */
unsigned char *buffer; /* Input buffer */
unsigned char *pBufferEnd; /* Pointer to end of buffer */
unsigned char *pBuffer; /* Pointer into input buffer */
unsigned char count; /* Run length count */
int i, j; /* Counters */
/*
* Allocate a new 24-bit index VFB.
*/
pDim = pRIG->rig_imageDim;
if ( (vfb = ImVfbAlloc( pDim->dim_width, pDim->dim_height, IMVFBRGB ))
== IMVFBNULL )
ImErrorFatal( ImQError( ), -1, ImErrNo );
/*
* Allocate a buffer big enough for the whole image, read it in,
* then process the whole thing. This takes more memory, but we
* have no othe rway of alloating space sufficient for just one
* scanline, then reading in only that scanline.
*/
Seek( imHdfDDQDataOffset( pRIG->rig_imageDD ) );
ImMalloc( buffer, unsigned char *, sizeof( unsigned char ) *
imHdfDDQDataLength( pRIG->rig_imageDD ) );
pBuffer = buffer;
pBufferEnd = buffer + imHdfDDQDataLength( pRIG->rig_imageDD );
Read( buffer, UCHAR, 1, imHdfDDQDataLength( pRIG->rig_imageDD ) );
j = pDim->dim_width * pDim->dim_height;
i = 0;
pPixel = ImVfbQFirst( vfb );
while ( pBuffer < pBufferEnd && i < j )
{
count = *pBuffer++;
if ( !(count & 0x80) )
{
/* Take next 'count' bytes as literal. */
i += count;
while ( count-- )
{
ImVfbSRed( vfb, pPixel, *pBuffer++ );
ImVfbSInc( vfb, pPixel );
}
continue;
}
/* Repeat next byte 'count' times. */
count &= 0x7F;
i += count;
while ( count-- )
{
ImVfbSRed( vfb, pPixel, *pBuffer );
ImVfbSInc( vfb, pPixel );
}
pBuffer++;
}
i = 0;
pPixel = ImVfbQFirst( vfb );
while ( pBuffer < pBufferEnd && i < j )
{
count = *pBuffer++;
if ( !(count & 0x80) )
{
/* Take next 'count' bytes as literal. */
i += count;
while ( count-- )
{
ImVfbSGreen( vfb, pPixel, *pBuffer++ );
ImVfbSInc( vfb, pPixel );
}
continue;
}
/* Repeat next byte 'count' times. */
count &= 0x7F;
i += count;
while ( count-- )
{
ImVfbSGreen( vfb, pPixel, *pBuffer );
ImVfbSInc( vfb, pPixel );
}
pBuffer++;
}
i = 0;
pPixel = ImVfbQFirst( vfb );
while ( pBuffer < pBufferEnd && i < j )
{
count = *pBuffer++;
if ( !(count & 0x80) )
{
/* Take next 'count' bytes as literal. */
i += count;
while ( count-- )
{
ImVfbSBlue( vfb, pPixel, *pBuffer++ );
ImVfbSInc( vfb, pPixel );
}
continue;
}
/* Repeat next byte 'count' times. */
count &= 0x7F;
i += count;
while ( count-- )
{
ImVfbSBlue( vfb, pPixel, *pBuffer );
ImVfbSInc( vfb, pPixel );
}
pBuffer++;
}
free( (char *)buffer );
*pVfb = vfb;
return ( 0 );
}