1405 lines
21 KiB
C
1405 lines
21 KiB
C
|
/**
|
||
|
|
||
|
** $Header: /roq/libim/imsynu.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/imsynu.c 1 11/02/99 4:38p Zaphod $"
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
|
||
|
** FILE
|
||
|
|
||
|
** imsynu.c - Synu image file I/O
|
||
|
|
||
|
**
|
||
|
|
||
|
** PROJECT
|
||
|
|
||
|
** libim - SDSC image manipulation library
|
||
|
|
||
|
**
|
||
|
|
||
|
** DESCRIPTION
|
||
|
|
||
|
** imsynu.c contains routines to read and write Synu image files
|
||
|
|
||
|
** for the image manipulation library.
|
||
|
|
||
|
**
|
||
|
|
||
|
** PUBLIC CONTENTS
|
||
|
|
||
|
** d =defined constant
|
||
|
|
||
|
** f =function
|
||
|
|
||
|
** m =defined macro
|
||
|
|
||
|
** t =typedef/struct/union
|
||
|
|
||
|
** v =variable
|
||
|
|
||
|
** ? =other
|
||
|
|
||
|
** none
|
||
|
|
||
|
**
|
||
|
|
||
|
** PRIVATE CONTENTS
|
||
|
|
||
|
**
|
||
|
|
||
|
** imSynuRead f read a Synu image file
|
||
|
|
||
|
** imSynuWrite f write a Synu image file
|
||
|
|
||
|
** imSynuRead f read a Synu image file
|
||
|
|
||
|
** imSynuWrite f write a Synu image file
|
||
|
|
||
|
**
|
||
|
|
||
|
** IMSYNUMAGIC d file magic "number"
|
||
|
|
||
|
** IMSYNURGB d mode string identifying RGB format
|
||
|
|
||
|
** IMSYNUGRAY d mode string identifying gray-scale format
|
||
|
|
||
|
**
|
||
|
|
||
|
** imGetFDStr f read a string in from fd or fp
|
||
|
|
||
|
**
|
||
|
|
||
|
** HISTORY
|
||
|
|
||
|
** $Log: /roq/libim/imsynu.c $
|
||
|
*
|
||
|
* 1 11/02/99 4:38p Zaphod
|
||
|
|
||
|
** Revision 1.16 1995/06/29 00:28:04 bduggan
|
||
|
|
||
|
** updated copyright year
|
||
|
|
||
|
**
|
||
|
|
||
|
** Revision 1.15 1995/06/15 21:14:33 bduggan
|
||
|
|
||
|
** Took out an embedded comment
|
||
|
|
||
|
**
|
||
|
|
||
|
** Revision 1.14 1995/04/03 21:37:14 bduggan
|
||
|
|
||
|
** took out #ifdef NEWMAGIC
|
||
|
|
||
|
**
|
||
|
|
||
|
** Revision 1.13 1995/01/10 23:43:54 bduggan
|
||
|
|
||
|
** put in IMMULTI, IMPIPE instead of TRUE/FALSE
|
||
|
|
||
|
** made read/write routines static
|
||
|
|
||
|
**
|
||
|
|
||
|
** Revision 1.12 94/10/03 11:30:58 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.11 92/12/03 01:52:31 nadeau
|
||
|
|
||
|
** Corrected info messages.
|
||
|
|
||
|
**
|
||
|
|
||
|
** Revision 1.10 92/11/04 12:07:48 groening
|
||
|
|
||
|
** put ImFIleFormat info and magic number info
|
||
|
|
||
|
** from imfmt.c into this file.
|
||
|
|
||
|
**
|
||
|
|
||
|
** Revision 1.9 92/10/19 14:09:40 groening
|
||
|
|
||
|
** added ImINfo statements
|
||
|
|
||
|
**
|
||
|
|
||
|
** Revision 1.8 92/08/31 17:35:37 vle
|
||
|
|
||
|
** Updated copyright notice.
|
||
|
|
||
|
**
|
||
|
|
||
|
** Revision 1.7 92/04/09 09:31:57 groening
|
||
|
|
||
|
** To make the compiler happy added extern statements.
|
||
|
|
||
|
**
|
||
|
|
||
|
** Revision 1.6 91/10/03 09:19:34 nadeau
|
||
|
|
||
|
** Fixed #includes.
|
||
|
|
||
|
**
|
||
|
|
||
|
** Revision 1.5 91/03/14 14:41:14 nadeau
|
||
|
|
||
|
** Changed 1L to 4L in line skip of image object.
|
||
|
|
||
|
** Added return(0) to end of write... was causing
|
||
|
|
||
|
** weirdness on Alliant FX/2800.
|
||
|
|
||
|
**
|
||
|
|
||
|
** Revision 1.4 91/03/08 14:33:43 nadeau
|
||
|
|
||
|
** Cleaned up some error checking and changed the name of the
|
||
|
|
||
|
** defined name globals giving buffer sizes.
|
||
|
|
||
|
**
|
||
|
|
||
|
** Revision 1.3 91/02/12 11:39:56 nadeau
|
||
|
|
||
|
** Almost completely rewrote. Removed the tag table checking
|
||
|
|
||
|
** now handled by ImFileRead and ImFileWrite. Removed
|
||
|
|
||
|
** goto's. Removed bogus static variables. Moved loop-
|
||
|
|
||
|
** invariant code outside of loops. Removed illegal read
|
||
|
|
||
|
** call that read directly into VFB (thus assuming internal
|
||
|
|
||
|
** data structure it shouldn't have). Buffered up writes by
|
||
|
|
||
|
** scanline rather than issue a write system call PER PIXEL.
|
||
|
|
||
|
** And generally optimized the code into a usable state.
|
||
|
|
||
|
**
|
||
|
|
||
|
** Revision 1.2 91/01/09 14:02:00 mercurio
|
||
|
|
||
|
** Minor spelling errors in comments fixed.
|
||
|
|
||
|
**
|
||
|
|
||
|
** Revision 1.1 90/09/20 09:46:38 mercurio
|
||
|
|
||
|
** Initial revision
|
||
|
|
||
|
**
|
||
|
|
||
|
**/
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#include "iminternal.h"
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
** FORMAT
|
||
|
|
||
|
** SYNU - Synthetic Universe
|
||
|
|
||
|
**
|
||
|
|
||
|
** AKA
|
||
|
|
||
|
**
|
||
|
|
||
|
** FORMAT REFERENCES
|
||
|
|
||
|
** Synu Reference Manual, San Diego Supercomputer Center
|
||
|
|
||
|
**
|
||
|
|
||
|
** CODE CREDITS
|
||
|
|
||
|
** Custom development, Dave Nadeau, San Diego Supercomputer Center, 1991.
|
||
|
|
||
|
**
|
||
|
|
||
|
** DESCRIPTION
|
||
|
|
||
|
** Synu images are stored in Synu object files, which may contain
|
||
|
|
||
|
** any of a number of objects of any type. We're interested in
|
||
|
|
||
|
** only the "image" (IMSYNUMAGIC) objects--all others are skipped
|
||
|
|
||
|
** past.
|
||
|
|
||
|
**
|
||
|
|
||
|
** Each object is preceeded by a header string, in ASCII, terminated
|
||
|
|
||
|
** by a newline character. The first space-delimited string in the
|
||
|
|
||
|
** header is the object type. The remaining strings are number-letter
|
||
|
|
||
|
** pairs (eg.: 786432b) describing the object contents. The letter
|
||
|
|
||
|
** may be either 'l', indicating that number of lines (newline-delimited
|
||
|
|
||
|
** strings), or 'b', indicating that number of bytes. 'L' and 'B'
|
||
|
|
||
|
** are also acceptable, and mean the same as their lower-case counter-
|
||
|
|
||
|
** parts. For example:
|
||
|
|
||
|
**
|
||
|
|
||
|
** image 4l 786432b
|
||
|
|
||
|
**
|
||
|
|
||
|
** indicates an "image" object, consisting of 4 lines followed by
|
||
|
|
||
|
** 786432 bytes. Reading four lines then 786432 bytes will skip
|
||
|
|
||
|
** past the entire object.
|
||
|
|
||
|
**
|
||
|
|
||
|
** The image object type will always consist of 4 header lines
|
||
|
|
||
|
** followed by some number of bytes. The header lines are of the
|
||
|
|
||
|
** form:
|
||
|
|
||
|
**
|
||
|
|
||
|
** <x>
|
||
|
|
||
|
** <y>
|
||
|
|
||
|
** <bytes>
|
||
|
|
||
|
** <mode>
|
||
|
|
||
|
**
|
||
|
|
||
|
** where <x> and <y> are the width and height of the image, <bytes>
|
||
|
|
||
|
** is the number of bytes per pixel, and <mode> is a string describing
|
||
|
|
||
|
** how the pixels are stored. Currently, <mode> will either be
|
||
|
|
||
|
** "rgb" for a three-byte-per-pixel, red-green-blue format, or
|
||
|
|
||
|
** "gray" for a one-byte-per-pixel, gray-scale format. Possible
|
||
|
|
||
|
** future extensions include "rgba", for RGB plus an alpha channel,
|
||
|
|
||
|
** or allowing the pixel components to be specified in another
|
||
|
|
||
|
** order, such as "bgr".
|
||
|
|
||
|
**
|
||
|
|
||
|
** Following the image header lines are <x> * <y> * <bytes> bytes,
|
||
|
|
||
|
** representing the pixel values in scanline order. The origin
|
||
|
|
||
|
** of the image is in the lower left corner.
|
||
|
|
||
|
**/
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
* SYNU - SDSC Synthetic Universe image renderer file
|
||
|
|
||
|
*/
|
||
|
|
||
|
|
||
|
|
||
|
#ifdef __STDC__
|
||
|
|
||
|
static int imGetFDStr( int ioType, int fd, FILE *fp, char *buf, int size);
|
||
|
|
||
|
static int imSynuRead(int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable);
|
||
|
|
||
|
static int imSynuWrite( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable );
|
||
|
|
||
|
#else
|
||
|
|
||
|
static int imGetFDStr();
|
||
|
|
||
|
static int imSynuRead( );
|
||
|
|
||
|
static int imSynuWrite( );
|
||
|
|
||
|
#endif
|
||
|
|
||
|
static char *imSynuNames[ ] = { "synu", NULL };
|
||
|
|
||
|
static ImFileFormatReadMap imSynuReadMap[ ] =
|
||
|
|
||
|
{
|
||
|
|
||
|
/* in out */
|
||
|
|
||
|
/* type,ch,dep, attr. VFB type attr. */
|
||
|
|
||
|
{ IN,1,8, 0, IMVFBINDEX8, 0 },
|
||
|
|
||
|
{ RGB,3,8, 0, IMVFBRGB, 0 },
|
||
|
|
||
|
{ -1, 0, -1, 0 },
|
||
|
|
||
|
};
|
||
|
|
||
|
static ImFileFormatWriteMap imSynuWriteMap[ ] =
|
||
|
|
||
|
{
|
||
|
|
||
|
/*
|
||
|
|
||
|
* For Synu, all image types vector thru to the same imSynuWrite()
|
||
|
|
||
|
* routine. This is necessary because a tagTable may be passed in
|
||
|
|
||
|
* that contains multiple VFB's, each with different depth, CLT
|
||
|
|
||
|
* and alpha attributes. The write map primarily serves as a
|
||
|
|
||
|
* filter to make sure all such incomming VFB's are in one of the
|
||
|
|
||
|
* supported formats.
|
||
|
|
||
|
*/
|
||
|
|
||
|
|
||
|
|
||
|
/* in out */
|
||
|
|
||
|
/* VFB type, attr., type,ch,dep, attr., func */
|
||
|
|
||
|
{ IMVFBINDEX8, 0, IN,1,8, 0, imSynuWrite },
|
||
|
|
||
|
{ IMVFBRGB, 0, RGB,3,8, 0, imSynuWrite },
|
||
|
|
||
|
{ -1, 0, -1, 0, NULL },
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
static ImFileMagic imFileSynuMagic []=
|
||
|
|
||
|
{
|
||
|
|
||
|
{ 0, 0, NULL},
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
ImFileFormat ImFileSynuFormat =
|
||
|
|
||
|
{
|
||
|
|
||
|
imSynuNames, "SDSC Synu image file",
|
||
|
|
||
|
"SDSC",
|
||
|
|
||
|
"8-bit grayscale and 24-bit RGB uncompressed image files.",
|
||
|
|
||
|
"8-bit grayscale and 24-bit RGB uncompressed image files.",
|
||
|
|
||
|
imFileSynuMagic,
|
||
|
|
||
|
IMMULTI, IMPIPE,
|
||
|
|
||
|
IMMULTI, IMPIPE,
|
||
|
|
||
|
imSynuRead, imSynuReadMap, imSynuWriteMap
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
* CONSTANTS
|
||
|
|
||
|
* IMSYNUMAGIC - file magic "number" (see below)
|
||
|
|
||
|
* IMSYNURGB - mode string indicating RGB data
|
||
|
|
||
|
* IMSYNUGRAY - mode string indicating gray-scale data
|
||
|
|
||
|
*
|
||
|
|
||
|
* DESCRIPTION
|
||
|
|
||
|
* IMSYNUMAGIC is the string identifying an image in the
|
||
|
|
||
|
* Synu object header. It serves as a magic number, also.
|
||
|
|
||
|
*
|
||
|
|
||
|
* IMSYNURGB and IMSYNUGRAY are possible values for the mode
|
||
|
|
||
|
* field of an image header line.
|
||
|
|
||
|
*/
|
||
|
|
||
|
#define IMSYNUMAGIC "image"
|
||
|
|
||
|
#define IMSYNURGB "rgb"
|
||
|
|
||
|
#define IMSYNUGRAY "gray"
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
* FUNCTION
|
||
|
|
||
|
* imSynuRead - read a Synu image file
|
||
|
|
||
|
*
|
||
|
|
||
|
* DESCRIPTION
|
||
|
|
||
|
* Each object in the input stream is read. "image" objects
|
||
|
|
||
|
* are reading 24- or 8-bit VFBs and added to the tagTable.
|
||
|
|
||
|
* All other objects are ignored.
|
||
|
|
||
|
*/
|
||
|
|
||
|
#define IMSYNUSTRSIZE (256) /* size of header string buffer */
|
||
|
|
||
|
#define IMSYNUBUFSIZE (2048) /* buffer size */
|
||
|
|
||
|
|
||
|
|
||
|
static int /* Returns status */
|
||
|
|
||
|
#ifdef __STDC__
|
||
|
|
||
|
imSynuRead(int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable)
|
||
|
|
||
|
#else
|
||
|
|
||
|
imSynuRead(ioType, fd, fp, flagsTable, tagTable)
|
||
|
|
||
|
int ioType; /* I/O flags */
|
||
|
|
||
|
int fd; /* Input file descriptor */
|
||
|
|
||
|
FILE *fp; /* Input file pointer */
|
||
|
|
||
|
TagTable *flagsTable; /* Flags */
|
||
|
|
||
|
TagTable *tagTable; /* Tag table to add to */
|
||
|
|
||
|
#endif
|
||
|
|
||
|
{
|
||
|
|
||
|
|
||
|
|
||
|
ImVfb *vfb; /* Read in image */
|
||
|
|
||
|
ImVfbPtr p; /* pixel pointer */
|
||
|
|
||
|
int i,y; /* Counters */
|
||
|
|
||
|
int status; /* Return status holder */
|
||
|
|
||
|
char str[IMSYNUSTRSIZE]; /* string used for header input */
|
||
|
|
||
|
char junk[IMSYNUBUFSIZE]; /* garbage buffer */
|
||
|
|
||
|
char * pHdr; /* pointer into header string */
|
||
|
|
||
|
int size; /* size of object part */
|
||
|
|
||
|
char type; /* type of object part */
|
||
|
|
||
|
int nRead; /* # of bytes scanned from string */
|
||
|
|
||
|
int width; /* width of image */
|
||
|
|
||
|
int height; /* height of image */
|
||
|
|
||
|
int nBytes; /* number of bytes per pixel */
|
||
|
|
||
|
char mode[IMSYNUSTRSIZE]; /* storage mode for image */
|
||
|
|
||
|
unsigned char *buffer; /* Allocated buffer */
|
||
|
|
||
|
unsigned char *bp; /* Buffer pointer */
|
||
|
|
||
|
int n; /* # of bytes */
|
||
|
|
||
|
char message[256]; /* print buffer for use with ImInfo */
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
* SYNU files don't really have a byte order, since everything
|
||
|
|
||
|
* is either ASCII or raw bytes. We set an order anyway, just to
|
||
|
|
||
|
* be sure.
|
||
|
|
||
|
*/
|
||
|
|
||
|
BinByteOrder( BINMBF );
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
* Loop until we get an EOF
|
||
|
|
||
|
*/
|
||
|
|
||
|
for ( ; ; )
|
||
|
|
||
|
{
|
||
|
|
||
|
/*
|
||
|
|
||
|
* Read in the magic number.
|
||
|
|
||
|
*/
|
||
|
|
||
|
status = imGetFDStr(ioType,fd,fp,str,IMSYNUSTRSIZE);
|
||
|
|
||
|
if ( status == -1) /* EOF reached, not an error */
|
||
|
|
||
|
break;
|
||
|
|
||
|
if ( status == -2) /* a read error */
|
||
|
|
||
|
{
|
||
|
|
||
|
ImReturnBinError();
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
if ( strncmp(IMSYNUMAGIC,str,strlen(IMSYNUMAGIC)) != 0)
|
||
|
|
||
|
{ /* uninteresting object, skip it */
|
||
|
|
||
|
pHdr = &str[strlen(IMSYNUMAGIC)];
|
||
|
|
||
|
while(sscanf(pHdr,"%d%c%n",&size,&type,&nRead) >= 2)
|
||
|
|
||
|
{
|
||
|
|
||
|
pHdr += nRead;
|
||
|
|
||
|
|
||
|
|
||
|
switch(type)
|
||
|
|
||
|
{
|
||
|
|
||
|
case 'b':
|
||
|
|
||
|
case 'B': /* skip bytes */
|
||
|
|
||
|
for ( ; size > 0; size-=IMSYNUBUFSIZE)
|
||
|
|
||
|
if ( ImBinRead(ioType,fd,fp,
|
||
|
|
||
|
junk,CHAR,1,IMSYNUBUFSIZE)<0)
|
||
|
|
||
|
{
|
||
|
|
||
|
ImReturnBinError();
|
||
|
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
|
||
|
|
||
|
case 'l':
|
||
|
|
||
|
case 'L': /* skip lines */
|
||
|
|
||
|
for ( ; size > 0; size-- )
|
||
|
|
||
|
if ( imGetFDStr(ioType,fd,fp,
|
||
|
|
||
|
junk,IMSYNUBUFSIZE) < 0)
|
||
|
|
||
|
{
|
||
|
|
||
|
ImReturnBinError();
|
||
|
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
continue;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* An image, read it in */
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
* Read width, height, nBytes, and mode (4 separate lines).
|
||
|
|
||
|
*/
|
||
|
|
||
|
if ( imGetFDStr(ioType,fd,fp,str,IMSYNUSTRSIZE) < 0)
|
||
|
|
||
|
{
|
||
|
|
||
|
ImReturnBinError( );
|
||
|
|
||
|
}
|
||
|
|
||
|
sscanf(str,"%d",&width);
|
||
|
|
||
|
|
||
|
|
||
|
if ( imGetFDStr(ioType,fd,fp,str,IMSYNUSTRSIZE) < 0)
|
||
|
|
||
|
{
|
||
|
|
||
|
ImReturnBinError( );
|
||
|
|
||
|
}
|
||
|
|
||
|
sscanf(str,"%d",&height);
|
||
|
|
||
|
|
||
|
|
||
|
if ( imGetFDStr(ioType,fd,fp,str,IMSYNUSTRSIZE) < 0)
|
||
|
|
||
|
{
|
||
|
|
||
|
ImReturnBinError( );
|
||
|
|
||
|
}
|
||
|
|
||
|
sscanf(str,"%d",&nBytes);
|
||
|
|
||
|
|
||
|
|
||
|
if ( imGetFDStr(ioType,fd,fp,str,IMSYNUSTRSIZE) < 0)
|
||
|
|
||
|
{
|
||
|
|
||
|
ImReturnBinError( );
|
||
|
|
||
|
}
|
||
|
|
||
|
sscanf(str,"%s",mode);
|
||
|
|
||
|
|
||
|
|
||
|
/* These lines sre to printout if a verbose flag
|
||
|
|
||
|
has been set in imfile or imconv */
|
||
|
|
||
|
ImInfo ("Byte Order", "Most Significant Byte First");
|
||
|
|
||
|
sprintf (message, "%d x %d",width, height);
|
||
|
|
||
|
ImInfo ("Resolution",message);
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
* Allocate the correct VFB
|
||
|
|
||
|
*/
|
||
|
|
||
|
if ( strcmp(mode,IMSYNURGB) == 0)
|
||
|
|
||
|
{
|
||
|
|
||
|
ImInfo ("Type","24-bit RGB");
|
||
|
|
||
|
vfb = ImVfbAlloc(width,height,IMVFBRGB);
|
||
|
|
||
|
}
|
||
|
|
||
|
else
|
||
|
|
||
|
{
|
||
|
|
||
|
ImInfo ("Type","8-bit Grayscale");
|
||
|
|
||
|
vfb = ImVfbAlloc(width,height,IMVFBINDEX8);
|
||
|
|
||
|
}
|
||
|
|
||
|
if ( vfb == IMVFBNULL)
|
||
|
|
||
|
{
|
||
|
|
||
|
ImErrorFatal(ImQError(), -1, ImErrNo);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
* Allocate a temp buffer big enough for 1 scanline.
|
||
|
|
||
|
*/
|
||
|
|
||
|
n = nBytes * width;
|
||
|
|
||
|
ImMalloc( buffer, unsigned char *, n );
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
* Read pixels in directly, one scanline at a time.
|
||
|
|
||
|
*/
|
||
|
|
||
|
p = ImVfbQPtr( vfb, 0, height - 1 );
|
||
|
|
||
|
for ( y = height-1; y >= 0; y-- )
|
||
|
|
||
|
{
|
||
|
|
||
|
if ( ImBinRead( ioType, fd, fp, buffer, UCHAR, 1, n ) != n )
|
||
|
|
||
|
{
|
||
|
|
||
|
free( (char *)buffer );
|
||
|
|
||
|
ImReturnBinError();
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
if ( ImVfbQFields( vfb ) & IMVFBINDEX8 )
|
||
|
|
||
|
{
|
||
|
|
||
|
for ( i = 0, bp = buffer; i < width; i++ )
|
||
|
|
||
|
{
|
||
|
|
||
|
ImVfbSIndex8( vfb, p, *bp++ );
|
||
|
|
||
|
ImVfbSInc( vfb, p );
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
else
|
||
|
|
||
|
{
|
||
|
|
||
|
for ( i = 0, bp = buffer; i < width; i++ )
|
||
|
|
||
|
{
|
||
|
|
||
|
ImVfbSRed( vfb, p, *bp );
|
||
|
|
||
|
ImVfbSGreen( vfb, p, *(bp+1) );
|
||
|
|
||
|
ImVfbSBlue( vfb, p, *(bp+2) );
|
||
|
|
||
|
ImVfbSInc( vfb, p );
|
||
|
|
||
|
bp += nBytes;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
ImVfbSUp( vfb, p );
|
||
|
|
||
|
ImVfbSUp( vfb, p );
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
* Append the new VFB to the tag table
|
||
|
|
||
|
*/
|
||
|
|
||
|
TagTableAppend( tagTable,
|
||
|
|
||
|
TagEntryAlloc( "image vfb", POINTER, &vfb ) );
|
||
|
|
||
|
|
||
|
|
||
|
free( (char *)buffer );
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
return ( 0 );
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
* FUNCTION
|
||
|
|
||
|
* imSynuWrite - write a Synu image file
|
||
|
|
||
|
*
|
||
|
|
||
|
* DESCRIPTION
|
||
|
|
||
|
* All of the VFBs are retrieved from the Tag Table and written
|
||
|
|
||
|
* to the output in Synu image format. Gray-scale VFBs are
|
||
|
|
||
|
* written as gray-scale Synu images, all others are written
|
||
|
|
||
|
* as RGB Synu images. Monochrome VFBs are not supported.
|
||
|
|
||
|
*/
|
||
|
|
||
|
|
||
|
|
||
|
static int /* Returns status */
|
||
|
|
||
|
#ifdef __STDC__
|
||
|
|
||
|
imSynuWrite( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable )
|
||
|
|
||
|
#else
|
||
|
|
||
|
imSynuWrite( 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; /* Flags */
|
||
|
|
||
|
TagTable *tagTable; /* Tag table to read from */
|
||
|
|
||
|
#endif
|
||
|
|
||
|
{
|
||
|
|
||
|
ImVfb * vfb; /* Written out image */
|
||
|
|
||
|
ImVfbPtr p; /* pixel pointer */
|
||
|
|
||
|
int fields; /* VFB flag fields */
|
||
|
|
||
|
int i,x,y; /* Counters */
|
||
|
|
||
|
int nVfbs; /* number of VFBs */
|
||
|
|
||
|
int width; /* width of image */
|
||
|
|
||
|
int height; /* height of image */
|
||
|
|
||
|
char str[IMSYNUSTRSIZE]; /* string used for header input */
|
||
|
|
||
|
unsigned char *buffer; /* Tmp scanline buffer */
|
||
|
|
||
|
unsigned char *bp; /* Buffer pointer */
|
||
|
|
||
|
char message[512]; /* print buffer for ImInfo */
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
* Process each of the VFBs
|
||
|
|
||
|
*/
|
||
|
|
||
|
nVfbs = TagTableQNEntry(tagTable,"image vfb");
|
||
|
|
||
|
for ( i=0; i < nVfbs; i++)
|
||
|
|
||
|
{
|
||
|
|
||
|
TagEntryQValue( TagTableQDirect( tagTable, "image vfb", i ), &vfb );
|
||
|
|
||
|
fields = ImVfbQFields(vfb);
|
||
|
|
||
|
width = ImVfbQWidth(vfb);
|
||
|
|
||
|
height = ImVfbQHeight(vfb);
|
||
|
|
||
|
|
||
|
|
||
|
/* These lines sre to printout if a verbose flag
|
||
|
|
||
|
has been set in imfile or imconv */
|
||
|
|
||
|
ImInfo ("Byte Order", "Most Significant Byte First");
|
||
|
|
||
|
sprintf (message, "%d x %d",width, height);
|
||
|
|
||
|
ImInfo ("Resolution",message);
|
||
|
|
||
|
|
||
|
|
||
|
if ( (fields & IMVFBINDEX8) != 0)
|
||
|
|
||
|
{
|
||
|
|
||
|
sprintf (message,"8-bit Grayscale");
|
||
|
|
||
|
ImInfo ("Type", message);
|
||
|
|
||
|
}
|
||
|
|
||
|
else
|
||
|
|
||
|
{
|
||
|
|
||
|
sprintf (message,"24-bit RGB");
|
||
|
|
||
|
ImInfo ("Type", message);
|
||
|
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
|
||
|
* Process the VFB.
|
||
|
|
||
|
*/
|
||
|
|
||
|
if ( (fields & IMVFBINDEX8) != 0)
|
||
|
|
||
|
{
|
||
|
|
||
|
/*
|
||
|
|
||
|
* Write the object header
|
||
|
|
||
|
*/
|
||
|
|
||
|
sprintf(str,"%s 4L %db\n",IMSYNUMAGIC,width*height);
|
||
|
|
||
|
if ( ImBinWrite(ioType,fd,fp,str,CHAR,1,strlen(str))
|
||
|
|
||
|
== -1 )
|
||
|
|
||
|
{
|
||
|
|
||
|
ImReturnBinError();
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
* Write the image header
|
||
|
|
||
|
*/
|
||
|
|
||
|
sprintf(str,"%d\n%d\n1\n%s\n",width,height,IMSYNUGRAY);
|
||
|
|
||
|
if ( ImBinWrite(ioType,fd,fp,str,CHAR,1,strlen(str))
|
||
|
|
||
|
== -1 )
|
||
|
|
||
|
{
|
||
|
|
||
|
ImReturnBinError();
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
* Allocate a buffer for one scanline.
|
||
|
|
||
|
*/
|
||
|
|
||
|
ImMalloc( buffer, unsigned char *, width );
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
* Write the pixel values, inverting the scanlines
|
||
|
|
||
|
* (since a VFB's origin is in the upper left)
|
||
|
|
||
|
*/
|
||
|
|
||
|
for ( y = height-1; y >= 0; y-- )
|
||
|
|
||
|
{
|
||
|
|
||
|
p = ImVfbQPtr( vfb, 0, y );
|
||
|
|
||
|
|
||
|
|
||
|
for ( bp = buffer, x = 0; x < width; x++, bp++ )
|
||
|
|
||
|
{
|
||
|
|
||
|
*bp = ImVfbQIndex8( vfb, p );
|
||
|
|
||
|
ImVfbSInc( vfb, p );
|
||
|
|
||
|
}
|
||
|
|
||
|
if ( ImBinWrite( ioType, fd, fp, buffer,
|
||
|
|
||
|
UCHAR, 1, width ) == -1 )
|
||
|
|
||
|
{
|
||
|
|
||
|
free( (char *)buffer );
|
||
|
|
||
|
ImReturnBinError( );
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
free( (char *)buffer );
|
||
|
|
||
|
continue;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
* Write the object header
|
||
|
|
||
|
*/
|
||
|
|
||
|
sprintf(str,"%s 4L %db\n",IMSYNUMAGIC, width*height*3);
|
||
|
|
||
|
if ( ImBinWrite(ioType,fd,fp,str,CHAR,1,strlen(str)) == -1 )
|
||
|
|
||
|
{
|
||
|
|
||
|
ImReturnBinError();
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
* Write the image header
|
||
|
|
||
|
*/
|
||
|
|
||
|
sprintf(str,"%d\n%d\n%d\n%s\n",width,height,3, IMSYNURGB);
|
||
|
|
||
|
if ( ImBinWrite(ioType,fd,fp,str,CHAR,1,strlen(str)) == -1 )
|
||
|
|
||
|
{
|
||
|
|
||
|
ImReturnBinError();
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
* Allocate a buffer for one scanline.
|
||
|
|
||
|
*/
|
||
|
|
||
|
ImMalloc( buffer, unsigned char *, width * 3 );
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
* Write the pixel values, inverting the scanlines
|
||
|
|
||
|
* (since a VFB's origin is in the upper left)
|
||
|
|
||
|
*/
|
||
|
|
||
|
for ( y = height-1; y >= 0; y-- )
|
||
|
|
||
|
{
|
||
|
|
||
|
p = ImVfbQPtr( vfb, 0, y );
|
||
|
|
||
|
for ( bp = buffer, x = 0; x < width; x++ )
|
||
|
|
||
|
{
|
||
|
|
||
|
*bp++ = ImVfbQRed( vfb, p );
|
||
|
|
||
|
*bp++ = ImVfbQGreen( vfb, p );
|
||
|
|
||
|
*bp++ = ImVfbQBlue( vfb, p );
|
||
|
|
||
|
ImVfbSInc( vfb, p );
|
||
|
|
||
|
}
|
||
|
|
||
|
if ( ImBinWrite( ioType, fd, fp, buffer, UCHAR, 1, width * 3 ) == -1 )
|
||
|
|
||
|
{
|
||
|
|
||
|
free( (char *)buffer );
|
||
|
|
||
|
ImReturnBinError();
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
free( (char *)buffer );
|
||
|
|
||
|
}
|
||
|
|
||
|
return ( 0 );
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
* FUNCTION
|
||
|
|
||
|
* imGetFDStr - Read a stream of bytes, looking for a newline
|
||
|
|
||
|
*
|
||
|
|
||
|
* DESCRIPTION
|
||
|
|
||
|
* Read from the file descriptor fd until EOL. Put the string
|
||
|
|
||
|
* into s. Return -2 on failure, -1 on EOF, 0 on success.
|
||
|
|
||
|
*
|
||
|
|
||
|
* STOLEN FROM
|
||
|
|
||
|
* imiff.c Thanks, Todd!
|
||
|
|
||
|
*/
|
||
|
|
||
|
|
||
|
|
||
|
static int /* Returns status */
|
||
|
|
||
|
#ifdef __STDC__
|
||
|
|
||
|
imGetFDStr( int ioType, int fd, FILE *fp, char *buf, int size)
|
||
|
|
||
|
#else
|
||
|
|
||
|
imGetFDStr( ioType, fd, fp, buf, size)
|
||
|
|
||
|
int ioType; /* I/O flags */
|
||
|
|
||
|
int fd; /* Output file descriptor */
|
||
|
|
||
|
FILE *fp; /* Output file pointer */
|
||
|
|
||
|
char *buf; /* Buffer to use */
|
||
|
|
||
|
int size; /* Size of that buffer */
|
||
|
|
||
|
#endif
|
||
|
|
||
|
{
|
||
|
|
||
|
size--; /* predecrement, to prevent read on size == 0 */
|
||
|
|
||
|
do
|
||
|
|
||
|
{
|
||
|
|
||
|
switch ( ImBinRead( ioType, fd, fp, buf, CHAR, 1, 1 ) )
|
||
|
|
||
|
{
|
||
|
|
||
|
case -1: return ( -2 ); /* read error */
|
||
|
|
||
|
case 0: return ( -1 ); /* EOF */
|
||
|
|
||
|
default: break;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
while ( size-- && *buf++ != '\n' );
|
||
|
|
||
|
|
||
|
|
||
|
if ( size <= 0)
|
||
|
|
||
|
return(-2); /* No newline? */
|
||
|
|
||
|
|
||
|
|
||
|
*--buf = '\0';
|
||
|
|
||
|
return( 0 );
|
||
|
|
||
|
}
|
||
|
|