summaryrefslogtreecommitdiffstats
path: root/tkimg/ico/ico.c
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2019-03-20 17:29:30 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2019-03-20 17:29:30 (GMT)
commitcfef685ad45bc8f98a2d59fba75ba9bc6e06496d (patch)
tree066005da150adf4bf7892796647154a49d5ea23c /tkimg/ico/ico.c
parentc31bd7553b6efd2407fc521dc14aec1936e3cbf0 (diff)
downloadblt-cfef685ad45bc8f98a2d59fba75ba9bc6e06496d.zip
blt-cfef685ad45bc8f98a2d59fba75ba9bc6e06496d.tar.gz
blt-cfef685ad45bc8f98a2d59fba75ba9bc6e06496d.tar.bz2
upgrade tkimg 1.4.9
Diffstat (limited to 'tkimg/ico/ico.c')
-rw-r--r--tkimg/ico/ico.c1089
1 files changed, 0 insertions, 1089 deletions
diff --git a/tkimg/ico/ico.c b/tkimg/ico/ico.c
deleted file mode 100644
index 3147d3d..0000000
--- a/tkimg/ico/ico.c
+++ /dev/null
@@ -1,1089 +0,0 @@
-/* STARTHEADER
- *
- * File : ico.c
- *
- * Author : Paul Obermeier (paul@poSoft.de)
- *
- * Date : Mon Aug 12 20:30:46 CEST 2002
- *
- * Copyright : (C) 2002 Paul Obermeier
- *
- * Description :
- *
- * A photo image handler for Windows Icon file format.
- *
- * The following icon types are supported:
- *
- * 1-bit pixels: Black and White.
- * 4-bit pixels: Grayscale or indexed.
- * 8-bit pixels: Grayscale or indexed.
- * 24-bit pixels: True-color (GBR, each channel 8 bit).
- * 32-bit pixels: True-color (GBRA, each channel 8 bit).
- *
- * List of currently supported features:
- *
- * Type | Read | Write |
- * | -file | -data | -file | -data |
- * ----------------------------------------
- * 1-bit | Yes | Yes | No | No |
- * 4-bit | Yes | Yes | No | No |
- * 8-bit | Yes | Yes | Yes | Yes |
- * 24-bit | Yes | Yes | Yes | Yes |
- * 32-bit | Yes | Yes | No | No |
- *
- *
- * The following format options are available:
- *
- * Read ICO image: "ico -verbose <bool> -index <uint>"
- * Write ICO image: "ico -verbose <bool>"
- *
- * -verbose <bool>: If set to true, additional information about the file
- * format is printed to stdout. Default is "false".
- * -index <uint>: Read the icon with specified index. Default is 0.
- *
- * Notes:
- *
- *
- * ENDHEADER
- *
- */
-
-/*
- * Generic initialization code, parameterized via CPACKAGE and PACKAGE.
- */
-
-#include "init.c"
-
-
-/* #define DEBUG_LOCAL */
-
-/* Some defines and typedefs. */
-#define TRUE 1
-#define FALSE 0
-typedef unsigned char Boln; /* Boolean value: TRUE or FALSE */
-typedef unsigned char UByte; /* Unsigned 8 bit integer */
-typedef char Byte; /* Signed 8 bit integer */
-typedef unsigned short UShort; /* Unsigned 16 bit integer */
-typedef short Short; /* Signed 16 bit integer */
-typedef unsigned int UInt; /* Unsigned 32 bit integer */
-typedef int Int; /* Signed 32 bit integer */
-
-#define BI_RGB 0
-
-typedef struct {
- UByte width;
- UByte height;
- UShort nColors;
- UByte reserved;
- UShort nPlanes;
- UShort bitCount;
- UInt sizeInBytes;
- UInt fileOffset;
-} ICOENTRY;
-
-/* ICO file header structure */
-typedef struct {
- UShort nIcons;
- ICOENTRY *entries;
-} ICOHEADER;
-
-typedef struct {
- UInt size;
- UInt width;
- UInt height;
- UShort nPlanes;
- UShort nBitsPerPixel;
- UInt compression;
- UInt imageSize;
- UInt xPixelsPerM;
- UInt yPixelsPerM;
- UInt nColorsUsed;
- UInt nColorsImportant;
-} INFOHEADER;
-
-typedef struct {
- UByte red;
- UByte green;
- UByte blue;
- UByte matte;
-} ICOCOLOR;
-
-/* ICO file format options structure for use with ParseFormatOpts */
-typedef struct {
- UInt index;
- Boln verbose;
-} FMTOPT;
-
-static Boln readUByte (tkimg_MFile *handle, UByte *b)
-{
- char buf[1];
- if (1 != tkimg_Read(handle, buf, 1)) {
- return FALSE;
- }
- *b = buf[0] & 0xFF;
- return TRUE;
-}
-
-/* Read 2 bytes, representing a unsigned 16 bit integer in the form
- <LowByte, HighByte>, from a file and convert them into the current
- machine's format. */
-
-static Boln readUShort (tkimg_MFile *handle, UShort *s)
-{
- char buf[2];
- UShort tmp;
-
- if (2 != tkimg_Read(handle, buf, 2)) {
- return FALSE;
- }
- tmp = buf[0] & 0xFF;
- tmp |= (buf[1] & 0xFF) << 8;
- *s = tmp;
- return TRUE;
-}
-
-/* Read 4 bytes, representing a unsigned 32 bit integer in the form
- <LowByte, HighByte>, from a file and convert them into the current
- machine's format. */
-
-static Boln readUInt (tkimg_MFile *handle, UInt *i)
-{
- char buf[4];
- UInt tmp;
-
- if (4 != tkimg_Read(handle, buf, 4)) {
- return FALSE;
- }
- tmp = buf[0] & 0xFF;
- tmp |= (buf[1] & 0xFF) << 8;
- tmp |= (buf[2] & 0xFF) << 16;
- tmp |= (buf[3] & 0xFF) << 24;
- *i = tmp;
- return TRUE;
-}
-
-/* Write a byte, representing an unsigned integer to a file. */
-
-static Boln writeUByte (tkimg_MFile *handle, UByte b)
-{
- UByte buf[1];
- buf[0] = b;
- if (1 != tkimg_Write(handle, (const char *)buf, 1)) {
- return FALSE;
- }
- return TRUE;
-}
-
-/* Convert a unsigned 16 bit integer number into the format
- <LowByte, HighByte> (an array of 2 bytes) and write the array to a file. */
-
-static Boln writeUShort (tkimg_MFile *handle, UShort s)
-{
- Byte buf[2];
- buf[0] = (Byte)s;
- buf[1] = s >> 8;
- if (2 != tkimg_Write(handle, buf, 2)) {
- return FALSE;
- }
- return TRUE;
-}
-
-/* Convert a unsigned 32 bit integer number into the format
- <LowByte, HighByte> (an array of 4 bytes) and write the array to a file. */
-
-static Boln writeUInt (tkimg_MFile *handle, UInt i)
-{
- Byte buf[4];
- buf[0] = i;
- buf[1] = i >> 8;
- buf[2] = i >> 16;
- buf[3] = i >> 24;
- if (4 != tkimg_Write(handle, buf, 4)) {
- return FALSE;
- }
- return TRUE;
-}
-
-#define OUT Tcl_WriteChars (outChan, str, -1)
-static void printImgInfo (ICOHEADER *th, INFOHEADER *ih, FMTOPT *opts,
- const char *filename, const char *msg)
-{
- Tcl_Channel outChan;
- char str[256];
- int i = opts->index;
-
- outChan = Tcl_GetStdChannel (TCL_STDOUT);
- if (!outChan) {
- return;
- }
- sprintf(str, "%s %s\n", msg, filename); OUT;
- sprintf(str, " No. of icons : %d\n", th->nIcons); OUT;
- sprintf(str, " Icon %d:\n", i); OUT;
- sprintf(str, " Width and Height: %dx%d\n", ih->width, ih->height/2); OUT;
- sprintf(str, " Number of colors: %d\n", th->entries[i].nColors); OUT;
- sprintf(str, " Number of planes: %d\n", ih->nPlanes); OUT;
- sprintf(str, " Bits per pixel: %d\n", ih->nBitsPerPixel); OUT;
- sprintf(str, " Size in bytes: %d\n", th->entries[i].sizeInBytes); OUT;
- sprintf(str, " File offset: %d\n", th->entries[i].fileOffset); OUT;
- Tcl_Flush(outChan);
-}
-#undef OUT
-
-static Boln readIcoHeader (tkimg_MFile *handle, ICOHEADER *th)
-{
- int i;
- UByte nColors;
- UShort reserved, type, nIcons;
-
- if (!readUShort (handle, &reserved)) {
- return FALSE;
- }
- if (reserved != 0) {
- return FALSE;
- }
-
- if (!readUShort (handle, &type)) {
- return FALSE;
- }
- if (type != 1) {
- return FALSE;
- }
- if (!readUShort (handle, &nIcons)) {
- return FALSE;
- }
- if (nIcons <= 0) {
- return FALSE;
- }
-
- th->nIcons = nIcons;
- if (!(th->entries = (ICOENTRY *)ckalloc (sizeof (ICOENTRY) * nIcons))) {
- return FALSE;
- }
-
- for (i=0; i<nIcons; i++) {
- if (!readUByte (handle, &th->entries[i].width) ||
- !readUByte (handle, &th->entries[i].height) ||
- !readUByte (handle, &nColors) ||
- !readUByte (handle, &th->entries[i].reserved) ||
- !readUShort (handle, &th->entries[i].nPlanes) ||
- !readUShort (handle, &th->entries[i].bitCount) ||
- !readUInt (handle, &th->entries[i].sizeInBytes) ||
- !readUInt (handle, &th->entries[i].fileOffset)) {
- ckfree ((char *)th->entries);
- return FALSE;
- }
- th->entries[i].nColors = (nColors == 0? 256: nColors);
-#ifdef DEBUG_LOCAL
- printf ("Icon %d:\n", i);
- printf (" Width : %d\n", th->entries[i].width);
- printf (" Height : %d\n", th->entries[i].height);
- printf (" Colors : %d\n", th->entries[i].nColors);
- printf (" Planes : %d\n", th->entries[i].nPlanes);
- printf (" BitCount : %d\n", th->entries[i].bitCount);
- printf (" Size : %d\n", th->entries[i].sizeInBytes);
- printf (" FileOffset: %d\n", th->entries[i].fileOffset);
-#endif
- }
- return TRUE;
-}
-
-static Boln writeIcoHeader (tkimg_MFile *handle, ICOHEADER *th)
-{
- int i;
- UByte nColors;
- UShort reserved = 0,
- type = 1;
-
- if (!writeUShort (handle, reserved)) {
- return FALSE;
- }
- if (!writeUShort (handle, type)) {
- return FALSE;
- }
- if (!writeUShort (handle, th->nIcons)) {
- return FALSE;
- }
- for (i=0; i<th->nIcons; i++) {
- nColors = (th->entries[i].nColors == 256? 0: th->entries[i].nColors);
- if (!writeUByte (handle, th->entries[i].width) ||
- !writeUByte (handle, th->entries[i].height) ||
- !writeUByte (handle, nColors) ||
- !writeUByte (handle, th->entries[i].reserved) ||
- !writeUShort (handle, th->entries[i].nPlanes) ||
- !writeUShort (handle, th->entries[i].bitCount) ||
- !writeUInt (handle, th->entries[i].sizeInBytes) ||
- !writeUInt (handle, th->entries[i].fileOffset)) {
- return FALSE;
- }
- }
- return TRUE;
-}
-
-static Boln readInfoHeader (tkimg_MFile *handle, INFOHEADER *ih)
-{
- if (!readUInt (handle, &ih->size) ||
- !readUInt (handle, &ih->width) ||
- !readUInt (handle, &ih->height) ||
- !readUShort (handle, &ih->nPlanes) ||
- !readUShort (handle, &ih->nBitsPerPixel) ||
- !readUInt (handle, &ih->compression) ||
- !readUInt (handle, &ih->imageSize) ||
- !readUInt (handle, &ih->xPixelsPerM) ||
- !readUInt (handle, &ih->yPixelsPerM) ||
- !readUInt (handle, &ih->nColorsUsed) ||
- !readUInt (handle, &ih->nColorsImportant)) {
- return FALSE;
- }
-#ifdef DEBUG_LOCAL
- printf("Info header:\n");
- printf("Size: %d\n", ih->size);
- printf("Width: %d\n", ih->width);
- printf("Height: %d\n", ih->height);
- printf("Planes: %d\n", ih->nPlanes);
- printf("BitsPerPixel: %d\n", ih->nBitsPerPixel);
- printf("Compression: %d\n", ih->compression);
- printf("Image size: %d\n", ih->imageSize);
- printf("XPixelsPerM: %d\n", ih->xPixelsPerM);
- printf("YPixelsPerM: %d\n", ih->yPixelsPerM);
- printf("ColorsUsed: %d\n", ih->nColorsUsed);
- printf("ColorsImportant: %d\n", ih->nColorsImportant);
-#endif
- return TRUE;
-}
-
-static Boln writeInfoHeader (tkimg_MFile *handle, INFOHEADER *ih)
-{
- if (!writeUInt (handle, ih->size) ||
- !writeUInt (handle, ih->width) ||
- !writeUInt (handle, ih->height) ||
- !writeUShort (handle, ih->nPlanes) ||
- !writeUShort (handle, ih->nBitsPerPixel) ||
- !writeUInt (handle, ih->compression) ||
- !writeUInt (handle, ih->imageSize) ||
- !writeUInt (handle, ih->xPixelsPerM) ||
- !writeUInt (handle, ih->yPixelsPerM) ||
- !writeUInt (handle, ih->nColorsUsed) ||
- !writeUInt (handle, ih->nColorsImportant)) {
- return FALSE;
- }
-#ifdef DEBUG_LOCAL
- printf("Writing Info header:\n");
- printf("Size : %d\n", ih->size);
- printf("Width : %d\n", ih->width);
- printf("Height : %d\n", ih->height);
- printf("Planes : %d\n", ih->nPlanes);
- printf("BitsPerPixel: %d\n", ih->nBitsPerPixel);
- printf("Compression : %d\n", ih->compression);
- printf("Image size : %d\n", ih->imageSize);
- printf("XPixelsPerM : %d\n", ih->xPixelsPerM);
- printf("YPixelsPerM : %d\n", ih->yPixelsPerM);
- printf("ColorsUsed : %d\n", ih->nColorsUsed);
- printf("ColorsImport: %d\n", ih->nColorsImportant);
-#endif
- return TRUE;
-}
-
-static Boln readColorMap (tkimg_MFile *handle, int mapSize, ICOCOLOR *colorMap)
-{
- int i;
- ICOCOLOR color;
-
- for (i=0; i<mapSize; i++) {
- if (!readUByte (handle, &color.blue) ||
- !readUByte (handle, &color.green) ||
- !readUByte (handle, &color.red) ||
- !readUByte (handle, &color.matte)) {
- return FALSE;
- }
- colorMap[i] = color;
- }
- return TRUE;
-}
-
-static Boln writeColorMap (tkimg_MFile *handle, int mapSize, ICOCOLOR *colorMap)
-{
- int i;
-
- for (i=0; i<mapSize; i++) {
- if (!writeUByte (handle, colorMap[i].blue) ||
- !writeUByte (handle, colorMap[i].green) ||
- !writeUByte (handle, colorMap[i].red) ||
- !writeUByte (handle, colorMap[i].matte)) {
- return FALSE;
- }
- }
- return TRUE;
-}
-
-/*
- * Prototypes for local procedures defined in this file.
- */
-
-static int ParseFormatOpts(Tcl_Interp *interp, Tcl_Obj *format,
- FMTOPT *opts);
-static int CommonMatch(tkimg_MFile *handle, int *widthPtr,
- int *heightPtr, int index, ICOHEADER *icoHeaderPtr);
-static int CommonRead(Tcl_Interp *interp, tkimg_MFile *handle,
- const char *filename, Tcl_Obj *format,
- Tk_PhotoHandle imageHandle, int destX, int destY,
- int width, int height, int srcX, int srcY);
-static int CommonWrite(Tcl_Interp *interp, tkimg_MFile *handle,
- Tk_PhotoImageBlock *blockPtr);
-
-static int ParseFormatOpts (interp, format, opts)
- Tcl_Interp *interp;
- Tcl_Obj *format;
- FMTOPT *opts;
-{
- static const char *const icoOptions[] = {
- "-verbose", "-index", NULL
- };
- int objc, length, i, index;
- Tcl_Obj **objv;
- const char *indexStr, *verboseStr;
-
- /* Initialize format options with default values. */
- verboseStr = "0";
- indexStr = "0";
-
- if (tkimg_ListObjGetElements(interp, format, &objc, &objv) != TCL_OK)
- return TCL_ERROR;
- if (objc) {
- for (i=1; i<objc; i++) {
- if (Tcl_GetIndexFromObj(interp, objv[i], (CONST84 char *CONST86 *)icoOptions,
- "format option", 0, &index) != TCL_OK) {
- return TCL_ERROR;
- }
- if (++i >= objc) {
- Tcl_AppendResult(interp, "No value for option \"",
- Tcl_GetStringFromObj (objv[--i], (int *) NULL),
- "\"", (char *) NULL);
- return TCL_ERROR;
- }
- switch (index) {
- case 0:
- verboseStr = Tcl_GetStringFromObj(objv[i], (int *) NULL);
- break;
- case 1:
- indexStr = Tcl_GetStringFromObj(objv[i], (int *) NULL);
- break;
- }
- }
- }
-
- /* OPA TODO: Check for valid integer strings. */
- opts->index = atoi (indexStr);
-
- length = strlen (verboseStr);
- if (!strncmp (verboseStr, "1", length) || \
- !strncmp (verboseStr, "true", length) || \
- !strncmp (verboseStr, "on", length)) {
- opts->verbose = 1;
- } else if (!strncmp (verboseStr, "0", length) || \
- !strncmp (verboseStr, "false", length) || \
- !strncmp (verboseStr, "off", length)) {
- opts->verbose = 0;
- } else {
- Tcl_AppendResult(interp, "invalid verbose mode \"", verboseStr,
- "\": should be 1 or 0, on or off, true or false",
- (char *) NULL);
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-static int ChnMatch(
- Tcl_Channel chan,
- const char *fileName,
- Tcl_Obj *format,
- int *widthPtr,
- int *heightPtr,
- Tcl_Interp *interp
-) {
- tkimg_MFile handle;
- FMTOPT opts;
-
- handle.data = (char *) chan;
- handle.state = IMG_CHAN;
-
- if (ParseFormatOpts(interp, format, &opts) != TCL_OK) {
- return 0;
- }
-
- return CommonMatch(&handle, widthPtr, heightPtr, opts.index, NULL);
-}
-
-static int ObjMatch(
- Tcl_Obj *data,
- Tcl_Obj *format,
- int *widthPtr,
- int *heightPtr,
- Tcl_Interp *interp
-) {
- tkimg_MFile handle;
- FMTOPT opts;
-
- if (ParseFormatOpts(interp, format, &opts) != TCL_OK) {
- return 0;
- }
- if (!tkimg_ReadInit(data, '\000', &handle)) {
- return 0;
- }
- return CommonMatch(&handle, widthPtr, heightPtr, opts.index, NULL);
-}
-
-static int CommonMatch(handle, widthPtr, heightPtr, index, icoHeaderPtr)
- tkimg_MFile *handle;
- int *widthPtr, *heightPtr;
- int index;
- ICOHEADER *icoHeaderPtr;
-{
- ICOHEADER icoHeader, *headerPtr;
-
- if (!icoHeaderPtr) {
- headerPtr = &icoHeader;
- } else {
- headerPtr = icoHeaderPtr;
- }
- if (!readIcoHeader (handle, headerPtr)) {
- return 0;
- }
-
- *widthPtr = headerPtr->entries[index].width;
- *heightPtr = headerPtr->entries[index].height;
-
- if (!icoHeaderPtr) {
- ckfree ((char *) headerPtr->entries);
- }
- return 1;
-}
-
-static int ChnRead(interp, chan, filename, format, imageHandle,
- destX, destY, width, height, srcX, srcY)
- Tcl_Interp *interp;
- Tcl_Channel chan;
- const char *filename;
- Tcl_Obj *format;
- Tk_PhotoHandle imageHandle;
- int destX, destY;
- int width, height;
- int srcX, srcY;
-{
- tkimg_MFile handle;
-
- handle.data = (char *) chan;
- handle.state = IMG_CHAN;
-
- return CommonRead (interp, &handle, filename, format,
- imageHandle, destX, destY,
- width, height, srcX, srcY);
-}
-
-static int ObjRead (interp, data, format, imageHandle,
- destX, destY, width, height, srcX, srcY)
- Tcl_Interp *interp;
- Tcl_Obj *data;
- Tcl_Obj *format;
- Tk_PhotoHandle imageHandle;
- int destX, destY;
- int width, height;
- int srcX, srcY;
-{
- tkimg_MFile handle;
-
- tkimg_ReadInit(data, '\000', &handle);
-
- return CommonRead (interp, &handle, "InlineData", format, imageHandle,
- destX, destY, width, height, srcX, srcY);
-}
-
-static int CommonRead (interp, handle, filename, format, imageHandle,
- destX, destY, width, height, srcX, srcY)
- Tcl_Interp *interp; /* Interpreter to use for reporting errors. */
- tkimg_MFile *handle; /* The image file, open for reading. */
- const char *filename; /* The name of the image file. */
- Tcl_Obj *format; /* User-specified format object, or NULL. */
- Tk_PhotoHandle imageHandle; /* The photo image to write into. */
- int destX, destY; /* Coordinates of top-left pixel in
- * photo image to be written to. */
- int width, height; /* Dimensions of block of photo image to
- * be written to. */
- int srcX, srcY; /* Coordinates of top-left pixel to be used
- * in image being read. */
-{
- Tk_PhotoImageBlock block;
- int x, y;
- int fileWidth, fileHeight;
- int icoHeaderWidth, icoHeaderHeight;
- int outWidth, outHeight, outY;
- int bytesPerLine;
- int nBytesToSkip;
- int errorFlag = TCL_OK;
- unsigned char *line = NULL, *expline = NULL;
- char msgStr[1024];
- ICOHEADER icoHeader;
- INFOHEADER infoHeader;
- ICOCOLOR colorMap[256];
- FMTOPT opts;
-
- if (ParseFormatOpts(interp, format, &opts) != TCL_OK) {
- return TCL_ERROR;
- }
-
- if (!CommonMatch(handle, &fileWidth, &fileHeight, opts.index, &icoHeader)) {
- Tcl_AppendResult(interp, "Error reading header", (char *)NULL);
- errorFlag = TCL_ERROR;
- goto error;
- }
-
- if (opts.index < 0 || opts.index >= icoHeader.nIcons) {
- sprintf(msgStr, "Invalid icon index: %d", opts.index);
- Tcl_AppendResult(interp, msgStr, (char *)NULL);
- errorFlag = TCL_ERROR;
- goto error;
- }
-
- /* Instead of seeking, which does not work on strings,
- we calculate the number of bytes from the current position
- till the start of the INFOHEADER and read these bytes with tkimg_Read. */
- nBytesToSkip = icoHeader.entries[opts.index].fileOffset -6 -
- 16 * icoHeader.nIcons;
- if (nBytesToSkip > 0) {
- char *dummy = ckalloc (nBytesToSkip);
- tkimg_Read(handle, dummy, nBytesToSkip);
- ckfree ((char *) dummy);
- }
-
- /* Read Info header and color map */
- if (!readInfoHeader (handle, &infoHeader)) {
- Tcl_AppendResult(interp, "Error reading info header", (char *)NULL);
- errorFlag = TCL_ERROR;
- goto error;
- }
-
- if (infoHeader.compression != BI_RGB) {
- sprintf(msgStr,"Unsupported compression type (%d)", infoHeader.compression);
- Tcl_AppendResult(interp, msgStr, (char *)NULL);
- errorFlag = TCL_ERROR;
- goto error;
- }
-
- if (infoHeader.nBitsPerPixel != 24 && infoHeader.nBitsPerPixel != 32) {
- if (!readColorMap (handle, icoHeader.entries[opts.index].nColors, colorMap)) {
- Tcl_AppendResult(interp, "Error reading color map", (char *)NULL);
- errorFlag = TCL_ERROR;
- goto error;
- }
- }
-
- fileWidth = infoHeader.width;
- fileHeight = infoHeader.height / 2;
- icoHeaderWidth = icoHeader.entries[opts.index].width;
- icoHeaderHeight = icoHeader.entries[opts.index].height;
- if (icoHeaderWidth == 0) {
- icoHeaderWidth = 256;
- }
- if (icoHeaderHeight == 0) {
- icoHeaderHeight = 256;
- }
- if (fileWidth != icoHeaderWidth || fileHeight != icoHeaderHeight) {
- sprintf(msgStr,"ICO sizes don't match (%dx%d) vs. (%dx%d)",
- fileWidth, fileHeight,
- icoHeaderWidth, icoHeaderHeight);
- Tcl_AppendResult(interp, msgStr, (char *)NULL);
- errorFlag = TCL_ERROR;
- goto error;
- }
- outWidth = fileWidth;
- outHeight = fileHeight;
- if (fileWidth != width || fileHeight != height) {
- if (srcX != 0 || srcY != 0 || destX != 0 || destY != 0) {
- if ((srcX + width) > fileWidth) {
- outWidth = fileWidth - srcX;
- } else {
- outWidth = width;
- }
- if ((srcY + height) > fileHeight) {
- outHeight = fileHeight - srcY;
- } else {
- outHeight = height;
- }
- }
- }
- if ((outWidth <= 0) || (outHeight <= 0)
- || (srcX >= fileWidth) || (srcY >= fileHeight)) {
- return TCL_OK;
- }
-
- if (opts.verbose) {
- printImgInfo (&icoHeader, &infoHeader, &opts,
- filename, "Reading image:");
- }
-
- if (tkimg_PhotoExpand(interp, imageHandle, destX + outWidth, destY + outHeight) == TCL_ERROR) {
- errorFlag = TCL_ERROR;
- goto error;
- }
-
- bytesPerLine = ((infoHeader.nBitsPerPixel * fileWidth + 31)/32)*4;
-
- block.pixelSize = 4;
- block.pitch = fileWidth * 4;
- block.width = outWidth;
- block.height = 1;
- block.offset[0] = 0;
- block.offset[1] = 1;
- block.offset[2] = 2;
- block.offset[3] = 3;
- block.pixelPtr = (unsigned char *) ckalloc (4 * fileWidth * fileHeight);
- expline = block.pixelPtr;
-
- line = (unsigned char *) ckalloc(bytesPerLine);
- switch (infoHeader.nBitsPerPixel) {
- case 32:
- for (y=0; y<fileHeight; y++) {
- tkimg_Read(handle, (char *)line, bytesPerLine);
- for (x = 0; x < fileWidth; x++) {
- expline[0] = line[x*4 + 2];
- expline[1] = line[x*4 + 1];
- expline[2] = line[x*4 + 0];
- expline[3] = line[x*4 + 3];
- expline += 4;
- }
- }
- break;
- case 24:
- for (y=0; y<fileHeight; y++) {
- tkimg_Read(handle, (char *)line, bytesPerLine);
- for (x = 0; x < fileWidth; x++) {
- expline[0] = line[x*3 + 2];
- expline[1] = line[x*3 + 1];
- expline[2] = line[x*3 + 0];
- expline += 4;
- }
- }
- break;
- case 8:
- for (y=0; y<fileHeight; y++) {
- tkimg_Read(handle, (char *)line, bytesPerLine);
- for (x = 0; x < fileWidth; x++) {
- expline[0] = colorMap[line[x]].red;
- expline[1] = colorMap[line[x]].green;
- expline[2] = colorMap[line[x]].blue;
- expline += 4;
- }
- }
- break;
- case 4:
- for (y=0; y<fileHeight; y++) {
- int c;
- tkimg_Read(handle, (char *)line, bytesPerLine);
- for (x=0; x<fileWidth; x++) {
- if (x&1) {
- c = line[x/2] & 0x0f;
- } else {
- c = line[x/2] >> 4;
- }
- expline[0] = colorMap[c].red;
- expline[1] = colorMap[c].green;
- expline[2] = colorMap[c].blue;
- expline += 4;
- }
- }
- break;
- case 1:
- for (y=0; y<fileHeight; y++) {
- int c;
- tkimg_Read(handle, (char *)line, bytesPerLine);
- for (x=0; x<fileWidth; x++) {
- c = (line[x/8] >> (7-(x%8))) & 1;
- expline[0] = colorMap[c].red;
- expline[1] = colorMap[c].green;
- expline[2] = colorMap[c].blue;
- expline += 4;
- }
- }
- break;
- default:
- sprintf(msgStr,"%d-bits ICO file not supported",
- infoHeader.nBitsPerPixel);
- Tcl_AppendResult(interp, msgStr, (char *)NULL);
- errorFlag = TCL_ERROR;
- goto error;
- }
-
- if (infoHeader.nBitsPerPixel != 32) {
- /* Read XAND bitmap. We don't need to read the alpha bitmap, if
- alpha is supplied already in the 32-bit case. */
- bytesPerLine = ((1 * fileWidth + 31)/32)*4;
-
- expline = block.pixelPtr;
- for (y=0; y<fileHeight; y++) {
- int c;
- tkimg_Read(handle, (char *)line, bytesPerLine);
- for (x=0; x<fileWidth; x++) {
- c = (line[x/8] >> (7-(x%8))) & 1;
- expline[3] = (c? 0: 255);
- expline += 4;
- }
- }
- }
-
- /* Store the pointer to allocated buffer for later freeing. */
- expline = block.pixelPtr;
- block.pixelPtr += srcX * 4;
-
- outY = destY + outHeight - 1;
- for (y=fileHeight-1; y>=0; y--) {
- if (y >= srcY && y < srcY + outHeight) {
- errorFlag = tkimg_PhotoPutBlock(interp, imageHandle, &block, destX, outY,
- outWidth, 1, TK_PHOTO_COMPOSITE_SET);
- if (errorFlag == TCL_ERROR) {
- break;
- }
- outY--;
- }
- block.pixelPtr += 4 * fileWidth;
- }
- block.pixelPtr = expline;
-
-error:
- if (icoHeader.entries) {
- ckfree((char *) icoHeader.entries);
- }
- if (line) {
- ckfree((char *) line);
- }
- if (expline) {
- ckfree((char *) block.pixelPtr);
- }
- return errorFlag;
-}
-
-static int ChnWrite (interp, filename, format, blockPtr)
- Tcl_Interp *interp;
- const char *filename;
- Tcl_Obj *format;
- Tk_PhotoImageBlock *blockPtr;
-{
- Tcl_Channel chan;
- tkimg_MFile handle;
- int result;
-
- chan = tkimg_OpenFileChannel(interp, filename, 0644);
- if (!chan) {
- return TCL_ERROR;
- }
-
- handle.data = (char *) chan;
- handle.state = IMG_CHAN;
-
- result = CommonWrite(interp, &handle, blockPtr);
- if (Tcl_Close(interp, chan) == TCL_ERROR) {
- return TCL_ERROR;
- }
- return result;
-}
-
-static int StringWrite(
- Tcl_Interp *interp,
- Tcl_Obj *format,
- Tk_PhotoImageBlock *blockPtr
-) {
- tkimg_MFile handle;
- int result;
- Tcl_DString data;
-
- Tcl_DStringInit(&data);
- tkimg_WriteInit(&data, &handle);
- result = CommonWrite(interp, &handle, blockPtr);
- tkimg_Putc(IMG_DONE, &handle);
-
- if (result == TCL_OK) {
- Tcl_DStringResult(interp, &data);
- } else {
- Tcl_DStringFree(&data);
- }
- return result;
-}
-
-static int CommonWrite (interp, handle, blockPtr)
- Tcl_Interp *interp;
- tkimg_MFile *handle;
- Tk_PhotoImageBlock *blockPtr;
-{
- int bytesPerLineXOR, bytesPerLineAND, nbytes, ncolors, i, x, y;
- int redOffset, greenOffset, blueOffset, alphaOffset;
- int foundColor;
- UByte *imagePtr, *pixelPtr;
- UByte buf[4];
- ICOHEADER icoHeader;
- INFOHEADER infoHeader;
- ICOCOLOR colorMap[256];
- ICOCOLOR pixel;
-
- if (blockPtr->width > 255 || blockPtr->height > 255) {
- Tcl_AppendResult(interp, "ICO images must be less than 256 pixels.",
- (char *) NULL);
- return TCL_ERROR;
- }
-
- redOffset = 0;
- greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
- blueOffset = blockPtr->offset[2] - blockPtr->offset[0];
- alphaOffset = blockPtr->offset[0];
- if (alphaOffset < blockPtr->offset[2]) {
- alphaOffset = blockPtr->offset[2];
- }
- if (++alphaOffset < blockPtr->pixelSize) {
- alphaOffset -= blockPtr->offset[0];
- } else {
- alphaOffset = 0;
- }
- ncolors = 0;
- if (greenOffset || blueOffset) {
- for (y = 0; ncolors <= 256 && y < blockPtr->height; y++) {
- pixelPtr = blockPtr->pixelPtr + y*blockPtr->pitch + blockPtr->offset[0];
- for (x=0; ncolors <= 256 && x<blockPtr->width; x++) {
- pixel.red = pixelPtr[redOffset];
- pixel.green = pixelPtr[greenOffset];
- pixel.blue = pixelPtr[blueOffset];
- if (alphaOffset && (pixelPtr[alphaOffset] == 0)) {
- pixel.matte = 0;
- } else {
- pixel.matte = 1;
- }
- foundColor = 0;
- for (i=0; i<ncolors; i++) {
- if (pixel.red == colorMap[i].red &&
- pixel.green == colorMap[i].green &&
- pixel.blue == colorMap[i].blue) {
- foundColor = 1;
- break;
- }
- }
- if (!foundColor) {
- if (ncolors < 256) {
- colorMap[ncolors] = pixel;
- }
- ncolors++;
- }
- pixelPtr += blockPtr->pixelSize;
- }
- }
- if (ncolors <= 256) {
- pixel.red = pixel.green = pixel.blue = pixel.matte = 0;
- while (ncolors < 256) {
- colorMap[ncolors++] = pixel;
- }
- nbytes = 1;
- } else {
- nbytes = 3;
- ncolors = 0;
- }
- } else {
- nbytes = 1;
- }
-
- bytesPerLineXOR = ((blockPtr->width * nbytes + 3) / 4) * 4;
- bytesPerLineAND = ((blockPtr->width * 1 + 31) / 32 )* 4;
-
- icoHeader.nIcons = 1;
- if (!(icoHeader.entries = (ICOENTRY *) ckalloc (sizeof (ICOENTRY)))) {
- return TCL_ERROR;
- }
- icoHeader.entries[0].width = blockPtr->width;
- icoHeader.entries[0].height = blockPtr->height;
- icoHeader.entries[0].nColors = (ncolors > 0? ncolors: 0);
- icoHeader.entries[0].reserved = 0;
- icoHeader.entries[0].nPlanes = 1;
- icoHeader.entries[0].bitCount = (ncolors > 0? 8: 24);
- icoHeader.entries[0].sizeInBytes = sizeof (INFOHEADER) +
- ncolors * sizeof (ICOCOLOR) +
- bytesPerLineXOR * blockPtr->height +
- bytesPerLineAND * blockPtr->height;
- icoHeader.entries[0].fileOffset = 6 + icoHeader.nIcons * 16;
-
- if (!writeIcoHeader (handle, &icoHeader)) {
- return TCL_ERROR;
- }
-
- infoHeader.size = sizeof (INFOHEADER);
- infoHeader.width = blockPtr->width;
- infoHeader.height = blockPtr->height * 2;
- infoHeader.nPlanes = 1;
- infoHeader.nBitsPerPixel = (ncolors > 0? 8: 24);
- infoHeader.compression = 0;
- infoHeader.imageSize = 0;
- infoHeader.xPixelsPerM = 0;
- infoHeader.yPixelsPerM = 0;
- infoHeader.nColorsUsed = 0;
- infoHeader.nColorsImportant = 0;
-
- if (!writeInfoHeader (handle, &infoHeader)) {
- return TCL_ERROR;
- }
-
- if (ncolors > 0) {
- if (!writeColorMap (handle, ncolors, colorMap)) {
- return TCL_ERROR;
- }
- }
-
- bytesPerLineXOR -= blockPtr->width * nbytes;
-
- imagePtr = blockPtr->pixelPtr + blockPtr->offset[0] +
- blockPtr->height * blockPtr->pitch;
- for (y = 0; y < blockPtr->height; y++) {
- pixelPtr = imagePtr -= blockPtr->pitch;
- for (x=0; x<blockPtr->width; x++) {
- if (ncolors) {
- for (i=0; i<ncolors; i++) {
- if (pixelPtr[redOffset] == colorMap[i].red &&
- pixelPtr[greenOffset] == colorMap[i].green &&
- pixelPtr[blueOffset] == colorMap[i].blue) {
- buf[0] = i;
- }
- }
- } else {
- buf[0] = pixelPtr[blueOffset];
- buf[1] = pixelPtr[greenOffset];
- buf[2] = pixelPtr[redOffset];
- }
- tkimg_Write(handle, (char *) buf, nbytes);
- pixelPtr += blockPtr->pixelSize;
- }
- if (bytesPerLineXOR) {
- tkimg_Write(handle, "\0\0\0", bytesPerLineXOR);
- }
- }
-
- bytesPerLineAND -= blockPtr->width / 8;
-
- imagePtr = blockPtr->pixelPtr + blockPtr->offset[0] +
- blockPtr->height * blockPtr->pitch;
- for (y = 0; y < blockPtr->height; y++) {
- int c;
- pixelPtr = imagePtr -= blockPtr->pitch;
- for (x=0; x<blockPtr->width; x++) {
- if (x % 8 == 0) {
- buf[0] = 0;
- }
- if (alphaOffset) {
- c = pixelPtr[alphaOffset];
- if (c == 0) {
- buf[0] |= 1<<(7-x%8);
- }
- }
- if (x % 8 == 7) {
- tkimg_Write(handle, (char *) buf, 1);
- }
- pixelPtr += blockPtr->pixelSize;
- }
- if (bytesPerLineAND) {
- tkimg_Write(handle, "\0\0\0", bytesPerLineAND);
- }
- }
- return TCL_OK;
-}