1860 lines
54 KiB
C
1860 lines
54 KiB
C
|
/**
|
||
|
** $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 );
|
||
|
}
|