jedioutcast/utils/roq2/libim/imico.c
2013-04-04 13:07:40 -05:00

3340 lines
51 KiB
C

/**
** $Header: /roq/libim/imico.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/imico.c 1 11/02/99 4:38p Zaphod $"
/**
** FILE
** imico.c - Microsoft Windows ICO file I/O
**
** PROJECT
** libim - SDSC image manipulation library
**
** DESCRIPTION
** imico.c contains routines to read and write Microsoft Windows ICO
** 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
** imIcoRead f read a Microsoft Windows ICO file
** imIcoWrite f control for what to write
**
** imIcoHeader t file header information
** imIcoHeaderFields v imIcoHeader description for Bin pkg.
** imIcoDirEntry t icon directory entry
** imIcoDirEntryFields v imIcoDirEntry description for Bin pkg.
** imIcoInfo t icon information
** imIcoInfoFields v imIcoInfo description for Bin pkg.
**
** imIcoImageRead f read the ith icon image
** imIcoReadImage f read the icon image
**
** imIcoWriteImage f write the icon image
** imIcoWriteRaw1 f write a Microsoft Windows ICO 1-bit file
** imIcoWriteRaw4 f write a Microsoft Windows ICO 4-bit file
**
** HISTORY
** $Log: /roq/libim/imico.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/06/15 20:26:23 bduggan
** took out some unused vars.
** turned bzero into memset
**
** Revision 1.10 1995/04/03 21:26:04 bduggan
** took out #ifdef NEWMAGIC
**
** Revision 1.9 1995/01/16 22:08:46 bduggan
** Fixed a typo that was hindering reading of
** alpha channels (changed 0x100 to 0x80)
**
** Revision 1.8 1995/01/10 23:27:34 bduggan
** uncapitlized i's in local functions, made read/write routines static,
** put in IMMULTI, IMPIPE instead of TRUE/FALSE
**
** Revision 1.7 1994/08/31 17:34:50 nadeau
** Updated to ANSI C comaptibility. Updated comments.
** Rearranged code a bit for better readability. Reformatted
** code for consistent indentation style. Misc cleanup.
**
** Revision 1.7 1994/08/31 17:34:50 nadeau
** Updated to ANSI C comaptibility. Updated comments.
** Rearranged code a bit for better readability. Reformatted
** code for consistent indentation style. Misc cleanup.
**
** Revision 1.6 92/12/03 01:49:00 nadeau
** Corrected info messages. Got rid of IMINFOMSG references.
**
** Revision 1.5 92/11/04 11:47:52 groening
** added multiple read and write.
** put ImFIleFormat info and magic number info
** from imfmt.c into this file.
**
** Revision 1.4 92/10/12 15:54:33 vle
** Made changes to make Cray happy.
**
** Revision 1.3 92/09/29 17:58:34 vle
** Added ImInfo messages.
**
** Revision 1.2 92/09/17 14:23:09 vle
** Fixed "scanlinesize" math bug that caused images to be cropped.
**
** Revision 1.1 92/08/18 12:21:58 vle
** Initial revision
**
**/
#include "iminternal.h"
/**
** FORMAT
** ICO Microsoft Windows icon image
**
** AKA
** None
**
** 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.
**
** CODE CREDITS
** Custom development, Vinh Le, San Diego Supercomputer Center, 1992.
**
** DESCRIPTION
** Microsoft's ICO (ICOn) format is used in Microsoft's Windows
** versions 3.0 and up for storage of one or more icons.
**
** The first item encountered in an ICO file is an Icon Directory
** Header. This tells that the file is indeed a file containing
** icons and that there are n number of them.
**
** Following the Icon Directory Header is an Icon Directory
** Entry for each icon. An Icon Directory Entry contains
** information on the icon's location within the file,
** its width, height, etc. There are n Icon Directory Entries.
**
** Following all this is the actual Icon Images themselves, which
** consist of an info header, a colortable, and XOR and AND masks.
** The XOR mask could be considered the "real" icon. The AND
** mask determines the XOR image's "tranparency". XOR masks
** can either be 1-, 3-, or 4-bits/pixel. 4-bits/pixel images
** are packed 2 pixels/byte. 3-bits/pixel images are currently
** unsupported. 1-bit/pixel images are packed 8 pixels/byte.
** AND masks are always monochrome images, thus they are
** packed as 1-bit/pixel images, or 8-bits/byte.
**
**
** Stucture Overview
** -----------------
**
** ICON DIRECTORY
** ---------------------------------------------------------
** |ICON |ICON |ICON | ... | | | |
** |ENTRY 1|ENTRY 2|ENTRY 3| | | | |
** ---------------------------------------------------------
** |
** | ---------
** +---------> |ICON |
** |IMAGE |
** |-------|
** |Header |
** |-------|
** |Color |
** |Table |
** |-------|
** |XOR |
** |Mask |
** |-------|
** |AND |
** |Mask |
** ---------
**
**
** Icon Directory Header (6 bytes + 16 bytes/icon entry)
** ---------------------
**
** The Icon Directory Header contains the resource type and
** number of icons in the Icon Directory.
**
** Name Type Size Comments
** ---- ---- ---- --------
** idReserved word 2 bytes reserved, must be 0
** idType word 2 bytes resource type,
** must be 1
** idCount word 2 bytes number of icons
** idEntries[] IconDirEntry 16 bytes array of info for
** per entry individual icons
**
** typedef struct ICONDIR
** {
** word idReserved;
** word idType;
** word idCount;
** ICONDIRENTRY idEntries[idCount];
** } ICONDIR;
**
** Icon Directory Entry (16 bytes/icon entry)
** --------------------
**
** An Icon Directory Entry stores information about the an icon's
** dimensions and color attributes.
**
** Name Type Size Comments
** ---- ---- ---- --------
** Width byte 1 byte width in pixels, must be 16, 32, or 64
** Height byte 1 byte height in pixels, must be 16, 32, or 64
** ColorCount byte 1 byte number of colors, must be 2, 8 or 16
** Reserved byte 1 byte reserved, must be 0
** Planes word 2 byte number of color planes
** BitCount word 2 byte number of bits
** BytesInRes dword 4 byte size of icon in bytes
** ImageOffset dword 4 byte offset from beginning of file to
** Icon Image
**
** typedef struct ICONDIRENTRY
** {
** byte Width;
** byte Height;
** byte ColorCount;
** byte Reserved;
** word Planes;
** word BitCount;
** dword BytesInRes;
** dword ImageOffset;
** } ICONDIRENTRY;
**
** Icon Image (40 bytes + 4 bytes/color entry + sizeof XOR mask +
** ---------- sizeof AND mask)
**
** Each Icon Image stores 1 icon.
**
** Name Type Size Comments
** ---- ---- ---- --------
** icHeader BITMAPFILEHEADER 40 bytes only biSize
** through
** biBitCount
** and
** biSizeImage
** are used
** icColors[] RGBQUAD 4 bytes per colortable used
** color in XOR mask
** icXOR[] byte 1 byte per XOR image mask
** element
** icAND[] byte 1 byte per AND image mask
** element
**
** Ico-Info Header (40 bytes)
** ------------------
**
** The Ico-Info Header contains information about the icon's
** size and dimensions.
**
** Name Type Size Comments
** ---- ---- ---- --------
** biSize dword 4 bytes number of bytes in
** Ico-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,
** 3, 4
** biCompression dword 4 bytes unused, must be 0
** biSizeImage dword 4 bytes image size in bytes
** biXPelsPerMeter long 4 bytes unused, must be 0
** biYPelsPerMeter long 4 bytes unused, must be 0
** biClrUsed dword 4 bytes unused, must be 0
** biClrImportant dword 4 bytes unused, must be 0
**
** 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;
**
** IMPLEMENTATION SPECIFIC NOTES
** 3-bits/pixel (8 color) icons are not supported due to the
** lack of documentation on the packing method for such icons.
**
**/
/*
* ICO - Microsoft Windows icon
* For information on these structures, how to use them, etc. please
* see imfmt.c.
*/
#ifdef __STDC__
static int imIcoRead( int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable );
static int imIcoWrite( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp,
TagTable *flagsTable, TagTable *tagTable );
#else
static int imIcoRead( ), imIcoWrite( );
#endif
static char *imIcoNames[ ] = { "ico", NULL };
static unsigned char imIcoMagicNumber[ ] = { 0x00, 0x00, 0x01, 0x00 };
static ImFileMagic imFileIcoMagic []=
{
{ 0, 4, imIcoMagicNumber },
{ 0, 0, NULL },
};
static ImFileFormatReadMap imIcoReadMap[ ] =
{
/* in out */
/* type,ch,dep, attr. VFB type attr. */
{ IN,1,1, C|A, IMVFBINDEX8, C|A },
{ IN,1,4, C|A, IMVFBINDEX8, C|A },
{ -1, 0, -1, 0 },
};
static ImFileFormatWriteMap imIcoWriteMap[ ] =
{
/* in out */
/* VFB type, attr., type,ch,dep, attr., func */
{ IMVFBMONO, 0, IN,1,1, C|A, imIcoWrite },
{ IMVFBMONO, C, IN,1,1, C|A, imIcoWrite },
{ IMVFBMONO, A, IN,1,1, C|A, imIcoWrite },
{ IMVFBMONO, C|A, IN,1,1, C|A, imIcoWrite },
{ IMVFBINDEX8, 0, IN,1,4, C|A, imIcoWrite },
{ IMVFBINDEX8, C, IN,1,4, C|A, imIcoWrite },
{ IMVFBINDEX8, A, IN,1,4, C|A, imIcoWrite },
{ IMVFBINDEX8, C|A, IN,1,4, C|A, imIcoWrite },
{ -1, 0, -1, 0, NULL },
};
ImFileFormat ImFileIcoFormat =
{
imIcoNames, "Windows icon image file",
"Microsoft Corp.",
"1- and 4-bit color index images with alpha channels.",
"1- and 4-bit color index images with alpha channels.",
imFileIcoMagic,
IMMULTI, IMPIPE, /* Read */
IMMULTI, IMPIPE, /* Write */
imIcoRead, imIcoReadMap, imIcoWriteMap
};
/*
* TYPEDEF & STRUCTURE
* imIcoHeader - ICO file header
* imIcoHeaderFields - ICO file header fields for binary pkg.
* imIcoDirEntry - ICO icon directory entry
* imIcoDirEntryFields - ICO icon directory entry for bin pkg.
* imIcoInfo - ICO file info
* imIcoInfoFields - ICO file info fields for bin pkg.
* imIcoRGBQuad - ICO color information
* imIcoRGBQuadFields - ICO color information fields for bin pkg.
*
* DESCRIPTION
* The imIcoRGBQuad is one entry in the colortable.
*/
typedef struct imIcoHeader
{
sdsc_uint16 ico_idReserved; /* reserved, must be zero */
sdsc_uint16 ico_idType; /* resource type, must be 1 */
sdsc_uint16 ico_idCount; /* number of entries in directory */
} imIcoHeader;
static BinField imIcoHeaderFields[ ] =
{
{ UINT16, 2, 1 }, /* ico_idReserved */
{ UINT16, 2, 1 }, /* ico_idType */
{ UINT16, 2, 1 }, /* ico_idCount */
{ 0, 0, 0 }
};
#define IMICOHEADERSIZE 6 /* bytes */
typedef struct imIcoDirEntry
{
unsigned char ico_Width; /* width in pixels, must be 16,32,or 64 */
unsigned char ico_Height; /* height in pixels, must be 16,32,or 64*/
unsigned char ico_ColorCount; /* number of colors, must be 2,8 or 16 */
unsigned char ico_Reserved; /* reserved, must be 0 */
sdsc_uint16 ico_Planes; /* number of color planes */
sdsc_uint16 ico_BitCount; /* number of bits */
sdsc_uint32 ico_BytesInRes; /* size of icon in bytes */
sdsc_uint32 ico_ImageOffset;/* offset from beginning of file to
Icon Image */
} imIcoDirEntry;
static BinField imIcoDirEntryFields[ ] =
{
{ UCHAR, 1, 1 }, /* ico_Width */
{ UCHAR, 1, 1 }, /* ico_Height */
{ UCHAR, 1, 1 }, /* ico_ColorCount */
{ UCHAR, 1, 1 }, /* ico_Reserved */
{ UINT16, 2, 1 }, /* ico_Planes */
{ UINT16, 2, 1 }, /* ico_BitCount */
{ UINT32, 4, 1 }, /* ico_ByteInRes */
{ UINT32, 4, 1 }, /* ico_ImageOffset */
{ 0, 0, 0 }
};
#define IMICODIRENTRYSIZE 16 /* bytes */
typedef struct imIcoInfo
{
sdsc_uint32 ico_bisize; /* number of bytes in icon info header */
sdsc_uint32 ico_biwidth; /* image width in pixels */
sdsc_uint32 ico_biheight; /* image height in pixels */
sdsc_uint16 ico_biplanes; /* number of planes for device, always 1*/
sdsc_uint16 ico_bibitcount; /* bits/pixel (1, 3, or 4) */
sdsc_uint32 ico_bicompress; /* unused, must be 0 */
sdsc_uint32 ico_bisizeimage;/* image size in bytes */
sdsc_uint32 ico_bixpm; /* unused, must be 0 */
sdsc_uint32 ico_biypm; /* unused, must be 0 */
sdsc_uint32 ico_biclrused; /* unused, must be 0 */
sdsc_uint32 ico_biclrim; /* unused, must be 0 */
} imIcoInfo;
static BinField imIcoInfoFields[ ] =
{
{ UINT32, 4, 1 }, /* ico_bisize */
{ UINT32, 4, 1 }, /* ico_biwidth */
{ UINT32, 4, 1 }, /* ico_biheight */
{ UINT16, 2, 1 }, /* ico_biplanes */
{ UINT16, 2, 1 }, /* ico_bibitcount */
{ UINT32, 4, 1 }, /* ico_bicompress */
{ UINT32, 4, 1 }, /* ico_bisizeimage */
{ UINT32, 4, 1 }, /* ico_bixpm */
{ UINT32, 4, 1 }, /* ico_biypm */
{ UINT32, 4, 1 }, /* ico_biclrused */
{ UINT32, 4, 1 }, /* ico_biclrim */
{ 0, 0, 0 }
};
#define IMICOINFOSIZE 40 /* bytes */
typedef struct imIcoRGBQuad
{
unsigned char blue; /* blue intensity */
unsigned char green; /* green intensity */
unsigned char red; /* red intensity */
unsigned char reserved; /* unused */
} imIcoRGBQuad;
static BinField imIcoRGBQuadFields[ ] =
{
{ UCHAR, 1, 1 }, /* blue */
{ UCHAR, 1, 1 }, /* green */
{ UCHAR, 1, 1 }, /* red */
{ UCHAR, 1, 1 }, /* reserved */
{ 0, 0, 0 }
};
#define IMICORGBQUADSIZE 4 /* bytes */
/*
* Various useful ICO specific constants
*/
#define IMICOMAGIC 1
/* magic resource number for icons */
#define IMICOXOR 0
/* XOR vfb flag, IMVFBINDEX8 */
#define IMICOAND 1
/* AND vfb flag, IMVFBMONO */
#ifdef __STDC__
static int imIcoImageRead ( int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable,
imIcoDirEntry *icodirentryptr);
static int imIcoReadImage( int ioType, int fd, FILE *fp, ImVfb *vfb, int what );
static int imIcoWriteRaw1(ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp, ImVfb *vfb, ImClt *clt,
imIcoDirEntry *direntry );
static int imIcoWriteRaw4( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp, ImVfb *vfb, ImClt *clt,
imIcoDirEntry *direntry);
static int imIcoWriteImage( int ioType, int fd, FILE *fp, ImVfb *vfb, int what );
#else
static int imIcoImageRead( );
static int imIcoReadImage( );
static int imIcoWriteRaw1( );
static int imIcoWriteRaw4( );
static int imIcoWriteImage( );
#endif
/*
* FUNCTION
* imIcoRead - read a Microsoft Windows Ico 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__
imIcoRead( int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable )
#else
imIcoRead( 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
{
imIcoHeader header; /* ICO file header */
imIcoDirEntry *icodirentries; /* ICO dir entries */
imIcoDirEntry *icodirentryptr; /* ICO dir entry pointer */
unsigned int i; /* Counter */
char message[100]; /* ImInfo message */
/*
* Set Binary Package byte order and read in part of header
*/
BinByteOrder( BINLBF );
if( ImBinReadStruct( ioType, fd, fp, &header,
imIcoHeaderFields ) == -1 )
{
ImReturnBinError( );
}
/*
* Use idType to determine byte ordering
*/
if( header.ico_idType != IMICOMAGIC )
{
/*
* Swap bytes
*/
header.ico_idType = (header.ico_idType&0xFF00)>>8 |
(header.ico_idType&0x00FF)<<8;
if( header.ico_idType != IMICOMAGIC )
{
ImErrorFatal( ImQError( ), -1, IMEMAGIC );
}
else
{
header.ico_idCount = (header.ico_idCount&0xFF00)>>8 |
(header.ico_idCount&0x00FF)<<8;
BinByteOrder( BINMBF );
ImInfo( "Byte Order", "Most Significant Byte First");
}
}
else
{
ImInfo( "Byte Order", "Least Significant Byte First" );
}
/*
* Allocate space for icon dir entries
*/
ImMalloc( icodirentries, imIcoDirEntry*,
header.ico_idCount * sizeof(imIcoDirEntry) );
/*
* Read in icon dir entries
*/
icodirentryptr = icodirentries;
for( i = 0; i < header.ico_idCount; ++i )
{
if( ImBinReadStruct( ioType, fd, fp, icodirentryptr,
imIcoDirEntryFields ) == -1 )
{
ImReturnBinError( );
}
++icodirentryptr;
}
/*
* Read in icon images
*/
icodirentryptr = icodirentries;
for( i = 0; i < header.ico_idCount; ++i )
{
/*
* Read in ith icon
*/
sprintf( message, "%d of %d", (i+1), header.ico_idCount );
ImInfo( "Image", message );
imIcoImageRead( ioType, fd, fp, flagsTable, tagTable,
icodirentryptr);
++icodirentryptr;
}
free( icodirentries );
return header.ico_idCount;
}
/*
* FUNCTION
* imIcoReadImage - read in an image's pixels
*
* DESCRIPTION
* A temporary buffer is allocated and the image's pixels read in.
* Pixels are unpacked from the buffer and dispersed into the VFB.
*/
#define IMREADMONO 0
#define IMREADINDEX8 1
#define IMREADALPHA 2
static int /* Returns status */
#ifdef __STDC__
imIcoReadImage( int ioType, int fd, FILE *fp, ImVfb *vfb, int what )
#else
imIcoReadImage( ioType, fd, fp, vfb, what )
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
ImVfb *vfb; /* Image to read into */
int what; /* What kind of thing to read */
#endif
{
ImVfbPtr vfbptr; /* Pixel pointer */
unsigned char mask; /* Mask for extracting pixels */
unsigned char *rbuf = NULL; /* Read buffer */
unsigned char *rbufptr; /* Read buffer data pointer */
int scanlinesize; /* Length of scanline in bytes */
int x, y; /* Width and Height */
int i, j, k; /* Counters */
int xgroup; /* # of groups of pixels */
/*
* Allocate read buffer space
*/
y = ImVfbQHeight( vfb );
x = ImVfbQWidth( vfb );
switch ( what )
{
case IMREADMONO:
case IMREADALPHA:
scanlinesize = (x * 1) / 8;
xgroup = x/8; /* 8 1-bit quantities per byte */
break;
case IMREADINDEX8:
scanlinesize = (x * 4) / 8;
xgroup = x/2; /* 2 4-bit quantities per byte */
break;
}
if ( scanlinesize & 0x3 )
scanlinesize = (scanlinesize & ~0x3) + 4;
ImCalloc( rbuf, unsigned char*, scanlinesize, sizeof( unsigned char) );
/*
* Read in pixels and put them into the selected VFB field.
*/
switch ( what )
{
case IMREADMONO: /* 8 pixels to a byte. */
/*
* An OFF bit uses the 1st CLT entry, while an ON bit
* uses the 2nd CLT entry.
*/
for ( i = y-1; i >= 0 ; --i )
{
vfbptr = ImVfbQPtr( vfb, 0, i );
if ( ImBinRead( ioType, fd, fp, rbuf, UCHAR, 1,
scanlinesize ) == -1 )
{
ImReturnBinError( );
}
rbufptr = rbuf;
for ( j = 0; j < xgroup; ++j )
{
mask = 0x80;
for ( k = 0; k < 8; k++ )
{
if ( (*rbufptr & mask) == mask )
ImVfbSIndex8( vfb, vfbptr, 1 );
else
ImVfbSIndex8( vfb, vfbptr, 0 );
ImVfbSInc( vfb, vfbptr );
mask >>= 1;
}
++rbufptr;
}
}
break;
case IMREADALPHA: /* 8 pixels to a byte. */
/*
* An ON bit maps to 255 (opaque) and an OFF bit to
* 0 (transparent).
*/
for ( i = y-1; i >= 0 ; --i )
{
vfbptr = ImVfbQPtr( vfb, 0, i );
if ( ImBinRead( ioType, fd, fp, rbuf, UCHAR, 1,
scanlinesize ) == -1 )
{
ImReturnBinError( );
}
rbufptr = rbuf;
for ( j = 0; j < xgroup; ++j )
{
mask = 0x80;
for ( k = 0; k < 8; k++ )
{
if ( (*rbufptr & mask) == mask )
ImVfbSAlpha( vfb, vfbptr, 255 );
else
ImVfbSAlpha( vfb, vfbptr, 0 );
ImVfbSInc( vfb, vfbptr );
mask >>= 1;
}
++rbufptr;
}
}
break;
case IMREADINDEX8:/* 2 pixels to a byte. */
for ( i = y-1; i >= 0 ; --i )
{
vfbptr = ImVfbQPtr( vfb, 0, i );
if ( ImBinRead( ioType, fd, fp, rbuf, UCHAR, 1,
scanlinesize ) == -1 )
{
ImReturnBinError( );
}
rbufptr = rbuf;
for ( j = 0; j < xgroup; ++j )
{
ImVfbSIndex8( vfb, vfbptr, (*rbufptr>>4)&0xF );
ImVfbSInc( vfb, vfbptr );
ImVfbSIndex8( vfb, vfbptr, *rbufptr&0x0F );
ImVfbSInc( vfb, vfbptr );
++rbufptr;
}
}
break;
}
free( (char *)rbuf );
return ( 0 );
}
/*
* FUNCTION
* imIcoImageRead - read in an image entry
*
* DESCRIPTION
* The next image's header, CLT, and pixels are read in and added
* to the tag table.
*/
static int
#ifdef __STDC__
imIcoImageRead ( int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable, imIcoDirEntry *icodirentryptr)
#else
imIcoImageRead ( ioType, fd, fp, flagsTable, tagTable, icodirentryptr)
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 */
imIcoDirEntry *icodirentryptr; /* Icon dir entry pointer */
#endif
{
imIcoInfo info; /* Icon image info */
ImVfb *vfb; /* Virtual Frame Buffers */
ImClt *clt = IMCLTNULL; /* Colortable */
ImCltPtr cltptr; /* Colortable entry pointer */
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 ncolors = 0; /* Number of colors used */
unsigned int x, y; /* Width and Height */
int i; /* Counters */
char message[100]; /* ImInfo message */
/*
* Read in icon image info.
*/
if( ImBinReadStruct( ioType, fd, fp, &info, imIcoInfoFields ) == -1 )
{
ImReturnBinError( );
}
/*
* Allocate a VFBs of the required size and type.
*/
x = info.ico_biwidth;
y = info.ico_biheight;
switch( info.ico_bibitcount )
{
case 1: /* 1-bit index image */
case 4: /* 4-bit index image */
if((vfb = ImVfbAlloc( x, y, IMVFBINDEX8 | IMVFBALPHA)) == IMVFBNULL)
{
ImErrorFatal( ImQError( ), -1, ImErrNo );
}
break;
default: /* unsupported image depth */
ImErrorFatal( ImQError( ), -1, IMEDEPTH );
}
/*
* Allocate and read in colortable
*/
ncolors = (1 << info.ico_bibitcount);
switch( ncolors )
{
case 2: /* 1-bit, monochrome */
case 16: /* 4-bit, indexed color */
break;
default:
ImErrorFatal( ImQError( ), -1, IMECLTLENGTH );
/* output warning */
}
clt = ImCltAlloc( ncolors );
if ( clt == IMCLTNULL )
{
ImErrorFatal( ImQError( ), -1, ImErrNo );
}
cltptr = ImCltQFirst( clt );
ImMalloc( rbuf, unsigned char*, ncolors*IMICORGBQUADSIZE );
rbufptr = rbuf;
if( ImBinRead( ioType, fd, fp, rbuf, UCHAR, 1,
ncolors*IMICORGBQUADSIZE ) == -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) );
/*
* Read in XOR mask image
*/
switch( info.ico_bibitcount )
{
case 1: /* 1-bit index image */
if ( imIcoReadImage( ioType, fd, fp, vfb, IMREADMONO ) == -1 )
return ( -1 ); /* ImErrNo already set */
break;
case 4: /* 4-bit index image */
if ( imIcoReadImage( ioType, fd, fp, vfb, IMREADINDEX8 ) == -1 )
return ( -1 ); /* ImErrNo already set */
break;
}
/*
* Read in AND mask image
*/
if ( imIcoReadImage( ioType, fd, fp, vfb, IMREADALPHA ) == -1 )
return ( -1 ); /* ImErrNo already set */
/*
* Add the VFB to the tagTable.
*/
TagTableAppend( tagTable,
TagEntryAlloc( "image vfb", POINTER, &(vfb) ) );
/*
* Output -verbose message
*/
sprintf( message, "%d x %d", x, y );
ImInfo( "Resolution", message );
if ( info.ico_bibitcount == 1 )
{
ImInfo( "Type", "1-bit Color Indexed (XOR mask)" );
}
else
{
ImInfo( "Type", "4-bit Color Indexed (XOR mask)" );
}
sprintf( message, "%d Entries", ncolors );
ImInfo( "Color Table", message );
ImInfo( "Alpha Channel", "1-bit Monochrome (AND mask)" );
return ( 2 );
}
/*
* FUNCTION
* imIcoWrite - top level control for writing Ico files
*
* DESCRIPTION
* A file header is written out, followed by a directory entry for
* each image in the VFB. The VFB's are then processed, one by one,
* to write them out with their individual headers, color tables, and
* pixels.
*/
static int /* Returns # of tags used */
#ifdef __STDC__
imIcoWrite( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp, TagTable *flagsTable, TagTable *tagTable )
#else
imIcoWrite( 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
{
imIcoHeader header; /* ICO file header */
imIcoDirEntry *direntries = NULL;/* List of ICO dir entries */
int ndirentries = 0;/* Number of ICO dir entries */
imIcoInfo info; /* ICO info */
ImVfb *vfb; /* Read in image */
ImClt *clt; /* Colortable */
unsigned int scanlinesize; /* Length of scanline */
unsigned int x, y; /* Width, Height */
int loop; /* Loop counter */
unsigned int iconx, icony; /* Width and Height of icon */
char message[100]; /* ImInfo message */
TagEntry *tagEntry; /* Tag table entry holder */
int fileOffset; /* Running file offset */
/*
* Set byte ordering
*/
BinByteOrder( BINLBF );
/*
* Get number of images
*/
ndirentries = TagTableQNEntry( tagTable, "image vfb" );
ImMalloc( direntries, imIcoDirEntry *,
(sizeof( imIcoDirEntry ) * ndirentries) );
/*
* Setup the file header and write it out
*/
header.ico_idReserved = 0;
header.ico_idType = IMICOMAGIC;
header.ico_idCount = ndirentries;
if ( ImBinWriteStruct( ioType, fd, fp, &header,
imIcoHeaderFields )==-1)
{
ImReturnBinError( );
}
/*
* Create and write out a directory entry for each VFB in the tag
* table.
*
* Note: the directory entry for an icon includes a file offset to
* that icon's data. Fortunately, we can compute this ahead of time
* by knowing the sizes and depths of the images being written out,
* knowing their order in the file (the same as that in the tag
* table), and knowing that they aren't being compressed (yeah!).
*/
fileOffset = IMICOHEADERSIZE + /* File header */
ndirentries * IMICODIRENTRYSIZE; /* All the dir entries */
for (loop = 0; loop < ndirentries; loop++)
{
/*
* Get vfb and clt
*/
tagEntry = TagTableQDirect( tagTable, "image vfb", loop );
TagEntryQValue( tagEntry, &vfb );
clt = ImVfbQClt( vfb ); /* Might be IMCLTNULL */
/*
* ICO icons are constrained to be 16, 32, or 64 pixels wide
* and high. If the VFB is larger than these, we'll have to
* to clip it.
*/
x = ImVfbQWidth( vfb );
y = ImVfbQHeight( vfb );
if ( x >= 64 ) iconx = x = 64;
else if ( x >= 32 ) iconx = x = 32;
else if ( x >= 16 ) iconx = x = 16;
else iconx = 16;
if ( y >= 64 ) icony = y = 64;
else if ( y >= 32 ) icony = y = 32;
else if ( y >= 16 ) icony = y = 16;
else icony = 16;
/*
* Setup icon directory and write it out.
*
* Note that only 2 color and 16 color icons are supported.
* 8 color icons are insufficiently described in the MicroSoft
* documentation.
*/
direntries[loop].ico_Width = iconx;
direntries[loop].ico_Height = icony;
if ( ImVfbQFields( vfb ) & IMVFBMONO )
/* Monochrome or only uses 2 colors. */
direntries[loop].ico_ColorCount = 2;
else
/* Uses more than 2 colors, so use 16 color version.*/
direntries[loop].ico_ColorCount = 16;
direntries[loop].ico_Reserved = 0;
direntries[loop].ico_Planes = 1;
if ( direntries[loop].ico_ColorCount == 2 )
/* Monochrome */
direntries[loop].ico_BitCount = 1;
else
/* Color */
direntries[loop].ico_BitCount = 4;
/*
* Resource size is the size of the icon header (IMICOINFOSIZE),
* plus the size of the color table (IMICORGBQUADSIZE for each
* entry), plus the icon byte data (icony scanlines), plus the
* size of the AND mask (iconx * icony bits).
*
* The scanline size is computed by calculating the number of
* bits on a scanline, then packing them into 8-bit bytes, then
* rounding up to the next higher 32-bit boundary.
*/
scanlinesize = (iconx * direntries[loop].ico_BitCount) / 8;
if ( scanlinesize & 0x3 )
scanlinesize = (scanlinesize & ~0x3) + 4;
direntries[loop].ico_BytesInRes = IMICOINFOSIZE +
direntries[loop].ico_ColorCount * IMICORGBQUADSIZE +
(scanlinesize * icony) + (iconx * icony / 8);
direntries[loop].ico_ImageOffset = fileOffset;
fileOffset += direntries[loop].ico_BytesInRes;
/*
* Write out the directory entry.
*/
if ( ImBinWriteStruct( ioType, fd, fp, &direntries[loop],
imIcoDirEntryFields )==-1)
{
ImReturnBinError( );
}
}
/*
* Loop through the images and write them out.
*/
for (loop = 0; loop < ndirentries; loop++)
{
/*
* Get vfb and clt
*/
tagEntry = TagTableQDirect( tagTable, "image vfb", loop );
clt = ImVfbQClt( vfb ); /* Might be IMCLTNULL */
/*
* ICO icons are constrained to be 16, 32, or 64 pixels wide
* and high. If the VFB is larger than these, we'll have to
* to clip it.
*/
x = ImVfbQWidth( vfb );
y = ImVfbQHeight( vfb );
if ( x >= 64 ) iconx = x = 64;
else if ( x >= 32 ) iconx = x = 32;
else if ( x >= 16 ) iconx = x = 16;
else iconx = 16;
if ( y >= 64 ) icony = y = 64;
else if ( y >= 32 ) icony = y = 32;
else if ( y >= 16 ) icony = y = 16;
else icony = 16;
/*
* The scanline size is computed by calculating the number of
* bits on a scanline, then packing them into 8-bit bytes, then
* rounding up to the next higher 32-bit boundary.
*/
scanlinesize = (iconx * direntries[loop].ico_BitCount) / 8;
if ( scanlinesize & 0x3 )
scanlinesize = (scanlinesize & ~0x3) + 4;
/*
* Setup icon info and write it out
*/
info.ico_bisize = IMICOINFOSIZE;
info.ico_biwidth = iconx;
info.ico_biheight = icony;
info.ico_biplanes = 1;
info.ico_bibitcount = direntries[loop].ico_BitCount;
info.ico_bicompress = 0;
info.ico_bisizeimage = scanlinesize * icony;
info.ico_bixpm = 0;
info.ico_biypm = 0;
info.ico_biclrused = 0;
info.ico_biclrim = 0;
if ( ImBinWriteStruct( ioType, fd, fp, &info,
imIcoInfoFields ) == -1 )
{
ImReturnBinError( );
}
/*
* Output -verbose messages
*/
ImInfo( "Byte Order", "Least Significant Byte First" );
sprintf( message, "%d of %d", loop+1, ndirentries );
ImInfo( "Image", message );
sprintf( message, "%d x %d", iconx, icony );
ImInfo( "Resolution", message );
if ( info.ico_bibitcount == 1 )
{
ImInfo( "Type", "1-bit Color Indexed (XOR mask)" );
ImInfo( "Color Table", "2 Entries" );
}
else
{
ImInfo( "Type", "4-bit Color Indexed (XOR mask)" );
ImInfo( "Color Table", "16 Entries" );
}
ImInfo( "Alpha Channel", "1-bit Monochrome (AND mask)" );
/*
* Write out the icon.
*/
if ( info.ico_bibitcount == 1 )
imIcoWriteRaw1( pMap, ioType, fd, fp, vfb, clt,
&direntries[loop] );
else
imIcoWriteRaw4( pMap, ioType, fd, fp, vfb, clt,
&direntries[loop] );
}
free( (char *)direntries );
return ndirentries;
}
/*
* FUNCTION
* imIcoWriteImage - write an icon image
*
* DESCRIPTION
* An icon image is written out, packing multiple pixels to a byte
* as appropriate.
*/
#define IMWRITEMONO 0
#define IMWRITEINDEX8 1
#define IMWRITEALPHA 2
static int /* Returns status */
#ifdef __STDC__
imIcoWriteImage( int ioType, int fd, FILE *fp, ImVfb *vfb, int what )
#else
imIcoWriteImage( ioType, fd, fp, vfb, what )
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
ImVfb *vfb; /* Read in image */
int what; /* What to write out */
#endif
{
ImVfbPtr vfbptr; /* Vfb pixel 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 char bitfield; /* Bitfield of 8 pixels */
unsigned int x, y; /* Width, Height */
int iconx, icony; /* Written icon size */
int i, j, k; /* Counters */
int xgroup; /* Number of pixel groups */
int xleft; /* Left over for last group */
/*
* Compute the written icon size (rounded up to 16, 32, or 64
* pixels).
*/
x = ImVfbQWidth( vfb );
y = ImVfbQHeight( vfb );
if ( x >= 64 ) iconx = x = 64;
else if ( x >= 32 ) iconx = x = 32;
else if ( x >= 16 ) iconx = x = 16;
else iconx = 16;
if ( y >= 64 ) icony = y = 64;
else if ( y >= 32 ) icony = y = 32;
else if ( y >= 16 ) icony = y = 16;
else icony = 16;
/*
* Allocate write buffer space
*/
switch ( what )
{
case IMWRITEMONO:
case IMWRITEALPHA:
scanlinesize = (iconx * 1) / 8;
xgroup = x/8; /* 8 1-bit quantities per byte */
xleft = x%8;
break;
case IMWRITEINDEX8:
scanlinesize = (iconx * 4) / 8;
xgroup = x/2; /* 2 4-bit quantities per byte */
xleft = x%2;
break;
}
if ( scanlinesize & 0x3 )
scanlinesize = (scanlinesize & ~0x3) + 4;
ImCalloc( wbuf, unsigned char*, scanlinesize, sizeof( unsigned char) );
/*
* Write image
*/
if ( what == IMWRITEALPHA && !(ImVfbQFields( vfb ) & IMVFBALPHA) )
{
/* No alpha on VFB. Write a zero alpha. */
memset( wbuf, 0x00, scanlinesize );
for ( i = 0; i < icony; ++i )
{
if( ImBinWrite( ioType, fd, fp, wbuf, UCHAR, 1,
scanlinesize )== -1 )
{
ImReturnBinError( );
}
}
free( (char *)wbuf );
return ( 0 );
}
if ( y < icony )
{
/*
* Image is smaller than icon being written. Dump some
* empty lines first.
*/
memset( wbuf, 0x00, scanlinesize );
for ( i = icony - y; i > 0; i-- )
{
if( ImBinWrite( ioType,fd,fp,wbuf,UCHAR,
1,scanlinesize )== -1 )
{
ImReturnBinError( );
}
}
}
for ( i = y-1; i >= 0; --i )
{
vfbptr = ImVfbQPtr( vfb, 0, i );
memset( wbuf, 0x00, scanlinesize );
wbufptr = wbuf;
for( j = 0; j < xgroup; ++j )
{
switch ( what )
{
case IMWRITEMONO: /* Pack 8 pixels to a byte */
for ( bitfield = 0, k = 0; k < 8; ++k )
{
pvalue = ImVfbQMono( vfb, vfbptr );
if ( pvalue )
bitfield |= (1 << (7-k));
ImVfbSInc( vfb, vfbptr );
}
break;
case IMWRITEALPHA:/* Pack 8 pixels to a byte */
for ( bitfield = 0, k = 0; k < 8; ++k )
{
pvalue = ImVfbQAlpha( vfb, vfbptr );
if ( pvalue < 128 )
bitfield |= (1 << (7-k));
ImVfbSInc( vfb, vfbptr );
}
break;
case IMWRITEINDEX8:/* Pack 2 pixels to a byte */
pvalue = ImVfbQIndex8( vfb, vfbptr ) & 0xF;
bitfield = pvalue << 4;
ImVfbSInc( vfb, vfbptr );
pvalue = ImVfbQIndex8( vfb, vfbptr ) & 0xF;
bitfield |= pvalue;
ImVfbSInc( vfb, vfbptr );
break;
}
*wbufptr++ = bitfield;
}
if ( xleft )
{
switch ( what )
{
case IMWRITEMONO: /* Pack <8 pixels to a byte */
for ( bitfield = 0, k = 0; k < xleft; ++k )
{
pvalue = ImVfbQMono( vfb, vfbptr );
if ( pvalue )
bitfield |= (1 << (7-k));
ImVfbSInc( vfb, vfbptr );
}
break;
case IMWRITEALPHA:/* Pack <8 pixels to a byte */
for ( bitfield = 0, k = 0; k < xleft; ++k )
{
pvalue = ImVfbQAlpha( vfb, vfbptr );
if ( pvalue < 128 )
bitfield |= (1 << (7-k));
ImVfbSInc( vfb, vfbptr );
}
break;
case IMWRITEINDEX8:/* Pack <2 pixels to a byte */
pvalue = ImVfbQIndex8( vfb, vfbptr ) & 0xF;
bitfield = pvalue << 4;
ImVfbSInc( vfb, vfbptr );
break;
}
*wbufptr++ = bitfield;
}
if( ImBinWrite( ioType,fd,fp,wbuf,UCHAR,1,scanlinesize ) == -1 )
{
ImReturnBinError( );
}
}
free( (unsigned char*) wbuf );
return ( 0 );
}
/*
* FUNCTION
* imIcoWriteRaw1 - write a 1-bit non-compressed ICO file
*
* DESCRIPTION
* An icon header and 2-color color table is written out, followed by
* the monochrome icon image.
*/
static int /* Returns # of tags used */
#ifdef __STDC__
imIcoWriteRaw1( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp, ImVfb *vfb, ImClt *clt, imIcoDirEntry *direntry )
#else
imIcoWriteRaw1( pMap, ioType, fd, fp, vfb, clt, direntry )
ImFileFormatWriteMap *pMap; /* Write map entry to adhear to */
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
ImVfb *vfb; /* Read in image */
ImClt *clt; /* Colortable */
imIcoDirEntry *direntry; /* ICO dir entry */
#endif
{
ImVfbPtr vfbptr; /* Vfb pixel pointer */
imIcoRGBQuad cltentry; /* Colortable RGBQuad entry */
ImCltPtr cltptr; /* Colortable entry pointer */
unsigned char bitfield; /* Bitfield of 8 pixels */
/*
* Write colortable
*/
if ( clt == IMCLTNULL )
{
/* Define the first entry to be black, by default. */
cltentry.reserved = 0;
cltentry.blue = 0;
cltentry.green = 0;
cltentry.red = 0;
if ( ImBinWriteStruct( ioType, fd, fp, &cltentry,
imIcoRGBQuadFields ) == -1 )
{
ImReturnBinError( );
}
/* And the second to be white. */
cltentry.blue = 255;
cltentry.green = 255;
cltentry.red = 255;
if ( ImBinWriteStruct( ioType, fd, fp, &cltentry,
imIcoRGBQuadFields ) == -1 )
{
ImReturnBinError( );
}
}
else
{
/* Use the first and second entries. */
cltptr = ImCltQFirst( clt );
cltentry.reserved = 0;
cltentry.blue = ImCltQBlue( cltptr );
cltentry.green = ImCltQGreen( cltptr );
cltentry.red = ImCltQRed( cltptr );
if ( ImBinWriteStruct( ioType, fd, fp, &cltentry,
imIcoRGBQuadFields ) == -1 )
{
ImReturnBinError( );
}
if ( ImCltQNColors( clt ) > 1 )
{
cltptr = ImCltQNext( clt, cltptr );
cltentry.blue = ImCltQBlue( cltptr );
cltentry.green = ImCltQGreen( cltptr );
cltentry.red = ImCltQRed( cltptr );
}
else
{
cltentry.blue = 255;
cltentry.green = 255;
cltentry.red = 255;
}
if ( ImBinWriteStruct( ioType, fd, fp, &cltentry,
imIcoRGBQuadFields ) == -1 )
{
ImReturnBinError( );
}
}
/*
* Write XOR mask and AND mask.
*/
if ( imIcoWriteImage( ioType, fd, fp, vfb, IMWRITEMONO ) != 0 )
return ( -1 ); /* ImErrNo already set */
if ( imIcoWriteImage( ioType, fd, fp, vfb, IMWRITEALPHA ) != 0 )
return ( -1 ); /* ImErrNo already set */
return ( 1 );
}
/*
* FUNCTION
* imIcoWriteRaw4 - write a 4-bit non-compressed ICO file
*
* DESCRIPTION
* An icon header and 16-color color table is written out, followed by
* the color icon image.
*/
static int /* Returns # of tags used */
#ifdef __STDC__
imIcoWriteRaw4( ImFileFormatWriteMap *pMap, int ioType, int fd, FILE *fp, ImVfb *vfb, ImClt *clt, imIcoDirEntry *direntry )
#else
imIcoWriteRaw4( pMap, ioType, fd, fp, vfb, clt, direntry )
ImFileFormatWriteMap *pMap; /* Write map entry to adhear to */
int ioType; /* I/O flags */
int fd; /* Input file descriptor */
FILE *fp; /* Input file pointer */
ImVfb *vfb; /* Read in image */
ImClt *clt; /* Colortable */
imIcoDirEntry *direntry; /* ICO dir entry */
#endif
{
ImVfb *newvfb; /* Icon image */
ImCltPtr cltptr; /* Colortable entry pointer */
unsigned char *wbuf; /* Pointer to write buffer */
unsigned char *wbufptr; /* Pointer to write buffer data */
unsigned int ncolors = 0; /* Number of colors used */
unsigned int x, y; /* Width, Height */
int i; /* Counter */
unsigned int iconx, icony; /* Width, Height of result icon */
char message[100]; /* ImInfo message */
x = ImVfbQWidth( vfb );
y = ImVfbQHeight( vfb );
if ( x >= 64 ) iconx = x = 64;
else if ( x >= 32 ) iconx = x = 32;
else if ( x >= 16 ) iconx = x = 16;
else iconx = 16;
if ( y >= 64 ) icony = y = 64;
else if ( y >= 32 ) icony = y = 32;
else if ( y >= 16 ) icony = y = 16;
else icony = 16;
/*
* We may have to reduce the number of colors in the image in order
* to make it fit into a 16 color table. To generally simplify the
* whole process, we'll copy the upper-left quadrant of the image
* into a new temporary VFB (up to 64 x 64) and only convert that
* smaller image.
*/
newvfb = ImVfbAlloc( iconx, icony, IMVFBINDEX8 | IMVFBALPHA );
ImVfbClear( IMVFBINDEX8, 0, newvfb );
ImVfbClear( IMVFBALPHA, 255, newvfb );
ImVfbSClt( newvfb, ImVfbQClt( vfb ) );
ImVfbCopy( vfb, 0, 0, x, y, IMVFBINDEX8 | IMVFBALPHA, newvfb, 0, 0 );
vfb = newvfb;
/*
* Reduce the number of colors (if necessary) and get clt
*/
ImVfbToIndex( vfb, 16, vfb );
clt = ImVfbQClt( vfb );
ncolors = ImCltQNColors( clt );
if( ncolors > 16 )
ncolors = 16;
/*
* Write colortable
*/
cltptr = ImCltQFirst( clt );
ImCalloc( wbuf, unsigned char*, 16, IMICORGBQUADSIZE );
memset( wbuf, 0x00, 16 * IMICORGBQUADSIZE );
wbufptr = wbuf;
for( i = 0; i < ncolors; ++i )
{
*wbufptr++ = ImCltQBlue( cltptr );
*wbufptr++ = ImCltQGreen( cltptr );
*wbufptr++ = ImCltQRed( cltptr );
wbufptr++; /* skip reserved field */
cltptr = ImCltQNext( clt, cltptr );
}
if ( ImBinWrite( ioType, fd, fp, wbuf, UCHAR, 1,
16*IMICORGBQUADSIZE ) == -1 )
{
ImReturnBinError( );
}
free( wbuf );
/*
* Write XOR mask and AND mask.
*/
if ( imIcoWriteImage( ioType, fd, fp, vfb, IMWRITEINDEX8 ) != 0 )
return ( -1 ); /* ImErrNo already set */
if ( imIcoWriteImage( ioType, fd, fp, vfb, IMWRITEALPHA ) != 0 )
return ( -1 ); /* ImErrNo already set */
ImVfbFree( newvfb );
return ( 1 );
}