jedi-outcast/utils/roq2/libim/imhdfwrite.c

3285 lines
49 KiB
C

/**
** $Header: /roq/libim/imhdfwrite.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/imhdfwrite.c 1 11/02/99 4:38p Zaphod $"
/**
** FILE
** imhdfwrite.c - HDF image file write
**
** PROJECT
** libim - SDSC image manipulation library
**
** DESCRIPTION
** imhdf.c contains routines to write HDF image files for
** the image manipulation library. Raster data written
** out is taken from a tag table.
**
** PUBLIC CONTENTS
** d =defined constant
** f =function
** m =defined macro
** t =typedef/struct/union
** v =variable
** ? =other
**
** ImHdfWrite f write an HDF file
**
** PRIVATE CONTENTS
** 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
**
** imHdfWrite f handle the writing of an HDF file
** imHdfDimWrite f write dimension tag to file
** imHdfCltWrite f write CLT to file
** imHdfVfbWrite f write VFB to file
**
** imHdfVfbWrite8 f write 8-bit uncomp. VFB
** imHdfVfbWriteRLE8 f write 8-bit RLE comp. VFB
** imHdfVfbWrite16 f write 16-bit uncomp. VFB
** imHdfVfbWriteRGB f write 24-bit uncomp. uninterleaved VFB
** imHdfVfbWriteRGBLine f write 24-bit uncomp. line interleaved VFB
** imHdfVfbWriteRGBPlan f write 24-bit uncomp. plane interleaved VFB
** imHdfVfbWriteRLERGB f write 24-bit RLE comp. uninterleaved VFB
** imHdfVfbWriteRLERGBLine f write 24-bit RLE comp. line interleaved VFB
** imHdfVfbWriteRLERGBPlane f write 24-bit RLE comp. plane interleaved VFB
**
** HISTORY
** $Log: /roq/libim/imhdfwrite.c $
*
* 1 11/02/99 4:38p Zaphod
** Revision 1.10 1995/06/29 00:28:04 bduggan
** updated copyright year
**
** Revision 1.9 1994/10/03 11:30:12 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.8 93/02/18 18:10:25 secoskyj
** Fixed carriage return being output before Image: output
** message.
**
** Revision 1.7 92/12/03 01:48:40 nadeau
** Corrected info messages.
**
** Revision 1.6 92/11/23 18:42:31 nadeau
** Removed use of IMINFOMSG.
**
** Revision 1.5 92/11/04 11:58:08 groening
** made minor changes in iminfo
**
** Revision 1.4 92/10/19 14:14:47 groening
** added ImInfo statements
**
** Revision 1.3 92/09/02 13:15:05 vle
** Updated copyright notice.
**
** Revision 1.2 92/04/09 09:34:58 groening
** To make the compiler happy added extern statements.
**
** Revision 1.1 91/10/03 09:05:31 nadeau
** Initial revision
**
**
**/
#include "iminternal.h"
#include "imhdfinternal.h"
/**
** CODE CREDITS
** Custom development, Dave Nadeau, San Diego Supercomputer Center, 1992.
**/
/*
* Function declarations, since they return longs, rather than
* integers. This caused a problem on a Cray.
*/
#ifdef __STDC__
static long imHdfVfbWrite8( int ioType, int fd, FILE *fp, ImVfb *vfb );
static long imHdfVfbWriteRLE8(int ioType, int fd, FILE *fp, ImVfb *vfb);
static long imHdfVfbWrite16(int ioType, int fd, FILE *fp, ImVfb *vfb);
static long imHdfVfbWriteRGB(int ioType, int fd, FILE *fp, ImVfb *vfb);
static long imHdfVfbWriteRGBLine(int ioType, int fd, FILE *fp, ImVfb *vfb);
static long imHdfVfbWriteRGBPlane(int ioType, int fd, FILE *fp, ImVfb *vfb);
static long imHdfVfbWriteRLERGB(int ioType, int fd, FILE *fp, ImVfb *vfb);
static long imHdfVfbWriteRLERGBLine(int ioType, int fd, FILE *fp, ImVfb *vfb);
static long imHdfVfbWriteRLERGBPlane(int ioType, int fd, FILE *fp, ImVfb *vfb);
static int imHdfCltWrite( int ioType, int fd, FILE *fp, ImClt *clt );
static int imHdfVfbWrite( int ioType, int fd, FILE *fp, int interRequest, int compRequest, int cltRequest,
int alphaRequest, ImVfb *vfb );
#else
static long imHdfVfbWrite8();
static long imHdfVfbWriteRLE8();
static long imHdfVfbWrite16();
static long imHdfVfbWriteRGB();
static long imHdfVfbWriteRGBLine();
static long imHdfVfbWriteRGBPlane();
static long imHdfVfbWriteRLERGB();
static long imHdfVfbWriteRLERGBLine();
static long imHdfVfbWriteRLERGBPlane();
static int imHdfCltWrite();
static int imHdfVfbWrite();
#endif
/*
* FORMAT
* HDF - Hierarchical Data Format
*
* DESCRIPTION
* See imhdfread.c.
*/
/*
* FUNCTION
* ImHdfWrite - write an HDF file
*
* DESCRIPTION
* ImHdfWrite() walks the tag table and writes out CLT's and VFB's it
* finds there. Because more than one VFB can use the same CLT, we'd
* like to avoid writing out the same CLT more than once. CLT's are
* added to a CLT list. As each new VFB is encountered, the CLT list
* is checked to see if we've already written out its CLT. If so,
* we just point to it. Otherwise that VFB's CLT is written out and
* added to the list.
*
* After a VFB has been written out, a raster image group (RIG) is
* created for all of the tags related to the image.
*
* As each new tag is written to the file, it is also added to a DD list.
* When we're done, the DD list is written out as a DD block and we go
* back and patch up the DD header at the top of the file to make it
* point to the DD block at the end of the file.
*
* The tags written to the file are as follows (but not in this order):
*
* NCSA For
* tools Image
* Tag output? Depths? Meaning
*
* MT yes all Machine characteristics
*
* RIG yes all Raster image group tag list
*
* RI yes all Raster image (uncompressed)
* CI yes all Compressed image
* ID yes all Image dimensions
* NT yes all Channel size/type
* RLE no all Flag RLE compression scheme
* CFM no all Color format
*
* LUT yes 8-bit CLT
* LD no 8-bit CLT dimensions
*
* RI8 yes 8-bit Raster image (uncompressed)
* CI8 yes 8-bit Compressed image
* ID8 yes 8-bit Image dimensions
* IP8 yes 8-bit CLT
*
* Note: some of the tags we output are standard tags that the HDF
* spec states should be written, yet the NCSA tools and NCSA HDF
* library doesn't normally write them.
*/
int /* Returns # of tags written */
#ifdef __STDC__
ImHdfWrite( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable )
#else
ImHdfWrite( pMap, ioType, fd, fp, flagsTable, tagTable )
ImFileFormatWriteMap *pMap; /* Write map entry to adhear to */
int ioType; /* I/O flags */
int fd; /* Output file descriptor */
FILE *fp; /* Output file pointer */
TagTable *flagsTable; /* Format flags */
TagTable *tagTable; /* Tag list to add to */
#endif
{
sdsc_uint16 nDD; /* # of DD's in block */
imHdfDD *pDD; /* DD list pointer */
unsigned char buffer[1024]; /* Temporary write buffer */
unsigned int tag; /* DD tag */
unsigned int ref; /* DD reference number */
long dataOffset; /* Offset to data */
long dataLength; /* Length of data */
BinMachineInfo *machine; /* Machine information */
ImClt *clt; /* CLT pointer */
ImVfb *vfb; /* VFB pointer */
char *s; /* Tag name string */
long offset; /* File offset to next DD header*/
int nTag = 0; /* # of tags written */
int n; /* # of tag table entries */
int i; /* Counter */
TagEntry *tagEntry; /* Tag table entry holder */
int interRequest; /* Interleave request */
int compRequest; /* Compression request */
int cltRequest; /* CLT request */
int alphaRequest; /* Alpha plane request */
int imageNum; /* number of vfb's in tagtable */
int imageNumII; /* number of vfb's in tagtable */
char message[100]; /* ImInfo message */
/*
* Get the requests from the flags table.
*/
interRequest = IMINTERPLANE;
compRequest = IMCOMPRLE;
cltRequest = IMCLTYES;
alphaRequest = IMALPHAYES;
if ( flagsTable != TAGTABLENULL )
{
tagEntry = TagTableQDirect( flagsTable, "image interleave request", 0 );
if ( tagEntry != TAGENTRYNULL )
TagEntryQValue( tagEntry, &interRequest );
/* interRequest is guaranteed to be one we can support. */
tagEntry = TagTableQDirect( flagsTable, "image compression request", 0 );
if ( tagEntry != TAGENTRYNULL )
TagEntryQValue( tagEntry, &compRequest );
/* compRequest is guaranteed to be one we can support. */
tagEntry = TagTableQDirect( flagsTable, "image clt request", 0 );
if ( tagEntry != TAGENTRYNULL )
TagEntryQValue( tagEntry, &cltRequest );
/* cltRequest is guaranteed to be one we can support. */
tagEntry = TagTableQDirect( flagsTable, "image alpha request", 0 );
if ( tagEntry != TAGENTRYNULL )
TagEntryQValue( tagEntry, &alphaRequest );
/* alphaRequest is guaranteed to be one we can support. */
}
/*
* All administrative stuff (tags, reference counts, file offsets)
* are in MBF byte order.
*/
BinByteOrder( BINMBF );
/*
* Write the magic number.
*/
buffer[0] = 0x0E; /* CTRL-N */
buffer[1] = 0x03; /* CTRL-C */
buffer[2] = 0x13; /* CTRL-S */
buffer[3] = 0x01; /* CTRL-A */
Write( buffer, UCHAR, 1, 4 );
/*
* Write out an initial data block with one DD (data descriptor)
* describing the machine type (MT tag). The rest of the data
* for the file will be listed in another DD placed at the end of
* the file. When we're done, we'll come back to this block and
* update its offset to point to that final DD.
*/
nDD = 1; /* 1 DD in this block */
Write( &nDD, UINT16, 2, 1 );
offset = 0; /* Filled in later */
Write( &offset, LONG, 4, 1 );
tag = IMHDFTMT; /* MT = machine type */
dataOffset = 0; /* No data */
dataLength = 0; /* No data */
machine = BinQMachine( );
ref = 0;
imHdfByteOrder = machine->bin_byteOrder;
switch ( machine->bin_byteOrder )
{
case BINLBF: /* Least-significant byte first */
ImInfo ("Byte Order","Least Significant Byte First");
ref = (IMHDFINTVBO<<12); /* unsigned ints are Vax bo */
break;
case BINMBF: /* Most-significant byte first */
ImInfo ("Byte Order","Most Significant Byte First");
ref = (IMHDFINTMBO<<12); /* unsigned ints are Motorola bo*/
break;
}
imHdfFloatFormat = machine->bin_floatFormat;
switch ( machine->bin_floatFormat )
{
case BINIEEE: /* IEEE floats and doubles */
if ( machine->bin_byteOrder == BINMBF )
ref |= (IMHDFFLOATIEEE<<8) | (IMHDFFLOATIEEE<<4);
else
ref |= (IMHDFFLOATPC<<8) | (IMHDFFLOATPC<<4);
break;
case BINVAX: /* Vax floats and doubles */
ref |= (IMHDFFLOATVAX<<8) | (IMHDFFLOATVAX<<4);
break;
case BINCRAYMP: /* Cray floats and doubles */
ref |= (IMHDFFLOATCRAY<<8) | (IMHDFFLOATCRAY<<4);
break;
}
ref |= IMHDFCHARASCII; /* unsigned chars are in ASCII */
Write( &tag, UINT, 2, 1 );
Write( &ref, UINT, 2, 1 );
Write( &dataOffset, LONG, 4, 1 );
Write( &dataLength, LONG, 4, 1 );
/*
* Walk the tag table, watching for CLT's and VFB's.
*/
BinByteOrder( imHdfByteOrder );
BinFloatFormat( imHdfFloatFormat );
n = TagTableQNEntry( tagTable, NULL );
imHdfDDEmpty( );
imHdfRef = 100;
/* count number of vfb's */
imageNum=0;
imageNumII=1;
for ( i = 0; i < n; i++, imHdfRef += 5 )
{
tagEntry = TagTableQLinear( tagTable, i );
s = TagEntryQTag( tagEntry );
if ( strcmp( s, "image vfb" ) == 0 ) imageNum++;
}
for ( i = 0; i < n; i++, imHdfRef += 5 )
{
tagEntry = TagTableQLinear( tagTable, i );
s = TagEntryQTag( tagEntry );
if ( (cltRequest == IMCLTYES) && strcmp( s, "image clt" ) == 0 )
{
TagEntryQValue( tagEntry, &clt );
if ( (nTag += imHdfCltWrite( ioType, fd, fp, clt ))== -1)
return ( -1 ); /* Error already posted */
}
if ( strcmp( s, "image vfb" ) == 0 )
{
sprintf (message, "%d of %d",imageNumII++,imageNum);
ImInfo ("Image",message);
TagEntryQValue( tagEntry, &vfb );
if ( (nTag += imHdfVfbWrite( ioType, fd, fp,
interRequest, compRequest, cltRequest,
alphaRequest, vfb ))== -1)
return ( -1 ); /* Error already posted */
}
/*
* Ignore all other tags.
*/
}
/*
* Write out the DD list, preceded by its header.
*/
BinByteOrder( BINMBF );
offset = Tell( );
nDD = imHdfDDQNEntry( );
dataOffset = 0; /* End of header list */
Write( &nDD, UINT16, 2, 1 );
Write( &dataOffset, LONG, 4, 1 );
for ( pDD = imHdfDDQFirst( ); pDD; pDD = imHdfDDQNext( pDD ) )
{
tag = imHdfDDQTag( pDD );
ref = imHdfDDQRef( pDD );
dataOffset = imHdfDDQDataOffset( pDD );
dataLength = imHdfDDQDataLength( pDD );
Write( &tag, UINT, 2, 1 );
Write( &ref, UINT, 2, 1 );
Write( &dataOffset, LONG, 4, 1 );
Write( &dataLength, LONG, 4, 1 );
}
/*
* Seek back to the first DD header nad change its offset pointer
* to point to the new DD header we just added at the end of the file.
*/
Seek( 4 + 2 ); /* Seek to 6th byte */
Write( &offset, LONG, 4, 1 );
return ( nTag );
}
/*
* FUNCTION
* imHdfDimWrite - write dimension tag to file
*
* DESCRIPTION
* Tags describing a dimension are written out:
*
* NT numeric type
* RLE compression scheme
*
* The dimension tag's data itself is also written out.
*/
static long /* Returns file offset */
#ifdef __STDC__
imHdfDimWrite( int ioType, int fd, FILE *fp, int tag, imHdfDim *pDim )
#else
imHdfDimWrite( ioType, fd, fp, tag, pDim )
int ioType; /* I/O flags */
int fd; /* Output file descriptor */
FILE *fp; /* Output file pointer */
int tag; /* Tag type */
imHdfDim *pDim; /* Dimension information */
#endif
{
long offset; /* File offset */
unsigned char nt[4]; /* NT buffer */
sdsc_uint16 tmpTag; /* Temp tag holder */
sdsc_uint16 tmpRef; /* Temp ref holder */
/*
* Write out an NT tag's data describing the type for a channel.
*
* 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)
*/
offset = Tell( );
nt[0] = 1; /* Version 1 */
if ( pDim->dim_channelType == UINT )
{
nt[1] = IMHDFNTUINT;
if ( pDim->dim_channelByteOrder == BINLBF )
nt[3] = IMHDFINTVBO;
else
nt[3] = IMHDFINTMBO;
}
else
{
nt[1] = IMHDFNTUCHAR;
nt[3] = IMHDFCHARBYTE; /* bitwise numeric */
}
nt[2] = pDim->dim_channelSize * 8;
Write( nt, UCHAR, 1, 4 );
if ( tag == IMHDFTID )
tmpRef = imHdfRef;
else
tmpRef = imHdfRef + 1;
imHdfDDAppend( IMHDFTNT, tmpRef, offset, 4 );
/*
* Add a no-data RLE tag if we are doing compression.
*/
if ( pDim->dim_compression == IMHDFTRLE )
imHdfDDAppend( IMHDFTRLE, imHdfRef, 0, 0 );
/*
* Write out the dimension tag.
*/
offset = Tell( );
tmpTag = IMHDFTNT;
Write( &pDim->dim_width, INT, 4, 1 );
Write( &pDim->dim_height, INT, 4, 1 );
Write( &tmpTag, UINT16, 2, 1 );
Write( &tmpRef, UINT16, 2, 1 );
Write( &pDim->dim_pixelSize, INT, 2, 1 );
Write( &pDim->dim_interleave, INT, 2, 1 );
Write( &pDim->dim_compression, UINT, 2, 1 );
if ( pDim->dim_compression == 0 )
{
tmpRef = 0;
Write( &tmpRef, UINT16, 2, 1 );
}
else
Write( &imHdfRef, UINT16, 2, 1 );
imHdfDDAppend( tag, imHdfRef, offset, 20 );
return ( 0 );
}
/*
* FUNCTION
* imHdfCltWrite - write CLT to file
*
* DESCRIPTION
* Tags describing a CLT are written out:
*
* LD lookup table dimensions
* LUT lookup table
* IP8 8-bit lookup table (if 256 or fewer CLT entries)
*
* The CLT is written out uncompressed and uninterleaved.
*/
static int /* Returns # of tags written */
#ifdef __STDC__
imHdfCltWrite( int ioType, int fd, FILE *fp, ImClt *clt )
#else
imHdfCltWrite( ioType, fd, fp, clt )
int ioType; /* I/O flags */
int fd; /* Output file descriptor */
FILE *fp; /* Output file pointer */
ImClt *clt; /* CLT to write out */
#endif
{
imHdfDim dim; /* Dimensions of CLT */
long offset; /* tag data offset */
int i; /* Counter */
ImCltPtr pColor; /* CLT color pointer */
unsigned char *buffer; /* RGB buffer */
int n; /* # of colors */
/*
* Write out an LD dimensions tag.
* Width is # of colors
* Height is always 1
* Each channel is a unsigned char (byte order & float format unused)
* 3 channels per pixel (RGB)
* CLT not interleaved or compressed
*/
dim.dim_width = n = ImCltQNColors( clt );
dim.dim_height = 1;
dim.dim_channelType = UCHAR;
dim.dim_channelSize = 1;
dim.dim_channelByteOrder = imHdfByteOrder;
dim.dim_channelFloatFormat = imHdfFloatFormat;
dim.dim_pixelSize = 3;
dim.dim_interleave = 0;
dim.dim_compression = 0;
if ( imHdfDimWrite( ioType, fd, fp, IMHDFTLD, &dim ) == -1 )
return ( -1 ); /* Error stuff already handled */
/*
* Write out the CLT, not interleaved or compressed.
*/
offset = Tell( );
n *= 3;
if ( n < 256*3 )
{
ImMalloc( buffer, unsigned char *, sizeof( unsigned char ) * 256 * 3 );
}
else
{
ImMalloc( buffer, unsigned char *, sizeof( unsigned char ) * n );
}
pColor = ImCltQFirst( clt );
for ( i = 0; i < n; )
{
buffer[i++] = ImCltQRed( pColor );
buffer[i++] = ImCltQGreen( pColor );
buffer[i++] = ImCltQBlue( pColor );
ImCltSInc( clt, pColor );
}
if ( dim.dim_width <= 256 )
{
/*
* With CLT's of 256 entries or less, we can support the
* IP8 tag. However, IP8 palettes must be 256 entries
* long. So, we pad the CLT with enough zero entries to
* make it the right size.
*
* The LD tag, which allows arbitrary CLT lengths, will only
* report the number of entries filled with real data, not
* our pad entries.
*
* The IP8 tag, which assumes 256 CLT entries, will have
* a data length that includes the pad entries.
*
* The LUT tag, which allows any CLT length, will have a
* data length that does not include the pad entries.
*/
while ( i < 256*3 )
{
buffer[i++] = 0;
buffer[i++] = 0;
buffer[i++] = 0;
}
imHdfDDAppend( IMHDFTIP8, imHdfRef, offset, 256 * 3 );
Write( buffer, UCHAR, 1, 256 * 3 );
}
else
Write( buffer, UCHAR, 1, n );
free( (char *)buffer );
imHdfDDAppend( IMHDFTLUT, imHdfRef, offset, n );
imHdfCltAppend( clt, imHdfRef, imHdfRef );
return ( 1 ); /* Wrote CLT from tag table */
}
/*
* FUNCTION
* imHdfVfbWrite - write VFB to file
*
* DESCRIPTION
* The tags associated with a VFB are written out:
*
* ID image dimensions
* RI raster image
* CI compressed raster image
* RLE run-length encoded
* CFM color format
* RIG raster image group
*
* The image is written out as either a compressed or uncompressed
* image, uninterleaved, scanline interleaved, or plane interleaved,
* all as selected by the interRequest from the flagsTable.
*/
static int /* Returns # of tags written */
#ifdef __STDC__
imHdfVfbWrite( int ioType, int fd, FILE *fp, int interRequest, int compRequest, int cltRequest, int alphaRequest, ImVfb *vfb )
#else
imHdfVfbWrite( ioType, fd, fp, interRequest, compRequest, cltRequest, alphaRequest, vfb )
int ioType; /* I/O flags */
int fd; /* Output file descriptor */
FILE *fp; /* Output file pointer */
int interRequest; /* Interleave request */
int compRequest; /* Compression request */
int cltRequest; /* CLT channel request */
int alphaRequest; /* Alpha channel request */
ImVfb *vfb; /* VFB to write out */
#endif
{
int i; /* Counter */
imHdfDim dim; /* Dimensions of VFB */
ImVfbPtr pPixel; /* VFB pixel pointer */
ImClt *clt; /* VFB's CLT */
imHdfClt *hdfClt; /* CLT list entry */
int n; /* # of colors */
long offset; /* tag data offset */
unsigned int fields; /* Field mask */
int nTag = 0; /* # of tags written */
unsigned char *buffer; /* RGB buffer */
int nRIG = 0; /* # of items in the RIG */
unsigned int tagList[50]; /* RIG tags */
unsigned int refList[50]; /* RIG refs */
TagEntry *tagEntry; /* Tag table entry holder */
char message[100]; /* ImInfo message */
/*
* If the VFB has a CLT, look it up in the CLT list to see if it
* has already been written out.
*/
if ( (cltRequest == IMCLTYES) && (clt = ImVfbQClt( vfb )) != IMCLTNULL )
{
if ( (hdfClt = imHdfCltFind( clt )) == NULL )
{
sprintf (message, "%d Entries", ImCltQNColors (clt));
ImInfo ("Color Table",message);
/*
* Not already written. Write it and add it to the
* written CLT list.
*/
if ( (nTag = imHdfCltWrite( ioType, fd, fp, clt ))== -1)
return ( -1 ); /* Error already posted */
hdfClt = imHdfCltFind( clt );
}
tagList[nRIG] = IMHDFTLD;
refList[nRIG++] = imHdfCltQRefLD( hdfClt );
tagList[nRIG] = IMHDFTLUT;
refList[nRIG++] = imHdfCltQRefLUT( hdfClt );
}
/*
* Write out an ID dimensions tag.
* Width and height of image
* Each channel is a unsigned char (RGB & INDEX8) or a unsigned int (INDEX16)
* Machine's byte order and float format
* 3 channels per pixel (RGB) or 1 per pixel (INDEX8 & INDEX16)
* Uninterleaved, scanline interleaved, or plane interleaved
* Compressed or uncompressed
*/
dim.dim_width = ImVfbQWidth( vfb );
dim.dim_height = ImVfbQHeight( vfb );
dim.dim_channelByteOrder = imHdfByteOrder;
dim.dim_channelFloatFormat = imHdfFloatFormat;
fields = ImVfbQFields( vfb );
if ( fields & IMVFBINDEX8 )
{
dim.dim_channelType= UCHAR;
dim.dim_pixelSize = 1;
dim.dim_channelSize= 1;
}
else if ( fields & IMVFBINDEX16 )
{
dim.dim_channelType= UINT;
dim.dim_pixelSize = 1;
clt = ImVfbQClt( vfb );
if ( clt != IMCLTNULL )
{
n = ImCltQNColors( clt );
if ( n < 256 ) /* 8-bit */
dim.dim_channelSize = 1;
else if ( n < 65536 ) /* 16-bit */
dim.dim_channelSize = 2;
else if ( n < 16777216 ) /* 24-bit */
dim.dim_channelSize = 3;
else /* 32-bit */
dim.dim_channelSize = 4;
}
else
dim.dim_channelSize = 4;
}
else
{
/* RGB */
dim.dim_channelType = UCHAR;
dim.dim_pixelSize = 3;
dim.dim_channelSize= 1;
}
if ( dim.dim_pixelSize == 1 )
dim.dim_interleave = 0; /* Can't interleave indexes*/
else if ( interRequest == IMINTERLINE )
dim.dim_interleave = 1; /* Scanline interleaved */
else if ( interRequest == IMINTERPLANE )
dim.dim_interleave = 2; /* Plane interleaved */
else
dim.dim_interleave = 0; /* Uninterleaved */
if ( (dim.dim_channelType != UINT) && (compRequest == IMCOMPRLE) )
dim.dim_compression= IMHDFTRLE; /* RLE compression */
else
dim.dim_compression= 0; /* No compression */
if ( imHdfDimWrite( ioType, fd, fp, IMHDFTID, &dim ) == -1 )
return ( -1 ); /* Error stuff already handled */
tagList[nRIG] = IMHDFTID;
refList[nRIG++] = imHdfRef;
/*
* If the image is an 8-bit image, write out an ID8 tag.
*/
if ( fields & IMVFBINDEX8 )
{
offset = Tell( );
Write( &dim.dim_width, INT, 2, 1 );
Write( &dim.dim_height, INT, 2, 1 );
imHdfDDAppend( IMHDFTID8, imHdfRef, offset, 4 );
}
/*
* Write out the color format used
*/
if ( dim.dim_pixelSize == 1 ) /* 8-bit and 16-bit indexes*/
{
offset = Tell( );
Write( "VALUE", CHAR, 1, 7 );
imHdfDDAppend( IMHDFTCFM, imHdfRef, offset, 7 );
tagList[nRIG] = IMHDFTCFM;
refList[nRIG++] = imHdfRef;
}
else
{
offset = Tell( );
Write( "RGB", CHAR, 1, 4 );
imHdfDDAppend( IMHDFTCFM, imHdfRef, offset, 4 );
tagList[nRIG] = IMHDFTCFM;
refList[nRIG++] = imHdfRef;
}
sprintf (message, "%d x %d",dim.dim_width, dim.dim_height);
ImInfo ("Resolution", message);
/*
* Write out the VFB.
*/
offset = Tell( );
if ( fields & IMVFBINDEX8 )
{
switch ( dim.dim_compression )
{
case 0: /* No compression. */
ImInfo ("Type","8-bit Color Indexed");
ImInfo ("Compression Type","none");
if ( (n = imHdfVfbWrite8( ioType, fd, fp, vfb )) == -1 )
return ( -1 ); /* Errors already handled*/
imHdfDDAppend( IMHDFTRI8, imHdfRef, offset, n );
imHdfDDAppend( IMHDFTRI, imHdfRef, offset, n );
tagList[nRIG] = IMHDFTRI;
refList[nRIG++] = imHdfRef;
break;
case IMHDFTRLE: /* Run-length encoding */
ImInfo ("Type","8-bit Color Indexed");
ImInfo ("Compression Type","Run Length Encoded (RLE)");
if ( (n = imHdfVfbWriteRLE8( ioType, fd, fp, vfb )) == -1 )
return ( -1 ); /* Errors already handled*/
imHdfDDAppend( IMHDFTCI8, imHdfRef, offset, n );
imHdfDDAppend( IMHDFTCI, imHdfRef, offset, n );
tagList[nRIG] = IMHDFTCI;
refList[nRIG++] = imHdfRef;
break;
}
}
else if ( fields & IMVFBINDEX16 )
{
ImInfo ("Type","16-bit Color Indexed");
ImInfo ("Compression Type","none");
if ( (n = imHdfVfbWrite16( ioType, fd, fp, vfb )) == -1 )
return ( -1 ); /* Errors already handled*/
imHdfDDAppend( IMHDFTRI, imHdfRef, offset, n );
tagList[nRIG] = IMHDFTRI;
refList[nRIG++] = imHdfRef;
}
else /* RGB */
{
switch ( dim.dim_compression )
{
case 0: /* No compression. */
switch ( dim.dim_interleave )
{
case 0: /* Uninterleaved */
ImInfo ("Type","24-bit RGB");
ImInfo ("Compression Type","none");
ImInfo ("Interleave Type","none (Non-interleaved)");
if ( (n = imHdfVfbWriteRGB( ioType, fd, fp,
vfb )) == -1 )
return ( -1 ); /* Errors done*/
break;
case 1: /* Scanline interleaved */
ImInfo ("Type","24-bit RGB");
ImInfo ("Compression Type","none");
ImInfo ("Interleave Type","Scanline");
if ( (n = imHdfVfbWriteRGBLine( ioType, fd, fp,
vfb )) == -1 )
return ( -1 ); /* Errors done*/
break;
case 2: /* Plane interleaved */
ImInfo ("Type","24-bit RGB");
ImInfo ("Compression Type","none");
ImInfo ("Interleave Type","Plane");
if ( (n = imHdfVfbWriteRGBPlane( ioType, fd, fp,
vfb )) == -1 )
return ( -1 ); /* Errors done*/
break;
}
imHdfDDAppend( IMHDFTRI, imHdfRef, offset, n );
tagList[nRIG] = IMHDFTRI;
refList[nRIG++] = imHdfRef;
break;
case IMHDFTRLE: /* Run-length encoding */
switch ( dim.dim_interleave )
{
case 0: /* Uninterleaved */
ImInfo ("Type","24-bit RGB");
ImInfo ("Compression Type","Run Length Encoded (RLE)");
ImInfo ("Interleave Type","none (Non-interleaved)");
if ( (n = imHdfVfbWriteRLERGB( ioType, fd, fp,
vfb )) == -1 )
return ( -1 ); /* Errors done*/
break;
case 1: /* Scanline interleaved */
ImInfo ("Type","24-bit RGB");
ImInfo ("Compression Type","Run Length Encoded (RLE)");
ImInfo ("Interleave Type","Scanline");
if ( (n = imHdfVfbWriteRLERGBLine( ioType,fd,fp,
vfb )) == -1 )
return ( -1 ); /* Errors done*/
break;
case 2: /* Plane interleaved */
ImInfo ("Type","24-bit RGB");
ImInfo ("Compression Type","Run Length Encoded (RLE)");
ImInfo ("Interleave Type","Plane");
if ( (n = imHdfVfbWriteRLERGBPlane( ioType, fd, fp,
vfb )) == -1 )
return ( -1 ); /* Errors done*/
break;
}
imHdfDDAppend( IMHDFTCI, imHdfRef, offset, n );
tagList[nRIG] = IMHDFTCI;
refList[nRIG++] = imHdfRef;
break;
}
}
/*
* Write out the RIG
*/
offset = Tell( );
for ( i = 0; i < nRIG; i++ )
{
Write( &tagList[i], UINT, 2, 1 );
Write( &refList[i], UINT, 2, 1 );
}
imHdfDDAppend( IMHDFTRIG, imHdfRef, offset, nRIG * 4 );
return ( nTag + 1 ); /* VFB and optional CLT */
}
/*
* MACRO
* IMADDTOBUFFER - add index to run buffer
*
* DESCRIPTION
* Each of the RLE routines which follow use the same basic scheme
* for adding a new value to the run buffer. Their only differences
* are in how the get the value to add (red, green, blue, index8, or
* index16). To make the code easier (and shorter), this macro
* implements the add-value-to-buffer scheme. It assumes all of
* these variables have been declared by the caller and that the
* value to add is in 'index'.
*/
#define IMADDTOBUFFER() \
{ \
if ( index != oldIndex ) \
{ \
/* Another unique pixel. */ \
if ( count < 0 ) \
{ \
/* Fill in run count first. */ \
*pCount = ((unsigned char)(-count)) | 0x80; \
count = 0; \
pCount = rbp++; \
} \
else if ( count >= 127 ) \
{ \
/* Fill in run count first. */ \
*pCount = (unsigned char)count; \
count = 0; \
pCount = rbp++; \
} \
\
/* Increase the unique pixel count */ \
oldIndex = index; \
++count; \
*rbp++ = index; \
continue; \
} \
\
/* Another non-unique pixel for the run. */ \
if ( count <= -127 ) \
{ \
*pCount = ((unsigned char)(-count)) | 0x80; \
count = 1; \
pCount = rbp++; \
*rbp++ = index; \
oldIndex = index; \
continue; \
} \
\
if ( count < 0 ) \
{ \
/* Continue the run */ \
--count; \
continue; \
} \
\
if ( count == 1 ) \
{ \
/* Change unique pixel to a run of 2 */ \
count = -2; \
continue; \
} \
\
*pCount = (unsigned char)(count - 1); \
oldIndex = index; \
count = -2; \
pCount = rbp - 1; \
*rbp++ = index; \
}
/*
* MACROS
* IMCOPYPLANE - copy a plane from a VFB to the output file
* IMENCODEPLANE - encode a plane from a VFB to the output file
*
* DESCRIPTION
* These macros represent commonly used code to take information from
* a VFB and write it out to the output file. This code is placed
* into macros to make it easier to maintain the same algorithm used
* by multiple functions, without the additional overhead of another
* subroutine call.
*
* IMCOPYPLANE() uses the given query functions (such as ImVfbQIndex8()
* or ImVfbQRed()), calls it to get the next pixel value, and copies
* it into the run buffer. After each scanline, it writes out the
* run buffer.
*
* IMENCODEPLANE() uses the query function, calls it to get the next
* pixel value, and worries about run-length encoding (using
* IMADDTOBUFFER()). After each scanline, it writes out the run buffer.
*
* These macros assume that all the appropriate variables have been
* declared by the caller.
*/
#define IMCOPYPLANE(query,type,size) \
{ \
for ( y = 0; y < height; y++ ) \
{ \
rbp = runBuffer; \
for ( x = 0; x < width; x++ ) \
{ \
*rbp++ = query( vfb, pPixel ); \
ImVfbSInc( vfb, pPixel ); \
} \
Write( runBuffer, type, size, width ); \
} \
}
#define IMENCODEPLANE(query,type,size) \
{ \
for ( y = 0; y < height; y++ ) \
{ \
rbp = runBuffer; \
oldIndex = query( vfb, pPixel ); \
count = 1; \
ImVfbSInc( vfb, pPixel ); \
pCount = rbp++; \
*rbp++ = oldIndex; \
for ( x = 1; x < width; x++ ) \
{ \
index = query( vfb, pPixel ); \
ImVfbSInc( vfb, pPixel ); \
IMADDTOBUFFER( ); \
} \
if ( count < 0 ) \
*pCount = ((unsigned char)(-count)) | 0x80; \
else \
*pCount = (unsigned char)count; \
Write( runBuffer, type, size, (rbp - runBuffer) ); \
nBytes += (rbp - runBuffer); \
} \
}
/*
* FUNCTION
* imHdfVfbWrite8 - write 8-bit uncomp. VFB
* imHdfVfbWriteRLE8 - write 8-bit RLE comp. VFB
*
* imHdfVfbWrite16 - write 16-bit uncomp. VFB
*
* imHdfVfbWriteRGB - write 24-bit uncomp. uninterleaved VFB
* imHdfVfbWriteRGBLine - write 24-bit uncomp. line interleaved VFB
* imHdfVfbWriteRGBPlane - write 24-bit uncomp. plane interleaved VFB
*
* imHdfVfbWriteRLERGB - write 24-bit RLE comp. uninterleaved VFB
* imHdfVfbWriteRLERGBLine - write 24-bit RLE comp. line interleaved VFB
* imHdfVfbWriteRLERGBPlane- write 24-bit RLE comp. plane interleaved VFB
*
* DESCRIPTION
* The given VFB is written out as an 8-bit, 16-bit, or 24-bit,
* uncompressed or RLE compressed, uninterleaved, scanline interleaved,
* or plane interleaved image.
*/
static long /* Returns number of bytes */
#ifdef __STDC__
imHdfVfbWrite8( int ioType, int fd, FILE *fp, ImVfb *vfb )
#else
imHdfVfbWrite8( ioType, fd, fp, vfb )
int ioType; /* I/O flags */
int fd; /* Output file descriptor */
FILE *fp; /* Output file pointer */
ImVfb *vfb; /* VFB to write out */
#endif
{
int width, height; /* Image size */
int x, y; /* X and Y image coordinates */
unsigned char *runBuffer; /* Buffered up runs */
unsigned char *rbp; /* Run buffer pointer */
ImVfbPtr pPixel; /* VFB pixel pointer */
/*
* Write out the uncompressed 8-bit index VFB.
*/
pPixel = ImVfbQFirst( vfb );
width = ImVfbQWidth( vfb );
height = ImVfbQHeight( vfb );
ImMalloc( runBuffer, unsigned char *, sizeof( unsigned char ) * width );
IMCOPYPLANE( ImVfbQIndex8, UCHAR, 1 );
free( (char *)runBuffer );
return ( width * height );
}
static long /* Returns number of bytes */
#ifdef __STDC__
imHdfVfbWriteRLE8( int ioType, int fd, FILE *fp, ImVfb *vfb )
#else
imHdfVfbWriteRLE8( ioType, fd, fp, vfb )
int ioType; /* I/O flags */
int fd; /* Output file descriptor */
FILE *fp; /* Output file pointer */
ImVfb *vfb; /* VFB to write out */
#endif
{
int width, height; /* Image size */
int x, y; /* X and Y image coordinates */
unsigned char *runBuffer; /* Buffered up runs */
unsigned char *rbp; /* Run buffer pointer */
unsigned char *pCount; /* Last run's count byte */
int index; /* New pixel index */
int oldIndex; /* Old pixel index */
int count; /* Run length */
ImVfbPtr pPixel; /* VFB pixel pointer */
long nBytes = 0; /* Total number of bytes written*/
/*
* Run-length encode the 8-bit index VFB.
* Worst case compression:
* input: ABB
* output: 1A2BB
* Worst case takes 5/3 * width bytes. Run buffer is
* allocated to be big enough for the worst case.
*/
pPixel = ImVfbQFirst( vfb );
width = ImVfbQWidth( vfb );
height = ImVfbQHeight( vfb );
ImMalloc( runBuffer, unsigned char *, sizeof( unsigned char ) * width * 2 );
IMENCODEPLANE( ImVfbQIndex8, UCHAR, 1 );
free( (char *)runBuffer );
return ( nBytes );
}
static long /* Returns number of bytes */
#ifdef __STDC__
imHdfVfbWrite16( int ioType, int fd, FILE *fp, ImVfb *vfb )
#else
imHdfVfbWrite16( ioType, fd, fp, vfb )
int ioType; /* I/O flags */
int fd; /* Output file descriptor */
FILE *fp; /* Output file pointer */
ImVfb *vfb; /* VFB to write out */
#endif
{
int width, height; /* Image size */
int x, y; /* X and Y image coordinates */
sdsc_uint32 *runBuffer; /* Buffered up runs */
sdsc_uint32 *rbp; /* Run buffer pointer */
ImVfbPtr pPixel; /* VFB pixel pointer */
ImClt *clt; /* VFB's clt */
int n; /* Number of colors */
int b; /* Number of bytes when in file */
/*
* Write out the uncompressed 16-bit index VFB.
* Worst case compression:
* input: ABB
* output: 1A2BB
* Worst case takes 5/3 * width bytes. Run buffer is
* allocated to be big enough for the worst case.
*/
pPixel = ImVfbQFirst( vfb );
width = ImVfbQWidth( vfb );
height = ImVfbQHeight( vfb );
ImMalloc( runBuffer, sdsc_uint32 *, sizeof( sdsc_uint32 ) * width * 2 );
clt = ImVfbQClt( vfb );
if ( clt != IMCLTNULL )
{
n = ImCltQNColors( clt );
if ( n <= 256 ) /* 8-bit */
b = 1;
else /* 16-bit */
b = 2;
}
else
b = 2;
IMCOPYPLANE( ImVfbQIndex16, UINT32, b );
free( (char *)runBuffer );
return ( width * height );
}
static long /* Returns number of bytes */
#ifdef __STDC__
imHdfVfbWriteRGB( int ioType, int fd, FILE *fp, ImVfb *vfb )
#else
imHdfVfbWriteRGB( ioType, fd, fp, vfb )
int ioType; /* I/O flags */
int fd; /* Output file descriptor */
FILE *fp; /* Output file pointer */
ImVfb *vfb; /* VFB to write out */
#endif
{
int width, height; /* Image size */
int width3; /* Width * 3 */
int x, y; /* X and Y image coordinates */
unsigned char *runBuffer; /* Buffered up runs */
unsigned char *rbp; /* Run buffer pointer */
ImVfbPtr pPixel; /* VFB pixel pointer */
/*
* Write out the uncompressed 24-bit RGB VFB, uninterleaved.
*/
pPixel = ImVfbQFirst( vfb );
width = ImVfbQWidth( vfb );
width3 = width * 3;
height = ImVfbQHeight( vfb );
ImMalloc( runBuffer, unsigned char *, sizeof( unsigned char ) * width3 );
for ( y = 0; y < height; y++ )
{
rbp = runBuffer;
for ( x = 0; x < width; x++ )
{
*rbp++ = ImVfbQRed( vfb, pPixel );
*rbp++ = ImVfbQGreen( vfb, pPixel );
*rbp++ = ImVfbQBlue( vfb, pPixel );
ImVfbSInc( vfb, pPixel );
}
Write( runBuffer, UCHAR, 1, width3 );
}
free( (char *)runBuffer );
return ( width3 * height );
}
static long /* Returns number of bytes */
#ifdef __STDC__
imHdfVfbWriteRGBLine( int ioType, int fd, FILE *fp, ImVfb *vfb )
#else
imHdfVfbWriteRGBLine( ioType, fd, fp, vfb )
int ioType; /* I/O flags */
int fd; /* Output file descriptor */
FILE *fp; /* Output file pointer */
ImVfb *vfb; /* VFB to write out */
#endif
{
int width, height; /* Image size */
int x, y; /* X and Y image coordinates */
unsigned char *runBuffer; /* Buffered up runs */
unsigned char *rbp; /* Run buffer pointer */
ImVfbPtr pPixel; /* VFB pixel pointer */
ImVfbPtr pPixel2; /* Start of scanline pixel ptr */
/*
* Write out the uncompressed 24-bit RGB VFB, scanline interleaved.
*/
pPixel = ImVfbQFirst( vfb );
width = ImVfbQWidth( vfb );
height = ImVfbQHeight( vfb );
ImMalloc( runBuffer, unsigned char *, sizeof( unsigned char ) * width );
for ( y = 0; y < height; y++ )
{
pPixel2 = pPixel;
rbp = runBuffer;
for ( x = 0; x < width; x++ )
{
*rbp++ = ImVfbQRed( vfb, pPixel );
ImVfbSInc( vfb, pPixel );
}
Write( runBuffer, UCHAR, 1, width );
pPixel = pPixel2;
rbp = runBuffer;
for ( x = 0; x < width; x++ )
{
*rbp++ = ImVfbQGreen( vfb, pPixel );
ImVfbSInc( vfb, pPixel );
}
Write( runBuffer, UCHAR, 1, width );
pPixel = pPixel2;
rbp = runBuffer;
for ( x = 0; x < width; x++ )
{
*rbp++ = ImVfbQBlue( vfb, pPixel );
ImVfbSInc( vfb, pPixel );
}
Write( runBuffer, UCHAR, 1, width );
}
free( (char *)runBuffer );
return ( width * height * 3 );
}
static long /* Returns number of bytes */
#ifdef __STDC__
imHdfVfbWriteRGBPlane( int ioType, int fd, FILE *fp, ImVfb *vfb )
#else
imHdfVfbWriteRGBPlane( ioType, fd, fp, vfb )
int ioType; /* I/O flags */
int fd; /* Output file descriptor */
FILE *fp; /* Output file pointer */
ImVfb *vfb; /* VFB to write out */
#endif
{
int width, height; /* Image size */
int x, y; /* X and Y image coordinates */
unsigned char *runBuffer; /* Buffered up runs */
unsigned char *rbp; /* Run buffer pointer */
ImVfbPtr pPixel; /* VFB pixel pointer */
/*
* Write out the uncompressed 24-bit RGB VFB, plane interleaved.
*/
width = ImVfbQWidth( vfb );
height = ImVfbQHeight( vfb );
ImMalloc( runBuffer, unsigned char *, sizeof( unsigned char ) * width );
pPixel = ImVfbQFirst( vfb );
IMCOPYPLANE( ImVfbQRed, UCHAR, 1 );
pPixel = ImVfbQFirst( vfb );
IMCOPYPLANE( ImVfbQGreen, UCHAR, 1 );
pPixel = ImVfbQFirst( vfb );
IMCOPYPLANE( ImVfbQBlue, UCHAR, 1 );
free( (char *)runBuffer );
return ( width * height * 3 );
}
static long /* Returns number of bytes */
#ifdef __STDC__
imHdfVfbWriteRLERGB( int ioType, int fd, FILE *fp, ImVfb *vfb )
#else
imHdfVfbWriteRLERGB( ioType, fd, fp, vfb )
int ioType; /* I/O flags */
int fd; /* Output file descriptor */
FILE *fp; /* Output file pointer */
ImVfb *vfb; /* VFB to write out */
#endif
{
int width, height; /* Image size */
int width3; /* 3 times width */
int x, y; /* X and Y image coordinates */
unsigned char *runBuffer; /* Buffered up runs */
unsigned char *rbp; /* Run buffer pointer */
unsigned char *pCount; /* Last run's count byte */
int index; /* New pixel index */
int oldIndex; /* Old pixel index */
int count; /* Run length */
ImVfbPtr pPixel; /* VFB pixel pointer */
int onRGB; /* Which RGB component are we on?*/
long nBytes = 0; /* Total number of bytes written*/
/*
* Run-length encode the 24-bit RGB VFB, uninterleaved.
* Worst case compression:
* input: ABB
* output: 1A2BB
* Worst case takes 5/3 * width * 3 bytes. Run buffer is
* allocated to be big enough for the worst case.
*/
pPixel = ImVfbQFirst( vfb );
width = ImVfbQWidth( vfb );
height = ImVfbQHeight( vfb );
width3 = width * 3;
ImMalloc( runBuffer, unsigned char *, sizeof( unsigned char ) * width3 * 2 );
for ( y = 0; y < height; y++ )
{
rbp = runBuffer;
oldIndex = ImVfbQRed( vfb, pPixel );
onRGB = GREEN;
count = 1;
pCount = rbp++;
*rbp++ = oldIndex;
for ( x = 1; x < width3; x++ )
{
switch ( onRGB )
{
case RED: index = ImVfbQRed( vfb, pPixel );
onRGB = GREEN;
break;
case GREEN: index = ImVfbQGreen( vfb, pPixel );
onRGB = BLUE;
break;
case BLUE: index = ImVfbQBlue( vfb, pPixel );
ImVfbSInc( vfb, pPixel );
onRGB = RED;
break;
}
IMADDTOBUFFER( );
}
if ( count < 0 )
*pCount = ((unsigned char)(-count)) | 0x80;
else
*pCount = (unsigned char)count;
/* Write out the run buffer. */
Write( runBuffer, UCHAR, 1, (rbp - runBuffer) );
nBytes += (rbp - runBuffer);
}
free( (char *)runBuffer );
return ( nBytes );
}
static long /* Returns number of bytes */
#ifdef __STDC__
imHdfVfbWriteRLERGBLine( int ioType, int fd, FILE *fp, ImVfb *vfb )
#else
imHdfVfbWriteRLERGBLine( ioType, fd, fp, vfb )
int ioType; /* I/O flags */
int fd; /* Output file descriptor */
FILE *fp; /* Output file pointer */
ImVfb *vfb; /* VFB to write out */
#endif
{
int width, height; /* Image size */
int x, y; /* X and Y image coordinates */
unsigned char *runBuffer; /* Buffered up runs */
unsigned char *rbp; /* Run buffer pointer */
unsigned char *pCount; /* Last run's count byte */
int index; /* New pixel index */
int oldIndex; /* Old pixel index */
int count; /* Run length */
ImVfbPtr pPixel; /* VFB pixel pointer */
ImVfbPtr pPixel2; /* Start of line pixel pointer */
long nBytes = 0; /* Total number of bytes written*/
/*
* Run-length encode the 24-bit RGB VFB, line interleaved.
* Worst case compression:
* input: ABB
* output: 1A2BB
* Worst case takes 5/3 * width bytes * 3. Run buffer is
* allocated to be big enough for the worst case.
*/
pPixel = ImVfbQFirst( vfb );
width = ImVfbQWidth( vfb );
height = ImVfbQHeight( vfb );
ImMalloc( runBuffer, unsigned char *, sizeof( unsigned char ) * width * 6 );
for ( y = 0; y < height; y++ )
{
rbp = runBuffer;
/* Red part of scan-line. */
pPixel2 = pPixel;
oldIndex = ImVfbQRed( vfb, pPixel );
ImVfbSInc( vfb, pPixel );
count = 1;
pCount = rbp++;
*rbp++ = oldIndex;
for ( x = 1; x < width; x++ )
{
index = ImVfbQRed( vfb, pPixel );
ImVfbSInc( vfb, pPixel );
IMADDTOBUFFER( );
}
if ( count < 0 )
*pCount = ((unsigned char)(-count)) | 0x80;
else
*pCount = (unsigned char)count;
/* Green part of scan-line. */
pPixel = pPixel2;
oldIndex = ImVfbQGreen( vfb, pPixel );
ImVfbSInc( vfb, pPixel );
count = 1;
pCount = rbp++;
*rbp++ = oldIndex;
for ( x = 1; x < width; x++ )
{
index = ImVfbQGreen( vfb, pPixel );
ImVfbSInc( vfb, pPixel );
IMADDTOBUFFER( );
}
if ( count < 0 )
*pCount = ((unsigned char)(-count)) | 0x80;
else
*pCount = (unsigned char)count;
/* Blue part of scan-line. */
pPixel = pPixel2;
oldIndex = ImVfbQBlue( vfb, pPixel );
ImVfbSInc( vfb, pPixel );
count = 1;
pCount = rbp++;
*rbp++ = oldIndex;
for ( x = 1; x < width; x++ )
{
index = ImVfbQBlue( vfb, pPixel );
ImVfbSInc( vfb, pPixel );
IMADDTOBUFFER( );
}
if ( count < 0 )
*pCount = ((unsigned char)(-count)) | 0x80;
else
*pCount = (unsigned char)count;
/* Write out the run buffer. */
Write( runBuffer, UCHAR, 1, (rbp - runBuffer) );
nBytes += (rbp - runBuffer);
}
free( (char *)runBuffer );
return ( nBytes );
}
static long /* Returns number of bytes */
#ifdef __STDC__
imHdfVfbWriteRLERGBPlane( int ioType, int fd, FILE *fp, ImVfb *vfb )
#else
imHdfVfbWriteRLERGBPlane( ioType, fd, fp, vfb )
int ioType; /* I/O flags */
int fd; /* Output file descriptor */
FILE *fp; /* Output file pointer */
ImVfb *vfb; /* VFB to write out */
#endif
{
int width, height; /* Image size */
int x, y; /* X and Y image coordinates */
unsigned char *runBuffer; /* Buffered up runs */
unsigned char *rbp; /* Run buffer pointer */
unsigned char *pCount; /* Last run's count byte */
int index; /* New pixel index */
int oldIndex; /* Old pixel index */
int count; /* Run length */
ImVfbPtr pPixel; /* VFB pixel pointer */
long nBytes = 0; /* Total number of bytes written*/
/*
* Run-length encode the 24-bit RGB VFB, uninterleaved.
* Worst case compression:
* input: ABB
* output: 1A2BB
* Worst case takes 5/3 * width bytes. Run buffer is
* allocated to be big enough for the worst case.
*/
width = ImVfbQWidth( vfb );
height = ImVfbQHeight( vfb );
ImMalloc( runBuffer, unsigned char *, sizeof( unsigned char ) * width * 2 );
/* Red plane. */
pPixel = ImVfbQFirst( vfb );
IMENCODEPLANE( ImVfbQRed, UCHAR, 1 );
/* Green plane. */
pPixel = ImVfbQFirst( vfb );
IMENCODEPLANE( ImVfbQGreen, UCHAR, 1 );
/* Blue plane. */
pPixel = ImVfbQFirst( vfb );
IMENCODEPLANE( ImVfbQBlue, UCHAR, 1 );
free( (char *)runBuffer );
return ( nBytes );
}