/** ** $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 ); }