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

3715 lines
89 KiB
C
Raw Normal View History

2013-04-22 05:25:59 +00:00
/**
** $Header: /roq/libim/imbmp.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/imbmp.c 1 11/02/99 4:38p Zaphod $"
/**
** FILE
** imbmp.c - Microsoft Windows BMP file I/O
**
** PROJECT
** libim - SDSC image manipulation library
**
** DESCRIPTION
** imbmp.c contains routines to read and write Microsoft Windows BMP
** (DIB) 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
**
** ImFileBmpFormat v file format information
**
** PRIVATE CONTENTS
** imBmpFileHeader t file header information for read
** imBmpHeaderFields v imBmpHeaderInfoRead description for Bin pkg
**
** imBmpFileHeaderWrite t file header information for write
** imBmpHeaderFieldsWrite v imBmpHeaderInfoWrite description for Bin pkg
**
** imBmpRGBQuad t BMP colortable entry
** imBmpRGBQuadFields v imBmpRGBQuad description for Bin pkg
**
** IMBMPCHECKBUFIN m test for full read buffer and do read
** imBmpWrite2Bytes m write two RLE bytes
**
** imBmpRead f read BMP file
** imBmpReadRLE4 f read 4-bit RLE BMP file
** imBmpReadRLE8 f read 8-bit RLE BMP file
**
** imBmpWriteRLE4 f write 4-bit RLE BMP file
** imBmpWriteRLE8 f write 8-bit RLE BMP file
** imBmpWriteRaw1 f write 1-bit uncompressed BMP file
** imBmpWriteRaw4 f write 4-bit uncompressed BMP file
** imBmpWriteRaw8 f write 8-bit uncompressed BMP file
** imBmpWriteRaw24 f write 24-bit uncompressed BMP file
**
** HISTORY
** $Log: /roq/libim/imbmp.c $
**
** 1 11/02/99 4:38p Zaphod
** Revision 1.14 1995/06/29 00:28:04 bduggan
** updated copyright year
**
** Revision 1.13 1995/06/15 20:14:44 bduggan
** Took out 'break's at unreachable points. Took out some
** unused variables.
**
** Revision 1.12 1995/04/03 21:19:36 bduggan
** took out -DNEWMAGIC
**
** Revision 1.11 1994/10/04 20:18:37 bduggan
** added IM to all defines
**
** Revision 1.10 1994/07/20 11:42:23 nadeau
** Changed SDSC custom types to match v3.0 sdsc.h, added ANSI
** C function prototypes, updated read and write maps, updated
** to the new magic number scheme.
**
** Revision 1.9 92/12/03 01:46:13 nadeau
** Corrected info messages.
**
** Revision 1.8 92/11/23 17:49:31 nadeau
** Removed use of IMINFOMSGWIDTH2
**
** Revision 1.7 92/11/04 11:48:24 groening
** put ImFIleFormat info and magic number info
** from imfmt.c into this file.
**
** Revision 1.6 92/10/12 15:53:40 vle
** Made changes to make Cray happy.
**
** Revision 1.5 92/09/29 17:59:17 vle
** Added ImInfo messages.
**
** Revision 1.4 92/09/17 14:06:48 vle
** Fixed "scanlinesize" math bug that caused images to be cropped.
**
** Revision 1.3 92/09/03 18:19:05 vle
** Removed one function parameter from imBmpReadRLE4() and
** imBmpReadRLE8().
**
** Revision 1.2 92/08/31 17:20:57 vle
** Updated copyright notice.
**
** Revision 1.1 92/08/12 16:46:02 vle
** Initial revision
**
**
**/
//#include <unistd.h>
#include "iminternal.h"
/**
** FORMAT
** bmp - Microsoft Windows bitmap image
**
** AKA
** dib (Device Independent Bitmap)
**
** FORMAT REFERENCES
** Microsoft Windows 3.1 Programmer's Reference, volume 3, Microsoft
** Press, 1992.
**
** Microsoft Windows 3.1 Programmer's Reference, volume 3, Microsoft
** Press, 1992.
**
** Graphics File Formats, David C. Kay, John R. Levine, McGraw-Hill,
** 1992.
**
** Supercharged Bitmapped Graphics, Steve Rimmer, McGraw-Hill, 1992.
**
** CODE CREDITS
** Custom development, Vinh Le, San Diego Supercomputer Center, 1992.
**
** DESCRIPTION
** Microsoft's BMP (BitMaP) format, also known as DIB (Device
** Independent Bitmap) format, is used in Microsoft's Windows
** versions 3.0 and up for bitmap image storage.
**
** The BMP format consists of four segments:
**
** Bitmap-File Header
** Bitmap-Info Header
** ColorTable
** BitmapBits
**
**
** Bitmap-File Header (14 bytes)
** ------------------
**
** The Bitmap-File Header contains information about the type,
** size, and layout of a device-independent bitmap file.
**
** Name Type Size Comments
** ---- ---- ---- --------
** bfType uint 2 bytes type of file, must be BM
** bfSize dword 4 bytes size of the file in bytes
** bfReserved1 uint 2 bytes reserved, must be zero
** bfReserved2 uint 2 bytes reserved, must be zero
** bfOffBits dword 4 bytes offset in bytes from the
** beginning of the file to
** the actual bitmap data in
** the file
**
** ( Note: types above and below are as reported in the Microsoft
** specification and refer to IBM PC-sized values. Usage of the
** SDSC Binary I/O library by this code insures that an appropriate
** portable mapping is made from PC types and sizes to this host's. )
**
** typedef struct tagBITMAPFILEHEADER
** {
** uint bfType;
** dword bfSize;
** uint bfReserved1;
** uint bfReserved2;
** dword bfOffBits;
** } BITMAPFILEHEADER;
**
**
** Bitmap-Info Header (40 bytes)
** ------------------
**
** The Bitmap-Info Header contains information about the bitmap's
** dimensions, compression type, and color format.
**
** Name Type Size Comments
** ---- ---- ---- --------
** biSize dword 4 bytes number of bytes in
** Bitmap-Info Header
** biWidth long 4 bytes width, in pixels
** biHeight long 4 bytes height, in pixels
** biPlanes word 2 bytes number of planes for the
** display device, must be 1
** biBitCount word 2 bytes bits per pixel, must be 1,
** 4, 8 or 24
** biCompression dword 4 bytes BI_RGB(0), no compression
** BI_RLE8(1), RLE compression of
** 8-bits/pixel image
** BI_RLE4(2), RLE compression of
** 4-bits/pixel image
** biSizeImage dword 4 bytes image size in bytes
** biXPelsPerMeter long 4 bytes horizontal resolution in
** pixels per meter, used for
** aspect scaling
** biYPelsPerMeter long 4 bytes vertical resolution in
** pixels per meter, used for
** aspect scaling
** biClrUsed dword 4 bytes number of color indexes
** actually used by bitmap
** biClrImportant dword 4 bytes number of color absolutely
** necessary to display the
** image; if 0, all colors are
** needed
**
** typedef struct tagBITMAPINFOHEADER
** {
** dword biSize;
** long biWidth;
** long biHeight;
** word biPlanes;
** word biBitCount;
** dword biCompression;
** dword biSizeImage;
** long biXPelsPerMeter;
** long biYPelsPerMeter;
** dword biClrUsed;
** dword biClrImportant;
** } BITMAPINFOHEADER;
**
**
** ColorTable (4 bytes per color)
** ----------
**
** ColorTable is an array of RGBQuad's. Each RGBQuad contains color
** intensity values for Red, Green, and Blue.
**
** RGBQuad
** -------
**
** Name Type Size Comment
** ---- ---- ---- -------
** rgbBlue byte 1 byte intensity of blue
** rgbGreen byte 1 byte intensity of green
** rgbRed byte 1 byte intensity of red
** rgbReserved byte 1 byte unused
**
** typedef struct tagRGBQUAD
** {
** byte rgbBlue;
** byte rgbGreen;
** byte rgbRed;
** byte rgbReserved;
** } RGBQUAD;
**
**
** BitmapBits
** ----------
**
** BitmapBits is the actual bitmap image data. It is an array
** of bytes representing consecutive scanlines. The number of
** bytes varies with the resolution and number of colors. Each
** scanline must be zero-padded to a 32-bit boundary. Scanlines
** are stored from the bottom up; that is, the first-byte is in
** the lower-left corner of the image.
**
** The biBitCount field of BITMAPINFOHEADER gives the bits per
** pixel information for the bitmap. Valid values are 1
** (monochrome image, 2 color image), 4 (16 color image),
** 8 (256 color image), or 24 (true color).
**
** Monochrome images have 2 color colortables. They are non-
** compressed, but are pixel packed. 8 pixels are packed into
** each stored byte. A clear bit means use the first color.
** A set bit means use the second color.
**
** 4-bits/pixel images can be non-compressed or compressed.
** Non-compressed images are pixel packed. Each byte stores
** two 4-bit pixels. Compressed images are compressed with
** a 4-bit RLE (RLE4) variant described below.
**
** 8-bits/pixel images can be non-compressed or compressed.
** For non-compressed images, each byte stores one 8-bit pixel.
** Compressed images are compressed with an 8-bit RLE (RLE8)
** variant described below.
**
** 24-bits/pixel images are stored non-compressed. Each pixel
** is represented by 3 bytes. Each byte represents Blue,
** Green, and Red, in this order.
**
** RLE4 - 4-bit RLE Encoding Scheme
** --------------------------------
**
** The 4-bit RLE encoding scheme consists of two modes, Encoded
** and Absolute.
**
** The Encoded Mode consists of two byte pairs.
** 1st byte length of run
** 2nd byte This byte contains 2 color indicies, one in
** the high 4 bits and one in the low 4 bits.
** The run is filled with alternating sequences
** of these indicies.
**
** if the 1st byte is zero (0x00), then the 2nd byte is interpreted
** as follows:
** 0x00 End of scanline
** 0x01 End of bitmap
** 0x02 "Delta". The next two bytes indicate right
** and down movements.
** 0x03- Copy the next 3 to 255 4-bit byte halves
** 0xFF literally. This is the Absolute Mode.
**
** The Absolute Mode is described as above. It always has zero
** (0x00) as the 1st byte. The 2nd byte can range between 0x03
** to 0xFF as described.
**
** ex. Compressed Expanded
** ---------- --------
** 03 04 0 4 0
** 05 06 0 6 0 6 0
** 00 06 45 56 67 00 4 5 5 6 6 7
** 00 02 05 01 Move 5 right and 1 down
** 04 78 7 8 7 8
** 00 00 End of scanline
** 09 1E 1 E 1 E 1 E 1 E 1
** 00 01 End of RLE bitmap
**
** Note: Runs must be word aligned!
**
** RLE8 - 8-bit RLE Encoding Scheme
** --------------------------------
**
** The 8-bit RLE encoding scheme consists of two modes, Encoded
** and Absolute.
**
** The Encoded Mode consists of two byte pairs.
** 1st byte length of run
** 2nd byte byte to repeat in run (color index for pixel)
**
** if the 1st byte is zero (0x00), then the 2nd byte is interpreted
** as follows:
** 0x00 End of scanline
** 0x01 End of bitmap
** 0x02 "Delta". The next two bytes indicate right
** and down movements.
** 0x03- Copy the next 3 - 255 bytes literally.
** 0xFF This is the Absolute Mode.
**
** The Absolute Mode is described as above. It always has zero
** (0x00) as the 1st byte. The 2nd byte can range between 0x03
** to 0xFF as described.
**
** ex. Compressed Expanded
** ---------- --------
** 03 04 04 04 04
** 05 06 06 06 06 06 06
** 00 03 45 56 67 00 45 56 67
** 00 02 05 01 Move 5 right and 1 down
** 02 78 78 78
** 00 00 End of scanline
** 09 1E 1E 1E 1E 1E 1E 1E 1E 1E 1E
** 00 01 End of RLE bitmap
**
** Note: Runs must be word aligned!
**
**/
/*
* FUNCTION DECLARATIONS
*/
#ifdef __STDC__
static int imBmpRead( int, int, FILE *, TagTable *, TagTable * );
static int imBmpReadRLE4( int, int, FILE *, ImVfb *, unsigned int );
static int imBmpReadRLE8( int, int, FILE *, ImVfb *, unsigned int );
static int imBmpWriteRaw1( ImFileFormatWriteMap *, int, int, FILE *,
TagTable *, TagTable * );
static int imBmpWriteRaw4( ImFileFormatWriteMap *, int, int, FILE *,
TagTable *, TagTable * );
static int imBmpWriteRaw8( ImFileFormatWriteMap *, int, int, FILE *,
TagTable *, TagTable * );
static int imBmpWriteRaw24( ImFileFormatWriteMap *, int, int, FILE *,
TagTable *, TagTable * );
static int imBmpWriteRLE4( ImFileFormatWriteMap *, int, int, FILE *,
TagTable *, TagTable * );
static int imBmpWriteRLE8( ImFileFormatWriteMap *, int, int, FILE *,
TagTable *, TagTable * );
#else
static int imBmpRead( ), imBmpReadRLE4( ), imBmpReadRLE8( );
static int imBmpWriteRaw1( ), imBmpWriteRaw4( ), imBmpWriteRaw8( ) ;
static int imBmpWriteRaw24( ), imBmpWriteRLE4( ), imBmpWriteRLE8( ) ;
#endif
/*
* FORMAT INFORMATION
* imBmpNames - format's name and aliases
* imBmpReadMap - read attributes
* imBmpWriteMap - write attributes
* imBmpMagicNumber - magic number
* imBmpMagic - list of magic numbers
* ImFileBmpFormat - master format description
*/
static char *imBmpNames[ ] = { "bmp", "dib", NULL };
static ImFileFormatReadMap imBmpReadMap[ ] =
{
/* in out */
/* type,ch,dep, attr. VFB type attr. */
{ RGB,3,8, 0, IMVFBRGB, 0 },
{ IN,1,8, C, IMVFBINDEX8, C },
{ IN,1,4, C, IMVFBINDEX8, C },
{ IN,1,8, RLE|C, IMVFBINDEX8, C },
{ IN,1,4, RLE|C, IMVFBINDEX8, C },
{ IN,1,1, C, IMVFBINDEX8, C },
{ -1, 0, -1, 0 },
};
static ImFileFormatWriteMap imBmpWriteMap[ ] =
{
/* in out */
/* VFB type, attr., type,ch,dep, attr., func */
{ IMVFBMONO, 0, IN,1,1, C, imBmpWriteRaw1 },
{ IMVFBINDEX8, C, IN,1,8, C, imBmpWriteRaw8 },
{ IMVFBINDEX8, C, IN,1,4, C, imBmpWriteRaw4 },
{ IMVFBINDEX8, C, IN,1,8, RLE|C, imBmpWriteRLE8 },
{ IMVFBINDEX8, C, IN,1,4, RLE|C, imBmpWriteRLE4 },
{ IMVFBRGB, 0, RGB,3,8, 0, imBmpWriteRaw24 },
{ -1, 0, -1, 0, NULL }
};
static unsigned char imBmpMagicNumber[ ] = { 'B', 'M' };
static ImFileMagic imBmpMagic[ ] =
{
{ 0, 2, imBmpMagicNumber },
{ 0, 0, NULL },
};
ImFileFormat ImFileBmpFormat =
{
imBmpNames, /* Names */
"Windows bitmap image file", /* Description */
"Microsoft", /* Creator */
"1-, 4-, and 8-bit color index, and 24-bit RGB color, and\n\
- and 8-bit RLE compressed images.", /* Read support */
"1-, 4-, and 8-bit color index, and 24-bit RGB color, and\n\
- and 8-bit RLE compressed images.", /* Write support*/
imBmpMagic, /* Magic #'s */
IMNOMULTI, IMPIPE, /* Read? */
IMNOMULTI, IMNOPIPE, /* Write? */
imBmpRead, imBmpReadMap, imBmpWriteMap /* Maps */
};
/*
* TYPEDEF & STRUCTURE
* imBmpHeaderInfoRead - BMP file header information for read
* imBmpHeaderFieldsRead - BMP file header fields for binary pkg.
* imBmpHeaderInfoWrite - BMP file header information for write
* imBmpHeaderFieldsWrite - BMP file header fields for binary pkg.
* imBmpRGBQuad - BMP color information
* imBmpRGBQuadFields - BMP color information fields for binary
* pkg.
*
* DESCRIPTION
* imBmpHeaderInfo contains both the Bitmap-File Header and
* Bitmap-Info Header as described in the format specifications.
*
* The imBmpRGBQuad is one entry in the colortable.
*/
typedef struct imBmpHeaderInfoRead
{
sdsc_uint32 bmp_size; /* size of file in bytes */
sdsc_uint16 bmp_reserved1; /* reserved1, must be zero */
sdsc_uint16 bmp_reserved2; /* reserved2, must be zero */
sdsc_uint32 bmp_offsetbits; /* offset to actual bitmap data */
sdsc_uint32 bmp_bisize; /* # bytes in bitmap info header*/
sdsc_uint32 bmp_biwidth; /* image width in pixels */
sdsc_uint32 bmp_biheight; /* image height in pixels */
sdsc_uint16 bmp_biplanes; /* # planes for device, always 1*/
sdsc_uint16 bmp_bibitcount; /* bits/pixel (1, 4, 8, or 24) */
sdsc_uint32 bmp_bicompress; /* compression method */
sdsc_uint32 bmp_bisizeimage; /* image size in bytes */
sdsc_uint32 bmp_bixpm; /* x pixels per meter */
sdsc_uint32 bmp_biypm; /* y pixels per meter */
sdsc_uint32 bmp_biclrused; /* # colors actually used in CLT*/
sdsc_uint32 bmp_biclrim; /* # required colors to display */
} imBmpHeaderInfoRead;
static BinField imBmpHeaderFieldsRead[ ] =
{
{ UINT32, 4, 1 }, /* bmp_size */
{ UINT16, 2, 1 }, /* bmp_reserved1 */
{ UINT16, 2, 1 }, /* bmp_reserved2 */
{ UINT32, 4, 1 }, /* bmp_offsetbits */
{ UINT32, 4, 1 }, /* bmp_bisize */
{ UINT32, 4, 1 }, /* bmp_biwidth */
{ UINT32, 4, 1 }, /* bmp_biheight */
{ UINT16, 2, 1 }, /* bmp_biplanes */
{ UINT16, 2, 1 }, /* bmp_bibitcount */
{ UINT32, 4, 1 }, /* bmp_bicompress */
{ UINT32, 4, 1 }, /* bmp_bisizeimage */
{ UINT32, 4, 1 }, /* bmp_bixpm */
{ UINT32, 4, 1 }, /* bmp_biypm */
{ UINT32, 4, 1 }, /* bmp_biclrused */
{ UINT32, 4, 1 }, /* bmp_biclrim */
{ 0, 0, 0 }
};
typedef struct imBmpHeaderInfoWrite
{
sdsc_uint16 bmp_type; /* type of image, must be 'BM' */
sdsc_uint32 bmp_size; /* size of file in bytes */
sdsc_uint16 bmp_reserved1; /* reserved1, must be zero */
sdsc_uint16 bmp_reserved2; /* reserved2, must be zero */
sdsc_uint32 bmp_offsetbits; /* offset to actual bitmap data */
sdsc_uint32 bmp_bisize; /* # bytes in bitmap info header*/
sdsc_uint32 bmp_biwidth; /* image width in pixels */
sdsc_uint32 bmp_biheight; /* image height in pixels */
sdsc_uint16 bmp_biplanes; /* # planes for device, always 1*/
sdsc_uint16 bmp_bibitcount; /* bits/pixel (1, 4, 8, or 24) */
sdsc_uint32 bmp_bicompress; /* compression method */
sdsc_uint32 bmp_bisizeimage; /* image size in bytes */
sdsc_uint32 bmp_bixpm; /* x pixels per meter */
sdsc_uint32 bmp_biypm; /* y pixels per meter */
sdsc_uint32 bmp_biclrused; /* # colors actually used from CLT*/
sdsc_uint32 bmp_biclrim; /* # required colors to display */
} imBmpHeaderInfoWrite;
static BinField imBmpHeaderFieldsWrite[ ] =
{
{ UINT16, 2, 1 }, /* bmp_type */
{ UINT32, 4, 1 }, /* bmp_size */
{ UINT16, 2, 1 }, /* bmp_reserved1 */
{ UINT16, 2, 1 }, /* bmp_reserved2 */
{ UINT32, 4, 1 }, /* bmp_offsetbits */
{ UINT32, 4, 1 }, /* bmp_bisize */
{ UINT32, 4, 1 }, /* bmp_biwidth */
{ UINT32, 4, 1 }, /* bmp_biheight */
{ UINT16, 2, 1 }, /* bmp_biplanes */
{ UINT16, 2, 1 }, /* bmp_bibitcount */
{ UINT32, 4, 1 }, /* bmp_bicompress */
{ UINT32, 4, 1 }, /* bmp_bisizeimage */
{ UINT32, 4, 1 }, /* bmp_bixpm */
{ UINT32, 4, 1 }, /* bmp_biypm */
{ UINT32, 4, 1 }, /* bmp_biclrused */
{ UINT32, 4, 1 }, /* bmp_biclrim */
{ 0, 0, 0 }
};
typedef struct imBmpRGBQuad
{
unsigned char blue; /* blue intensity */
unsigned char green; /* green intensity */
unsigned char red; /* red intensity */
unsigned char reserved; /* unused */
} imBmpRGBQuad;
static BinField imBmpRGBQuadFields[ ] =
{
{ UCHAR, 1, 1 }, /* blue */
{ UCHAR, 1, 1 }, /* green */
{ UCHAR, 1, 1 }, /* red */
{ UCHAR, 1, 1 }, /* reserved */
{ 0, 0, 0 }
};
/*
* CONSTANTS
* BMP* - assorted useful BMP constants
*/
#define IMBMPMAGIC_MBF 0x424d
/* magic value, 'BM' */
#define IMBMPMAGIC_LBF 0x4d42
/* magic value, 'BM' in reverse byte order */
#define IMBMPFILEHEADERSIZE 14
/* 14 bytes */
#define IMBMPINFOHEADERSIZE 40
/* 40 bytes */
#define IMBMPHEADERSIZE (IMBMPFILEHEADERSIZE + IMBMPINFOHEADERSIZE)
/* size of complete header */
#define IMBMPRGBQUADSIZE 4
/* 4 bytes */
#define IMBMPRGB 0
/* no compression */
#define IMBMPRLE8 1
/* 8-bit RLE compression */
#define IMBMPRLE4 2
/* 4-bit RLE compression */
#define IMBLKSIZE (BUFSIZ)
/* number of bytes to read */
#define IMBMPCHECKBUFIN \
if( bufin > (IMBLKSIZE-1) ) \
{ \
if( ImBinRead( ioType,fd,fp,buf,UCHAR,1,IMBLKSIZE )==-1) \
{ \
ImReturnBinError( ); \
} \
bufin = 0; \
} \
/*
* FUNCTION
* imBmpReadRLE8 - Read a BMP 8-bit RLE compressed image
*
* DESCRIPTION
* This function reads in and decompresses a BMP 8-bit RLE image
* into a vfb. See encoding scheme in FORMAT section.
*/
static int /* Returns status */
#ifdef __STDC__
imBmpReadRLE8( int ioType, int fd, FILE *fp, ImVfb *vfb, unsigned int y )
#else
imBmpReadRLE8( ioType, fd, fp, vfb, y )
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
ImVfb *vfb; /* Pointer to image */
unsigned int y; /* height of image */
#endif
{
ImVfbPtr vfbptr; /* Pointer into vfb image */
unsigned char pair[ 2 ];/* RLE code pair */
unsigned char ampair[ 2 ];/* RLE Absolute Mode pair */
int ycount; /* Current scanline */
unsigned char buf[ IMBLKSIZE ]; /* File input buffer */
int bufin; /* File input buffer index */
int i; /* Counters */
/*
* The image is stored from the bottom up; that is,
* the first scanline in the file is the last
* scanline in the image.
*/
/*
* Go to the last scanline in the vfb
*/
vfbptr = ImVfbQPtr( vfb, 0, y-1 );
/*
* Initializations
*/
ycount = 0;
bufin = IMBLKSIZE;
/*
* Read in and decompress image bitmap
*/
while( ycount < y)
{
/*
* Read in file data into buf
*/
IMBMPCHECKBUFIN;
pair[0] = buf[ bufin++ ];
IMBMPCHECKBUFIN;
pair[1] = buf[ bufin++ ];
if ( pair[0] != 0x00 )
{
/* Encoded Mode */
for( i = 0; i < pair[0]; ++i )
{
ImVfbSIndex8( vfb, vfbptr, pair[1] );
vfbptr = ImVfbQRight( vfb, vfbptr );
}
continue;
}
switch( pair[1] )
{
case 0x00: /* end of scanline */
vfbptr = ImVfbQUp( vfb, vfbptr );
vfbptr = ImVfbQUp( vfb, vfbptr );
++ycount;
break;
case 0x01: /* end of bitmap */
if( ycount != y-1 )
{
/* issue warning to user */
ImErrorWarning( "Unexpected end of bitmap. Input file may be corrupted!", -1, IMEDECODING );
}
return( 1 );
case 0x02: /* "delta", right and down movement */
/*
* Read in file data into buf
*/
IMBMPCHECKBUFIN;
pair[0] = buf[ bufin++ ];
IMBMPCHECKBUFIN;
pair[1] = buf[ bufin++ ];
for( i = 0; i < pair[0]; ++i )
{
vfbptr = ImVfbQRight( vfb, vfbptr );
}
for( i = 0; i < pair[1]; ++i )
{
vfbptr = ImVfbQDown( vfb, vfbptr );
}
break;
default: /* Absolute Mode */
for( i = 0; i < pair[1]/2; ++i )
{
/*
* Read in file data into buf
*/
IMBMPCHECKBUFIN;
ampair[0] = buf[ bufin++ ];
IMBMPCHECKBUFIN;
ampair[1] = buf[ bufin++ ];
ImVfbSIndex8( vfb, vfbptr, ampair[0] );
vfbptr = ImVfbQRight( vfb, vfbptr );
ImVfbSIndex8( vfb, vfbptr, ampair[1] );
vfbptr = ImVfbQRight( vfb, vfbptr );
}
if( (pair[1]%2) != 0 )
{
/*
* Read in file data into buf
*/
IMBMPCHECKBUFIN;
ampair[0] = buf[ bufin++ ];
IMBMPCHECKBUFIN;
ampair[1] = buf[ bufin++ ];
ImVfbSIndex8( vfb, vfbptr, ampair[0] );
vfbptr = ImVfbQRight( vfb, vfbptr );
}
break;
} /* end switch */
}
return( 1 );
}
/*
* FUNCTION
* imBmpReadRLE4 - Read a BMP 4-bit RLE compressed image
*
* DESCRIPTION
* This function reads in and decompresses a BMP 4-bit RLE image
* into a vfb. See encoding scheme in FORMAT section.
*/
static int /* Returns status */
#ifdef __STDC__
imBmpReadRLE4( int ioType, int fd, FILE *fp, ImVfb *vfb, unsigned int y )
#else
imBmpReadRLE4( ioType, fd, fp, vfb, y )
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
ImVfb *vfb; /* Pointer to image */
unsigned int y; /* height of image */
#endif
{
ImVfbPtr vfbptr; /* Pointer into vfb image */
unsigned char pair[ 2 ];/* RLE code pair */
unsigned char ampair[ 2 ];/* RLE Absolute Mode pair */
int ycount; /* Current scanline */
unsigned char buf[ IMBLKSIZE ]; /* File input buffer */
int bufin; /* File input buffer pointer */
int i; /* Counters */
/*
* The image is stored from the bottom up; that is,
* the first scanline in the file is the last
* scanline in the image.
*/
/*
* Go to the last scanline in the vfb
*/
vfbptr = ImVfbQPtr( vfb, 0, y-1 );
/*
* Initializations
*/
ycount = 0;
bufin = IMBLKSIZE;
/*
* Read in and decompress image bitmap
*/
while( ycount < y )
{
/*
* Read in file data into buf
*/
IMBMPCHECKBUFIN;
pair[0] = buf[ bufin++ ];
IMBMPCHECKBUFIN;
pair[1] = buf[ bufin++ ];
if ( pair[0] != 0x00 )
{
/* Encoded Mode */
for( i = 0; i < pair[0]/2; ++i )
{
ImVfbSIndex8( vfb, vfbptr, (pair[1] >> 4) );
vfbptr = ImVfbQRight( vfb, vfbptr );
ImVfbSIndex8( vfb, vfbptr, pair[1] & 0x0F );
vfbptr = ImVfbQRight( vfb, vfbptr );
}
if( pair[0]%2 != 0 )
{
ImVfbSIndex8( vfb, vfbptr, (pair[1] >> 4) );
vfbptr = ImVfbQRight( vfb, vfbptr );
}
continue;
}
switch( pair[1] )
{
case 0x00: /* end of scanline */
vfbptr = ImVfbQUp( vfb, vfbptr );
vfbptr = ImVfbQUp( vfb, vfbptr );
++ycount;
break;
case 0x01: /* end of bitmap */
if( ycount != y-1 )
{
/* issue warning to user */
ImErrorWarning( "Unexpected end of bitmap. Input file may be corrupted!", -1, IMEDECODING );
}
return( 1 );
case 0x02: /* "delta", right and down movement */
/*
* Read in file data into buf
*/
IMBMPCHECKBUFIN;
pair[0] = buf[ bufin++ ];
IMBMPCHECKBUFIN;
pair[1] = buf[ bufin++ ];
for( i = 0; i < pair[0]; ++i )
{
vfbptr = ImVfbQRight( vfb, vfbptr );
}
for( i = 0; i < pair[1]; ++i )
{
vfbptr = ImVfbQDown( vfb, vfbptr );
}
break;
default: /* Absolute Mode */
for( i = 0; i < pair[1]/4; ++i )
{
/*
* Read in file data into buf
*/
IMBMPCHECKBUFIN;
ampair[0] = buf[ bufin++ ];
IMBMPCHECKBUFIN;
ampair[1] = buf[ bufin++ ];
ImVfbSIndex8( vfb, vfbptr,
(ampair[0] >> 4) );
vfbptr = ImVfbQRight( vfb, vfbptr );
ImVfbSIndex8( vfb, vfbptr,
ampair[0] & 0x0F );
vfbptr = ImVfbQRight( vfb, vfbptr );
ImVfbSIndex8( vfb, vfbptr,
(ampair[1] >> 4) );
vfbptr = ImVfbQRight( vfb, vfbptr );
ImVfbSIndex8( vfb, vfbptr,
ampair[1] & 0x0F );
vfbptr = ImVfbQRight( vfb, vfbptr );
}
if( (pair[1]%4) != 0 )
{
/*
* Read in file data into buf
*/
IMBMPCHECKBUFIN;
ampair[0] = buf[ bufin++ ];
IMBMPCHECKBUFIN;
ampair[1] = buf[ bufin++ ];
ImVfbSIndex8( vfb, vfbptr,
(ampair[0] >> 4) );
vfbptr = ImVfbQRight( vfb, vfbptr );
if( pair[1]%4 > 1 )
{
ImVfbSIndex8( vfb, vfbptr,
ampair[0] & 0x0F );
vfbptr = ImVfbQRight( vfb,
vfbptr );
}
if( pair[1]%4 > 2 )
{
ImVfbSIndex8( vfb, vfbptr,
ampair[1] >> 4 );
vfbptr = ImVfbQRight( vfb,
vfbptr );
}
}
break;
} /* end switch */
}
return( 1 );
}
/*
* FUNCTION
* imBmpRead - read a Microsoft Windows Bmp file
*
* DESCRIPTION
* The file header is read and the size of the image determined.
* Space is allocated for the VFB and the file is read into the
* VFB.
*/
static int /* Returns # tags read in */
#ifdef __STDC__
imBmpRead( int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable )
#else
imBmpRead( 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
{
imBmpHeaderInfoRead header; /* BMP file header */
ImVfb *vfb; /* Virtual Frame Buffer */
ImVfbPtr vfbptr; /* Pixel pointer */
ImClt *clt = IMCLTNULL; /* Colortable */
ImCltPtr cltptr; /* Colortable entry pointer */
int x,y; /* Convenient short names */
unsigned char mask; /* Mask for extracting pixels */
sdsc_uint16 bmp_type; /* BMP type (magic number) */
unsigned char *rbuf = NULL; /* read buffer */
unsigned char *rbufptr; /* read buffer data pointer */
unsigned char *sbuf = NULL; /* skip buffer */
unsigned int skipsize = 0; /* number of bytes to skip */
unsigned int scanlinesize; /* length of scanline in bytes */
unsigned int ncolors = 0; /* number of colors used */
unsigned int i, j, k; /* Counters */
char message[100]; /* ImInfo message */
/*
* Set Binary Package byte order and read in BMP type
*/
BinByteOrder( BINLBF );
if( ImBinRead( ioType, fd, fp, &bmp_type, UINT16, 2, 1) == -1 )
{
ImReturnBinError( );
}
/*
* Use BMP type (magic number) to determine byte ordering of rest
* of file
*/
switch( bmp_type )
{
case IMBMPMAGIC_LBF:
/* no need to change byte ordering */
ImInfo( "Byte Order", "Least Significant Byte First" );
break;
case IMBMPMAGIC_MBF:
ImInfo( "Byte Order", "Most Significant Byte First" );
BinByteOrder( BINMBF );
break;
default:
/*
* Bad BMP type (magic number)
*/
ImErrorFatal( ImQError( ), -1, IMEMAGIC );
}
/*
* Read in rest of Bmp file header
*/
if( ImBinReadStruct( ioType, fd, fp, &header,
imBmpHeaderFieldsRead )== -1)
{
ImReturnBinError( );
}
x = header.bmp_biwidth;
y = header.bmp_biheight;
sprintf( message, "%d x %d", x, y );
ImInfo( "Resolution", message );
/*
* Allocate a VFB of the required size and type.
*/
switch( header.bmp_bibitcount )
{
case 1: /* 1-bit index image */
case 4: /* 4-bit index image */
case 8: /* 8-bit index image */
if( (vfb = ImVfbAlloc( x, y, IMVFBINDEX8 )) == IMVFBNULL )
{
ImErrorFatal( ImQError( ), -1, ImErrNo );
}
ImVfbClear( IMVFBINDEX8, 0, vfb );
sprintf( message, "%d-bit Color Indexed", header.bmp_bibitcount );
ImInfo( "Type", message );
break;
case 24: /* 24-bit RGB image */
if( (vfb = ImVfbAlloc( x, y, IMVFBRGB )) == IMVFBNULL )
{
ImErrorFatal( ImQError( ), -1, ImErrNo );
}
ImVfbClear( IMVFBRGB, 0, vfb );
sprintf( message, "24-bit RGB" );
ImInfo( "Type", message );
break;
default: /* unsupported image depth */
ImErrorFatal( ImQError( ), -1, IMEDEPTH );
}
/*
* Allocate and read in colortable, if necessary
*/
if( header.bmp_bibitcount != 24)
{
/*
* Find number of colors used and allocate space
* for colortable
*/
ncolors = header.bmp_biclrused;
if( ncolors == 0 )
{
ncolors = 1 << header.bmp_bibitcount;
}
clt = ImCltAlloc( ncolors );
/*
* Output -verbose messages
*/
sprintf( message, "%d Entries", ncolors );
ImInfo( "Color Table", message );
/*
* Read in colortable and set RGB values
*/
cltptr = ImCltQFirst( clt );
ImMalloc( rbuf, unsigned char*, ncolors*IMBMPRGBQUADSIZE );
rbufptr = rbuf;
if( ImBinRead( ioType, fd, fp, rbuf, UCHAR, 1,
ncolors*IMBMPRGBQUADSIZE ) == -1 )
{
ImReturnBinError( );
}
for( i = 0; i < ncolors; ++i )
{
ImCltSBlue( cltptr, *rbufptr );
++rbufptr;
ImCltSGreen( cltptr, *rbufptr );
++rbufptr;
ImCltSRed( cltptr, *rbufptr );
++rbufptr;
/* skip reserved field */
++rbufptr;
cltptr = ImCltQNext( clt, cltptr );
}
free( rbuf );
/*
* Attach colortable to vfb and append to tagTable
*/
ImVfbSClt( vfb, clt );
TagTableAppend( tagTable, TagEntryAlloc( "image clt",
POINTER, &clt));
}
/*
* Skip to beginning of bitmap data
*/
skipsize = ( (header.bmp_offsetbits - IMBMPHEADERSIZE) -
(ncolors * IMBMPRGBQUADSIZE ) );
if( skipsize > 0 )
{
if( ioType & IMFILEIOFD )
{
ImSeek( ioType, fd, fp, header.bmp_offsetbits, L_SET );
}
else
{
ImMalloc( sbuf, unsigned char*, skipsize );
if( ImBinRead( ioType, fd, fp, sbuf, UCHAR, 1,
skipsize ) == -1 )
{
free( (char*) sbuf );
ImReturnBinError( );
}
free( (unsigned char*) sbuf );
}
}
/*
* Use image compression type info to determine whether to do
* verbatim copy into the vfb or RLE expansion into the vfb
*/
if( header.bmp_bicompress == IMBMPRGB ) /* no compression */
{
/*
* The image is stored from the bottom up; that is,
* the first scanline in the file is the last
* scanline in the image.
*/
/*
* Go to the last scanline in the vfb
*/
vfbptr = ImVfbQPtr( vfb, 0, y-1 );
/*
* Read in non-compressed image
*/
switch( header.bmp_bibitcount )
{
case 1:
ImInfo( "Compression Type", "none" );
/*
* Read 1-bit non-compressed image
*
* 1 bytes contains info for 8 pixels
*
* -------- <- 1 byte
* 12345678
*
* Set = first color in colortable
* Not Set = second color in colortable
*
*/
/*
* Find scanline size to nearest 32-bit
* boundary and allocate read buffer
*
* Note: bit shifting is used to speed up
* calculations
*/
scanlinesize = x>>5;
if( x%32 ) scanlinesize++;
scanlinesize <<= 2;
ImMalloc( rbuf, unsigned char*, scanlinesize );
for( i = 0; i < y ; ++i )
{
if( ImBinRead( ioType, fd, fp,
rbuf, UCHAR, 1, scanlinesize ) == -1)
{
ImReturnBinError( );
}
rbufptr = rbuf;
for( j = 0; j < (x/8); ++j )
{
mask = 128;
for( k = 0; k < 8; ++k )
{
if( ( *(rbufptr) & mask ) == mask )
{
ImVfbSIndex8( vfb, vfbptr, 1 );
}
else
{
ImVfbSIndex8( vfb, vfbptr, 0 );
}
vfbptr = ImVfbQRight( vfb, vfbptr );
mask = mask >> 1;
}
++rbufptr;
}
if( x%8 )
{
mask = 128;
for( k = 0; k < x%8; ++k )
{
if( ( *(rbufptr) & mask ) == mask )
{
ImVfbSIndex8( vfb, vfbptr, 1 );
}
else
{
ImVfbSIndex8( vfb, vfbptr, 0 );
}
vfbptr = ImVfbQRight( vfb, vfbptr );
mask = mask >> 1;
}
}
/*
* Go up two scanline since we
* wrapped-around with ImVfbQRight( )
*/
vfbptr = ImVfbQUp( vfb, vfbptr );
vfbptr = ImVfbQUp( vfb, vfbptr );
}
break;
case 4:
ImInfo( "Compression Type", "none" );
/*
* Read 4-bit non-compressed image
*
* 1 byte contains info for 2 pixels
*
* ---- ---- <-- 1 byte
* 1111 2222
*
*/
/*
* Find scanline size to nearest 32-bit
* boundary and allocate read buffer
*
* Note: bit shifting is used to speed up
* calculations
*/
scanlinesize = x>>3;
if( x%8 ) scanlinesize++;
scanlinesize <<= 2;
ImMalloc( rbuf, unsigned char*, scanlinesize );
/*
* Read in image and store in vfb
*/
for( i = 0; i < y; ++i )
{
if( ImBinRead( ioType, fd, fp,
rbuf, UCHAR, 1, scanlinesize ) == -1)
{
ImReturnBinError( );
}
rbufptr = rbuf;
for( j = 0; j < (x/2); ++j )
{
mask = 0xF0;
ImVfbSIndex8( vfb, vfbptr,
((*(rbufptr) & mask) >> 4) );
vfbptr = ImVfbQRight( vfb, vfbptr );
mask = 0x0F;
ImVfbSIndex8( vfb, vfbptr,
*(rbufptr) & mask );
vfbptr = ImVfbQRight( vfb, vfbptr );
++rbufptr;
}
if( x%2 )
{
mask = 0xF0;
ImVfbSIndex8( vfb, vfbptr,
((*(rbufptr) & mask) >> 4) );
vfbptr = ImVfbQRight( vfb, vfbptr );
}
/*
* Go up two scanline since we
* wrapped-around with ImVfbQRight( )
*/
vfbptr = ImVfbQUp( vfb, vfbptr );
vfbptr = ImVfbQUp( vfb, vfbptr );
}
break;
case 8:
ImInfo( "Compression Type", "none" );
/*
* Read 8-bit non-compressed image
*
* 1 byte contains info for 1 pixel
*
* -------- <-- 1 byte
* 11111111
*
*/
/*
* Find scanline size to nearest 32-bit
* boundary and allocate read buffer
*
* Note: bit shifting is used to speed up
* calculations
*/
scanlinesize = x>>2;
if( x%4 ) scanlinesize++;
scanlinesize <<= 2;
ImMalloc( rbuf, unsigned char*, scanlinesize );
/*
* Read in image and store in vfb
*/
for( i = 0; i < y; ++i )
{
if( ImBinRead( ioType, fd, fp,
rbuf, UCHAR, 1, scanlinesize ) == -1)
{
ImReturnBinError( );
}
rbufptr = rbuf;
for( j = 0; j < x; ++j )
{
ImVfbSIndex8( vfb, vfbptr,
*(rbufptr) );
vfbptr = ImVfbQRight( vfb, vfbptr );
++rbufptr;
}
/*
* Go up two scanline since we
* wrapped-around with ImVfbQRight( )
*/
vfbptr = ImVfbQUp( vfb, vfbptr );
vfbptr = ImVfbQUp( vfb, vfbptr );
}
break;
case 24:
ImInfo( "Compression Type", "none" );
/*
* Read 24-bit non-compressed image
*
* 3 bytes contain info for 1 pixel
*
* -------- -------- -------- <-- 3 bytes
* BBBBBBBB GGGGGGGG RRRRRRRR
*
*/
/*
* Find scanline size to nearest 32-bit
* boundary and allocate read buffer
*
* Note: bit shifting is used to speed up
* calculations
*/
scanlinesize = (x*3)>>2;
if( x%4 ) scanlinesize++;
scanlinesize <<= 2;
ImMalloc( rbuf, unsigned char*, scanlinesize );
/*
* Read in image and store in vfb
*/
for( i = 0; i < y; ++i )
{
if( ImBinRead( ioType, fd, fp,
rbuf, UCHAR, 1, scanlinesize ) == -1)
{
ImReturnBinError( );
}
rbufptr = rbuf;
for( j = 0; j < x; ++j )
{
ImVfbSBlue( vfb, vfbptr, *(rbufptr) );
++rbufptr;
ImVfbSGreen( vfb, vfbptr, *(rbufptr) );
++rbufptr;
ImVfbSRed( vfb, vfbptr, *(rbufptr) );
++rbufptr;
vfbptr = ImVfbQRight( vfb, vfbptr );
}
/*
* Go up two scanline since we
* wrapped-around with ImVfbQRight( )
*/
vfbptr = ImVfbQUp( vfb, vfbptr );
vfbptr = ImVfbQUp( vfb, vfbptr );
}
break;
} /* end switch */
free( (unsigned char*) rbuf );
}
else /* RLE decompression for 4-bit or 8-bit images */
{
switch( header.bmp_bicompress )
{
case IMBMPRLE4:
if( imBmpReadRLE4( ioType, fd, fp, vfb, y ) == -1 )
{
return( -1 );
}
ImInfo( "Compression Type",
"Run Length Encoded (RLE4)" );
break;
case IMBMPRLE8:
if( imBmpReadRLE8( ioType, fd, fp, vfb, y ) == -1 )
{
return( -1 );
}
ImInfo( "Compression Type", "Run Length Encoded (RLE8)" );
break;
default:
/* unknown decompression type */
ImErrorFatal( ImQError( ), -1, IMEIMAGETYPE );
} /* end switch */
}
/*
* Add the VFB to the tagTable.
*/
TagTableAppend( tagTable,
TagEntryAlloc( "image vfb", POINTER, &vfb ) );
return ( 2 );
}
/*
* FUNCTION
* imBmpWriteRaw1 - write an 1-bit non-compressed BMP file
*
* DESCRIPTION
* That VFB is queried, and the BMP file header set up and written out.
* The VFB data is then converted and written out.
*/
static int /* Returns # of tags used */
#ifdef __STDC__
imBmpWriteRaw1( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp,
TagTable *flagsTable, TagTable *tagTable )
#else
imBmpWriteRaw1( 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 list to read from */
#endif
{
imBmpHeaderInfoWrite header; /* BMP file header */
ImVfb *vfb; /* Read in image */
ImVfbPtr vfbptr; /* Vfb pixel pointer */
imBmpRGBQuad cltentry; /* Colortable RGBQuad entry */
ImClt *clt; /* Colortable */
ImCltPtr cltptr; /* Colortable entry pointer */
unsigned char pvalue; /* Pixel value */
unsigned char *wbuf; /* Pointer to write buffer */
unsigned char *wbufptr; /* Pointer to write buffer data */
unsigned int scanlinesize; /* Length of scanline */
unsigned int ncolors = 0; /* Number of colors used */
unsigned char bitfield; /* Bitfield of 8 pixels */
unsigned int x, y; /* Width, Height */
int i, j, k; /* Counters */
char message[100]; /* ImInfo message */
/*
* Set byte ordering
*/
BinByteOrder( BINLBF );
/*
* Get vfb and clt
*/
TagEntryQValue( TagTableQDirect( tagTable, "image vfb", 0 ), &vfb );
clt = ImVfbQClt( vfb );
x = ImVfbQWidth( vfb );
y = ImVfbQHeight( vfb );
/*
* Find scanline size to nearest 32-bit
* boundary and allocate write buffer
*
* Note: bit shifting is used to speed up
* calculations
*/
scanlinesize = x>>5;
if( x%32 ) scanlinesize++;
scanlinesize <<= 2;
if( clt != IMCLTNULL )
{
ncolors = ImCltQNColors( clt );
if( ncolors > 2 )
{
ncolors = 2;
}
}
/*
* Setup header and write it out
*/
header.bmp_type = IMBMPMAGIC_LBF;
header.bmp_size = (unsigned int) ( IMBMPHEADERSIZE +
( 2 * IMBMPRGBQUADSIZE ) +
( scanlinesize * y ) );
/*
* file size = complete header size +
* colortable size + image data size
*/
header.bmp_reserved1 = 0;
header.bmp_reserved2 = 0;
header.bmp_offsetbits = (unsigned int) IMBMPHEADERSIZE +
( 2 * IMBMPRGBQUADSIZE );
/*
* offset to image data =
* BMP header +
* colortable size
*/
header.bmp_bisize = IMBMPINFOHEADERSIZE;
header.bmp_biwidth = x;
header.bmp_biheight = y;
header.bmp_biplanes = 1;
header.bmp_bibitcount = 1;
header.bmp_bicompress = IMBMPRGB;
header.bmp_bisizeimage = scanlinesize * y;
header.bmp_bixpm = 0;
header.bmp_biypm = 0;
header.bmp_biclrused = 0;
header.bmp_biclrim = 0;
if ( ImBinWriteStruct( ioType, fd, fp, &header,
imBmpHeaderFieldsWrite )==-1)
{
ImReturnBinError( );
}
/*
* Output -verbose messages
*/
ImInfo( "Byte Order", "Least Significant Byte First" );
sprintf( message, "%d x %d", x, y );
ImInfo( "Resolution", message );
ImInfo( "Type", "1-bit Color Indexed" );
ImInfo( "Color Table", "2 Entries" );
ImInfo( "Compression Type", "none" );
/*
* Output Color Table
*/
cltentry.reserved = 0;
cltentry.blue = 0;
cltentry.green = 0;
cltentry.red = 0;
if( clt != IMCLTNULL )
{
clt = ImVfbQClt( vfb );
cltptr = ImCltQFirst( clt );
cltentry.blue = (unsigned char) ImCltQBlue( cltptr );
cltentry.green = (unsigned char) ImCltQGreen( cltptr );
cltentry.red = (unsigned char) ImCltQRed( cltptr );
}
if ( ImBinWriteStruct(ioType,fd,fp,&cltentry,imBmpRGBQuadFields )==-1)
{
ImReturnBinError( );
}
cltentry.blue = 255;
cltentry.green = 255;
cltentry.red = 255;
if( clt != IMCLTNULL )
{
cltptr = ImCltQNext( clt, cltptr );
cltentry.blue = (unsigned char) ImCltQBlue( cltptr );
cltentry.green = (unsigned char) ImCltQGreen( cltptr );
cltentry.red = (unsigned char) ImCltQRed( cltptr );
}
if ( ImBinWriteStruct(ioType,fd,fp,&cltentry,imBmpRGBQuadFields )==-1)
{
ImReturnBinError( );
}
/*
* Allocate write buffer space
*/
ImCalloc( wbuf, unsigned char*, scanlinesize, sizeof( unsigned char) );
/*
* Output image bitmap
*/
/*
* Go to last vfb scanline
*/
vfbptr = ImVfbQPtr( vfb, 0, y-1 );
for( i = 0; i < y; ++i )
{
wbufptr = wbuf;
for( j = 0; j < (x/8); ++j )
{
/*
* Pack 8 pixels into a 1 byte bitfield
*
* -------- <-- 1 byte
* 12345678
*
*/
bitfield = 0;
for( k = 0; k < 8; ++k )
{
pvalue = (unsigned char) ImVfbQMono( vfb, vfbptr );
if( pvalue ) {
bitfield = ( bitfield | (1 << (7-k) ) );
}
vfbptr = ImVfbQRight( vfb, vfbptr );
}
*( wbufptr ) = bitfield;
++wbufptr;
}
if( x%8 )
{
/*
* Pack 8 pixels into a 1 byte bitfield
*
* -------- <-- 1 byte
* 12345678
*
*/
bitfield = 0;
for( k = 0; k < x%8; ++k )
{
pvalue = (unsigned char) ImVfbQMono( vfb, vfbptr );
if( pvalue ) {
bitfield = ( bitfield | (1 << (7-k) ) );
}
vfbptr = ImVfbQRight( vfb, vfbptr );
}
*( wbufptr ) = bitfield;
}
if( ImBinWrite( ioType,fd,fp,wbuf,UCHAR,1,scanlinesize ) == -1 )
{
ImReturnBinError( );
}
/*
* Go up two scanline since we
* wrapped-around with ImVfbQRight( )
*/
vfbptr = ImVfbQUp( vfb, vfbptr );
vfbptr = ImVfbQUp( vfb, vfbptr );
}
free( (unsigned char*) wbuf );
return ( 1 );
}
/*
* FUNCTION
* imBmpWriteRaw4 - write a 4-bit non-compressed BMP file
*
* DESCRIPTION
* That VFB is queried, and the BMP file header set up and written out.
* The VFB data is then converted and written out.
*/
static int /* Returns # of tags used */
#ifdef __STDC__
imBmpWriteRaw4( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp,
TagTable *flagsTable, TagTable *tagTable )
#else
imBmpWriteRaw4( 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 list to read from */
#endif
{
imBmpHeaderInfoWrite header; /* BMP file header */
ImVfb *vfb; /* Read in image */
ImVfbPtr vfbptr; /* Vfb pixel pointer */
imBmpRGBQuad cltentry; /* Colortable RGBQuad entry */
ImClt *clt; /* Colortable */
ImCltPtr cltptr; /* Colortable entry pointer */
unsigned char pvalue1; /* Pixel value */
unsigned char pvalue2; /* Pixel value */
unsigned char *wbuf; /* Pointer to write buffer */
unsigned char *wbufptr; /* Pointer to write buffer data */
unsigned int scanlinesize; /* Length of scanline */
unsigned int ncolors = 0; /* Number of colors used */
unsigned int x, y; /* Width, Height */
int i, j; /* Counters */
char message[100]; /* ImInfo message */
/*
* Set byte ordering
*/
BinByteOrder( BINLBF );
/*
* Get vfb and clt
*/
TagEntryQValue( TagTableQDirect( tagTable, "image vfb", 0 ), &vfb );
ImVfbToIndex( vfb, 16, vfb );
clt = ImVfbQClt( vfb );
x = ImVfbQWidth( vfb );
y = ImVfbQHeight( vfb );
/*
* Find scanline size to nearest 32-bit
* boundary and allocate write buffer
*
* Note: bit shifting is used to speed up
* calculations
*/
scanlinesize = x>>3;
if( x%8 ) scanlinesize++;
scanlinesize <<= 2;
ncolors = ImCltQNColors( clt );
if( ncolors > 16 )
{
ncolors = 16;
}
/*
* Setup header and write it out
*/
header.bmp_type = IMBMPMAGIC_LBF;
header.bmp_size = (unsigned int) ( IMBMPHEADERSIZE +
( ncolors * IMBMPRGBQUADSIZE ) +
( scanlinesize * y ) );
/*
* file size = complete header size +
* colortable size + image data size
*/
header.bmp_reserved1 = 0;
header.bmp_reserved2 = 0;
header.bmp_offsetbits = (unsigned int) IMBMPHEADERSIZE +
( ncolors * IMBMPRGBQUADSIZE );
/*
* offset to image data =
* BMP header +
* colortable size
*/
header.bmp_bisize = IMBMPINFOHEADERSIZE;
header.bmp_biwidth = x;
header.bmp_biheight = y;
header.bmp_biplanes = 1;
header.bmp_bibitcount = 4;
header.bmp_bicompress = IMBMPRGB;
header.bmp_bisizeimage = scanlinesize * y;
header.bmp_bixpm = 0;
header.bmp_biypm = 0;
header.bmp_biclrused = (unsigned int) ncolors;
if( ncolors == 16 )
{
header.bmp_biclrused = 0;
}
header.bmp_biclrim = (unsigned int) ncolors;
if ( ImBinWriteStruct( ioType, fd, fp, &header,
imBmpHeaderFieldsWrite )==-1)
{
ImReturnBinError( );
}
/*
* Output -verbose messages
*/
ImInfo( "Byte Order", "Least Significant Byte First" );
sprintf( message, "%d x %d", x, y );
ImInfo( "Resolution", message );
ImInfo( "Type", "4-bit Color Indexed" );
sprintf( message, "%d Entries", ncolors );
ImInfo( "Color Table", message );
ImInfo( "Compression Type", "none" );
/*
* Write colortable
*/
cltptr = ImCltQFirst( clt );
ImMalloc( wbuf, unsigned char*, ncolors*IMBMPRGBQUADSIZE );
wbufptr = wbuf;
for( i = 0; i < ncolors; ++i )
{
*wbufptr = (unsigned char) ImCltQBlue( cltptr );
++wbufptr;
*wbufptr = (unsigned char) ImCltQGreen( cltptr );
++wbufptr;
*wbufptr = (unsigned char) ImCltQRed( cltptr );
++wbufptr;
*wbufptr = 0;
++wbufptr;
cltptr = ImCltQNext( clt, cltptr );
}
if ( ImBinWrite( ioType, fd, fp, wbuf, UCHAR, 1,
ncolors*IMBMPRGBQUADSIZE ) == -1 )
{
ImReturnBinError( );
}
free( wbuf );
/*
* Allocate write buffer space
*/
ImCalloc( wbuf, unsigned char*, scanlinesize, sizeof( unsigned char) );
/*
* Output image bitmap
*/
/*
* Go to last vfb scanline
*/
vfbptr = ImVfbQPtr( vfb, 0, y-1 );
for( i = 0; i < y; ++i )
{
wbufptr = wbuf;
for( j = 0; j < (x/2); ++j )
{
/*
* Pack 2 pixels into 1 byte
*
* ---- ---- <-- 1 byte
* 1111 2222
*
*/
pvalue1 = (unsigned char) ImVfbQIndex8( vfb, vfbptr );
/* check for out of range pvalue */
if( pvalue1 > 15 ) pvalue1 = 15;
vfbptr = ImVfbQRight( vfb, vfbptr );
pvalue2 = (unsigned char) ImVfbQIndex8( vfb, vfbptr );
/* check for out of range pvalue */
if( pvalue2 > 15 ) pvalue2 = 15;
vfbptr = ImVfbQRight( vfb, vfbptr );
*( wbufptr ) = ( ( pvalue1 << 4 ) | pvalue2 );
++wbufptr;
}
if( x%2 )
{
pvalue1 = (unsigned char) ImVfbQIndex8( vfb, vfbptr );
/* check for out of range pvalue */
if( pvalue1 > 15 ) pvalue1 = 15;
vfbptr = ImVfbQRight( vfb, vfbptr );
*( wbufptr ) = ( pvalue1 << 4 );
}
if( ImBinWrite( ioType,fd,fp,wbuf,UCHAR,1,scanlinesize )== -1 )
{
ImReturnBinError( );
}
/*
* Go up two scanline since we
* wrapped-around with ImVfbQRight( )
*/
vfbptr = ImVfbQUp( vfb, vfbptr );
vfbptr = ImVfbQUp( vfb, vfbptr );
}
free( (unsigned char*) wbuf );
return ( 1 );
}
/*
* FUNCTION
* imBmpWriteRaw8 - write an 8-bit non-compressed BMP file
*
* DESCRIPTION
* That VFB is queried, and the BMP file header set up and written out.
* The VFB data is then converted and written out.
*/
static int /* Returns # of tags used */
#ifdef __STDC__
imBmpWriteRaw8( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp,
TagTable *flagsTable, TagTable *tagTable )
#else
imBmpWriteRaw8( 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 list to read from */
#endif
{
imBmpHeaderInfoWrite header; /* BMP file header */
ImVfb *vfb; /* Read in image */
ImVfbPtr vfbptr; /* Vfb pixel pointer */
ImClt *clt; /* Colortable */
ImCltPtr cltptr; /* Colortable entry pointer */
unsigned char *wbuf; /* Pointer to write buffer */
unsigned char *wbufptr; /* Pointer to write buffer data */
unsigned int scanlinesize; /* Length of scanline */
unsigned int ncolors = 0; /* Number of colors used */
unsigned int x, y; /* Width, Height */
int i, j; /* Counters */
char message[100]; /* ImInfo message */
/*
* Set byte ordering
*/
BinByteOrder( BINLBF );
/*
* Get vfb and clt
*/
TagEntryQValue( TagTableQDirect( tagTable, "image vfb", 0 ), &vfb );
clt = ImVfbQClt( vfb );
x = ImVfbQWidth( vfb );
y = ImVfbQHeight( vfb );
/*
* Find scanline size to nearest 32-bit
* boundary and allocate write buffer
*
* Note: bit shifting is used to speed up
* calculations
*/
scanlinesize = x>>2;
if( x%4 ) scanlinesize++;
scanlinesize <<= 2;
ncolors = ImCltQNColors( clt );
if( ncolors > 256 )
{
ncolors = 256;
}
/*
* Setup header and write it out
*/
header.bmp_type = IMBMPMAGIC_LBF;
header.bmp_size = (unsigned int) ( IMBMPHEADERSIZE +
( ncolors * IMBMPRGBQUADSIZE ) +
( scanlinesize * y ) );
/*
* file size = complete header size +
* colortable size + image data size
*/
header.bmp_reserved1 = 0;
header.bmp_reserved2 = 0;
header.bmp_offsetbits = (unsigned int) IMBMPHEADERSIZE +
( ncolors * IMBMPRGBQUADSIZE );
/*
* offset to image data =
* BMP header +
* colortable size
*/
header.bmp_bisize = IMBMPINFOHEADERSIZE;
header.bmp_biwidth = x;
header.bmp_biheight = y;
header.bmp_biplanes = 1;
header.bmp_bibitcount = 8;
header.bmp_bicompress = IMBMPRGB;
header.bmp_bisizeimage = scanlinesize * y;
header.bmp_bixpm = 0;
header.bmp_biypm = 0;
header.bmp_biclrused = (unsigned int) ncolors;
if( ncolors == 256 )
{
header.bmp_biclrused = 0;
}
header.bmp_biclrim = (unsigned int) ncolors;
if( ImBinWriteStruct( ioType, fd, fp, &header,
imBmpHeaderFieldsWrite ) == -1)
{
ImReturnBinError( );
}
/*
* Output -verbose messages
*/
ImInfo( "Byte Order", "Least Significant Byte First" );
sprintf( message, "%d x %d", x, y );
ImInfo( "Resolution", message );
ImInfo( "Type", "8-bit Color Indexed" );
sprintf( message, "%d Entries", ncolors );
ImInfo( "Color Table", message );
ImInfo( "Compression Type", "none" );
/*
* Write colortable
*/
cltptr = ImCltQFirst( clt );
ImMalloc( wbuf, unsigned char*, ncolors*IMBMPRGBQUADSIZE );
wbufptr = wbuf;
for( i = 0; i < ncolors; ++i )
{
*wbufptr = (unsigned char) ImCltQBlue( cltptr );
++wbufptr;
*wbufptr = (unsigned char) ImCltQGreen( cltptr );
++wbufptr;
*wbufptr = (unsigned char) ImCltQRed( cltptr );
++wbufptr;
*wbufptr = 0;
++wbufptr;
cltptr = ImCltQNext( clt, cltptr );
}
if ( ImBinWrite( ioType, fd, fp, wbuf, UCHAR, 1,
ncolors*IMBMPRGBQUADSIZE ) == -1 )
{
ImReturnBinError( );
}
free( wbuf );
/*
* Allocate write buffer space
*/
ImCalloc( wbuf, unsigned char*, scanlinesize, sizeof( unsigned char) );
/*
* Output image bitmap
*/
/*
* Go to last vfb scanline
*/
vfbptr = ImVfbQPtr( vfb, 0, y-1 );
for( i = 0; i < y; ++i )
{
wbufptr = wbuf;
for( j = 0; j < x; ++j )
{
*( wbufptr ) = (unsigned char) ImVfbQIndex8( vfb, vfbptr );
vfbptr = ImVfbQRight( vfb, vfbptr );
++wbufptr;
}
if( ImBinWrite( ioType,fd,fp,wbuf,UCHAR,1,scanlinesize )== -1 )
{
ImReturnBinError( );
}
/*
* Go up two scanline since we
* wrapped-around with ImVfbQRight( )
*/
vfbptr = ImVfbQUp( vfb, vfbptr );
vfbptr = ImVfbQUp( vfb, vfbptr );
}
free( (unsigned char*) wbuf );
return( 1 );
}
/*
* FUNCTION
* imBmpWriteRaw24 - write a 24-bit non-compressed BMP file
*
* DESCRIPTION
* That VFB is queried, and the BMP file header set up and written out.
* The VFB data is then converted and written out.
*/
static int /* Returns # of tags used */
#ifdef __STDC__
imBmpWriteRaw24( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp,
TagTable *flagsTable, TagTable *tagTable )
#else
imBmpWriteRaw24( 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 list to read from */
#endif
{
imBmpHeaderInfoWrite header; /* BMP file header */
ImVfb *vfb; /* Read in image */
ImVfbPtr vfbptr; /* Vfb pixel pointer */
unsigned char *wbuf; /* Pointer to write buffer */
unsigned char *wbufptr; /* Pointer to write buffer data */
unsigned int scanlinesize; /* Length of scanline */
unsigned int x, y; /* Width, height */
int i, j; /* Counters */
char message[100]; /* ImInfo message */
/*
* Set byte ordering
*/
BinByteOrder( BINLBF );
/*
* Get vfb
*/
TagEntryQValue( TagTableQDirect( tagTable, "image vfb", 0 ), &vfb );
x = ImVfbQWidth( vfb );
y = ImVfbQHeight( vfb );
/*
* Find scanline size to nearest 32-bit
* boundary and allocate write buffer
*
* Note: bit shifting is used to speed up
* calculations
*/
scanlinesize = (x*3)>>2;
if( x%4 ) scanlinesize++;
scanlinesize <<= 2;
/*
* Setup header and write it out
*/
header.bmp_type = IMBMPMAGIC_LBF;
header.bmp_size = (unsigned int) ( IMBMPHEADERSIZE +
( scanlinesize * y ) );
/*
* file size = complete header size +
* image data size
*/
header.bmp_reserved1 = 0;
header.bmp_reserved2 = 0;
header.bmp_offsetbits = IMBMPHEADERSIZE;
/*
* offset to image data = BMP header
*/
header.bmp_bisize = IMBMPINFOHEADERSIZE;
header.bmp_biwidth = x;
header.bmp_biheight = y;
header.bmp_biplanes = 1;
header.bmp_bibitcount = 24;
header.bmp_bicompress = IMBMPRGB;
header.bmp_bisizeimage = scanlinesize * y;
header.bmp_bixpm = 0;
header.bmp_biypm = 0;
header.bmp_biclrused = 0;
header.bmp_biclrim = 0;
if( ImBinWriteStruct( ioType, fd, fp, &header,
imBmpHeaderFieldsWrite )==-1)
{
ImReturnBinError( );
}
/*
* Output -verbose messages
*/
ImInfo( "Byte Order", "Least Significant Byte First" );
sprintf( message, "%d x %d", x, y );
ImInfo( "Resolution", message );
ImInfo( "Type", "24-bit RGB" );
ImInfo( "Compression Type", "none" );
/*
* Allocate write buffer space
*/
ImCalloc( wbuf, unsigned char*, scanlinesize, sizeof( unsigned char) );
/*
* Output image bitmap
*/
/*
* Go to last vfb scanline
*/
vfbptr = ImVfbQPtr( vfb, 0, y-1 );
/*
* Output pixels
*/
for( i = 0; i < y; ++i )
{
wbufptr = wbuf;
for( j = 0; j < x; ++j )
{
*( wbufptr ) = (unsigned char) ImVfbQBlue( vfb, vfbptr );
++wbufptr;
*( wbufptr ) = (unsigned char) ImVfbQGreen( vfb, vfbptr );
++wbufptr;
*( wbufptr ) = (unsigned char) ImVfbQRed( vfb, vfbptr );
++wbufptr;
vfbptr = ImVfbQRight( vfb, vfbptr );
}
if( ImBinWrite( ioType,fd,fp,wbuf,UCHAR,1,scanlinesize )== -1 )
{
ImReturnBinError( );
}
/*
* Go up two scanline since we
* wrapped-around with ImVfbQRight( )
*/
vfbptr = ImVfbQUp( vfb, vfbptr );
vfbptr = ImVfbQUp( vfb, vfbptr );
}
free( (unsigned char*) wbuf );
return( 1 );
}
#define imBmpWrite2Bytes( arg1, arg2 ) \
\
buf[ bufin ] = arg1; \
++bufin; \
buf[ bufin ] = arg2; \
++bufin; \
if( bufin > (IMBLKSIZE-1) ) \
{ \
if( ImBinWrite( ioType,fd,fp,buf,UCHAR,1,IMBLKSIZE )==-1) \
{ \
ImReturnBinError( ); \
} \
bufin = 0; \
} \
/*
* FUNCTION
* imBmpWriteRLE4 - write a 4-bit RLE compressed BMP file
*
* DESCRIPTION
* That VFB is queried, and the BMP file header set up and written out.
* The VFB data is then converted and written out. See encoding
* scheme in format section.
*/
static int /* Returns # of tags used */
#ifdef __STDC__
imBmpWriteRLE4( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp,
TagTable *flagsTable, TagTable *tagTable )
#else
imBmpWriteRLE4( 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 list to read from */
#endif
{
imBmpHeaderInfoWrite header; /* BMP file header */
ImVfb *vfb; /* Read in image */
ImVfbPtr vfbptr; /* Vfb pixel pointer */
ImClt *clt; /* Colortable */
ImCltPtr cltptr; /* Colortable entry pointer */
unsigned int ncolors = 0; /* Number of colors used */
unsigned int x, y; /* Width, Height */
unsigned int run; /* Number of consecutive bytes */
unsigned char pixel; /* Temp pixel value */
unsigned int bytecount = 0; /* Bytes in compressed image */
unsigned int nowrite; /* Write status */
unsigned char pixbuf[ 256 ]; /* Pixel buffer */
unsigned char *cbuf; /* Buffer for colortable write */
unsigned char *cbufptr; /* Buffer pointer */
unsigned char buf[ IMBLKSIZE ];/* File write output buffer */
int bufin; /* Output buffer index */
int xcount, ycount; /* Counters */
int i; /* Counters */
int count; /* Counter */
char message[100]; /* ImInfo message */
/*
* Set byte ordering
*/
BinByteOrder( BINLBF );
/*
* Get vfb and clt
*/
TagEntryQValue( TagTableQDirect( tagTable, "image vfb", 0 ), &vfb );
ImVfbToIndex( vfb, 16, vfb );
clt = ImVfbQClt( vfb );
x = ImVfbQWidth( vfb );
y = ImVfbQHeight( vfb );
ncolors = ImCltQNColors( clt );
if( ncolors > 16 )
{
ncolors = 16;
}
/*
* Setup header and write it out
*/
header.bmp_type = IMBMPMAGIC_LBF;
header.bmp_reserved1 = 0;
header.bmp_reserved2 = 0;
header.bmp_offsetbits = (unsigned int) IMBMPHEADERSIZE +
( ncolors * IMBMPRGBQUADSIZE );
/*
* offset to image data =
* BMP header +
* colortable size
*/
header.bmp_bisize = IMBMPINFOHEADERSIZE;
header.bmp_biwidth = x;
header.bmp_biheight = y;
header.bmp_biplanes = 1;
header.bmp_bibitcount = 4;
header.bmp_bicompress = IMBMPRLE4;
header.bmp_bixpm = 0;
header.bmp_biypm = 0;
header.bmp_biclrused = (unsigned int) ncolors;
if( ncolors == 16 )
{
header.bmp_biclrused = 0;
}
header.bmp_biclrim = (unsigned int) ncolors;
if( ImBinWriteStruct( ioType, fd, fp, &header,
imBmpHeaderFieldsWrite ) == -1 )
{
ImReturnBinError( );
}
/*
* Output -verbose messages
*/
ImInfo( "Byte Order", "Least Significant Byte First" );
sprintf( message, "%d x %d", x, y );
ImInfo( "Resolution", message );
ImInfo( "Type", "4-bit Color Indexed" );
sprintf( message, "%d Entries", ncolors );
ImInfo( "Color Table", message );
ImInfo( "Compression Type", "Run Length Encoded (RLE4)" );
/*
* Write colortable
*/
cltptr = ImCltQFirst( clt );
ImMalloc( cbuf, unsigned char*, ncolors*IMBMPRGBQUADSIZE );
cbufptr = cbuf;
for( i = 0; i < ncolors; ++i )
{
*cbufptr = (unsigned char) ImCltQBlue( cltptr );
++cbufptr;
*cbufptr = (unsigned char) ImCltQGreen( cltptr );
++cbufptr;
*cbufptr = (unsigned char) ImCltQRed( cltptr );
++cbufptr;
*cbufptr = 0;
++cbufptr;
cltptr = ImCltQNext( clt, cltptr );
}
if ( ImBinWrite( ioType, fd, fp, cbuf, UCHAR, 1,
ncolors*IMBMPRGBQUADSIZE ) == -1 )
{
ImReturnBinError( );
}
free( cbuf );
/*
* Output image bitmap
*/
/*
* Go to last vfb scanline
*/
vfbptr = ImVfbQPtr( vfb, 0, y-1 );
/*
* RLE encode the image
*/
bytecount = 0;
xcount = 0;
ycount = 0;
bufin = 0;
pixel = ImVfbQIndex8( vfb, vfbptr );
/* check for out of range pixel */
if( pixel > 15 ) pixel = 15;
vfbptr = ImVfbQRight( vfb, vfbptr );
while( ycount < y )
{
/*
* Boundary condition: 1 pixel at the end
* of a scanline.
*/
if( xcount == (x-1) )
{
/*
* Encoded pixel as run of 1
*/
imBmpWrite2Bytes( 1, pixel << 4 );
/*
* Write end of scanline code
*/
imBmpWrite2Bytes( 0, 0 );
/*
* Adjust counters and vfb pointers
*/
bytecount += 4;
xcount = 0;
++ycount;
vfbptr = ImVfbQUp( vfb, vfbptr );
vfbptr = ImVfbQUp( vfb, vfbptr );
pixel = ImVfbQIndex8( vfb, vfbptr );
/* check for out of range pixel */
if( pixel > 15 ) pixel = 15;
vfbptr = ImVfbQRight( vfb, vfbptr );
}
/*
* Boundary condition: 2 pixels at the end
* of a scanline.
*/
if( xcount == (x-2) )
{
/*
* Write the last two pixels as a run of two
*/
imBmpWrite2Bytes( 2, ( pixel << 4 )
| ImVfbQIndex8(vfb,vfbptr) );
/*
* Write end of scanline code
*/
imBmpWrite2Bytes( 0, 0 );
/*
* Adjust counters and vfb pointers
*/
bytecount += 4;
xcount = 0;
++ycount;
vfbptr = ImVfbQRight( vfb, vfbptr );
vfbptr = ImVfbQUp( vfb, vfbptr );
vfbptr = ImVfbQUp( vfb, vfbptr );
pixel = ImVfbQIndex8( vfb, vfbptr );
/* check for out of range pixel */
if( pixel > 15 ) pixel = 15;
vfbptr = ImVfbQRight( vfb, vfbptr );
}
/*
* Encoded Mode - encoding of multiple consecutive
* pixels of the same value into a run and
* pixel value
*/
if( pixel == ImVfbQIndex8( vfb, vfbptr ) )
{
run = 0;
nowrite = TRUE;
/*
* While two adjacent pixels are the same,
* count them up. If we reach the
* end of a scanline, write out the
* current run and pixel. If we
* have a run of 255 pixels, write
* out the run and pixel.
*/
while( pixel == ImVfbQIndex8( vfb, vfbptr ) )
{
++run;
++xcount;
pixel = ImVfbQIndex8( vfb, vfbptr );
/* check for out of range pixel */
if( pixel > 15 ) pixel = 15;
vfbptr = ImVfbQRight( vfb, vfbptr );
/*
* End of a scanline
*/
if( xcount == x-1 )
{
/*
* Write run and pixel value
*/
imBmpWrite2Bytes( run+1, (pixel<<4)
| pixel );
/*
* Write end of scanline code
*/
imBmpWrite2Bytes( 0, 0 );
/*
* Adjust counters and vfb pointers
*/
bytecount += 4;
xcount = 0;
++ycount;
vfbptr = ImVfbQUp( vfb, vfbptr );
vfbptr = ImVfbQUp( vfb, vfbptr );
pixel = ImVfbQIndex8( vfb, vfbptr );
/* check for out of range pixel */
if( pixel > 15 ) pixel = 15;
vfbptr = ImVfbQRight( vfb, vfbptr );
nowrite = FALSE;
break;
}
/*
* End of 255 pixels
*/
if( run == 254 )
{
/*
* Write run and pixel value
*/
imBmpWrite2Bytes( 255, (pixel<<4)
| pixel );
/*
* Adjust counters and vfb pointers
*/
bytecount += 2;
run = 0;
++xcount;
pixel = ImVfbQIndex8( vfb, vfbptr );
/* check for out of range pixel */
if( pixel > 15 ) pixel = 15;
vfbptr = ImVfbQRight( vfb, vfbptr );
nowrite = FALSE;
break;
}
}
/*
* If we haven't written out the run and pixel,
* do it now.
*/
if( nowrite == TRUE )
{
/*
* Write run and pixel
*/
imBmpWrite2Bytes( run+1, (pixel<<4) | pixel );
/*
* Adjust counters and vfb pointers
*/
bytecount += 2;
++xcount;
pixel = ImVfbQIndex8( vfb, vfbptr );
/* check for out of range pixel */
if( pixel > 15 ) pixel = 15;
vfbptr = ImVfbQRight( vfb, vfbptr );
}
}
/*
* Absolute Mode - copying of consecutive different pixels
* literally
*/
if( (pixel != ImVfbQIndex8( vfb, vfbptr ))
&& (xcount < (x-2) )
&& (ycount < y) )
{
run = 0;
nowrite = TRUE;
pixbuf[ 0 ] = pixel;
pixel = ImVfbQIndex8( vfb, vfbptr );
/* check for out of range pixel */
if( pixel > 15 ) pixel = 15;
vfbptr = ImVfbQRight( vfb, vfbptr );
++xcount;
/*
* Since Absolute Mode requires that there
* be at least 3 different adjacent
* pixels, we check for this condition
* first. If there are only 1 or 2
* different adjacent bytes, then
* we write them out as runs of 1
* and pixel.
*/
if( pixel == ImVfbQIndex8( vfb, vfbptr ) )
{
/*
* There is only 1 different pixel
*/
/*
* Write out run and pixel
*/
imBmpWrite2Bytes( 1, pixbuf[ 0 ] << 4 );
bytecount += 2;
nowrite = FALSE;
}
else
{
pixbuf[ 1 ] = pixel;
pixel = ImVfbQIndex8( vfb, vfbptr );
/* check for out of range pixel */
if( pixel > 15 ) pixel = 15;
vfbptr = ImVfbQRight( vfb, vfbptr );
++xcount;
if( pixel == ImVfbQIndex8( vfb, vfbptr ) )
{
/*
* There are only 2 different
* adjacent pixels
*/
/*
* Write run and pixel
*/
imBmpWrite2Bytes( 2, (pixbuf[ 0 ]<<4)
| pixbuf[ 1 ]);
bytecount += 2;
nowrite = FALSE;
}
else
{
/*
* There are at least 3 different
* adjacent pixels, so we reset
* the vfb pointers
*/
xcount -= 2;
vfbptr = ImVfbQLeft( vfb, vfbptr );
vfbptr = ImVfbQLeft( vfb, vfbptr );
vfbptr = ImVfbQLeft( vfb, vfbptr );
pixel = ImVfbQIndex8( vfb, vfbptr );
/* check for out of range pixel */
if( pixel > 15 ) pixel = 15;
vfbptr = ImVfbQRight( vfb, vfbptr );
}
}
/*
* While adjacent pixels are different, count them
* up and store them in pixbuf.
*/
while( pixel != ImVfbQIndex8( vfb, vfbptr ) )
{
pixbuf[ run ] = pixel;
pixel = ImVfbQIndex8( vfb, vfbptr );
/* check for out of range pixel */
if( pixel > 15 ) pixel = 15;
vfbptr = ImVfbQRight( vfb, vfbptr );
++run;
++xcount;
/*
* End of scanline
*/
if( xcount == x-1 )
{
pixbuf[ run ] = pixel;
pixbuf[ run+1 ] = 0;
/*
* Write escape(0) and run
*/
imBmpWrite2Bytes( 0, run+1 );
/*
* Write pixels in pixbuf
*/
count = 0;
for( i = 0; i < run+1; i += 2)
{
buf[ bufin ] = (pixbuf[ i ]<<4)
| pixbuf[ i+1 ];
++bufin;
if( bufin > (IMBLKSIZE-1) )
{
if( ImBinWrite( ioType,
fd,fp,buf,
UCHAR,1,
IMBLKSIZE )==-1)
{
ImReturnBinError( );
}
bufin = 0;
}
++count;
}
bytecount += count;
/*
* Pad to word boundary if necessary
*/
if( (count%2) != 0 )
{
buf[ bufin ] = 0;
++bufin;
if( bufin > (IMBLKSIZE-1) )
{
if( ImBinWrite( ioType,
fd,fp,buf,
UCHAR,1,
IMBLKSIZE )==-1)
{
ImReturnBinError( );
}
bufin = 0;
}
++bytecount;
}
/*
* Write end of scanline code
*/
imBmpWrite2Bytes( 0, 0 );
/*
* Adjust counters and vfb pointers
*/
bytecount += 4;
xcount = 0;
++ycount;
vfbptr = ImVfbQUp( vfb, vfbptr );
vfbptr = ImVfbQUp( vfb, vfbptr );
pixel = ImVfbQIndex8( vfb, vfbptr );
/* check for out of range pixel */
if( pixel > 15 ) pixel = 15;
vfbptr = ImVfbQRight( vfb, vfbptr );
nowrite = FALSE;
break;
}
/*
* End of 255 consecutive different pixels
*/
if( run == 254 )
{
pixbuf[ run ] = pixel;
pixbuf[ run+1 ] = 0;
/*
* Write escape code(0) and run
*/
imBmpWrite2Bytes( 0, 255 );
/*
* Write pixel literals
*/
for( i = 0; i < 255; i += 2 )
{
buf[ bufin ] = (pixbuf[ i ]<<4)
| pixbuf[ i+1 ];
++bufin;
if( bufin > (IMBLKSIZE-1) )
{
if( ImBinWrite( ioType,
fd,fp,buf,
UCHAR,1,
IMBLKSIZE )==-1)
{
ImReturnBinError( );
}
bufin = 0;
}
}
/*
* Adjust counters and vfb pointers
*/
bytecount += 130;
run = 0;
++xcount;
pixel = ImVfbQIndex8( vfb, vfbptr );
/* check for out of range pixel */
if( pixel > 15 ) pixel = 15;
vfbptr = ImVfbQRight( vfb, vfbptr );
nowrite = FALSE;
break;
}
}
/*
* If we haven't written out the pixels, then
* write it now
*/
if( nowrite == TRUE )
{
pixbuf[ run ] = 0;
/*
* Write escape code(0) and run
*/
imBmpWrite2Bytes( 0, run );
/*
* Write pixel literals
*/
count = 0;
for( i = 0; i < run; i += 2 )
{
buf[ bufin ] = (pixbuf[ i ]<<4)
| pixbuf[ i+1 ];
++bufin;
if( bufin > (IMBLKSIZE-1) )
{
if( ImBinWrite( ioType,fd,fp
,buf,UCHAR,1
,IMBLKSIZE )==-1)
{
ImReturnBinError( );
}
bufin = 0;
}
++count;
}
bytecount += count;
/*
* Pad to word boundary if necessary
*/
if( count%2 != 0 )
{
buf[ bufin ] = 0;
++bufin;
if( bufin > (IMBLKSIZE-1) )
{
if( ImBinWrite( ioType,
fd,fp,buf,
UCHAR,1,
IMBLKSIZE )==-1)
{
ImReturnBinError( );
}
bufin = 0;
}
++bytecount;
}
/*
* Adjust bytecount
*/
bytecount += 2;
}
}
}
/*
* Write end of bitmap code
*/
buf[ bufin ] = 0;
++bufin;
buf[ bufin ] = 1;
++bufin;
if( ImBinWrite( ioType,fd,fp,buf,UCHAR,1,bufin )==-1)
{
ImReturnBinError( );
}
/*
* Adjust bytecount
*/
bytecount += 2;
/*
* Seek to header and write file size
*/
if( ImSeek( ioType, fd, fp, 2, L_SET ) == -1 )
{
ImReturnBinError( );
}
header.bmp_size = IMBMPHEADERSIZE + ( ncolors * IMBMPRGBQUADSIZE )
+ bytecount;
if( ImBinWrite( ioType, fd, fp, &header.bmp_size, UINT32, 4, 1) == -1 )
{
ImReturnBinError( );
}
/*
* Seek to header and write bitmap size
*/
if( ImSeek( ioType, fd, fp, 34, L_SET ) == -1 )
{
ImReturnBinError( );
}
header.bmp_bisizeimage = bytecount;
if( ImBinWrite( ioType, fd, fp, &header.bmp_bisizeimage,
UINT32, 4, 1) == -1 )
{
ImReturnBinError( );
}
return( 1 );
}
/*
* FUNCTION
* imBmpWriteRLE8 - write an 8-bit RLE compressed BMP file
*
* DESCRIPTION
* That VFB is queried, and the BMP file header set up and written out.
* The VFB data is then converted and written out. See encoding
* scheme in FORMAT section.
*/
static int /* Returns # of tags used */
#ifdef __STDC__
imBmpWriteRLE8( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp,
TagTable *flagsTable, TagTable *tagTable )
#else
imBmpWriteRLE8( 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 list to read from */
#endif
{
imBmpHeaderInfoWrite header; /* BMP file header */
ImVfb *vfb; /* Read in image */
ImVfbPtr vfbptr; /* Vfb pixel pointer */
ImClt *clt; /* Colortable */
ImCltPtr cltptr; /* Colortable entry pointer */
unsigned int ncolors = 0; /* Number of colors used */
unsigned int x, y; /* Width, Height */
unsigned int run; /* Number of consecutive bytes */
unsigned char pixel; /* Temp pixel value */
unsigned int bytecount = 0; /* Bytes in compressed image */
unsigned int nowrite; /* Write status */
unsigned char pixbuf[ 255 ]; /* Pixel buffer */
unsigned char *cbuf; /* Buffer for colortable write */
unsigned char *cbufptr; /* Buffer pointer */
unsigned char buf[ IMBLKSIZE ];/* File write output buffer */
int bufin; /* Output buffer index */
int xcount, ycount; /* Counters */
int i; /* Counters */
char message[100]; /* ImInfo message */
/*
* Set byte ordering
*/
BinByteOrder( BINLBF );
/*
* Get vfb and clt
*/
TagEntryQValue( TagTableQDirect( tagTable, "image vfb", 0 ), &vfb );
clt = ImVfbQClt( vfb );
x = ImVfbQWidth( vfb );
y = ImVfbQHeight( vfb );
ncolors = ImCltQNColors( clt );
if( ncolors > 256 )
{
ncolors = 256;
}
/*
* Setup header and write it out
*/
header.bmp_type = IMBMPMAGIC_LBF;
header.bmp_reserved1 = 0;
header.bmp_reserved2 = 0;
header.bmp_offsetbits = (unsigned int) IMBMPHEADERSIZE +
( ncolors * IMBMPRGBQUADSIZE );
/*
* offset to image data =
* BMP header +
* colortable size
*/
header.bmp_bisize = IMBMPINFOHEADERSIZE;
header.bmp_biwidth = x;
header.bmp_biheight = y;
header.bmp_biplanes = 1;
header.bmp_bibitcount = 8;
header.bmp_bicompress = IMBMPRLE8;
header.bmp_bixpm = 0;
header.bmp_biypm = 0;
header.bmp_biclrused = (unsigned int) ncolors;
if( ncolors == 256 )
{
header.bmp_biclrused = 0;
}
header.bmp_biclrim = (unsigned int) ncolors;;
if( ImBinWriteStruct( ioType, fd, fp, &header,
imBmpHeaderFieldsWrite ) == -1 )
{
ImReturnBinError( );
}
/*
* Output -verbose messages
*/
ImInfo( "Byte Order", "Least Significant Byte First" );
sprintf( message, "%d x %d", x, y );
ImInfo( "Resolution", message );
ImInfo( "Type", "8-bit Color Indexed" );
sprintf( message, "%d Entries", ncolors );
ImInfo( "Color Table", message );
ImInfo( "Compression Type", "Run Length Encoded (RLE8)" );
/*
* Write colortable
*/
cltptr = ImCltQFirst( clt );
ImMalloc( cbuf, unsigned char*, ncolors*IMBMPRGBQUADSIZE );
cbufptr = cbuf;
for( i = 0; i < ncolors; ++i )
{
*cbufptr = (unsigned char) ImCltQBlue( cltptr );
++cbufptr;
*cbufptr = (unsigned char) ImCltQGreen( cltptr );
++cbufptr;
*cbufptr = (unsigned char) ImCltQRed( cltptr );
++cbufptr;
*cbufptr = 0;
++cbufptr;
cltptr = ImCltQNext( clt, cltptr );
}
if ( ImBinWrite( ioType, fd, fp, cbuf, UCHAR, 1,
ncolors*IMBMPRGBQUADSIZE ) == -1 )
{
ImReturnBinError( );
}
free( cbuf );
/*
* Output image bitmap
*/
/*
* Go to last vfb scanline
*/
vfbptr = ImVfbQPtr( vfb, 0, y-1 );
/*
* RLE encode the image
*/
bytecount = 0;
xcount = 0;
ycount = 0;
bufin = 0;
pixel = ImVfbQIndex8( vfb, vfbptr );
vfbptr = ImVfbQRight( vfb, vfbptr );
while( ycount < y )
{
/*
* Boundary condition: 1 pixel at the end
* of a scanline.
*/
if( xcount == (x-1) )
{
/*
* Encoded pixel as run of 1
*/
imBmpWrite2Bytes( 1, pixel );
/*
* Write end of scanline code
*/
imBmpWrite2Bytes( 0, 0 );
/*
* Adjust counters and vfb pointers
*/
bytecount += 4;
xcount = 0;
++ycount;
vfbptr = ImVfbQUp( vfb, vfbptr );
vfbptr = ImVfbQUp( vfb, vfbptr );
pixel = ImVfbQIndex8( vfb, vfbptr );
vfbptr = ImVfbQRight( vfb, vfbptr );
}
/*
* Boundary condition: 2 pixels at the end
* of a scanline.
*/
if( xcount == (x-2) )
{
/*
* If the last two pixels are the same
* then write them as a run of 2 with
* pixel value. Else, write each
* pixel value as runs of 1.
*/
if( pixel == ImVfbQIndex8( vfb, vfbptr ) )
{
imBmpWrite2Bytes( 2, pixel );
bytecount += 4;
}
else
{
imBmpWrite2Bytes( 1, pixel );
imBmpWrite2Bytes( 1, ImVfbQIndex8(vfb,vfbptr));
bytecount += 6;
}
/*
* Write end of scanline code
*/
imBmpWrite2Bytes( 0, 0 );
/*
* Adjust counters and vfb pointers
*/
xcount = 0;
++ycount;
vfbptr = ImVfbQRight( vfb, vfbptr );
vfbptr = ImVfbQUp( vfb, vfbptr );
vfbptr = ImVfbQUp( vfb, vfbptr );
pixel = ImVfbQIndex8( vfb, vfbptr );
vfbptr = ImVfbQRight( vfb, vfbptr );
}
/*
* Encoded Mode - encoding of multiple consecutive
* pixels of the same value into a run and
* pixel value
*/
if( pixel == ImVfbQIndex8( vfb, vfbptr ) )
{
run = 0;
nowrite = TRUE;
/*
* While two adjacent pixels are the same,
* count them up. If we reach the
* end of a scanline, write out the
* current run and pixel. If we
* have a run of 255 pixels, write
* out the run and pixel.
*/
while( pixel == ImVfbQIndex8( vfb, vfbptr ) )
{
++run;
++xcount;
pixel = ImVfbQIndex8( vfb, vfbptr );
vfbptr = ImVfbQRight( vfb, vfbptr );
/*
* End of a scanline
*/
if( xcount == x-1 )
{
/*
* Write run and pixel value
*/
imBmpWrite2Bytes( run+1, pixel );
/*
* Write end of scanline code
*/
imBmpWrite2Bytes( 0, 0 );
/*
* Adjust counters and vfb pointers
*/
bytecount += 4;
xcount = 0;
++ycount;
vfbptr = ImVfbQUp( vfb, vfbptr );
vfbptr = ImVfbQUp( vfb, vfbptr );
pixel = ImVfbQIndex8( vfb, vfbptr );
vfbptr = ImVfbQRight( vfb, vfbptr );
nowrite = FALSE;
break;
}
/*
* End of 255 pixels
*/
if( run == 254 )
{
/*
* Write run and pixel value
*/
imBmpWrite2Bytes( 255, pixel );
/*
* Adjust counters and vfb pointers
*/
bytecount += 2;
run = 0;
++xcount;
pixel = ImVfbQIndex8( vfb, vfbptr );
vfbptr = ImVfbQRight( vfb, vfbptr );
nowrite = FALSE;
break;
}
}
/*
* If we haven't written out the run and pixel,
* do it now.
*/
if( nowrite == TRUE )
{
/*
* Write run and pixel
*/
imBmpWrite2Bytes( run+1, pixel );
/*
* Adjust counters and vfb pointers
*/
bytecount += 2;
++xcount;
pixel = ImVfbQIndex8( vfb, vfbptr );
vfbptr = ImVfbQRight( vfb, vfbptr );
}
}
/*
* Absolute Mode - copying of consecutive different pixels
* literally
*/
if( (pixel != ImVfbQIndex8( vfb, vfbptr ))
&& (xcount < (x-2) )
&& (ycount < y) )
{
run = 0;
nowrite = TRUE;
pixbuf[ 0 ] = pixel;
pixel = ImVfbQIndex8( vfb, vfbptr );
vfbptr = ImVfbQRight( vfb, vfbptr );
++xcount;
/*
* Since Absolute Mode requires that there
* be at least 3 different adjacent
* pixels, we check for this condition
* first. If there are only 1 or 2
* different adjacent bytes, then
* we write them out as runs of 1
* and pixel.
*/
if( pixel == ImVfbQIndex8( vfb, vfbptr ) )
{
/*
* There is only 1 different pixel
*/
/*
* Write out run and pixel
*/
imBmpWrite2Bytes( 1, pixbuf[ 0 ] );
bytecount += 2;
nowrite = FALSE;
}
else
{
pixbuf[ 1 ] = pixel;
pixel = ImVfbQIndex8( vfb, vfbptr );
vfbptr = ImVfbQRight( vfb, vfbptr );
++xcount;
if( pixel == ImVfbQIndex8( vfb, vfbptr ) )
{
/*
* There are only 2 different
* adjacent pixels
*/
/*
* Write run and pixel
*/
imBmpWrite2Bytes( 1, pixbuf[ 0 ] );
/*
* Write run and pixel
*/
imBmpWrite2Bytes( 1, pixbuf[ 1 ] );
bytecount += 4;
nowrite = FALSE;
}
else
{
/*
* There are at least 3 different
* adjacent pixels, so we reset
* the vfb pointers
*/
xcount -= 2;
vfbptr = ImVfbQLeft( vfb, vfbptr );
vfbptr = ImVfbQLeft( vfb, vfbptr );
vfbptr = ImVfbQLeft( vfb, vfbptr );
pixel = ImVfbQIndex8( vfb, vfbptr );
vfbptr = ImVfbQRight( vfb, vfbptr );
}
}
/*
* While adjacent pixels are different, count them
* up and store them in pixbuf.
*/
while( pixel != ImVfbQIndex8( vfb, vfbptr ) )
{
pixbuf[ run ] = pixel;
pixel = ImVfbQIndex8( vfb, vfbptr );
vfbptr = ImVfbQRight( vfb, vfbptr );
++run;
++xcount;
/*
* End of scanline
*/
if( xcount == x-1 )
{
pixbuf[ run ] = pixel;
/*
* Write escape(0) and run
*/
imBmpWrite2Bytes( 0, run+1 );
/*
* Write pixels in pixbuf
*/
for( i = 0; i < run+1; ++i )
{
buf[ bufin ] = pixbuf[ i ];
++bufin;
if( bufin > (IMBLKSIZE-1) )
{
if( ImBinWrite( ioType,
fd,fp,buf,
UCHAR,1,
IMBLKSIZE )==-1)
{
ImReturnBinError( );
}
bufin = 0;
}
}
/*
* Pad to word boundary if necessary
*/
if( ((run+1)%2) != 0 )
{
buf[ bufin ] = 0;
++bufin;
if( bufin > (IMBLKSIZE-1) )
{
if( ImBinWrite( ioType,
fd,fp,buf,
UCHAR,1,
IMBLKSIZE )==-1)
{
ImReturnBinError( );
}
bufin = 0;
}
++bytecount;
}
/*
* Write end of scanline code
*/
imBmpWrite2Bytes( 0, 0 );
/*
* Adjust counters and vfb pointers
*/
bytecount += (5+run);
xcount = 0;
++ycount;
vfbptr = ImVfbQUp( vfb, vfbptr );
vfbptr = ImVfbQUp( vfb, vfbptr );
pixel = ImVfbQIndex8( vfb, vfbptr );
vfbptr = ImVfbQRight( vfb, vfbptr );
nowrite = FALSE;
break;
}
/*
* End of 255 consecutive different pixels
*/
if( run == 254 )
{
pixbuf[ run ] = pixel;
/*
* Write escape code(0) and run
*/
imBmpWrite2Bytes( 0, 255 );
/*
* Write pixel literals
*/
for( i = 0; i < 255; ++i )
{
buf[ bufin ] = pixbuf[ i ];
++bufin;
if( bufin > (IMBLKSIZE-1) )
{
if( ImBinWrite( ioType,
fd,fp,buf,
UCHAR,1,
IMBLKSIZE )==-1)
{
ImReturnBinError( );
}
bufin = 0;
}
}
/*
* Write word boundary padding
*/
buf[ bufin ] = 0;
++bufin;
if( bufin > (IMBLKSIZE-1) )
{
if( ImBinWrite( ioType,
fd,fp,buf,
UCHAR,1,
IMBLKSIZE )==-1)
{
ImReturnBinError( );
}
bufin = 0;
}
/*
* Adjust counters and vfb pointers
*/
bytecount += 258;
run = 0;
++xcount;
pixel = ImVfbQIndex8( vfb, vfbptr );
vfbptr = ImVfbQRight( vfb, vfbptr );
nowrite = FALSE;
break;
}
}
/*
* If we haven't written out the pixels, then
* write it now
*/
if( nowrite == TRUE )
{
/*
* Write escape code(0) and run
*/
imBmpWrite2Bytes( 0, run );
/*
* Write pixel literals
*/
for( i = 0; i < run; ++i )
{
buf[ bufin ] = pixbuf[ i ];
++bufin;
if( bufin > (IMBLKSIZE-1) )
{
if( ImBinWrite( ioType,fd,fp
,buf,UCHAR,1
,IMBLKSIZE )==-1)
{
ImReturnBinError( );
}
bufin = 0;
}
}
/*
* Write padding to word boundary if
* necessary
*/
if( run%2 != 0 )
{
buf[ bufin ] = 0;
++bufin;
if( bufin > (IMBLKSIZE-1) )
{
if( ImBinWrite( ioType,fd,fp
,buf,UCHAR,1
,IMBLKSIZE )==-1)
{
ImReturnBinError( );
}
bufin = 0;
}
++bytecount;
}
/*
* Adjust bytecount
*/
bytecount += (2+run);
}
}
}
/*
* Write end of bitmap code
*/
buf[ bufin ] = 0;
++bufin;
buf[ bufin ] = 1;
++bufin;
if( ImBinWrite( ioType,fd,fp,buf,UCHAR,1,bufin )==-1)
{
ImReturnBinError( );
}
/*
* Adjust bytecount
*/
bytecount += 2;
/*
* Seek to header and write file size
*/
if( ImSeek( ioType, fd, fp, 2, L_SET ) == -1 )
{
ImReturnBinError( );
}
header.bmp_size = IMBMPHEADERSIZE + ( ncolors * IMBMPRGBQUADSIZE )
+ bytecount;
if( ImBinWrite( ioType, fd, fp, &header.bmp_size, UINT32, 4, 1) == -1 )
{
ImReturnBinError( );
}
/*
* Seek to header and write bitmap size
*/
if( ImSeek( ioType, fd, fp, 34, L_SET ) == -1 )
{
ImReturnBinError( );
}
header.bmp_bisizeimage = bytecount;
if( ImBinWrite( ioType, fd, fp, &header.bmp_bisizeimage,
UINT32, 4, 1) == -1 )
{
ImReturnBinError( );
}
return( 1 );
}