diff options
Diffstat (limited to 'tkimg/xbm/xbm.c')
-rw-r--r-- | tkimg/xbm/xbm.c | 669 |
1 files changed, 0 insertions, 669 deletions
diff --git a/tkimg/xbm/xbm.c b/tkimg/xbm/xbm.c deleted file mode 100644 index 5918755..0000000 --- a/tkimg/xbm/xbm.c +++ /dev/null @@ -1,669 +0,0 @@ -/* - * imgXBM.c -- - * - * A photo image file handler for XBM files. - * - * Written by: - * Jan Nijtmans - * email: nijtmans@users.sourceforge.net - * url: http://purl.oclc.org/net/nijtmans/ - * - * <paul@poSoft.de> Paul Obermeier - * Feb 2001: - * - Bugfix in CommonWrite: const char *fileName was overwritten. - * - * $Id: xbm.c,v 1.1.1.1 2016/01/25 21:20:47 joye Exp $ - * - */ - -/* - * Generic initialization code, parameterized via CPACKAGE and PACKAGE. - */ - -#include "init.c" - - -/* constants used only in this file */ - -#define MAX_BUFFER 4096 - -/* - * The following data structure is used to describe the state of - * parsing a bitmap file or string. It is used for communication - * between TkGetBitmapData and NextBitmapWord. - */ - -#define MAX_WORD_LENGTH 100 -typedef struct ParseInfo { - tkimg_MFile handle; - char word[MAX_WORD_LENGTH+1]; - /* Current word of bitmap data, NULL - * terminated. */ - int wordLength; /* Number of non-NULL bytes in word. */ -} ParseInfo; - -/* - * Prototypes for local procedures defined in this file: - */ - -static int CommonRead(Tcl_Interp *interp, - ParseInfo *parseInfo, - Tcl_Obj *format, Tk_PhotoHandle imageHandle, - int destX, int destY, int width, int height, - int srcX, int srcY); -static int CommonWrite(Tcl_Interp *interp, - const char *fileName, Tcl_DString *dataPtr, - Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr); - -static int ReadXBMFileHeader(ParseInfo *parseInfo, - int *widthPtr, int *heightPtr); -static int NextBitmapWord(ParseInfo *parseInfoPtr); - -/* - *---------------------------------------------------------------------- - * - * ObjMatch -- - * - * This procedure is invoked by the photo image type to see if - * a datastring contains image data in XBM format. - * - * Results: - * The return value is >0 if the first characters in data look - * like XBM data, and 0 otherwise. - * - * Side effects: - * none - * - *---------------------------------------------------------------------- - */ -static int ObjMatch( - Tcl_Obj *data, /* The data supplied by the image */ - Tcl_Obj *format, /* User-specified format string, or NULL. */ - int *widthPtr, /* The dimensions of the image are */ - int *heightPtr, /* returned here if the file is a valid - * raw XBM file. */ - Tcl_Interp *interp -) { - ParseInfo parseInfo; - - parseInfo.handle.data = (char *)tkimg_GetStringFromObj(data, &parseInfo.handle.length); - parseInfo.handle.state = IMG_STRING; - - return ReadXBMFileHeader(&parseInfo, widthPtr, heightPtr); -} - - -/* - *---------------------------------------------------------------------- - * - * ChnMatch -- - * - * This procedure is invoked by the photo image type to see if - * a channel contains image data in XBM format. - * - * Results: - * The return value is >0 if the first characters in channel "chan" - * look like XBM data, and 0 otherwise. - * - * Side effects: - * The access position in chan may change. - * - *---------------------------------------------------------------------- - */ - -static int ChnMatch( - Tcl_Channel chan, /* The image channel, open for reading. */ - const char *fileName, /* The name of the image file. */ - Tcl_Obj *format, /* User-specified format object, or NULL. */ - int *widthPtr, /* The dimensions of the image are */ - int *heightPtr, /* returned here if the file is a valid - * raw XBM file. */ - Tcl_Interp *interp -) { - ParseInfo parseInfo; - - parseInfo.handle.data = (char *) chan; - parseInfo.handle.state = IMG_CHAN; - - return ReadXBMFileHeader(&parseInfo, widthPtr, heightPtr); -} - -/* - *---------------------------------------------------------------------- - * - * CommonRead -- - * - * This procedure is called by the photo image type to read - * XBM format data from a file or string and write it into a - * given photo image. - * - * Results: - * A standard TCL completion code. If TCL_ERROR is returned - * then an error message is left in interp->result. - * - * Side effects: - * The access position in file f is changed (if read from file) - * and new data is added to the image given by imageHandle. - * - *---------------------------------------------------------------------- - */ -static int -CommonRead(interp, parseInfo, format, imageHandle, destX, destY, - width, height, srcX, srcY) - Tcl_Interp *interp; /* Interpreter to use for reporting errors. */ - ParseInfo *parseInfo; - Tcl_Obj *format; /* User-specified format string, 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 fileWidth, fileHeight; - int numBytes, row, col, value, i; - unsigned char *data, *pixelPtr; - char *end; - int result = TCL_OK; - - ReadXBMFileHeader(parseInfo, &fileWidth, &fileHeight); - - if ((srcX + width) > fileWidth) { - width = fileWidth - srcX; - } - if ((srcY + height) > fileHeight) { - height = fileHeight - srcY; - } - if ((width <= 0) || (height <= 0) - || (srcX >= fileWidth) || (srcY >= fileHeight)) { - return TCL_OK; - } - - if (tkimg_PhotoExpand(interp, imageHandle, destX + width, destY + height) == TCL_ERROR) { - return TCL_ERROR; - } - - numBytes = ((fileWidth+7)/8)*32; - block.width = fileWidth; - block.height = 1; - block.pixelSize = 4; - block.offset[0] = 0; - block.offset[1] = 1; - block.offset[2] = 2; - block.offset[3] = 3; - - data = (unsigned char *) ckalloc((unsigned) numBytes); - block.pixelPtr = data + srcX*4; - for (row = 0; row < srcY + height; row++) { - pixelPtr = data; - for (col = 0; col<(numBytes/32); col++) { - if (NextBitmapWord(parseInfo) != TCL_OK) { - ckfree((char *) data); - return TCL_ERROR; - } - value = (int) strtol(parseInfo->word, &end, 0); - if (end == parseInfo->word) { - ckfree((char *) data); - return TCL_ERROR; - } - for (i=0; i<8; i++) { - *pixelPtr++ = 0; - *pixelPtr++ = 0; - *pixelPtr++ = 0; - *pixelPtr++ = (value & 0x1)? 255:0; - value >>= 1; - } - } - if (row >= srcY) { - if (tkimg_PhotoPutBlock(interp, imageHandle, &block, destX, destY++, width, 1, TK_PHOTO_COMPOSITE_SET) == TCL_ERROR) { - result = TCL_ERROR; - break; - } - } - } - ckfree((char *) data); - return result; -} - -/* - *---------------------------------------------------------------------- - * - * ChnRead -- - * - * This procedure is called by the photo image type to read - * XBM format data from a channel and write it into a given - * photo image. - * - * Results: - * A standard TCL completion code. If TCL_ERROR is returned - * then an error message is left in interp->result. - * - * Side effects: - * The access position in channel chan is changed, and new data is - * added to the image given by imageHandle. - * - *---------------------------------------------------------------------- - */ - -static int -ChnRead(interp, chan, fileName, format, imageHandle, destX, destY, - width, height, srcX, srcY) - Tcl_Interp *interp; /* Interpreter to use for reporting errors. */ - Tcl_Channel chan; /* The image channel, 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. */ -{ - ParseInfo parseInfo; - - parseInfo.handle.data = (char *) chan; - parseInfo.handle.state = IMG_CHAN; - - return CommonRead(interp, &parseInfo, format, imageHandle, - destX, destY, width, height, srcX, srcY); -} - -/* - *---------------------------------------------------------------------- - * - * ObjRead -- - * - * This procedure is called by the photo image type to read - * XBM format data from a string and write it into a given - * photo image. - * - * Results: - * A standard TCL completion code. If TCL_ERROR is returned - * then an error message is left in interp->result. - * - * Side effects: - * New data is added to the image given by imageHandle. - * - *---------------------------------------------------------------------- - */ - -static int -ObjRead(interp, data, format, imageHandle, destX, destY, - width, height, srcX, srcY) - Tcl_Interp *interp; /* Interpreter to use for reporting errors. */ - Tcl_Obj *data; - Tcl_Obj *format; /* User-specified format string, 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. */ -{ - ParseInfo parseInfo; - parseInfo.handle.data = (char *)tkimg_GetStringFromObj(data, &parseInfo.handle.length); - parseInfo.handle.state = IMG_STRING; - - return CommonRead(interp, &parseInfo, format, imageHandle, - destX, destY, width, height, srcX, srcY); -} - -/* - *---------------------------------------------------------------------- - * - * ReadXBMFileHeader -- - * - * This procedure reads the XBM header from the beginning of a - * XBM file and returns information from the header. - * - * Results: - * The return value is 1 if file "f" appears to start with a valid - * XBM header, and 0 otherwise. If the header is valid, - * then *widthPtr and *heightPtr are modified to hold the - * dimensions of the image and *numColors holds the number of - * colors and byteSize the number of bytes used for 1 pixel. - * - * Side effects: - * The access position in f advances. - * - *---------------------------------------------------------------------- - */ - -#define UCHAR(c) ((unsigned char) (c)) - -/* - *---------------------------------------------------------------------- - * - * NextBitmapWord -- - * - * This procedure retrieves the next word of information (stuff - * between commas or white space) from a bitmap description. - * - * Results: - * Returns TCL_OK if all went well. In this case the next word, - * and its length, will be availble in *parseInfoPtr. If the end - * of the bitmap description was reached then TCL_ERROR is returned. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static int -NextBitmapWord(parseInfoPtr) - ParseInfo *parseInfoPtr; /* Describes what we're reading - * and where we are in it. */ -{ - char *dst, buf; - int num; - - parseInfoPtr->wordLength = 0; - dst = parseInfoPtr->word; - - for (num=tkimg_Read(&parseInfoPtr->handle,&buf,1); isspace(UCHAR(buf)) || (buf == ','); - num=tkimg_Read(&parseInfoPtr->handle,&buf,1)) { - if (num == 0) { - return TCL_ERROR; - } - } - for ( ; !isspace(UCHAR(buf)) && (buf != ',') && (num != 0); - num=tkimg_Read(&parseInfoPtr->handle,&buf,1)) { - *dst = buf; - dst++; - parseInfoPtr->wordLength++; - if (num == 0 || parseInfoPtr->wordLength > MAX_WORD_LENGTH) { - return TCL_ERROR; - } - } - - if (parseInfoPtr->wordLength == 0) { - return TCL_ERROR; - } - parseInfoPtr->word[parseInfoPtr->wordLength] = 0; - return TCL_OK; -} - -static int -ReadXBMFileHeader(pi, widthPtr, heightPtr) - ParseInfo *pi; - int *widthPtr, *heightPtr; /* The dimensions of the image are - * returned here. */ -{ - int width, height; - char *end; - - /* - * Parse the lines that define the dimensions of the bitmap, - * plus the first line that defines the bitmap data (it declares - * the name of a data variable but doesn't include any actual - * data). These lines look something like the following: - * - * #define foo_width 16 - * #define foo_height 16 - * #define foo_x_hot 3 - * #define foo_y_hot 3 - * static char foo_bits[] = { - * - * The x_hot and y_hot lines may or may not be present. It's - * important to check for "char" in the last line, in order to - * reject old X10-style bitmaps that used shorts. - */ - - width = 0; - height = 0; - while (1) { - if (NextBitmapWord(pi) != TCL_OK) { - return 0; - } - if ((pi->wordLength >= 6) && (pi->word[pi->wordLength-6] == '_') - && (strcmp(pi->word+pi->wordLength-6, "_width") == 0)) { - if (NextBitmapWord(pi) != TCL_OK) { - return 0; - } - width = strtol(pi->word, &end, 0); - if ((end == pi->word) || (*end != 0)) { - return 0; - } - } else if ((pi->wordLength >= 7) && (pi->word[pi->wordLength-7] == '_') - && (strcmp(pi->word+pi->wordLength-7, "_height") == 0)) { - if (NextBitmapWord(pi) != TCL_OK) { - return 0; - } - height = strtol(pi->word, &end, 0); - if ((end == pi->word) || (*end != 0)) { - return 0; - } - } else if ((pi->wordLength >= 6) && (pi->word[pi->wordLength-6] == '_') - && (strcmp(pi->word+pi->wordLength-6, "_x_hot") == 0)) { - if (NextBitmapWord(pi) != TCL_OK) { - return 0; - } - strtol(pi->word, &end, 0); - if ((end == pi->word) || (*end != 0)) { - return 0; - } - } else if ((pi->wordLength >= 6) && (pi->word[pi->wordLength-6] == '_') - && (strcmp(pi->word+pi->wordLength-6, "_y_hot") == 0)) { - if (NextBitmapWord(pi) != TCL_OK) { - return 0; - } - strtol(pi->word, &end, 0); - if ((end == pi->word) || (*end != 0)) { - return 0; - } - } else if ((pi->word[0] == 'c') && (strcmp(pi->word, "char") == 0)) { - while (1) { - if (NextBitmapWord(pi) != TCL_OK) { - return 0; - } - if ((pi->word[0] == '{') && (pi->word[1] == 0)) { - goto getData; - } - } - } else if ((pi->word[0] == '{') && (pi->word[1] == 0)) { - - return 0; - } - } - -getData: - *widthPtr = width; - *heightPtr = height; - return 1; -} - - -/* - *---------------------------------------------------------------------- - * - * ChnWrite - * - * Writes a XBM image to a file. Just calls CommonWrite - * with appropriate arguments. - * - * Results: - * Returns the return value of CommonWrite - * - * Side effects: - * A file is (hopefully) created on success. - * - *---------------------------------------------------------------------- - */ -static int -ChnWrite(interp, fileName, format, blockPtr) - Tcl_Interp *interp; - const char *fileName; - Tcl_Obj *format; - Tk_PhotoImageBlock *blockPtr; -{ - return CommonWrite(interp, fileName, (Tcl_DString *)NULL, format, blockPtr); -} - - -/* - *---------------------------------------------------------------------- - * - * StringWrite - * - * Writes a XBM image to a string. Just calls CommonWrite - * with appropriate arguments. - * - * Results: - * Returns the return value of CommonWrite - * - * Side effects: - * The Tcl_DString dataPtr is modified on success. - * - *---------------------------------------------------------------------- - */ -static int StringWrite( - Tcl_Interp *interp, - Tcl_Obj *format, - Tk_PhotoImageBlock *blockPtr -) { - int result; - Tcl_DString data; - - Tcl_DStringInit(&data); - result = CommonWrite(interp, "InlineData", &data, format, blockPtr); - - if (result == TCL_OK) { - Tcl_DStringResult(interp, &data); - } else { - Tcl_DStringFree(&data); - } - return result; -} - - -/* - * Yes, I know these macros are dangerous. But it should work fine - */ -#define WRITE(buf) { if (chan) Tcl_Write(chan, buf, -1); else Tcl_DStringAppend(dataPtr, buf, -1);} - -/* - *---------------------------------------------------------------------- - * - * CommonWrite - * - * This procedure writes a XBM image to the file filename - * (if filename != NULL) or to dataPtr. - * - * Results: - * Returns TCL_OK on success, or TCL_ERROR on error. - * - * Side effects: - * varies (see StringWrite and ChnWrite) - * - *---------------------------------------------------------------------- - */ -static int -CommonWrite(interp, fileName, dataPtr, format, blockPtr) - Tcl_Interp *interp; - const char *fileName; - Tcl_DString *dataPtr; - Tcl_Obj *format; - Tk_PhotoImageBlock *blockPtr; -{ - Tcl_Channel chan = (Tcl_Channel) NULL; - char buffer[256]; - unsigned char *pp; - int x, y, value, mask; - int sep = ' '; - int alphaOffset; - char *p = (char *) NULL; - char *imgName; - static const char header[] = -"#define %s_width %d\n\ -#define %s_height %d\n\ -static char %s_bits[] = {\n"; - - alphaOffset = blockPtr->offset[0]; - if (alphaOffset < blockPtr->offset[1]) alphaOffset = blockPtr->offset[1]; - if (alphaOffset < blockPtr->offset[2]) alphaOffset = blockPtr->offset[2]; - if (++alphaOffset < blockPtr->pixelSize) { - alphaOffset -= blockPtr->offset[0]; - } else { - alphaOffset = 0; - } - - - /* open the output file (if needed) */ - if (!dataPtr) { - chan = Tcl_OpenFileChannel(interp, (CONST84 char *) fileName, "w", 0644); - if (!chan) { - return TCL_ERROR; - } - } - - /* compute image name */ - imgName = (char*)ckalloc(strlen(fileName)+1); - memcpy (imgName, fileName, strlen(fileName)+1); - p = strrchr(imgName, '/'); - if (p) { - imgName = p+1; - } - p = strrchr(imgName, '\\'); - if (p) { - imgName = p+1; - } - p = strrchr(imgName, ':'); - if (p) { - imgName = p+1; - } - p = strchr(imgName, '.'); - if (p) { - *p = 0; - } - - sprintf(buffer, header, imgName, blockPtr->width, imgName, - blockPtr->height, imgName); - WRITE(buffer); - - /* write image itself */ - pp = blockPtr->pixelPtr + blockPtr->offset[0]; - sep = ' '; - for (y = 0; y < blockPtr->height; y++) { - value = 0; - mask = 1; - for (x = 0; x < blockPtr->width; x++) { - if (!alphaOffset || pp[alphaOffset]) { - value |= mask; - } else { - /* make transparent pixel */ - } - pp += blockPtr->pixelSize; - mask <<= 1; - if (mask >= 256) - { - sprintf(buffer,"%c 0x%02x",sep,value); - WRITE(buffer); - value = 0; - mask = 1; - sep = ','; - } - } - if (mask != 1) { - sprintf(buffer,"%c 0x%02x",sep, value); - WRITE(buffer); - } - - if (y == blockPtr->height - 1) { - WRITE("};\n"); - } else { - WRITE(",\n"); - sep = ' '; - } - } - - /* close the channel */ - if (chan) { - Tcl_Close(interp, chan); - } - return TCL_OK; -} |