jedioutcast/utils/roq2/libim/imxwd.c

1860 lines
54 KiB
C
Raw Normal View History

2013-04-04 18:02:27 +00:00
/**
** $Header: /roq/libim/imxwd.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/imxwd.c 1 11/02/99 4:38p Zaphod $"
/**
** FILE
** imxwd.c - X Window System window dump file I/O
**
** PROJECT
** libim - SDSC image manipulation library
**
** DESCRIPTION
** imxwd.c contains routines to read and write X XWD files for
** the image manipulation library. Raster data read in is stored
** in a VFB. 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
**
** none
**
** PRIVATE CONTENTS
** imXwdRead f read an X XWD file
** imXwdWrite8 f write an 8-bit X XWD file
** imXwdWriteRGB f write a 24-bit X XWD file
**
** imXwdHeaderInfo t header for X window dump files
** imXwdHeaderFields v header description for binary I/O package
** imXwdColor t CLT entry
**
** imXwd8Read8 f read 8-bit image in 8-bit bitmapUnit
** imXwd8Read16 f read 8-bit image in 16-bit bitmapUnit
** imXwd8Read32 f read 8-bit image in 32-bit bitmapUnit
** imXwd24Read32 f read 24-bit image in 32-bit bitmapUnit
**
** imXwdWriteHeader f write an XWD file header
**
** HISTORY
** $Log: /roq/libim/imxwd.c $
*
* 1 11/02/99 4:38p Zaphod
** Revision 1.12 1995/06/29 00:28:04 bduggan
** updated copyright year
**
** Revision 1.11 1995/04/03 21:42:00 bduggan
** took out #ifdef NEWMAGIC
**
** Revision 1.10 1995/01/10 23:51:41 bduggan
** made read/write routines static
**
** Revision 1.9 94/10/03 11:31:15 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 92/12/03 01:56:59 nadeau
** Corrected info messages.
**
** Revision 1.7 92/11/04 12:11:11 groening
** put ImFIleFormat info and magic number info
** from imfmt.c into this file.
**
** Revision 1.6 92/09/25 17:08:11 vle
** Modified to use byte ordering info in header to read in data. This
** fixes the Decstation bug. Added code to read in window name in
** header, instead of just ignoring it. Updated copyright notice.
** Added ImInfo() messages.
**
** Revision 1.5 92/05/05 16:51:42 vle
** Fixed 24-bit write bug that caused imconv to segmentation fault.
**
** Revision 1.4 92/03/26 11:21:07 vle
** Fixed 24-bit read bug that caused imconv to segmentation fault.
** Added code to more closely match xwud.c's interpretation of
** the "flags" field.
**
** Revision 1.3 91/10/03 09:25:42 nadeau
** Added 24-bit image read and write support.
**
** Revision 1.2 91/02/12 10:49:11 nadeau
** Removed the tag table checking and VFB conversion now
** handled by ImFileRead and ImFileWrite.
**
** Revision 1.1 90/07/25 16:21:46 nadeau
** Initial revision
**/
#include "iminternal.h"
/**
** FORMAT
** XWD - X Window System window dump
**
** AKA
** x11
**
** FORMAT REFERENCES
** Xlib - C Language X Interface, MIT X Window System, Version 11.
**
** CODE CREDITS
** Custom development, Dave Nadeau, San Diego Supercomputer Center, 1990.
**
** DESCRIPTION
** The X Window System's XWD (X Window Dump) format is that produced
** by the 'xwd' utility in the X tool set. XWD files may be redisplayed
** using 'xwud' (un-dump).
**
** Version 11 of X upgraded the XWD format from its larval stages in
** version 10. This code only supports the X11 version.
**
** XWD files start with a fixed size header describing the file's contents:
**
** headerSize The size of the "entire" header, in bytes. The "entire"
** header includes the fixed size header, and a window
** name string immediately following the header.
**
** version The format's version number. For X10, this is a 6.
** For X11, this is a 7.
**
** pixmapFormat The storage format for the image. One of:
**
** XY bitmap A 1-bit deep image. Consecutive
** bits are for consecutive pixels.
**
** XY pixmap A multi-bit deep image. Consecutive
** bits are for consecutive pixels, one
** plane at a time. (ie., all of bit
** plane 1, then all of bit plane 2, ...).
**
** Z pixmap A multi-bit deep image. Consecutive
** bits make up a complete multi-bit pixel,
** followed by the next pixel, ...
**
** pixmapDepth The number of bits that make up one pixel.
**
** pixmapWidth The width of the image, in pixels.
**
** pixmapHeight The height of the image, in pixels.
**
** xOffset An offset for the image in the X direction. Ignored
** by this and most software.
**
** byteOrder The byte order for multi-byte data. Only relevant
** when the bitmapUnit (see below) is greater than one
** byte.
**
** bitmapUnit The unit of storage for pixel data. Pixels of size
** bitsPerPixel (see blow) are packed into chunks of
** size bitmapUnit bits. For example, 8-bit index
** images might have bitsPerPixel = 8, and bitmapUnit
** = 32.
**
** bitmapBitOrder The order of bits within a byte of data.
**
** bitmapPad The unit of storage to which scanlines are padded.
** Usually the same as bitmapUnit.
**
** bitsPerPixel The number of bits that make up one pixel, as stored
** in the file. For a 24-bit image, the pixmapDepth
** would be 24, but the bitsPerPixel could be 32. This
** indicates that each 32-bit file quantity contains
** 24 bits of pixel data and 8 bits that are to be ignored.
**
** bytesPerLine The number of bytes of data per scanline, including
** padding (see bitmapPad).
**
** visualClass How colormaps are handled. One of
**
** StaticGrey Fixed colormap greyscale
** GreyScale Variable colormap greyscale
**
** StaticColor Fixed colormap color
** PseudoColor Variable colormap color
**
** TrueColor Fixed RGB
** DirectColor Variable RGB
**
** 8-bit index displays are StaticColor if the CLT is
** not changeable (owned by the server?), and PseudoColor
** if the CLT can be changed to that of the image. A
** StaticColor image displayed by 'xwud' uses the server's
** default CLT. A PseudoColor image displayed by 'xwud'
** uses the CLT given with the image. When the cursor
** is outside the image's window, the normal CLT's are
** used. When the cursor is inside the window, the
** image's CLT is used.
**
** RGB displays are almost always TrueColor. DirectColor
** displays use a CLT at the "backend" of the display
** hardware and are usually only there for fancy gamma
** correction.
**
** redMask A mask to get the red-component bits from an RGB pixel.
**
** greenMask A mask to get the green-component bits from an RGB pixel
**
** blueMask A mask to get the blue-component bits from an RGB pixel.
**
** bitsPerRGB The number of bits for one component of an RGB image.
** Typically 8.
**
** colormapEntries The maximum number of entries allowed in a CLT. This
** is 2 to the power bitsPerPixel. For 8-bit images,
** this would be 256.
**
** nColors The number of CLT entries actually given in the image
** file. This may be less than or equal to
** colormapEntries.
**
** windowWidth The width of the window to display the image.
**
** windowHeight The height of the window to display the image.
**
** windowX The X location of the window to display the image.
**
** windowY The Y location of the window to display the image.
**
** windowBorderWith The width of the border around the window to display
** the image.
**
** headerEnd 32-bits of padding to make the header an even number
** of 32-bit words. However, it appears that even the
** Cray does not use this field, so we drop it.
**
** Immediately following the fixed size header is a variable number of
** bytes giving the name of the window, NULL terminated. The number of
** bytes is given by (headerSize - sizeof( header )), where sizeof(
** header ) is, of course, given in a non-machine-specific way.
**
** If the window has no name, 'xwd' uses the name 'xwdump'.
**
** Following the header (headerSize bytes into the file) are zero or more
** CLT entries (see nColors). Each CLT entry gives:
**
** pixel The CLT index at which to store the color.
**
** red,green,blue The RGB components of the color. Color components are
** each 16-bits wide. Color values are scaled down to
** fit into standard 8-bit per component CLTs:
**
** CLT[pixel].red = red * 256 / 65536
** CLT[pixel].green = green * 256 / 65536
** CLT[pixel].blue = blue * 256 / 65536
**
** flags Flags indicating which of the components should be
** stored into the CLT entry. Flags is the bitwise OR of:
**
** DoRed store the red component
** DoGreen store the green component
** DoBlue store the blue component
**
** Note: X11R5 xwud incorrectly ignores this field,
** so images that xwud displays uses the whole CLT.
** This does not follow the X Window specs!
**
** pad Unused space to pad structure to a multiple of 4 bytes
** in length.
**
** After all that is the image data.
**
** IMAGE DATA READ ALGORITHM
** With all of the bitsPerThis and bytesPerThat fields in the header,
** a very wide range of pixel storage arrangements are possible. A
** generic read algorithm might be structured as follows:
**
** -- read in the raw data
** nBytes = bytesPerLine * pixmap_Height
** read nBytes of data into buffer
**
** -- byte swap based on byteOrder and bitmapUnit
** if byteOrder is MBF,
** for each group of (bitmapUnit/8) bytes,
** reverse their order
**
** -- bit swap based on bitmapBitOrder
** if bitmapBitOrder is MBF,
** for each byte,
** reverse the bit order
**
** -- copy them to the VFB
** for each scanline,
** for each pixel in the scanline,
** copy the next pixmapDepth bits into VFB
** advance to next VFB pixel
** advance in buffer by bitsPerPixel bits
** skip to the next bitmapPad bit boundary
**
** This algorithm is generic and handles all of the quirky features of
** the header. It is also painfully slow.
**
** The reality of image storage is that there are only a couple common
** configurations:
**
** pixmapDepth 8 or 24
** byteOrder MBF or LBF (but usually MBF)
** bitmapUnit 8, 16, or 32 (but usually 32)
** bitmapBitOrder LBF
** bitmapPad 8, 16, or 32 (but usually 32)
** bitsPerPixel 8 or 32
**
** Rather than use a generic, but very slow algorithm for image data
** read, this code uses four depth-specific read routines that handle
** each of the common image depth cases:
**
** pixmapDepth 8
** bitmapUnit 8
**
** pixmapDepth 8
** bitmapUnit 16
**
** pixmapDepth 8
** bitmapUnit 32
**
** pixmapDepth 24
** bitmapUnit 32
**
** All other cases are considered unreadable.
**
** RESTRICTIONS
** In addition to the read restrictions discussed above, this code
** handles XWD file header information as follows on read operations:
**
** version Must be 7.
** pixmapFormat Must be a Z pixmap.
** xOffset Ignored.
** visualClass Ignored.
** window* Ignored.
**
** Images written by this code set header values to the following:
**
** version Always 7.
** pixmapFormat Always a Z pixmap.
** pixmapDepth Always 8 or 24.
** xOffset Always 0.
** byteOrder Always MBF.
** bitmapUnit Always 8 or 32 bits.
** bitmapBitOrder Always MBF.
** bitmapPad Always the same as bitmapUnit.
** bitsPerPixel Always 8 or 32.
** visualClass Always PseudoColor (8-bit) or TrueColor (RGB).
** windowWidth Always the same as pixmapWidth.
** windowHeight Always the same as pixmapHeight.
** windowX Always 0.
** windowY Always 0.
** windowBorderWidth Always 0.
**/
/*
* Flag the removal of the optional 'headerEnd' field of the header. This
* field is flagged in the standard X XWDFile.h include file as only being
* included on 64-bit systems. However, the Cray doesn't even include it.
* So, we don't either.
*/
#define no_headerEnd
/*
* XWD - MIT X11 Window System Window Dump
* For information on these structures, how to use them, etc. please
* see imfmt.c.
*/
#ifdef __STDC__
static int imXwdRead( int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable );
static int imXwdWrite8( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp,
TagTable *flagsTable, TagTable *tagTable );
static int imXwdWriteRGB( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp,
TagTable *flagsTable, TagTable *tagTable );
#else
static int imXwdRead( );
static int imXwdWrite8( ), imXwdWriteRGB( );
#endif
#ifdef notdef
static int imXwdWrite1( );
#endif
static char *imXwdNames[ ] = { "xwd", "x11", NULL };
static ImFileFormatReadMap imXwdReadMap[ ] =
{
/* in out */
/* type,ch,dep, attr. VFB type attr. */
#ifdef notdef
{ IN,1,1, 0, IMVFBMONO, 0 },
{ IN,1,1, C, IMVFBMONO, C },
#endif
{ IN,1,8, 0, IMVFBINDEX8, 0 },
{ IN,1,8, C, IMVFBINDEX8, C },
{ RGB,3,8, 0, IMVFBRGB, 0 },
{ RGB,3,8, C, IMVFBRGB, 0 },
{ -1, 0, -1, 0 },
};
static ImFileFormatWriteMap imXwdWriteMap[ ] =
{
/* in out */
/* VFB type, attr., type,ch,dep, attr., func */
#ifdef notdef
{ IMVFBMONO, 0, IN,1,1, 0, imXwdWrite1 },
{ IMVFBMONO, C, IN,1,1, C, imXwdWrite1 },
{ IMVFBINDEX8, 0, IN,1,8, 0, imXwdWrite8 },
#endif
{ IMVFBINDEX8, C, IN,1,8, C, imXwdWrite8 },
{ IMVFBRGB, 0, RGB,3,8, 0, imXwdWriteRGB },
{ -1, 0, -1, 0, NULL },
};
static ImFileMagic imFileXwdMagic []=
{
{ 0, 0, NULL },
};
ImFileFormat ImFileXwdFormat =
{
imXwdNames, "X Window System window dump image file",
"X Consortium / MIT",
#ifdef notdef
"1-bit XY format bitmaps. 8-bit and 24-bit RGB Z format pixmaps.\n\
8-bit and 24-bit RGB Z format pixmaps, with or without a CLT.",
"1-bit XY format bitmaps. 8-bit and 24-bit RGB Z format pixmaps.\n\
8-bit and 24-bit RGB Z format pixmaps, with or without a CLT.",
#else
"8-bit and 24-bit RGB Z format pixmaps, with or without a CLT.",
"8-bit with CLT and 24-bit RGB Z format pixmaps without CLT.",
#endif
imFileXwdMagic,
IMNOMULTI, IMPIPE,
IMNOMULTI, IMPIPE,
imXwdRead, imXwdReadMap, imXwdWriteMap
};
/*
* TYPEDEF & STRUCT
* imXwdHeaderInfo - header for X window dump files
* imXwdHeaderFields - header description for binary I/O package
*
* DESCRIPTION
* XWD files start with a header that gives various details of the
* image contained in the file. Different formats of image storage
* will use different numbers of fields in the header, the other fields
* being ignored.
*
* Immediately following the header is the name of the window, if any.
*/
typedef struct imXwdHeaderInfo /* X11 window dump, version 7 */
{
unsigned long xwd_pixmapFormat; /* Pixmap format */
unsigned long xwd_pixmapDepth; /* Pixmap depth */
unsigned long xwd_pixmapWidth; /* Pixmap width */
unsigned long xwd_pixmapHeight; /* Pixmap height */
unsigned long xwd_xOffset; /* Bitmap x offset */
unsigned long xwd_byteOrder; /* MSBFirst, LSBFirst */
unsigned long xwd_bitmapUnit; /* Bitmap unit */
unsigned long xwd_bitmapBitOrder; /* MSBFirst, LSBFirst */
unsigned long xwd_bitmapPad; /* Bitmap scanline pad */
unsigned long xwd_bitsPerPixel; /* Bits per pixel */
unsigned long xwd_bytesPerLine; /* Bytes per scanline */
unsigned long xwd_visual; /* Class of colormap */
unsigned long xwd_redMask; /* Red mask */
unsigned long xwd_greenMask; /* Green mask */
unsigned long xwd_blueMask; /* Blue mask */
unsigned long xwd_bitsPerRGB; /* Log base 2 of distinct color */
unsigned long xwd_colormapEntries; /* Number of entries in colormap*/
unsigned long xwd_nColors; /* Number of Color structures */
unsigned long xwd_windowWidth; /* Window width */
unsigned long xwd_windowHeight; /* Window height */
long xwd_windowX; /* Window upper left X coordinate*/
long xwd_windowY; /* Window upper left Y coordinate*/
unsigned long xwd_windowBorderWidth; /* Window border width */
#ifndef no_headerEnd
/* Removed since even the Cray doesn't include it in the header.*/
unsigned long xwd_headerEnd; /* Header padding */
#endif
} imXwdHeaderInfo;
static BinField imXwdHeaderFields[ ] =
{
/* xwd_pixmapFormat */ ULONG, 4, 1,
/* xwd_pixmapDepth */ ULONG, 4, 1,
/* xwd_pixmapWidth */ ULONG, 4, 1,
/* xwd_pixmapHeight */ ULONG, 4, 1,
/* xwd_xOffset */ ULONG, 4, 1,
/* xwd_byteOrder */ ULONG, 4, 1,
/* xwd_bitmapUnit */ ULONG, 4, 1,
/* xwd_bitmapBitOrder */ ULONG, 4, 1,
/* xwd_bitmapPad */ ULONG, 4, 1,
/* xwd_bitsPerPixel */ ULONG, 4, 1,
/* xwd_bytesPerLine */ ULONG, 4, 1,
/* xwd_visual */ ULONG, 4, 1,
/* xwd_redMask */ ULONG, 4, 1,
/* xwd_greenMask */ ULONG, 4, 1,
/* xwd_blueMask */ ULONG, 4, 1,
/* xwd_bitsPerRGB */ ULONG, 4, 1,
/* xwd_colormapEntries */ ULONG, 4, 1,
/* xwd_nColors */ ULONG, 4, 1,
/* xwd_windowWidth */ ULONG, 4, 1,
/* xwd_windowHeight */ ULONG, 4, 1,
/* xwd_windowX */ LONG, 4, 1,
/* xwd_windowY */ LONG, 4, 1,
/* xwd_windowBorderWidth */ ULONG, 4, 1,
#ifndef no_headerEnd
/* Removed since even the Cray doesn't include it in the header.*/
/* xwd_headerEnd */ ULONG, 4, 1,
#endif
0, 0, 0,
};
unsigned char *xwd_windowName = NULL; /* XWD window name in file */
#ifndef no_headerEnd
#define IMXWDHEADERSIZE (26 * 4) /* 26 4-byte integers */
/* includes header size & version*/
/* fields not in above struct */
#else
#define IMXWDHEADERSIZE (25 * 4) /* 25 4-byte integers */
/* includes header size & version*/
/* fields not in above struct */
#endif
/*
* Value for xwd_version:
*/
#define IMXWDVERSION 7 /* 1st X11 version */
/*
* Values for xwd_byteOrder and xwd_bitmapBitOrder:
*/
#define IMXWDLBF 0 /* Least significatn first */
#define IMXWDMBF 1 /* Most significatn first */
/*
* Values for xwd_pixmapFormat:
*/
#define IMXWDXYBITMAP 0 /* 1-bit plane bitmap */
#define IMXWDXYPIXMAP 1 /* plane interleaved pixmap */
#define IMXWDZPIXMAP 2 /* uninterleaved pixmap */
/*
* Values for xwd_visual:
*/
#define IMXWDSTATICGREY 0 /* Fixed greyscale */
#define IMXWDGREYSCALE 1 /* Adjustable greyscale */
#define IMXWDSTATICCOLOR 2 /* Fixed colormap */
#define IMXWDPSEUDOCOLOR 3 /* Adjustable colormap */
#define IMXWDTRUECOLOR 4 /* Fixed RGB */
#define IMXWDDIRECTCOLOR 5 /* Adjustable RGB */
/*
* TYPEDEF & STRUCT
* imXwdColor - CLT entry
*
* DESCRIPTION
* Rather than dump the entire CLT to the file, XWD files may contain
* only those CLT entries actually used by the image. Each Color
* structure gives the CLT index to fill and the RGB value to place
* there.
*/
typedef struct imXwdColor
{
unsigned long xwd_pixel; /* CLT index */
unsigned short xwd_red, xwd_green, xwd_blue;/* RGB value for that location*/
char xwd_flags; /* DoRed, DoGreen, DoBlue */
char xwd_pad; /* Unused space */
} imXwdColor;
static BinField imXwdColorFields[ ] =
{
/* xwd_pixel */ ULONG, 4, 1,
/* xwd_red */ USHORT, 2, 1,
/* xwd_green */ USHORT, 2, 1,
/* xwd_blue */ USHORT, 2, 1,
/* xwd_flags */ CHAR, 1, 1,
/* xwd_pad */ CHAR, 1, 1,
0, 0, 0,
};
/*
* Values for xwd_flags:
*/
#define IMXWDDORED (1<<0)
#define IMXWDDOGREEN (1<<1)
#define IMXWDDOBLUE (1<<2)
#define IMXWDNONAME "xwdump"
#ifdef __STDC__
static int imXwd8Read8(int ioType, int fd, FILE *fp, imXwdHeaderInfo *header, ImVfb **vfb);
static int imXwd8Read16(int ioType, int fd, FILE *fp, imXwdHeaderInfo *header, ImVfb **vfb);
static int imXwd8Read32(int ioType, int fd, FILE *fp, imXwdHeaderInfo *header, ImVfb **vfb);
static int imXwd24Read32( int ioType, int fd, FILE *fp, imXwdHeaderInfo *header, ImVfb **vfb, ImClt *clt );
#else
static int imXwd8Read8();
static int imXwd8Read16();
static int imXwd8Read32();
static int imXwd24Read32();
#endif
/*
* FUNCTION
* imXwdRead - read an X XWD file
* imXwd8Read16 - read 16-bit bitmapUnit image
* imXwd8Read32 - read 32-bit bitmapUnit image
*
* DESCRIPTION
* The file header is read, followed by the CLT (if any). Based upon
* the bitmapUnit one of three routines are called to read the image
* data into a new VFB. The VFB (and CLT?) are added to the tag table.
*/
static int /* Returns # tags read in */
#ifdef __STDC__
imXwdRead( int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable )
#else
imXwdRead( 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 pPixel; /* Xwdel pointer */
ImClt *clt; /* Image CLT */
ImCltPtr pColor; /* Color pointer */
imXwdColor color; /* XWD color */
unsigned long mask; /* Pixel index mask */
unsigned long headerSize; /* Size, in bytes, of header */
unsigned long version; /* Format version */
imXwdHeaderInfo header; /* XWD file header */
unsigned char swapBuffer[sizeof(unsigned long)]; /* Byte swapping buffer */
int i; /* Counter */
char message[100]; /* Error message buffer */
/*
* Read in the header size and version number (each 4 bytes long).
*
* We don't know what byte order to use, so we assume MBF and
* read in these two values. If the version number is not one
* we recognize, we try swapping bytes. If we recognize it then,
* then we have an LBF file instead. If we still don't recognize
* it, then probably the file is in a version we don't understand
* and we give up.
*/
BinByteOrder( BINMBF );
if ( ImBinRead( ioType, fd, fp, &headerSize, ULONG, 4, 1 ) == -1 )
ImReturnBinError( );
if ( ImBinRead( ioType, fd, fp, &version, ULONG, 4, 1 ) == -1 )
ImReturnBinError( );
if ( version != IMXWDVERSION )
{
/*
* Swap bytes of version value. Don't depend upon a unsigned long
* being 4 bytes long.
*/
for ( i = 0; i < sizeof( unsigned long ); i++ )
swapBuffer[i] = (version>>(i*8)) & 0xFF;
version = 0;
for ( i = 0; i < sizeof( unsigned long ); i++ )
version = (version << 8) | swapBuffer[i];
if ( version != IMXWDVERSION )
{
sprintf( message, "Unsupported XWD format version. Only support version %d.", IMXWDVERSION );
ImErrorFatal( message, -1, IMEUNSUPPORTED );
}
for ( i = 0; i < sizeof( unsigned long ); i++ )
swapBuffer[i] = (headerSize>>(i*8)) & 0xFF;
headerSize = 0;
for ( i = 0; i < sizeof( unsigned long ); i++ )
headerSize = (headerSize << 8) | swapBuffer[i];
BinByteOrder( BINLBF );
}
/*
* Read in the rest of the header. Skip the window name.
*/
if ( ImBinReadStruct( ioType, fd, fp, &header, imXwdHeaderFields )== -1)
ImReturnBinError( );
i = headerSize - IMXWDHEADERSIZE;
if ( i < 0 )
{
/* Whoa! Stated header size is bogus. Give up! */
ImErrorFatal( "Bogus XWD file header size!", -1, IMESYNTAX );
}
if ( i > 0 ) /* read window name */
{
ImMalloc( xwd_windowName, unsigned char*, i+1 );
if( ImBinRead( ioType, fd, fp, xwd_windowName, UCHAR,
1, i ) == -1 )
{
ImReturnBinError( );
}
TagTableAppend( tagTable, TagEntryAlloc( "image name",
POINTER, &xwd_windowName ) );
}
/*
* Check for unsupported variations.
*/
if ( header.xwd_pixmapFormat != IMXWDZPIXMAP )
{
ImErrorFatal( "Only XWD file Z format pixmaps are supported",
-1, IMEUNSUPPORTED );
}
#ifdef bogus
if ( header.xwd_pixmapDepth != header.xwd_bitsPerPixel )
{
ImErrorFatal( "XWD file image depth not the same as bits per pixel?",
-1, IMEUNSUPPORTED );
}
#endif
if ( header.xwd_pixmapDepth != 8 && header.xwd_pixmapDepth != 24 )
{
ImErrorFatal( "Only 8-bit and 24-bit XWD image depths supported",
-1, IMEUNSUPPORTED );
}
if ( header.xwd_bitmapUnit != 8 && header.xwd_bitmapUnit != 16 &&
header.xwd_bitmapUnit != 32 )
{
ImErrorFatal( "XWD bitmap units must be 8-, 16-, or 32-bits wide",
-1, IMEUNSUPPORTED );
}
if ( (header.xwd_bitmapPad % 8) != 0 )
{
ImErrorFatal( "XWD bitmap pad must be a multiple of 8 bits",
-1, IMEUNSUPPORTED );
}
if ( header.xwd_pixmapDepth == 24 &&
(header.xwd_bitmapPad != 32 || header.xwd_bitmapUnit != 32 ||
header.xwd_bitsPerPixel != 32 ) )
{
ImErrorFatal( "XWD 24-bit images must be stored in 32-bit units",
-1, IMEUNSUPPORTED );
}
/*
* Output -verbose file info
*/
if( xwd_windowName != NULL )
ImInfo( "Window Name", xwd_windowName );
sprintf( message, "%d", version );
ImInfo( "Version", message );
if( header.xwd_byteOrder == IMXWDMBF )
{
ImInfo( "Byte Order", "Most Significant Byte First" );
}
else
{
ImInfo( "Byte Order", "Least Significant Byte First" );
}
sprintf( message, "%d x %d", header.xwd_pixmapWidth,
header.xwd_pixmapHeight );
ImInfo( "Resolution", message );
switch( header.xwd_visual )
{
case IMXWDSTATICGREY:
sprintf( message, "%d-bit Grayscale (Static Grey)",
header.xwd_pixmapDepth );
break;
case IMXWDGREYSCALE:
sprintf( message, "%d-bit Grayscale (Grey Scale)",
header.xwd_pixmapDepth );
break;
case IMXWDSTATICCOLOR:
sprintf( message, "%d-bit Color Indexed (Static Color)",
header.xwd_pixmapDepth );
break;
case IMXWDPSEUDOCOLOR:
sprintf( message, "%d-bit Color Indexed (Pseudo Color)",
header.xwd_pixmapDepth );
break;
case IMXWDTRUECOLOR:
sprintf( message, "%d-bit RGB (True Color)",
header.xwd_pixmapDepth );
break;
case IMXWDDIRECTCOLOR:
sprintf( message, "%d-bit RGB (Direct Color)",
header.xwd_pixmapDepth );
break;
default:
strcpy( message, "unknown" );
break;
}
ImInfo( "Type", message );
/*
* Read in the CLT, if any.
*/
clt = IMCLTNULL;
if ( header.xwd_colormapEntries != 0 && header.xwd_nColors != 0 )
{
if ( (clt = ImCltAlloc( header.xwd_colormapEntries )) ==
IMCLTNULL )
{
ImErrorFatal( ImQError( ), -1, ImErrNo );
}
/*
* Output -verbose info
*/
sprintf( message, "%d Entries",
header.xwd_colormapEntries );
ImInfo( "Color Table", message );
/* Initialize the CLT to black entries. */
pColor = ImCltQFirst( clt );
for ( i = 0; i < header.xwd_colormapEntries; i++ )
{
ImCltSRed( pColor, 0 );
ImCltSGreen( pColor, 0 );
ImCltSBlue( pColor, 0 );
ImCltSInc( clt, pColor );
}
if ( header.xwd_visual == IMXWDDIRECTCOLOR )
mask = ~((~0) << header.xwd_bitsPerRGB);
else
mask = ~0; /* Any pixel index */
/*
* Read in the CLT entries. Scale color components down
* to 8-bit values.
*/
for ( i = 0; i < header.xwd_nColors; i++ )
{
if ( ImBinReadStruct( ioType, fd, fp, &color,
imXwdColorFields ) == -1 )
{
ImReturnBinError( );
}
/*
* Check to see if xwd_flags is zero. If
* yes, assume that all the primary color
* components, RGB, should be used. This
* is to compensate for the xwud code in X11R5
* which incorrectly ignores the flags field.
*
* Remove this conditional if xwud.c is fixed
* to correctly use the flags field.
*
* (see xwud.c, Do_Pseudo(), in X11R5 distribution)
*/
if( color.xwd_flags == 0 )
{
color.xwd_flags = IMXWDDORED|IMXWDDOGREEN|
IMXWDDOBLUE;
}
/*
* if color index given in file is out of range
* of the colortable, just make it the ith
* one.
*/
if( color.xwd_pixel > header.xwd_nColors )
{
pColor = ImCltQPtr( clt, i & mask);
}
else
{
pColor = ImCltQPtr( clt,
(int) color.xwd_pixel & mask );
}
if ( color.xwd_flags & IMXWDDORED )
ImCltSRed( pColor,
(color.xwd_red *255/65535));
if ( color.xwd_flags & IMXWDDOGREEN )
ImCltSGreen( pColor,
(color.xwd_green *255/65535));
if ( color.xwd_flags & IMXWDDOBLUE )
ImCltSBlue( pColor,
(color.xwd_blue *255/65535));
}
}
else /* no colortable */
{
/*
* Output -verbose info
*/
ImInfo( "Color Table", "none" );
}
/*
* Use byteOrder field in header to set Bin package byte
* order for image data.
*/
if ( header.xwd_byteOrder == IMXWDMBF )
{
BinByteOrder( BINMBF );
}
else if ( header.xwd_byteOrder == IMXWDLBF )
{
BinByteOrder( BINLBF );
}
else
{
sprintf( message, "Unknown XWD file byte order: '%d'",
header.xwd_byteOrder );
ImErrorFatal( message, -1, IMEUNSUPPORTED );
}
/*
* Read in the image.
*/
if ( header.xwd_pixmapDepth == 8 )
{
/*
* 8-bit index image.
*
* Image may be stored in units of 8, 16 and 32 bit quantities,
* with padding.
*/
if ( (vfb = ImVfbAlloc( header.xwd_pixmapWidth,
header.xwd_pixmapHeight, IMVFBINDEX8 )) == IMVFBNULL )
ImErrorFatal( ImQError( ), -1, ImErrNo );
ImVfbSClt( vfb, clt ); /* CLT could be NULL */
switch ( header.xwd_bitmapUnit )
{
case 8:
if ( imXwd8Read8( ioType, fd, fp, &header, &vfb)== -1)
{
ImVfbFree( vfb );
return ( -1 ); /* Error already handled */
}
break;
case 16:
if ( imXwd8Read16( ioType, fd, fp, &header,&vfb)== -1)
{
ImVfbFree( vfb );
return ( -1 ); /* Error already handled */
}
break;
case 32:
if ( imXwd8Read32( ioType, fd, fp, &header,&vfb)== -1)
{
ImVfbFree( vfb );
return ( -1 ); /* Error already handled */
}
break;
}
TagTableAppend( tagTable,
TagEntryAlloc( "image clt", POINTER, &clt ) );
TagTableAppend( tagTable,
TagEntryAlloc( "image vfb", POINTER, &vfb ) );
if ( ImVfbQClt( vfb ) != IMCLTNULL )
return ( 2 );
return ( 1 );
}
/*
* RGB image.
*
* Image must be stored in 32-bit quantities, with padding.
*/
if ( (vfb = ImVfbAlloc( header.xwd_pixmapWidth,
header.xwd_pixmapHeight, IMVFBRGB )) == IMVFBNULL )
ImErrorFatal( ImQError( ), -1, ImErrNo );
if ( imXwd24Read32( ioType, fd, fp, &header, &vfb, clt ) == -1 )
{
if ( clt != IMCLTNULL )
ImCltFree( clt );
ImVfbFree( vfb );
return ( -1 ); /* Error already handled */
}
/*
* Add the VFB to the tagTable.
*/
TagTableAppend( tagTable, TagEntryAlloc( "image vfb", POINTER, &vfb ) );
#ifdef notdef
if ( clt != IMCLTNULL )
ImCltFree( clt );
#endif
return ( 1 );
}
/*
* FUNCTION
* imXwd8Read8 - read 8-bit image in 8-bit bitmapUnit
* imXwd8Read16 - read 8-bit image in 16-bit bitmapUnit
* imXwd8Read32 - read 8-bit image in 32-bit bitmapUnit
* imXwd24Read32 - read 24-bit image in 32-bit bitmapUnit
*
* DESCRIPTION
* 8-bit pixel data is read in where:
*
* bitmapUnit = 8 bits
* byteOrder = irrelevant
* bitmapBitOrder = MBF (does any machine use LBF?)
* bitmapPad = 8, 16, or 32
* bitsPerPixel = 8
* bytesPerLine = whatever
*/
static int /* Returns status */
#ifdef __STDC__
imXwd8Read8( int ioType, int fd, FILE *fp, imXwdHeaderInfo *header, ImVfb **vfb )
#else
imXwd8Read8( ioType, fd, fp, header, vfb )
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
imXwdHeaderInfo *header; /* XWD file header */
ImVfb **vfb; /* Read in image */
#endif
{
ImVfbPtr pPixel; /* Pixel pointer */
int y; /* Scanline counter */
int pad; /* # of bytes into next padding */
int nBytes; /* # of bytes per scanline */
unsigned char *buffer; /* Input buffer */
unsigned char *pBufferEnd; /* End of buffer */
unsigned char *pBuffer; /* Buffer pointer */
/* Get space enough for one scanline. */
nBytes = header->xwd_pixmapWidth;
if ( header->xwd_bytesPerLine == 0 )
{
pad = nBytes % (header->xwd_bitmapPad/8);
if ( pad != 0 )
header->xwd_bytesPerLine = nBytes +
header->xwd_bitmapPad / 8 - pad;
else
header->xwd_bytesPerLine = nBytes;
}
ImMalloc( buffer, unsigned char *, header->xwd_bytesPerLine );
/* Read in each scanline and copy it into the VFB. */
pPixel = ImVfbQFirst( *vfb );
pBufferEnd = buffer + nBytes;
for ( y = 0; y < header->xwd_pixmapHeight; y++ )
{
pBuffer = buffer;
if ( ImBinRead( ioType, fd, fp, buffer, UCHAR, 1, header->xwd_bytesPerLine ) == -1 )
{
free( (char *)buffer );
ImReturnBinError( );
}
while ( pBuffer != pBufferEnd )
{
ImVfbSIndex8( *vfb, pPixel, *pBuffer++ );
ImVfbSInc( *vfb, pPixel );
}
}
free( (char *)buffer );
return ( 0 );
}
static int /* Returns status */
#ifdef __STDC__
imXwd8Read16( int ioType, int fd, FILE *fp, imXwdHeaderInfo *header, ImVfb **vfb )
#else
imXwd8Read16( ioType, fd, fp, header, vfb )
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
imXwdHeaderInfo *header; /* XWD file header */
ImVfb **vfb; /* Read in image */
#endif
{
ImVfbPtr pPixel; /* Pixel pointer */
int y; /* Scanline counter */
int pad; /* # of bytes into next padding */
int nBytes; /* # of bytes per scanline */
sdsc_uint16 *buffer; /* Input buffer */
sdsc_uint16 *pBufferEnd; /* End of buffer */
sdsc_uint16 *pBuffer; /* Buffer pointer */
/*
* Read 8-bit image stored in 16-bit units.
*/
nBytes = header->xwd_pixmapWidth;
pad = nBytes % (header->xwd_bitmapPad/8);
if ( pad != 0 )
nBytes += header->xwd_bitmapPad / 8 - pad;
ImMalloc( buffer, sdsc_uint16 *, nBytes );
nBytes /= 2;
pPixel = ImVfbQFirst( *vfb );
/* Compute end. Don't include last partially filled unit. */
pBufferEnd = buffer + (header->xwd_pixmapWidth/2);
/*
* Read in each scanline and copy it into VFB pixels. For speed,
* this is split into two slightly different loops, one for LBF
* and one for MBF data. In both cases each 16-bit quantity is read
* into a host short (which may or may not be 16 bits long). The
* 16-bit value is then split into two pixels by shifting and masking.
* The difference between these two loops is only in the order of
* the pixels in the 16-bit value and the shifting and masking needed.
*/
if ( header->xwd_bitmapBitOrder == IMXWDLBF )
{
/* 1st pixel is at the bottom of the sdsc_uint16. */
for ( y = 0; y < header->xwd_pixmapHeight; y++ )
{
pBuffer = buffer;
if ( ImBinRead( ioType, fd, fp, buffer, UINT16, 2,
nBytes ) == -1 )
{
free( (char *)buffer );
ImReturnBinError( );
}
while ( pBuffer != pBufferEnd )
{
ImVfbSIndex8( *vfb, pPixel, *pBuffer&0xFF );
ImVfbSInc( *vfb, pPixel );
ImVfbSIndex8( *vfb, pPixel, (*pBuffer++>>8)&0xFF );
ImVfbSInc( *vfb, pPixel );
}
if ( pad != 0 )
{
ImVfbSIndex8( *vfb, pPixel, *pBuffer&0xFF );
ImVfbSInc( *vfb, pPixel );
}
}
free( (char *)buffer );
return ( 0 );
}
/* 1st pixel is at the top of the sdsc_uint16. */
for ( y = 0; y < header->xwd_pixmapHeight; y++ )
{
pBuffer = buffer;
if ( ImBinRead( ioType, fd, fp, buffer, UINT16, 2,
nBytes ) == -1 )
{
free( (char *)buffer );
ImReturnBinError( );
}
while ( pBuffer != pBufferEnd )
{
ImVfbSIndex8( *vfb, pPixel, (*pBuffer>>8)&0xFF );
ImVfbSInc( *vfb, pPixel );
ImVfbSIndex8( *vfb, pPixel, *pBuffer++&0xFF );
ImVfbSInc( *vfb, pPixel );
}
if ( pad != 0 )
{
ImVfbSIndex8( *vfb, pPixel, (*pBuffer>>8)&0xFF );
ImVfbSInc( *vfb, pPixel );
}
}
free( (char *)buffer );
return ( 0 );
}
static int /* Returns status */
#ifdef __STDC__
imXwd8Read32( int ioType, int fd, FILE *fp, imXwdHeaderInfo *header, ImVfb **vfb )
#else
imXwd8Read32( ioType, fd, fp, header, vfb )
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
imXwdHeaderInfo *header; /* XWD file header */
ImVfb **vfb; /* Read in image */
#endif
{
ImVfbPtr pPixel; /* Pixel pointer */
int y; /* Scanline counter */
int pad; /* # of bytes into next padding */
int nBytes; /* # of bytes per scanline */
sdsc_uint32 *buffer; /* Input buffer */
sdsc_uint32 *pBufferEnd; /* End of buffer */
sdsc_uint32 *pBuffer; /* Buffer pointer */
int i; /* Counter */
/*
* Read 8-bit image stored in 32-bit units.
*/
nBytes = header->xwd_pixmapWidth;
pad = nBytes % (header->xwd_bitmapPad/8);
if ( pad != 0 )
nBytes += header->xwd_bitmapPad / 8 - pad;
ImMalloc( buffer, sdsc_uint32 *, nBytes );
nBytes /= 4;
pPixel = ImVfbQFirst( *vfb );
/* Compute end. Don't include last partially filled unit. */
pBufferEnd = buffer + (header->xwd_pixmapWidth/4);
/*
* Read in each scanline and copy it into VFB pixels. For speed,
* this is split into two slightly different loops, one for LBF
* and one for MBF data. In both cases each 32-bit quantity is read
* into a host int (which may or may not be 32 bits long). The
* 32-bit value is then split into four pixels by shifting and masking.
* The difference between these two loops is only in the order of
* the pixels in the 32-bit value and the shifting and masking needed.
*/
if ( header->xwd_bitmapBitOrder == IMXWDLBF )
{
/* 1st pixel is at bottom of sdsc_uint32. */
for ( y = 0; y < header->xwd_pixmapHeight; y++ )
{
pBuffer = buffer;
if ( ImBinRead( ioType, fd, fp, buffer, UINT32, 4,
nBytes ) == -1 )
{
free( (char *)buffer );
ImReturnBinError( );
}
while ( pBuffer != pBufferEnd )
{
ImVfbSIndex8( *vfb, pPixel, *pBuffer&0xFF );
ImVfbSInc( *vfb, pPixel );
ImVfbSIndex8( *vfb, pPixel, (*pBuffer>>8)&0xFF );
ImVfbSInc( *vfb, pPixel );
ImVfbSIndex8( *vfb, pPixel, (*pBuffer>>16)&0xFF );
ImVfbSInc( *vfb, pPixel );
ImVfbSIndex8( *vfb, pPixel, (*pBuffer>>24)&0xFF );
ImVfbSInc( *vfb, pPixel );
pBuffer++;
}
for ( i = 0; i < pad; i++ )
{
ImVfbSIndex8( *vfb, pPixel, (*pBuffer>>(i*8))&0xFF );
ImVfbSInc( *vfb, pPixel );
}
}
free( (char *)buffer );
return ( 0 );
}
/* 1st pixel is at top of sdsc_uint32. */
for ( y = 0; y < header->xwd_pixmapHeight; y++ )
{
pBuffer = buffer;
if ( ImBinRead( ioType, fd, fp, buffer, UINT32, 4,
nBytes ) == -1 )
{
free( (char *)buffer );
ImReturnBinError( );
}
while ( pBuffer != pBufferEnd )
{
ImVfbSIndex8( *vfb, pPixel, (*pBuffer>>24)&0xFF );
ImVfbSInc( *vfb, pPixel );
ImVfbSIndex8( *vfb, pPixel, (*pBuffer>>16)&0xFF );
ImVfbSInc( *vfb, pPixel );
ImVfbSIndex8( *vfb, pPixel, (*pBuffer>>8)&0xFF );
ImVfbSInc( *vfb, pPixel );
ImVfbSIndex8( *vfb, pPixel, *pBuffer&0xFF );
ImVfbSInc( *vfb, pPixel );
pBuffer++;
}
for ( i = 0; i < pad; i++ )
{
ImVfbSIndex8( *vfb, pPixel, (*pBuffer>>(24-i*8))&0xFF );
ImVfbSInc( *vfb, pPixel );
}
}
free( (char *)buffer );
return ( 0 );
}
static int /* Returns status */
#ifdef __STDC__
imXwd24Read32( int ioType, int fd, FILE *fp, imXwdHeaderInfo *header, ImVfb **vfb, ImClt *clt )
#else
imXwd24Read32( ioType, fd, fp, header, vfb, clt )
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
imXwdHeaderInfo *header; /* XWD file header */
ImVfb **vfb; /* Read in image */
ImClt *clt; /* CLT to apply */
#endif
{
ImVfbPtr pPixel; /* Pixel pointer */
int y; /* Scanline counter */
int nPix; /* # of pixels per scanline */
sdsc_uint32 *buffer; /* Input buffer */
sdsc_uint32 *pBufferEnd; /* End of buffer */
sdsc_uint32 *pBuffer; /* Buffer pointer */
sdsc_uint32 redMask; /* Mask to get red value */
sdsc_uint32 greenMask; /* Mask to get green value */
sdsc_uint32 blueMask; /* Mask to get blue value */
int redShift; /* Shift to put red into 8-bits */
int greenShift; /* Shift to put green into 8-bits*/
int blueShift; /* Shift to put blue into 8-bits*/
sdsc_uint32 tmp; /* Temp value holder */
ImCltPtr pColor; /* CLT entry pointer */
int index; /* CLT index */
/*
* Read 24-bit image stored in 32-bit units.
*/
nPix = header->xwd_pixmapWidth;
ImMalloc( buffer, sdsc_uint32 *, nPix * sizeof( sdsc_uint32 ) );
pPixel = ImVfbQFirst( *vfb );
pBufferEnd = buffer + header->xwd_pixmapWidth;
/*
* Compute shift values.
*/
tmp = redMask = header->xwd_redMask;
for ( redShift = 0; (tmp&0x1) == 0; redShift++, tmp >>= 1 )
;
tmp = greenMask = header->xwd_greenMask;
for ( greenShift = 0; (tmp&0x1) == 0; greenShift++, tmp >>= 1 )
;
tmp = blueMask = header->xwd_blueMask;
for ( blueShift = 0; (tmp&0x1) == 0; blueShift++, tmp >>= 1 )
;
/*
* Read in each scanline. For each 32-bit quantity, pull out the
* red, green, and blue components as indicated by the header's
* masks.
*/
for ( y = 0; y < header->xwd_pixmapHeight; y++ )
{
pBuffer = buffer;
if ( ImBinRead( ioType, fd, fp, buffer, UINT32, 4, nPix)== -1)
{
free( (char *)buffer );
ImReturnBinError( );
}
while ( pBuffer != pBufferEnd )
{
tmp = *pBuffer++;
if ( clt == IMCLTNULL )
{
ImVfbSRed( *vfb, pPixel,
(tmp&redMask)>>redShift);
ImVfbSGreen( *vfb, pPixel,
(tmp&greenMask)>>greenShift);
ImVfbSBlue( *vfb, pPixel,
(tmp&blueMask)>>blueShift);
}
else
{
index = (tmp&redMask)>>redShift;
pColor = ImCltQPtr( clt, index );
ImVfbSRed( *vfb, pPixel, ImCltQRed( pColor ));
index = (tmp&greenMask)>>greenShift;
pColor = ImCltQPtr( clt, index );
ImVfbSGreen( *vfb, pPixel, ImCltQGreen(pColor));
index = (tmp&blueMask)>>blueShift;
pColor = ImCltQPtr( clt, index );
ImVfbSBlue( *vfb, pPixel, ImCltQBlue( pColor));
}
ImVfbSInc( *vfb, pPixel );
}
}
free( (char *)buffer );
return ( 0 );
}
/*
* FUNCTION
* imXwdWriteHeader - write an XWD file header
*
* DESCRIPTION
* The XWD file header is written out for 8-bit or 24-bit images.
* The header includes the image's name, if any.
*/
static int /* Returns status */
#ifdef __STDC__
imXwdWriteHeader( int ioType, int fd, FILE *fp, ImVfb *vfb, char *name, int writeClt )
#else
imXwdWriteHeader( ioType, fd, fp, vfb, name, writeClt )
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
ImVfb *vfb; /* Read in image */
char *name; /* Window name */
int writeClt; /* Include CLT in XWD file? */
#endif
{
ImClt *clt; /* VFB's CLT */
ImCltPtr pColor; /* CLT color pointer */
imXwdHeaderInfo header; /* XWD file header */
imXwdColor color; /* XWD color holder */
unsigned long headerSize; /* Size of header, in bytes */
unsigned long version; /* Header version number */
int n; /* Counter */
char message[100]; /* ImInfo message */
/*
* Set up the header and write it out. Include a default window
* name after the header.
*/
headerSize = IMXWDHEADERSIZE + strlen( name ) + 1;
version = IMXWDVERSION;
BinByteOrder( BINMBF );
if ( ImBinWrite( ioType, fd, fp, &headerSize, ULONG, 4, 1 ) == -1 )
{
ImReturnBinError( );
}
if ( ImBinWrite( ioType, fd, fp, &version, ULONG, 4, 1 ) == -1 )
{
ImReturnBinError( );
}
header.xwd_pixmapFormat = IMXWDZPIXMAP;
if ( ImVfbQFields( vfb ) & IMVFBINDEX8 )
{
/* 8-bit image. */
header.xwd_pixmapDepth = 8;
header.xwd_bitmapUnit = 8;
header.xwd_redMask = 0;
header.xwd_greenMask = 0;
header.xwd_blueMask = 0;
header.xwd_visual = IMXWDPSEUDOCOLOR;
}
else
{
/* RGB image. */
header.xwd_pixmapDepth = 24;
header.xwd_bitmapUnit = 32;
header.xwd_redMask = 0xFF0000;
header.xwd_greenMask = 0x00FF00;
header.xwd_blueMask = 0x0000FF;
header.xwd_visual = IMXWDTRUECOLOR;
}
header.xwd_pixmapWidth = ImVfbQWidth( vfb );
header.xwd_pixmapHeight = ImVfbQHeight( vfb );
header.xwd_xOffset = 0;
header.xwd_byteOrder = IMXWDMBF; /* Always MBF from us */
header.xwd_bitmapBitOrder = IMXWDMBF;
header.xwd_bitmapPad = header.xwd_bitmapUnit;
header.xwd_bitsPerPixel = header.xwd_bitmapUnit;
header.xwd_bytesPerLine = header.xwd_pixmapWidth * header.xwd_bitsPerPixel / 8;
header.xwd_bitsPerRGB = 8; /* Always 8 */
if ( writeClt )
{
clt = ImVfbQClt( vfb );
header.xwd_colormapEntries = 256;
header.xwd_nColors = ImCltQNColors( clt );
}
else
{
header.xwd_colormapEntries = 0;
header.xwd_nColors = 0;
}
header.xwd_windowWidth = header.xwd_pixmapWidth;
header.xwd_windowHeight = header.xwd_pixmapHeight;
header.xwd_windowX = 0;
header.xwd_windowY = 0;
header.xwd_windowBorderWidth = 0;
#ifndef no_headerEnd
header.xwd_headerEnd = 0;
#endif
if ( ImBinWriteStruct( ioType, fd, fp, &header, imXwdHeaderFields )==-1)
{
ImReturnBinError( );
}
if ( ImBinWrite( ioType, fd, fp, name, UCHAR, 1,
strlen( name ) + 1 ) == -1 )
{
ImReturnBinError( );
}
/*
* Write out the CLT, if any.
*/
if ( writeClt )
{
pColor = ImCltQFirst( clt );
color.xwd_flags = IMXWDDORED | IMXWDDOGREEN | IMXWDDOBLUE;
color.xwd_pad = 0;
for ( n = 0; n < ImCltQNColors( clt ); n++ )
{
color.xwd_pixel = n;
color.xwd_red = ImCltQRed( pColor ) *65535/255;
color.xwd_green = ImCltQGreen( pColor ) *65535/255;
color.xwd_blue = ImCltQBlue( pColor ) *65535/255;
ImCltSInc( clt, pColor );
if ( ImBinWriteStruct( ioType, fd, fp, &color,
imXwdColorFields ) == -1 )
{
ImReturnBinError( );
}
}
}
/*
* Output -verbose file info
*/
if( name != NULL )
ImInfo( "Window Name", name );
sprintf( message, "%d", version );
ImInfo( "Version", message );
if( header.xwd_byteOrder == IMXWDMBF )
{
ImInfo( "Byte Order", "Most Significant Byte First" );
}
else
{
ImInfo( "Byte Order", "Least Significant Byte First" );
}
sprintf( message, "%d x %d", header.xwd_pixmapWidth,
header.xwd_pixmapHeight );
ImInfo( "Resolution", message );
switch( header.xwd_visual )
{
case IMXWDSTATICGREY:
sprintf( message, "%d-bit Grayscale (Static Grey)",
header.xwd_pixmapDepth );
break;
case IMXWDGREYSCALE:
sprintf( message, "%d-bit Grayscale (Grey Scale)",
header.xwd_pixmapDepth );
break;
case IMXWDSTATICCOLOR:
sprintf( message, "%d-bit Color Indexed (Static Color)",
header.xwd_pixmapDepth );
break;
case IMXWDPSEUDOCOLOR:
sprintf( message, "%d-bit Color Indexed (Pseudo Color)",
header.xwd_pixmapDepth );
break;
case IMXWDTRUECOLOR:
sprintf( message, "%d-bit RGB (True Color)",
header.xwd_pixmapDepth );
break;
case IMXWDDIRECTCOLOR:
sprintf( message, "%d-bit RGB (Direct Color)",
header.xwd_pixmapDepth );
break;
default:
strcpy( message, "unknown" );
break;
}
ImInfo( "Type", message );
if( header.xwd_colormapEntries )
{
sprintf( message, "%d Entries",
header.xwd_colormapEntries );
ImInfo( "Color Table", message );
}
else
ImInfo( "Color Table", "none" );
return ( 0 );
}
/*
* FUNCTION
* imXwdWrite8 - write an 8-bit X XWD file
*
* DESCRIPTION
* The XWD file header set up and written out, followed by the CLT
* (if any). The VFB is then written into the file.
*/
static int /* Returns # of tags used */
#ifdef __STDC__
imXwdWrite8( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable )
#else
imXwdWrite8( pMap, ioType, fd, fp, flagsTable, tagTable )
ImFileFormatWriteMap *pMap; /* Write map entry to adhear to */
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
TagTable *flagsTable; /* Flags */
TagTable *tagTable; /* Tag table to read from */
#endif
{
ImVfb *vfb; /* Read in image */
ImVfbPtr pPixel; /* Pixel pointer */
unsigned char *buffer; /* Output buffer */
unsigned char *pBuffer; /* Buffer pointer */
char *name; /* Window name */
int x, y; /* Pixel counters */
int width, height; /* Image size */
/*
* Get the image, and its name, and write out the XWD file header.
*/
TagEntryQValue( TagTableQDirect( tagTable, "image vfb", 0 ), &vfb );
if ( TagTableQNEntry( tagTable, "image name" ) != 0 )
TagEntryQValue( TagTableQDirect( tagTable, "image name", 0 ),
&name );
else
name = IMXWDNONAME;
if ( pMap->map_outAttributes & IMCLTYES )
{
if ( imXwdWriteHeader( ioType, fd, fp, vfb, name, TRUE ) == -1 )
return ( -1 ); /* Error already set */
}
else
{
if ( imXwdWriteHeader( ioType, fd, fp, vfb, name, FALSE )== -1 )
return ( -1 ); /* Error already set */
}
/*
* Copy the VFB to the file, one scanline at a time.
*/
pPixel = ImVfbQFirst( vfb );
width = ImVfbQWidth( vfb );
height = ImVfbQHeight( vfb );
ImMalloc( buffer, unsigned char *, width );
for ( y = 0; y < height; y++ )
{
pBuffer = buffer;
for ( x = 0; x < width; x++ )
{
*pBuffer++ = ImVfbQIndex8( vfb, pPixel );
ImVfbSInc( vfb, pPixel );
}
/*
* Write out the buffer.
*/
if ( ImBinWrite( ioType, fd, fp, buffer, UCHAR, 1, width)== -1 )
{
free( (char *)buffer );
ImReturnBinError( );
}
}
free( (char *)buffer );
return ( 1 );
}
/*
* FUNCTION
* imXwdWriteRGB - write a 24-bit X XWD file
*
* DESCRIPTION
* The XWD file header set up and written out, followed by the CLT
* (if any). The VFB is then written into the file.
*/
static int /* Returns # of tags used */
#ifdef __STDC__
imXwdWriteRGB( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp,
TagTable *flagsTable, TagTable *tagTable )
#else
imXwdWriteRGB( pMap, ioType, fd, fp, flagsTable, tagTable )
ImFileFormatWriteMap *pMap; /* Write map entry to adhear to */
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
TagTable *flagsTable; /* Flags */
TagTable *tagTable; /* Tag table to read from */
#endif
{
ImVfb *vfb; /* Read in image */
ImVfbPtr pPixel; /* Pixel pointer */
sdsc_uint32 *buffer; /* Output buffer */
sdsc_uint32 *pBuffer; /* Buffer pointer */
char *name; /* Window name */
int x, y; /* Pixel counters */
int width, height; /* Image size */
/*
* Get the image, and its name, and write out the XWD file header.
*/
TagEntryQValue( TagTableQDirect( tagTable, "image vfb", 0 ), &vfb );
if ( TagTableQNEntry( tagTable, "image name" ) != 0 )
TagEntryQValue( TagTableQDirect( tagTable, "image name", 0 ),
&name );
else
name = IMXWDNONAME;
if ( pMap->map_outAttributes & IMCLTYES )
{
if ( imXwdWriteHeader( ioType, fd, fp, vfb, name, TRUE ) == -1 )
return ( -1 ); /* Error already set */
}
else
{
if ( imXwdWriteHeader( ioType, fd, fp, vfb, name, FALSE )== -1 )
return ( -1 ); /* Error already set */
}
/*
* Copy the VFB to the file, one scanline at a time.
*/
pPixel = ImVfbQFirst( vfb );
width = ImVfbQWidth( vfb );
height = ImVfbQHeight( vfb );
ImMalloc( buffer, sdsc_uint32 *, sizeof( sdsc_uint32 ) * width );
for ( y = 0; y < height; y++ )
{
pBuffer = buffer;
for ( x = 0; x < width; x++ )
{
*pBuffer++ = ((sdsc_uint32) ImVfbQRed( vfb, pPixel ) << 16) |
((sdsc_uint32) ImVfbQGreen( vfb, pPixel ) << 8) |
(sdsc_uint32) ImVfbQBlue( vfb, pPixel );
ImVfbSInc( vfb, pPixel );
}
/*
* Write out the buffer.
*/
if ( ImBinWrite( ioType, fd, fp, buffer, UINT32, 4, width)== -1)
{
free( (char *)buffer );
ImReturnBinError( );
}
}
free( (char *)buffer );
return ( 1 );
}