3284 lines
52 KiB
C
3284 lines
52 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 );
|
|
|
|
}
|
|
|