diff options
author | hobbs <hobbs> | 1999-10-29 03:57:55 (GMT) |
---|---|---|
committer | hobbs <hobbs> | 1999-10-29 03:57:55 (GMT) |
commit | 8e52a87a0be5a9969812bdd4c5439688cc5cc9fc (patch) | |
tree | 71b94aa4df21cf83d8b4dfaeff16f8c4d6d9bd30 /generic/tkImgPhoto.c | |
parent | 62b72b828e6c010209ab75d9d8507adf8f7d6836 (diff) | |
download | tk-8e52a87a0be5a9969812bdd4c5439688cc5cc9fc.zip tk-8e52a87a0be5a9969812bdd4c5439688cc5cc9fc.tar.gz tk-8e52a87a0be5a9969812bdd4c5439688cc5cc9fc.tar.bz2 |
* generic/tk.h:
* generic/tkCmds.c:
* generic/tkImage.c:
* generic/tkImgBmap.c:
* generic/tkImgGIF.c:
* generic/tkImgPPM.c:
* generic/tkImgPhoto.c:
* generic/tkInt.h:
* generic/tkTest.c:
* generic/tkWindow.c:
* tests/imgPhoto.test: added Img patch (Nijtmans) with docs,
headers #def'd with USE_OLD_IMAGE. Upgrades image stuff to
Tcl_Obj API, adds alpha channel (images are now 32 bpp)
Diffstat (limited to 'generic/tkImgPhoto.c')
-rw-r--r-- | generic/tkImgPhoto.c | 1205 |
1 files changed, 986 insertions, 219 deletions
diff --git a/generic/tkImgPhoto.c b/generic/tkImgPhoto.c index 895f201..7e3b804 100644 --- a/generic/tkImgPhoto.c +++ b/generic/tkImgPhoto.c @@ -2,7 +2,7 @@ * tkImgPhoto.c -- * * Implements images of type "photo" for Tk. Photo images are - * stored in full color (24 bits per pixel) and displayed using + * stored in full color (32 bits per pixel) and displayed using * dithering if necessary. * * Copyright (c) 1994 The Australian National University. @@ -15,7 +15,7 @@ * Department of Computer Science, * Australian National University. * - * RCS: @(#) $Id: tkImgPhoto.c,v 1.9 1999/07/01 00:39:44 redman Exp $ + * RCS: @(#) $Id: tkImgPhoto.c,v 1.10 1999/10/29 03:57:56 hobbs Exp $ */ #include "tkInt.h" @@ -158,8 +158,8 @@ typedef struct PhotoMaster { * instances of this image. */ double gamma; /* Display gamma value to correct for. */ char *fileString; /* Name of file to read into image. */ - char *dataString; /* String value to use as contents of image. */ - char *format; /* User-specified format of data in image + Tcl_Obj *dataString; /* Object to use as contents of image. */ + Tcl_Obj *format; /* User-specified format of data in image * file or string value. */ unsigned char *pix24; /* Local storage for 24-bit image. */ int ditherX, ditherY; /* Location of first incorrectly @@ -222,14 +222,15 @@ typedef struct PhotoInstance { struct SubcommandOptions { int options; /* Individual bits indicate which * options were specified - see below. */ - char *name; /* Name specified without an option. */ + Tcl_Obj *name; /* Name specified without an option. */ int fromX, fromY; /* Values specified for -from option. */ int fromX2, fromY2; /* Second coordinate pair for -from option. */ int toX, toY; /* Values specified for -to option. */ int toX2, toY2; /* Second coordinate pair for -to option. */ int zoomX, zoomY; /* Values specified for -zoom option. */ int subsampleX, subsampleY; /* Values specified for -subsample option. */ - char *format; /* Value specified for -format option. */ + Tcl_Obj *format; /* Value specified for -format option. */ + XColor *background; /* Value specified for -background option. */ }; /* @@ -239,20 +240,24 @@ struct SubcommandOptions { * photo image subcommand. On return, the bit is set in the options * field of the SubcommandOptions structure if that option was specified. * + * OPT_BACKGROUND: Set if -format option allowed/specified. * OPT_FORMAT: Set if -format option allowed/specified. * OPT_FROM: Set if -from option allowed/specified. + * OPT_GRAYSCALE: Set if -grayscale option allowed/specified. * OPT_SHRINK: Set if -shrink option allowed/specified. * OPT_SUBSAMPLE: Set if -subsample option allowed/spec'd. * OPT_TO: Set if -to option allowed/specified. * OPT_ZOOM: Set if -zoom option allowed/specified. */ -#define OPT_FORMAT 1 -#define OPT_FROM 2 -#define OPT_SHRINK 4 -#define OPT_SUBSAMPLE 8 -#define OPT_TO 0x10 -#define OPT_ZOOM 0x20 +#define OPT_BACKGROUND 1 +#define OPT_FORMAT 2 +#define OPT_FROM 4 +#define OPT_GRAYSCALE 8 +#define OPT_SHRINK 0x10 +#define OPT_SUBSAMPLE 0x20 +#define OPT_TO 0x40 +#define OPT_ZOOM 0x80 /* * List of option names. The order here must match the order of @@ -260,8 +265,10 @@ struct SubcommandOptions { */ static char *optionNames[] = { + "-background", "-format", "-from", + "-grayscale", "-shrink", "-subsample", "-to", @@ -274,7 +281,7 @@ static char *optionNames[] = { */ static int ImgPhotoCreate _ANSI_ARGS_((Tcl_Interp *interp, - char *name, int argc, char **argv, + char *name, int objc, Tcl_Obj *CONST objv[], Tk_ImageType *typePtr, Tk_ImageMaster master, ClientData *clientDataPtr)); static ClientData ImgPhotoGet _ANSI_ARGS_((Tk_Window tkwin, @@ -300,6 +307,8 @@ Tk_ImageType tkPhotoImageType = { typedef struct ThreadSpecificData { Tk_PhotoImageFormat *formatList; /* Pointer to the first in the * list of known photo image formats.*/ + Tk_PhotoImageFormat *oldFormatList; /* Pointer to the first in the + * list of known photo image formats.*/ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; @@ -316,10 +325,6 @@ static Tcl_ThreadDataKey dataKey; * Information used for parsing configuration specifications: */ static Tk_ConfigSpec configSpecs[] = { - {TK_CONFIG_STRING, "-data", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(PhotoMaster, dataString), TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-format", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(PhotoMaster, format), TK_CONFIG_NULL_OK}, {TK_CONFIG_STRING, "-file", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(PhotoMaster, fileString), TK_CONFIG_NULL_OK}, {TK_CONFIG_DOUBLE, "-gamma", (char *) NULL, (char *) NULL, @@ -348,22 +353,28 @@ static int imgPhotoColorHashInitialized; */ static int ImgPhotoCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); static int ParseSubcommandOptions _ANSI_ARGS_(( struct SubcommandOptions *optPtr, Tcl_Interp *interp, int allowedOptions, - int *indexPtr, int argc, char **argv)); + int *indexPtr, int objc, Tcl_Obj *CONST objv[])); static void ImgPhotoCmdDeletedProc _ANSI_ARGS_(( ClientData clientData)); static int ImgPhotoConfigureMaster _ANSI_ARGS_(( Tcl_Interp *interp, PhotoMaster *masterPtr, - int argc, char **argv, int flags)); + int objc, Tcl_Obj *CONST objv[], int flags)); static void ImgPhotoConfigureInstance _ANSI_ARGS_(( PhotoInstance *instancePtr)); static void ImgPhotoSetSize _ANSI_ARGS_((PhotoMaster *masterPtr, int width, int height)); static void ImgPhotoInstanceSetSize _ANSI_ARGS_(( PhotoInstance *instancePtr)); +static int ImgStringWrite _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_DString *dataPtr, Tcl_Obj *formatString, + Tk_PhotoImageBlock *blockPtr)); +static char * ImgGetPhoto _ANSI_ARGS_((PhotoMaster *masterPtr, + Tk_PhotoImageBlock *blockPtr, + struct SubcommandOptions *optPtr)); static int IsValidPalette _ANSI_ARGS_((PhotoInstance *instancePtr, char *palette)); static int CountBits _ANSI_ARGS_((pixel mask)); @@ -376,14 +387,13 @@ static void DisposeInstance _ANSI_ARGS_((ClientData clientData)); static int ReclaimColors _ANSI_ARGS_((ColorTableId *id, int numColors)); static int MatchFileFormat _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Channel chan, char *fileName, - char *formatString, + Tcl_Channel chan, char *fileName, Tcl_Obj *formatString, Tk_PhotoImageFormat **imageFormatPtr, - int *widthPtr, int *heightPtr)); + int *widthPtr, int *heightPtr, int *oldformat)); static int MatchStringFormat _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char *formatString, + Tcl_Obj *data, Tcl_Obj *formatString, Tk_PhotoImageFormat **imageFormatPtr, - int *widthPtr, int *heightPtr)); + int *widthPtr, int *heightPtr, int *oldformat)); static void Dither _ANSI_ARGS_((PhotoMaster *masterPtr, int x, int y, int width, int height)); static void DitherInstance _ANSI_ARGS_((PhotoInstance *instancePtr, @@ -397,7 +407,7 @@ static void DitherInstance _ANSI_ARGS_((PhotoInstance *instancePtr, /* *---------------------------------------------------------------------- * - * Tk_CreatePhotoImageFormat -- + * Tk_CreateOldPhotoImageFormat, Tk_CreatePhotoImageFormat -- * * This procedure is invoked by an image file handler to register * a new photo image format and the procedures that handle the @@ -413,6 +423,25 @@ static void DitherInstance _ANSI_ARGS_((PhotoInstance *instancePtr, * *---------------------------------------------------------------------- */ +void +Tk_CreateOldPhotoImageFormat(formatPtr) + Tk_PhotoImageFormat *formatPtr; + /* Structure describing the format. All of + * the fields except "nextPtr" must be filled + * in by caller. Must not have been passed + * to Tk_CreatePhotoImageFormat previously. */ +{ + Tk_PhotoImageFormat *copyPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + copyPtr = (Tk_PhotoImageFormat *) ckalloc(sizeof(Tk_PhotoImageFormat)); + *copyPtr = *formatPtr; + copyPtr->name = (char *) ckalloc((unsigned) (strlen(formatPtr->name) + 1)); + strcpy(copyPtr->name, formatPtr->name); + copyPtr->nextPtr = tsdPtr->oldFormatList; + tsdPtr->oldFormatList = copyPtr; +} void Tk_CreatePhotoImageFormat(formatPtr) @@ -453,12 +482,12 @@ Tk_CreatePhotoImageFormat(formatPtr) */ static int -ImgPhotoCreate(interp, name, argc, argv, typePtr, master, clientDataPtr) +ImgPhotoCreate(interp, name, objc, objv, typePtr, master, clientDataPtr) Tcl_Interp *interp; /* Interpreter for application containing * image. */ char *name; /* Name to use for image. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings for options (doesn't + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects for options (doesn't * include image name or type). */ Tk_ImageType *typePtr; /* Pointer to our type record (not used). */ Tk_ImageMaster master; /* Token for image, to be used by us in @@ -476,7 +505,7 @@ ImgPhotoCreate(interp, name, argc, argv, typePtr, master, clientDataPtr) memset((void *) masterPtr, 0, sizeof(PhotoMaster)); masterPtr->tkMaster = master; masterPtr->interp = interp; - masterPtr->imageCmd = Tcl_CreateCommand(interp, name, ImgPhotoCmd, + masterPtr->imageCmd = Tcl_CreateObjCommand(interp, name, ImgPhotoCmd, (ClientData) masterPtr, ImgPhotoCmdDeletedProc); masterPtr->palette = NULL; masterPtr->pix24 = NULL; @@ -487,7 +516,7 @@ ImgPhotoCreate(interp, name, argc, argv, typePtr, master, clientDataPtr) * Process configuration options given in the image create command. */ - if (ImgPhotoConfigureMaster(interp, masterPtr, argc, argv, 0) != TCL_OK) { + if (ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, 0) != TCL_OK) { ImgPhotoDelete((ClientData) masterPtr); return TCL_ERROR; } @@ -515,14 +544,24 @@ ImgPhotoCreate(interp, name, argc, argv, typePtr, master, clientDataPtr) */ static int -ImgPhotoCmd(clientData, interp, argc, argv) +ImgPhotoCmd(clientData, interp, objc, objv) ClientData clientData; /* Information about photo master. */ Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ { + int oldformat = 0; + static char *photoOptions[] = { + "blank", "cget", "configure", "copy", "data", "get", "put", + "read", "redither", "write", (char *) NULL + }; + enum options { + PHOTO_BLANK, PHOTO_CGET, PHOTO_CONFIGURE, PHOTO_COPY, PHOTO_DATA, + PHOTO_GET, PHOTO_PUT, PHOTO_READ, PHOTO_REDITHER, PHOTO_WRITE + }; + PhotoMaster *masterPtr = (PhotoMaster *) clientData; - int c, result, index; + int result, index; int x, y, width, height; int dataWidth, dataHeight; struct SubcommandOptions options; @@ -542,54 +581,117 @@ ImgPhotoCmd(clientData, interp, argc, argv) ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - if (argc < 2) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " option ?arg arg ...?\"", (char *) NULL); + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); return TCL_ERROR; } - c = argv[1][0]; - length = strlen(argv[1]); - if ((c == 'b') && (strncmp(argv[1], "blank", length) == 0)) { + if (Tcl_GetIndexFromObj(interp, objv[1], photoOptions, "option", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + switch ((enum options) index) { + case PHOTO_BLANK: { /* * photo blank command - just call Tk_PhotoBlank. */ - if (argc == 2) { + if (objc == 2) { Tk_PhotoBlank(masterPtr); } else { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " blank\"", (char *) NULL); + Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL); return TCL_ERROR; } - } else if ((c == 'c') && (length >= 2) - && (strncmp(argv[1], "cget", length) == 0)) { - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " cget option\"", - (char *) NULL); + break; + } + case PHOTO_CGET: { + char *arg; + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option"); return TCL_ERROR; } + arg = Tcl_GetStringFromObj(objv[2],&length); + if (strncmp(arg,"-data", length) == 0) { + if (masterPtr->dataString) { + Tcl_SetObjResult(interp, masterPtr->dataString); + } + return TCL_OK; + } + if (strncmp(arg,"-format", length) == 0) { + if (masterPtr->format) { + Tcl_SetObjResult(interp, masterPtr->format); + } + return TCL_OK; + } Tk_ConfigureValue(interp, Tk_MainWindow(interp), configSpecs, - (char *) masterPtr, argv[2], 0); - } else if ((c == 'c') && (length >= 3) - && (strncmp(argv[1], "configure", length) == 0)) { + (char *) masterPtr, Tcl_GetString(objv[2]), 0); + break; + } + case PHOTO_CONFIGURE: { /* * photo configure command - handle this in the standard way. */ - if (argc == 2) { - return Tk_ConfigureInfo(interp, Tk_MainWindow(interp), + if (objc == 2) { + Tcl_Obj *obj, *subobj; + result = Tk_ConfigureInfo(interp, Tk_MainWindow(interp), configSpecs, (char *) masterPtr, (char *) NULL, 0); + if (result != TCL_OK) { + return result; + } + obj = Tcl_NewObj(); + subobj = Tcl_NewStringObj("-data {} {} {}", 14); + if (masterPtr->dataString) { + Tcl_ListObjAppendElement(interp, subobj, masterPtr->dataString); + } else { + Tcl_AppendStringsToObj(subobj, " {}", (char *) NULL); + } + Tcl_ListObjAppendElement(interp, obj, subobj); + subobj = Tcl_NewStringObj("-format {} {} {}", 16); + if (masterPtr->format) { + Tcl_ListObjAppendElement(interp, subobj, masterPtr->format); + } else { + Tcl_AppendStringsToObj(subobj, " {}", (char *) NULL); + } + Tcl_ListObjAppendElement(interp, obj, subobj); + Tcl_ListObjAppendList(interp, obj, Tcl_GetObjResult(interp)); + Tcl_SetObjResult(interp, obj); + return TCL_OK; } - if (argc == 3) { + if (objc == 3) { + char *arg = Tcl_GetStringFromObj(objv[2], &length); + if (!strncmp(arg, "-data", length)) { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "-data {} {} {}", (char *) NULL); + if (masterPtr->dataString) { + Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp), + masterPtr->dataString); + } else { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + " {}", (char *) NULL); + } + return TCL_OK; + } else if (!strncmp(arg, "-format", length)) { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + "-format {} {} {}", (char *) NULL); + if (masterPtr->format) { + Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp), + masterPtr->format); + } else { + Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), + " {}", (char *) NULL); + } + return TCL_OK; + } else { return Tk_ConfigureInfo(interp, Tk_MainWindow(interp), - configSpecs, (char *) masterPtr, argv[2], 0); + configSpecs, (char *) masterPtr, arg, 0); + } } - return ImgPhotoConfigureMaster(interp, masterPtr, argc-2, argv+2, + return ImgPhotoConfigureMaster(interp, masterPtr, objc-2, objv+2, TK_CONFIG_ARGV_ONLY); - } else if ((c == 'c') && (length >= 3) - && (strncmp(argv[1], "copy", length) == 0)) { + break; + } + case PHOTO_COPY: { /* * photo copy command - first parse options. */ @@ -601,14 +703,12 @@ ImgPhotoCmd(clientData, interp, argc, argv) options.name = NULL; if (ParseSubcommandOptions(&options, interp, OPT_FROM | OPT_TO | OPT_ZOOM | OPT_SUBSAMPLE | OPT_SHRINK, - &index, argc, argv) != TCL_OK) { + &index, objc, objv) != TCL_OK) { return TCL_ERROR; } - if (options.name == NULL || index < argc) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " copy source-image ?-from x1 y1 x2 y2?", - " ?-to x1 y1 x2 y2? ?-zoom x y? ?-subsample x y?", - "\"", (char *) NULL); + if (options.name == NULL || index < objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "source-image ?-from x1 y1 x2 y2? ?-to x1 y1 x2 y2? ?-zoom x y? ?-subsample x y?"); return TCL_ERROR; } @@ -617,8 +717,9 @@ ImgPhotoCmd(clientData, interp, argc, argv) * Check the values given for the -from option. */ - if ((srcHandle = Tk_FindPhoto(interp, options.name)) == NULL) { - Tcl_AppendResult(interp, "image \"", argv[2], "\" doesn't", + if ((srcHandle = Tk_FindPhoto(interp, Tcl_GetString(options.name))) == NULL) { + Tcl_AppendResult(interp, "image \"", + Tcl_GetString(options.name), "\" doesn't", " exist or is not a photo image", (char *) NULL); return TCL_ERROR; } @@ -684,25 +785,135 @@ ImgPhotoCmd(clientData, interp, argc, argv) options.toY2 - options.toY, options.zoomX, options.zoomY, options.subsampleX, options.subsampleY); - } else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) { + break; + } + case PHOTO_DATA: { + Tcl_DString buffer; + char *data; + Tcl_Obj *formatObj; + + /* + * photo data command - first parse and check any options given. + */ + Tk_ImageStringWriteProc *stringWriteProc = NULL; + + index = 2; + memset((VOID *) &options, 0, sizeof(options)); + options.name = NULL; + options.format = NULL; + options.fromX = 0; + options.fromY = 0; + if (ParseSubcommandOptions(&options, interp, + OPT_FORMAT | OPT_FROM | OPT_GRAYSCALE | OPT_BACKGROUND, + &index, objc, objv) != TCL_OK) { + return TCL_ERROR; + } + if ((options.name != NULL) || (index < objc)) { + Tcl_WrongNumArgs(interp, 2, objv, "?options?"); + return TCL_ERROR; + } + if ((options.fromX > masterPtr->width) + || (options.fromY > masterPtr->height) + || (options.fromX2 > masterPtr->width) + || (options.fromY2 > masterPtr->height)) { + Tcl_AppendResult(interp, "coordinates for -from option extend ", + "outside image", (char *) NULL); + return TCL_ERROR; + } + + /* + * Fill in default values for unspecified parameters. + */ + + if (((options.options & OPT_FROM) == 0) || (options.fromX2 < 0)) { + options.fromX2 = masterPtr->width; + options.fromY2 = masterPtr->height; + } + + /* + * Search for an appropriate image string format handler. + */ + + if (options.options & OPT_FORMAT) { + for (imageFormat = tsdPtr->formatList; imageFormat != NULL; + imageFormat = imageFormat->nextPtr) { + if ((strncasecmp(Tcl_GetString(options.format), + imageFormat->name, strlen(imageFormat->name)) == 0)) { + if (imageFormat->stringWriteProc != NULL) { + stringWriteProc = imageFormat->stringWriteProc; + break; + } + } + } + if (stringWriteProc == NULL) { + oldformat = 1; + for (imageFormat = tsdPtr->oldFormatList; imageFormat != NULL; + imageFormat = imageFormat->nextPtr) { + if ((strncasecmp(Tcl_GetString(options.format), + imageFormat->name, strlen(imageFormat->name)) == 0)) { + if (imageFormat->stringWriteProc != NULL) { + stringWriteProc = imageFormat->stringWriteProc; + break; + } + } + } + } + if (stringWriteProc == NULL) { + Tcl_AppendResult(interp, "image string format \"", + Tcl_GetString(options.format), + "\" is not supported", (char *) NULL); + return TCL_ERROR; + } + } else { + stringWriteProc = ImgStringWrite; + } + + /* + * Call the handler's string write procedure to write out + * the image. + */ + + data = ImgGetPhoto(masterPtr, &block, &options); + Tcl_DStringInit(&buffer); + + formatObj = options.format; + if (oldformat && formatObj) { + formatObj = (Tcl_Obj *) Tcl_GetString(options.format); + } + result = stringWriteProc(interp, &buffer, + formatObj, &block); + if (options.background) { + Tk_FreeColor(options.background); + } + if (data) { + ckfree(data); + } + if (result == TCL_OK) { + Tcl_DStringResult(interp, &buffer); + } else { + Tcl_DStringFree(&buffer); + } + return result; + break; + } + case PHOTO_GET: { /* * photo get command - first parse and check parameters. */ char string[TCL_INTEGER_SPACE * 3]; - if (argc != 4) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " get x y\"", (char *) NULL); + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "x y"); return TCL_ERROR; } - if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) - || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) { + if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) { return TCL_ERROR; } if ((x < 0) || (x >= masterPtr->width) || (y < 0) || (y >= masterPtr->height)) { - Tcl_AppendResult(interp, argv[0], " get: ", + Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " get: ", "coordinates out of range", (char *) NULL); return TCL_ERROR; } @@ -711,11 +922,13 @@ ImgPhotoCmd(clientData, interp, argc, argv) * Extract the value of the desired pixel and format it as a string. */ - pixelPtr = masterPtr->pix24 + (y * masterPtr->width + x) * 3; + pixelPtr = masterPtr->pix24 + (y * masterPtr->width + x) * 4; sprintf(string, "%d %d %d", pixelPtr[0], pixelPtr[1], pixelPtr[2]); Tcl_AppendResult(interp, string, (char *) NULL); - } else if ((c == 'p') && (strncmp(argv[1], "put", length) == 0)) { + break; + } + case PHOTO_PUT: { /* * photo put command - first parse the options and colors specified. */ @@ -723,17 +936,53 @@ ImgPhotoCmd(clientData, interp, argc, argv) index = 2; memset((VOID *) &options, 0, sizeof(options)); options.name = NULL; - if (ParseSubcommandOptions(&options, interp, OPT_TO, - &index, argc, argv) != TCL_OK) { + if (ParseSubcommandOptions(&options, interp, OPT_TO|OPT_FORMAT, + &index, objc, objv) != TCL_OK) { + return TCL_ERROR; + } + if ((options.name == NULL) || (index < objc)) { + Tcl_WrongNumArgs(interp, 2, objv, "data ?options?"); return TCL_ERROR; } - if ((options.name == NULL) || (index < argc)) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " put {{colors...}...} ?-to x1 y1 x2 y2?\"", - (char *) NULL); + + if (MatchStringFormat(interp, options.name ? objv[2]:NULL, + options.format, &imageFormat, &imageWidth, + &imageHeight, &oldformat) == TCL_OK) { + Tcl_Obj *format; + Tcl_Obj *data; + if (((options.options & OPT_TO) == 0) || (options.toX2 < 0)) { + options.toX2 = options.toX + imageWidth; + options.toY2 = options.toY + imageHeight; + } + if (imageWidth > options.toX2 - options.toX) { + imageWidth = options.toX2 - options.toX; + } + if (imageHeight > options.toY2 - options.toY) { + imageHeight = options.toY2 - options.toY; + } + format = options.format; + data = objv[2]; + if (oldformat) { + if (format) { + format = (Tcl_Obj *) Tcl_GetString(format); + } + data = (Tcl_Obj *) Tcl_GetString(data); + } + if ((*imageFormat->stringReadProc)(interp, data, + format, (Tk_PhotoHandle) masterPtr, + 0, 0, imageWidth, imageHeight, options.toX, options.toY) + != TCL_OK) { + return TCL_ERROR; + } + masterPtr->flags |= IMAGE_CHANGED; + return TCL_OK; + } + if (options.options & OPT_FORMAT) { return TCL_ERROR; } - if (Tcl_SplitList(interp, options.name, &dataHeight, &srcArgv) + Tcl_ResetResult(interp); + if (Tcl_SplitList(interp, Tcl_GetString(options.name), + &dataHeight, &srcArgv) != TCL_OK) { return TCL_ERROR; } @@ -807,26 +1056,26 @@ ImgPhotoCmd(clientData, interp, argc, argv) options.toX, options.toY, options.toX2 - options.toX, options.toY2 - options.toY); ckfree((char *) block.pixelPtr); - } else if ((c == 'r') && (length >= 3) - && (strncmp(argv[1], "read", length) == 0)) { + break; + } + case PHOTO_READ: { /* * photo read command - first parse the options specified. */ + Tcl_Obj *format; index = 2; memset((VOID *) &options, 0, sizeof(options)); options.name = NULL; options.format = NULL; if (ParseSubcommandOptions(&options, interp, OPT_FORMAT | OPT_FROM | OPT_TO | OPT_SHRINK, - &index, argc, argv) != TCL_OK) { + &index, objc, objv) != TCL_OK) { return TCL_ERROR; } - if ((options.name == NULL) || (index < argc)) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " read fileName ?-format format-name?", - " ?-from x1 y1 x2 y2? ?-to x y? ?-shrink?\"", - (char *) NULL); + if ((options.name == NULL) || (index < objc)) { + Tcl_WrongNumArgs(interp, 2, objv, + "fileName ?options?"); return TCL_ERROR; } @@ -844,7 +1093,8 @@ ImgPhotoCmd(clientData, interp, argc, argv) * Open the image file and look for a handler for it. */ - chan = Tcl_OpenFileChannel(interp, options.name, "r", 0); + chan = Tcl_OpenFileChannel(interp, + Tcl_GetString(options.name), "r", 0); if (chan == NULL) { return TCL_ERROR; } @@ -857,8 +1107,9 @@ ImgPhotoCmd(clientData, interp, argc, argv) return TCL_ERROR; } - if (MatchFileFormat(interp, chan, options.name, options.format, - &imageFormat, &imageWidth, &imageHeight) != TCL_OK) { + if (MatchFileFormat(interp, chan, + Tcl_GetString(options.name), options.format, + &imageFormat, &imageWidth, &imageHeight, &oldformat) != TCL_OK) { Tcl_Close(NULL, chan); return TCL_ERROR; } @@ -897,17 +1148,22 @@ ImgPhotoCmd(clientData, interp, argc, argv) * into the image. */ - result = (*imageFormat->fileReadProc)(interp, chan, options.name, - options.format, (Tk_PhotoHandle) masterPtr, options.toX, + format = options.format; + if (oldformat && format) { + format = (Tcl_Obj *) Tcl_GetString(format); + } + result = (*imageFormat->fileReadProc)(interp, chan, + Tcl_GetString(options.name), + format, (Tk_PhotoHandle) masterPtr, options.toX, options.toY, width, height, options.fromX, options.fromY); if (chan != NULL) { Tcl_Close(NULL, chan); } return result; - } else if ((c == 'r') && (length >= 3) - && (strncmp(argv[1], "redither", length) == 0)) { - - if (argc == 2) { + break; + } + case PHOTO_REDITHER: { + if (objc == 2) { /* * Call Dither if any part of the image is not correctly * dithered at present. @@ -935,11 +1191,14 @@ ImgPhotoCmd(clientData, interp, argc, argv) } } else { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " redither\"", (char *) NULL); + Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL); return TCL_ERROR; } - } else if ((c == 'w') && (strncmp(argv[1], "write", length) == 0)) { + break; + } + case PHOTO_WRITE: { + char *data; + Tcl_Obj *format; /* * Prevent file system access in safe interpreters. @@ -959,14 +1218,13 @@ ImgPhotoCmd(clientData, interp, argc, argv) memset((VOID *) &options, 0, sizeof(options)); options.name = NULL; options.format = NULL; - if (ParseSubcommandOptions(&options, interp, OPT_FORMAT | OPT_FROM, - &index, argc, argv) != TCL_OK) { + if (ParseSubcommandOptions(&options, interp, + OPT_FORMAT | OPT_FROM | OPT_GRAYSCALE | OPT_BACKGROUND, + &index, objc, objv) != TCL_OK) { return TCL_ERROR; } - if ((options.name == NULL) || (index < argc)) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " write fileName ?-format format-name?", - "?-from x1 y1 x2 y2?\"", (char *) NULL); + if ((options.name == NULL) || (index < objc)) { + Tcl_WrongNumArgs(interp, 2, objv, "fileName ?options?"); return TCL_ERROR; } if ((options.fromX > masterPtr->width) @@ -996,8 +1254,8 @@ ImgPhotoCmd(clientData, interp, argc, argv) for (imageFormat = tsdPtr->formatList; imageFormat != NULL; imageFormat = imageFormat->nextPtr) { if ((options.format == NULL) - || (strncasecmp(options.format, imageFormat->name, - strlen(imageFormat->name)) == 0)) { + || (strncasecmp(Tcl_GetString(options.format), + imageFormat->name, strlen(imageFormat->name)) == 0)) { matched = 1; if (imageFormat->fileWriteProc != NULL) { break; @@ -1005,15 +1263,31 @@ ImgPhotoCmd(clientData, interp, argc, argv) } } if (imageFormat == NULL) { + oldformat = 1; + for (imageFormat = tsdPtr->oldFormatList; imageFormat != NULL; + imageFormat = imageFormat->nextPtr) { + if ((options.format == NULL) + || (strncasecmp(Tcl_GetString(options.format), + imageFormat->name, strlen(imageFormat->name)) == 0)) { + matched = 1; + if (imageFormat->fileWriteProc != NULL) { + break; + } + } + } + } + if (imageFormat == NULL) { if (options.format == NULL) { Tcl_AppendResult(interp, "no available image file format ", "has file writing capability", (char *) NULL); } else if (!matched) { Tcl_AppendResult(interp, "image file format \"", - options.format, "\" is unknown", (char *) NULL); + Tcl_GetString(options.format), + "\" is unknown", (char *) NULL); } else { Tcl_AppendResult(interp, "image file format \"", - options.format, "\" has no file writing capability", + Tcl_GetString(options.format), + "\" has no file writing capability", (char *) NULL); } return TCL_ERROR; @@ -1024,17 +1298,23 @@ ImgPhotoCmd(clientData, interp, argc, argv) * the image. */ - Tk_PhotoGetImage((Tk_PhotoHandle) masterPtr, &block); - block.pixelPtr += options.fromY * block.pitch + options.fromX * 3; - block.width = options.fromX2 - options.fromX; - block.height = options.fromY2 - options.fromY; - return (*imageFormat->fileWriteProc)(interp, options.name, - options.format, &block); - } else { - Tcl_AppendResult(interp, "bad option \"", argv[1], - "\": must be blank, cget, configure, copy, get, put,", - " read, redither, or write", (char *) NULL); - return TCL_ERROR; + data = ImgGetPhoto(masterPtr, &block, &options); + format = options.format; + if (oldformat && format) { + format = (Tcl_Obj *) Tcl_GetString(options.format); + } + result = (*imageFormat->fileWriteProc)(interp, + Tcl_GetString(options.name), + format, &block); + if (options.background) { + Tk_FreeColor(options.background); + } + if (data) { + ckfree(data); + } + return result; + break; + } } return TCL_OK; @@ -1059,7 +1339,7 @@ ImgPhotoCmd(clientData, interp, argc, argv) */ static int -ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, argc, argv) +ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) struct SubcommandOptions *optPtr; /* Information about the options specified * and the values given is returned here. */ @@ -1067,27 +1347,27 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, argc, argv) int allowedOptions; /* Indicates which options are valid for * the current command. */ int *optIndexPtr; /* Points to a variable containing the - * current index in argv; this variable is + * current index in objv; this variable is * updated by this procedure. */ - int argc; /* Number of arguments in argv[]. */ - char **argv; /* Arguments to be parsed. */ + int objc; /* Number of arguments in objv[]. */ + Tcl_Obj *CONST objv[]; /* Arguments to be parsed. */ { int index, c, bit, currentBit; - size_t length; + int length; char *option, **listPtr; int values[4]; int numValues, maxValues, argIndex; - for (index = *optIndexPtr; index < argc; *optIndexPtr = ++index) { + for (index = *optIndexPtr; index < objc; *optIndexPtr = ++index) { /* * We can have one value specified without an option; * it goes into optPtr->name. */ - option = argv[index]; + option = Tcl_GetStringFromObj(objv[index], &length); if (option[0] != '-') { if (optPtr->name == NULL) { - optPtr->name = option; + optPtr->name = objv[index]; continue; } break; @@ -1097,13 +1377,12 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, argc, argv) * Work out which option this is. */ - length = strlen(option); c = option[0]; bit = 0; currentBit = 1; for (listPtr = optionNames; *listPtr != NULL; ++listPtr) { if ((c == *listPtr[0]) - && (strncmp(option, *listPtr, length) == 0)) { + && (strncmp(option, *listPtr, (size_t) length) == 0)) { if (bit != 0) { bit = 0; /* An ambiguous option. */ break; @@ -1119,7 +1398,8 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, argc, argv) */ if ((allowedOptions & bit) == 0) { - Tcl_AppendResult(interp, "unrecognized option \"", argv[index], + Tcl_AppendResult(interp, "unrecognized option \"", + Tcl_GetString(objv[index]), "\": must be ", (char *)NULL); bit = 1; for (listPtr = optionNames; *listPtr != NULL; ++listPtr) { @@ -1143,14 +1423,44 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, argc, argv) * or too many values are given. */ - if ((bit != OPT_SHRINK) && (bit != OPT_FORMAT)) { + if (bit == OPT_BACKGROUND) { + /* + * The -background option takes a single XColor value. + */ + + if (index + 1 < objc) { + *optIndexPtr = ++index; + optPtr->background = Tk_GetColor(interp, Tk_MainWindow(interp), + Tk_GetUid(Tcl_GetString(objv[index]))); + if (!optPtr->background) { + return TCL_ERROR; + } + } else { + Tcl_AppendResult(interp, "the \"-background\" option ", + "requires a value", (char *) NULL); + return TCL_ERROR; + } + } else if (bit == OPT_FORMAT) { + /* + * The -format option takes a single string value. + */ + + if (index + 1 < objc) { + *optIndexPtr = ++index; + optPtr->format = objv[index]; + } else { + Tcl_AppendResult(interp, "the \"-format\" option ", + "requires a value", (char *) NULL); + return TCL_ERROR; + } + } else if ((bit != OPT_SHRINK) && (bit != OPT_GRAYSCALE)) { maxValues = ((bit == OPT_FROM) || (bit == OPT_TO))? 4: 2; argIndex = index + 1; for (numValues = 0; numValues < maxValues; ++numValues) { - if ((argIndex < argc) && (isdigit(UCHAR(argv[argIndex][0])) - || ((argv[argIndex][0] == '-') - && (isdigit(UCHAR(argv[argIndex][1])))))) { - if (Tcl_GetInt(interp, argv[argIndex], &values[numValues]) + char *val = Tcl_GetString(objv[argIndex]); + if ((argIndex < objc) && (isdigit(UCHAR(val[0])) + || ((val[0] == '-') && isdigit(UCHAR(val[1]))))) { + if (Tcl_GetInt(interp, val, &values[numValues]) != TCL_OK) { return TCL_ERROR; } @@ -1161,7 +1471,7 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, argc, argv) } if (numValues == 0) { - Tcl_AppendResult(interp, "the \"", argv[index], "\" option ", + Tcl_AppendResult(interp, "the \"", option, "\" option ", "requires one ", maxValues == 2? "or two": "to four", " integer values", (char *) NULL); return TCL_ERROR; @@ -1237,19 +1547,6 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, argc, argv) optPtr->zoomY = values[1]; break; } - } else if (bit == OPT_FORMAT) { - /* - * The -format option takes a single string value. - */ - - if (index + 1 < argc) { - *optIndexPtr = ++index; - optPtr->format = argv[index]; - } else { - Tcl_AppendResult(interp, "the \"-format\" option ", - "requires a value", (char *) NULL); - return TCL_ERROR; - } } /* @@ -1283,30 +1580,60 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, argc, argv) */ static int -ImgPhotoConfigureMaster(interp, masterPtr, argc, argv, flags) +ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) Tcl_Interp *interp; /* Interpreter to use for reporting errors. */ PhotoMaster *masterPtr; /* Pointer to data structure describing * overall photo image to (re)configure. */ - int argc; /* Number of entries in argv. */ - char **argv; /* Pairs of configuration options for image. */ + int objc; /* Number of entries in objv. */ + Tcl_Obj *CONST objv[]; /* Pairs of configuration options for image. */ int flags; /* Flags to pass to Tk_ConfigureWidget, * such as TK_CONFIG_ARGV_ONLY. */ { PhotoInstance *instancePtr; - char *oldFileString, *oldDataString, *oldPaletteString; + char *oldFileString, *oldPaletteString; + Tcl_Obj *oldData, *data = NULL, *oldFormat, *format = NULL; + int length, i, j; double oldGamma; int result; Tcl_Channel chan; Tk_PhotoImageFormat *imageFormat; int imageWidth, imageHeight; + char **args; + int oldformat; + Tcl_Obj *tempdata, *tempformat; + + args = (char **) ckalloc((objc + 1) * sizeof(char *)); + for (i = 0, j = 0; i < objc; i++,j++) { + args[j] = Tcl_GetStringFromObj(objv[i], &length); + if ((length > 1) && (args[j][0] == '-')) { + if ((args[j][1] == 'd') && + !strncmp(args[j],"-data", (size_t) length)) { + if (i < objc) { + data = objv[++i]; + j--; + } + } else if ((args[j][1] == 'f') && + !strncmp(args[j],"-format", (size_t) length)) { + if (i < objc) { + format = objv[++i]; + j--; + } + } + } + } /* * Save the current values for fileString and dataString, so we * can tell if the user specifies them anew. + * IMPORTANT: if the format changes we have to interpret + * "-file" and "-data" again as well!!!!!!! It might be + * that the format string influences how "-data" or "-file" + * is interpreted. */ oldFileString = masterPtr->fileString; - oldDataString = (oldFileString == NULL)? masterPtr->dataString: NULL; + oldData = (oldFileString == NULL) ? masterPtr->dataString: NULL; + oldFormat = masterPtr->format; oldPaletteString = masterPtr->palette; oldGamma = masterPtr->gamma; @@ -1315,9 +1642,11 @@ ImgPhotoConfigureMaster(interp, masterPtr, argc, argv, flags) */ if (Tk_ConfigureWidget(interp, Tk_MainWindow(interp), configSpecs, - argc, argv, (char *) masterPtr, flags) != TCL_OK) { + j, args, (char *) masterPtr, flags) != TCL_OK) { + ckfree((char *) args); return TCL_ERROR; } + ckfree((char *) args); /* * Regard the empty string for -file, -data or -format as the null @@ -1328,15 +1657,28 @@ ImgPhotoConfigureMaster(interp, masterPtr, argc, argv, flags) ckfree(masterPtr->fileString); masterPtr->fileString = NULL; } - if ((masterPtr->dataString != NULL) && (masterPtr->dataString[0] == 0)) { - ckfree(masterPtr->dataString); - masterPtr->dataString = NULL; + if (data) { + if (data->length) { + Tcl_IncrRefCount(data); + } else { + data = NULL; + } + if (masterPtr->dataString) { + Tcl_DecrRefCount(masterPtr->dataString); + } + masterPtr->dataString = data; } - if ((masterPtr->format != NULL) && (masterPtr->format[0] == 0)) { - ckfree(masterPtr->format); - masterPtr->format = NULL; + if (format) { + if (format->length) { + Tcl_IncrRefCount(format); + } else { + format = NULL; + } + if (masterPtr->format) { + Tcl_DecrRefCount(masterPtr->format); + } + masterPtr->format = format; } - /* * Set the image to the user-requested size, if any, * and make sure storage is correctly allocated for this image. @@ -1350,7 +1692,8 @@ ImgPhotoConfigureMaster(interp, masterPtr, argc, argv, flags) */ if ((masterPtr->fileString != NULL) - && (masterPtr->fileString != oldFileString)) { + && ((masterPtr->fileString != oldFileString) + || (masterPtr->format != oldFormat))) { /* * Prevent file system access in a safe interpreter. @@ -1376,13 +1719,17 @@ ImgPhotoConfigureMaster(interp, masterPtr, argc, argv, flags) } if (MatchFileFormat(interp, chan, masterPtr->fileString, masterPtr->format, &imageFormat, &imageWidth, - &imageHeight) != TCL_OK) { + &imageHeight, &oldformat) != TCL_OK) { Tcl_Close(NULL, chan); return TCL_ERROR; } ImgPhotoSetSize(masterPtr, imageWidth, imageHeight); + tempformat = masterPtr->format; + if (oldformat && tempformat) { + tempformat = (Tcl_Obj *) Tcl_GetString(tempformat); + } result = (*imageFormat->fileReadProc)(interp, chan, - masterPtr->fileString, masterPtr->format, + masterPtr->fileString, tempformat, (Tk_PhotoHandle) masterPtr, 0, 0, imageWidth, imageHeight, 0, 0); Tcl_Close(NULL, chan); @@ -1390,24 +1737,35 @@ ImgPhotoConfigureMaster(interp, masterPtr, argc, argv, flags) return TCL_ERROR; } + Tcl_ResetResult(interp); masterPtr->flags |= IMAGE_CHANGED; } if ((masterPtr->fileString == NULL) && (masterPtr->dataString != NULL) - && (masterPtr->dataString != oldDataString)) { + && ((masterPtr->dataString != oldData) + || (masterPtr->format != oldFormat))) { if (MatchStringFormat(interp, masterPtr->dataString, masterPtr->format, &imageFormat, &imageWidth, - &imageHeight) != TCL_OK) { + &imageHeight, &oldformat) != TCL_OK) { return TCL_ERROR; } ImgPhotoSetSize(masterPtr, imageWidth, imageHeight); - if ((*imageFormat->stringReadProc)(interp, masterPtr->dataString, - masterPtr->format, (Tk_PhotoHandle) masterPtr, + tempformat = masterPtr->format; + tempdata = masterPtr->dataString; + if (oldformat) { + if (tempformat) { + tempformat = (Tcl_Obj *) Tcl_GetString(tempformat); + } + tempdata = (Tcl_Obj *) Tcl_GetString(tempdata); + } + if ((*imageFormat->stringReadProc)(interp, tempdata, + tempformat, (Tk_PhotoHandle) masterPtr, 0, 0, imageWidth, imageHeight, 0, 0) != TCL_OK) { return TCL_ERROR; } + Tcl_ResetResult(interp); masterPtr->flags |= IMAGE_CHANGED; } @@ -1939,6 +2297,12 @@ ImgPhotoDelete(masterData) if (masterPtr->validRegion != NULL) { TkDestroyRegion(masterPtr->validRegion); } + if (masterPtr->dataString != NULL) { + Tcl_DecrRefCount(masterPtr->dataString); + } + if (masterPtr->format != NULL) { + Tcl_DecrRefCount(masterPtr->format); + } Tk_FreeOptions(configSpecs, (char *) masterPtr, (Display *) NULL, 0); ckfree((char *) masterPtr); } @@ -2038,7 +2402,7 @@ ImgPhotoSetSize(masterPtr, width, height) * over valid regions. */ - pitch = width * 3; + pitch = width * 4; newPix24 = (unsigned char *) ckalloc((unsigned) (height * pitch)); /* @@ -2085,14 +2449,14 @@ ImgPhotoSetSize(masterPtr, width, height) * Area to be copied is not contiguous - copy line by line. */ - destPtr = newPix24 + (validBox.y * width + validBox.x) * 3; + destPtr = newPix24 + (validBox.y * width + validBox.x) * 4; srcPtr = masterPtr->pix24 + (validBox.y * masterPtr->width - + validBox.x) * 3; + + validBox.x) * 4; for (h = validBox.height; h > 0; h--) { memcpy((VOID *) destPtr, (VOID *) srcPtr, - (size_t) (validBox.width * 3)); - destPtr += width * 3; - srcPtr += masterPtr->width * 3; + (size_t) (validBox.width * 4)); + destPtr += width * 4; + srcPtr += masterPtr->width * 4; } } @@ -3027,22 +3391,29 @@ DisposeInstance(clientData) */ static int -MatchFileFormat(interp, chan, fileName, formatString, imageFormatPtr, - widthPtr, heightPtr) +MatchFileFormat(interp, chan, fileName, formatObj, imageFormatPtr, + widthPtr, heightPtr, oldformat) Tcl_Interp *interp; /* Interpreter to use for reporting errors. */ Tcl_Channel chan; /* The image file, open for reading. */ char *fileName; /* The name of the image file. */ - char *formatString; /* User-specified format string, or NULL. */ + Tcl_Obj *formatObj; /* User-specified format string, or NULL. */ Tk_PhotoImageFormat **imageFormatPtr; /* A pointer to the photo image format * record is returned here. */ int *widthPtr, *heightPtr; /* The dimensions of the image are * returned here. */ + int *oldformat; { int matched; + int useoldformat = 0; Tk_PhotoImageFormat *formatPtr; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + char *formatString = NULL; + + if (formatObj) { + formatString = Tcl_GetString(formatObj); + } /* * Scan through the table of file format handlers to find @@ -3052,9 +3423,9 @@ MatchFileFormat(interp, chan, fileName, formatString, imageFormatPtr, matched = 0; for (formatPtr = tsdPtr->formatList; formatPtr != NULL; formatPtr = formatPtr->nextPtr) { - if (formatString != NULL) { - if (strncasecmp(formatString, formatPtr->name, - strlen(formatPtr->name)) != 0) { + if (formatObj != NULL) { + if (strncasecmp(formatString, + formatPtr->name, strlen(formatPtr->name)) != 0) { continue; } matched = 1; @@ -3067,8 +3438,8 @@ MatchFileFormat(interp, chan, fileName, formatString, imageFormatPtr, if (formatPtr->fileMatchProc != NULL) { (void) Tcl_Seek(chan, 0L, SEEK_SET); - if ((*formatPtr->fileMatchProc)(chan, fileName, formatString, - widthPtr, heightPtr)) { + if ((*formatPtr->fileMatchProc)(chan, fileName, formatObj, + widthPtr, heightPtr, interp)) { if (*widthPtr < 1) { *widthPtr = 1; } @@ -3079,10 +3450,42 @@ MatchFileFormat(interp, chan, fileName, formatString, imageFormatPtr, } } } + if (formatPtr == NULL) { + useoldformat = 1; + for (formatPtr = tsdPtr->oldFormatList; formatPtr != NULL; + formatPtr = formatPtr->nextPtr) { + if (formatString != NULL) { + if (strncasecmp(formatString, + formatPtr->name, strlen(formatPtr->name)) != 0) { + continue; + } + matched = 1; + if (formatPtr->fileMatchProc == NULL) { + Tcl_AppendResult(interp, "-file option isn't supported for ", + formatString, " images", (char *) NULL); + return TCL_ERROR; + } + } + if (formatPtr->fileMatchProc != NULL) { + (void) Tcl_Seek(chan, 0L, SEEK_SET); + if ((*formatPtr->fileMatchProc)(chan, fileName, (Tcl_Obj *) formatString, + widthPtr, heightPtr, interp)) { + if (*widthPtr < 1) { + *widthPtr = 1; + } + if (*heightPtr < 1) { + *heightPtr = 1; + } + break; + } + } + } + } if (formatPtr == NULL) { - if ((formatString != NULL) && !matched) { - Tcl_AppendResult(interp, "image file format \"", formatString, + if ((formatObj != NULL) && !matched) { + Tcl_AppendResult(interp, "image file format \"", + formatString, "\" is not supported", (char *) NULL); } else { Tcl_AppendResult(interp, @@ -3093,6 +3496,7 @@ MatchFileFormat(interp, chan, fileName, formatString, imageFormatPtr, } *imageFormatPtr = formatPtr; + *oldformat = useoldformat; (void) Tcl_Seek(chan, 0L, SEEK_SET); return TCL_OK; } @@ -3120,21 +3524,28 @@ MatchFileFormat(interp, chan, fileName, formatString, imageFormatPtr, */ static int -MatchStringFormat(interp, string, formatString, imageFormatPtr, - widthPtr, heightPtr) +MatchStringFormat(interp, data, formatObj, imageFormatPtr, + widthPtr, heightPtr, oldformat) Tcl_Interp *interp; /* Interpreter to use for reporting errors. */ - char *string; /* String containing the image data. */ - char *formatString; /* User-specified format string, or NULL. */ + Tcl_Obj *data; /* Object containing the image data. */ + Tcl_Obj *formatObj; /* User-specified format string, or NULL. */ Tk_PhotoImageFormat **imageFormatPtr; /* A pointer to the photo image format * record is returned here. */ int *widthPtr, *heightPtr; /* The dimensions of the image are * returned here. */ + int *oldformat; /* returns 1 if the old image API is used */ { int matched; + int useoldformat = 0; Tk_PhotoImageFormat *formatPtr; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + char *formatString = NULL; + + if (formatObj) { + formatString = Tcl_GetString(formatObj); + } /* * Scan through the table of file format handlers to find @@ -3144,9 +3555,9 @@ MatchStringFormat(interp, string, formatString, imageFormatPtr, matched = 0; for (formatPtr = tsdPtr->formatList; formatPtr != NULL; formatPtr = formatPtr->nextPtr) { - if (formatString != NULL) { - if (strncasecmp(formatString, formatPtr->name, - strlen(formatPtr->name)) != 0) { + if (formatObj != NULL) { + if (strncasecmp(formatString, + formatPtr->name, strlen(formatPtr->name)) != 0) { continue; } matched = 1; @@ -3157,15 +3568,42 @@ MatchStringFormat(interp, string, formatString, imageFormatPtr, } } if ((formatPtr->stringMatchProc != NULL) - && (*formatPtr->stringMatchProc)(string, formatString, - widthPtr, heightPtr)) { + && (formatPtr->stringReadProc != NULL) + && (*formatPtr->stringMatchProc)(data, formatObj, + widthPtr, heightPtr, interp)) { break; } } if (formatPtr == NULL) { - if ((formatString != NULL) && !matched) { - Tcl_AppendResult(interp, "image format \"", formatString, + useoldformat = 1; + for (formatPtr = tsdPtr->oldFormatList; formatPtr != NULL; + formatPtr = formatPtr->nextPtr) { + if (formatObj != NULL) { + if (strncasecmp(formatString, + formatPtr->name, strlen(formatPtr->name)) != 0) { + continue; + } + matched = 1; + if (formatPtr->stringMatchProc == NULL) { + Tcl_AppendResult(interp, "-data option isn't supported for ", + formatString, " images", (char *) NULL); + return TCL_ERROR; + } + } + if ((formatPtr->stringMatchProc != NULL) + && (formatPtr->stringReadProc != NULL) + && (*formatPtr->stringMatchProc)((Tcl_Obj *) Tcl_GetString(data), + (Tcl_Obj *) formatString, + widthPtr, heightPtr, interp)) { + break; + } + } + } + if (formatPtr == NULL) { + if ((formatObj != NULL) && !matched) { + Tcl_AppendResult(interp, "image format \"", + formatString, "\" is not supported", (char *) NULL); } else { Tcl_AppendResult(interp, "couldn't recognize image data", @@ -3175,6 +3613,7 @@ MatchStringFormat(interp, string, formatString, imageFormatPtr, } *imageFormatPtr = formatPtr; + *oldformat = useoldformat; return TCL_OK; } @@ -3244,7 +3683,7 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height) { register PhotoMaster *masterPtr; int xEnd, yEnd; - int greenOffset, blueOffset; + int greenOffset, blueOffset, alphaOffset; int wLeft, hLeft; int wCopy, hCopy; unsigned char *srcPtr, *srcLinePtr; @@ -3287,6 +3726,12 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height) greenOffset = blockPtr->offset[1] - blockPtr->offset[0]; blueOffset = blockPtr->offset[2] - blockPtr->offset[0]; + alphaOffset = blockPtr->offset[3]; + if ((alphaOffset >= blockPtr->pixelSize) || (alphaOffset < 0)) { + alphaOffset = 0; + } else { + alphaOffset -= blockPtr->offset[0]; + } if ((greenOffset != 0) || (blueOffset != 0)) { masterPtr->flags |= COLOR_IMAGE; } @@ -3296,16 +3741,16 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height) * If we can do it with a single memcpy, we do. */ - destLinePtr = masterPtr->pix24 + (y * masterPtr->width + x) * 3; - pitch = masterPtr->width * 3; + destLinePtr = masterPtr->pix24 + (y * masterPtr->width + x) * 4; + pitch = masterPtr->width * 4; - if ((blockPtr->pixelSize == 3) && (greenOffset == 1) && (blueOffset == 2) + if ((blockPtr->pixelSize == 4) && (greenOffset == 1) && (blueOffset == 2) && (alphaOffset == 0) && (width <= blockPtr->width) && (height <= blockPtr->height) && ((height == 1) || ((x == 0) && (width == masterPtr->width) && (blockPtr->pitch == pitch)))) { memcpy((VOID *) destLinePtr, (VOID *) (blockPtr->pixelPtr + blockPtr->offset[0]), - (size_t) (height * width * 3)); + (size_t) (height * width * 4)); } else { for (hLeft = height; hLeft > 0;) { srcLinePtr = blockPtr->pixelPtr + blockPtr->offset[0]; @@ -3318,10 +3763,24 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height) wLeft -= wCopy; srcPtr = srcLinePtr; for (; wCopy > 0; --wCopy) { + if (!destPtr[3]) { + destPtr[0] = destPtr[1] = destPtr[2] = 0xd9; + } + if (!alphaOffset || (srcPtr[alphaOffset] == 255)) { *destPtr++ = srcPtr[0]; *destPtr++ = srcPtr[greenOffset]; *destPtr++ = srcPtr[blueOffset]; - srcPtr += blockPtr->pixelSize; + *destPtr++ = 255; + } else { + if (srcPtr[alphaOffset]) { + destPtr[0] += (srcPtr[0] - destPtr[0]) * srcPtr[alphaOffset] / 255; + destPtr[1] += (srcPtr[greenOffset] - destPtr[1]) * srcPtr[alphaOffset] / 255; + destPtr[2] += (srcPtr[blueOffset] - destPtr[2]) * srcPtr[alphaOffset] / 255; + destPtr[3] += (255 - destPtr[3]) * srcPtr[alphaOffset] / 255; + } + destPtr+=4; + } + srcPtr += blockPtr->pixelSize; } } srcLinePtr += blockPtr->pitch; @@ -3334,12 +3793,43 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height) * Add this new block to the region which specifies which data is valid. */ + if (alphaOffset) { + int x1, y1, end; + + destLinePtr = masterPtr->pix24 + (y * masterPtr->width + x) * 4 + 3; + for (y1 = 0; y1 < height; y1++) { + x1 = 0; + destPtr = destLinePtr; + while (x1 < width) { + /* search for first non-transparent pixel */ + while ((x1 < width) && !*destPtr) { + x1++; destPtr += 4; + } + end = x1; + /* search for first transparent pixel */ + while ((end < width) && *destPtr) { + end++; destPtr += 4; + } + if (end > x1) { + rect.x = x + x1; + rect.y = y + y1; + rect.width = end - x1; + rect.height = 1; + TkUnionRectWithRegion(&rect, masterPtr->validRegion, + masterPtr->validRegion); + } + x1 = end; + } + destLinePtr += masterPtr->width * 4; + } + } else { rect.x = x; rect.y = y; rect.width = width; rect.height = height; TkUnionRectWithRegion(&rect, masterPtr->validRegion, masterPtr->validRegion); + } /* * Update each instance. @@ -3390,7 +3880,7 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, { register PhotoMaster *masterPtr; int xEnd, yEnd; - int greenOffset, blueOffset; + int greenOffset, blueOffset, alphaOffset; int wLeft, hLeft; int wCopy, hCopy; int blockWid, blockHt; @@ -3449,6 +3939,12 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, greenOffset = blockPtr->offset[1] - blockPtr->offset[0]; blueOffset = blockPtr->offset[2] - blockPtr->offset[0]; + alphaOffset = blockPtr->offset[3]; + if ((alphaOffset >= blockPtr->pixelSize) || (alphaOffset < 0)) { + alphaOffset = 0; + } else { + alphaOffset -= blockPtr->offset[0]; + } if ((greenOffset != 0) || (blueOffset != 0)) { masterPtr->flags |= COLOR_IMAGE; } @@ -3477,7 +3973,7 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, * Copy the data into our local 24-bit/pixel array. */ - destLinePtr = masterPtr->pix24 + (y * masterPtr->width + x) * 3; + destLinePtr = masterPtr->pix24 + (y * masterPtr->width + x) * 4; srcOrigPtr = blockPtr->pixelPtr + blockPtr->offset[0]; if (subsampleX < 0) { srcOrigPtr += (blockPtr->width - 1) * blockPtr->pixelSize; @@ -3486,7 +3982,7 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, srcOrigPtr += (blockPtr->height - 1) * blockPtr->pitch; } - pitch = masterPtr->width * 3; + pitch = masterPtr->width * 4; for (hLeft = height; hLeft > 0; ) { hCopy = MIN(hLeft, blockHt); hLeft -= hCopy; @@ -3500,9 +3996,23 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, srcPtr = srcLinePtr; for (; wCopy > 0; wCopy -= zoomX) { for (xRepeat = MIN(wCopy, zoomX); xRepeat > 0; xRepeat--) { + if (!destPtr[3]) { + destPtr[0] = destPtr[1] = destPtr[2] = 0xd9; + } + if (!alphaOffset || (srcPtr[alphaOffset] == 255)) { *destPtr++ = srcPtr[0]; *destPtr++ = srcPtr[greenOffset]; *destPtr++ = srcPtr[blueOffset]; + *destPtr++ = 255; + } else { + if (srcPtr[alphaOffset]) { + destPtr[0] += (srcPtr[0] - destPtr[0]) * srcPtr[alphaOffset] / 255; + destPtr[1] += (srcPtr[greenOffset] - destPtr[1]) * srcPtr[alphaOffset] / 255; + destPtr[2] += (srcPtr[blueOffset] - destPtr[2]) * srcPtr[alphaOffset] / 255; + destPtr[3] += (255 - destPtr[3]) * srcPtr[alphaOffset] / 255; + } + destPtr+=4; + } } srcPtr += blockXSkip; } @@ -3520,12 +4030,43 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, * Add this new block to the region that specifies which data is valid. */ + if (alphaOffset) { + int x1, y1, end; + + destLinePtr = masterPtr->pix24 + (y * masterPtr->width + x) * 4 + 3; + for (y1 = 0; y1 < height; y1++) { + x1 = 0; + destPtr = destLinePtr; + while (x1 < width) { + /* search for first non-transparent pixel */ + while ((x1 < width) && !*destPtr) { + x1++; destPtr += 4; + } + end = x1; + /* search for first transparent pixel */ + while ((end < width) && *destPtr) { + end++; destPtr += 4; + } + if (end > x1) { + rect.x = x + x1; + rect.y = y + y1; + rect.width = end - x1; + rect.height = 1; + TkUnionRectWithRegion(&rect, masterPtr->validRegion, + masterPtr->validRegion); + } + x1 = end; + } + destLinePtr += masterPtr->width * 4; + } + } else { rect.x = x; rect.y = y; rect.width = width; rect.height = height; TkUnionRectWithRegion(&rect, masterPtr->validRegion, masterPtr->validRegion); + } /* * Update each instance. @@ -3708,7 +4249,7 @@ DitherInstance(instancePtr, xStart, yStart, width, height) firstBit = bigEndian? (1 << (imagePtr->bitmap_unit - 1)): 1; lineLength = masterPtr->width * 3; - srcLinePtr = masterPtr->pix24 + yStart * lineLength + xStart * 3; + srcLinePtr = masterPtr->pix24 + (yStart * masterPtr->width + xStart) * 4; errLinePtr = instancePtr->error + yStart * lineLength + xStart * 3; xEnd = xStart + width; @@ -3789,6 +4330,7 @@ DitherInstance(instancePtr, xStart, yStart, width, height) col[1] = *srcPtr++; col[2] = *srcPtr++; } + srcPtr++; /* * Translate the quantized component values into @@ -3851,7 +4393,7 @@ DitherInstance(instancePtr, xStart, yStart, width, height) c += (unsigned)(srcPtr[0] * 11 + srcPtr[1] * 16 + srcPtr[2] * 5 + 16) >> 5; } - srcPtr += 3; + srcPtr += 4; if (c < 0) { c = 0; @@ -3922,7 +4464,7 @@ DitherInstance(instancePtr, xStart, yStart, width, height) c += (unsigned)(srcPtr[0] * 11 + srcPtr[1] * 16 + srcPtr[2] * 5 + 16) >> 5; } - srcPtr += 3; + srcPtr += 4; if (c < 0) { c = 0; @@ -3939,7 +4481,7 @@ DitherInstance(instancePtr, xStart, yStart, width, height) } *destLongPtr = word; } - srcLinePtr += lineLength; + srcLinePtr += masterPtr->width * 4; errLinePtr += lineLength; dstLinePtr += bytesPerLine; } @@ -4004,7 +4546,7 @@ Tk_PhotoBlank(handle) */ memset((VOID *) masterPtr->pix24, 0, - (size_t) (masterPtr->width * masterPtr->height * 3)); + (size_t) (masterPtr->width * masterPtr->height * 4)); for (instancePtr = masterPtr->instancePtr; instancePtr != NULL; instancePtr = instancePtr->nextPtr) { if (instancePtr->error) { @@ -4138,6 +4680,231 @@ Tk_PhotoSetSize(handle, width, height) /* *---------------------------------------------------------------------- * + * ImgGetPhoto -- + * + * This procedure is called to obtain image data from a photo + * image. This procedure fills in the Tk_PhotoImageBlock structure + * pointed to by `blockPtr' with details of the address and + * layout of the image data in memory. + * + * Results: + * A pointer to the allocated data which should be freed later. + * NULL if there is no need to free data because + * blockPtr->pixelPtr points directly to the image data. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static char * +ImgGetPhoto(masterPtr, blockPtr, optPtr) + PhotoMaster *masterPtr; /* Handle for the photo image from which + * image data is desired. */ + Tk_PhotoImageBlock *blockPtr; + /* Information about the address and layout + * of the image data is returned here. */ + struct SubcommandOptions *optPtr; +{ + unsigned char *pixelPtr; + int x, y, greenOffset, blueOffset, alphaOffset; + + Tk_PhotoGetImage((Tk_PhotoHandle) masterPtr, blockPtr); + blockPtr->pixelPtr += optPtr->fromY * blockPtr->pitch + + optPtr->fromX * blockPtr->pixelSize; + blockPtr->width = optPtr->fromX2 - optPtr->fromX; + blockPtr->height = optPtr->fromY2 - optPtr->fromY; + + if (!(masterPtr->flags & COLOR_IMAGE) && + (!(optPtr->options & OPT_BACKGROUND) + || ((optPtr->background->red == optPtr->background->green) + && (optPtr->background->red == optPtr->background->blue)))) { + blockPtr->offset[0] = blockPtr->offset[1] = + blockPtr->offset[2]; + } + alphaOffset = 0; + for (y = 0; y < blockPtr->height; y++) { + pixelPtr = blockPtr->pixelPtr + (y * blockPtr->pitch) + + blockPtr->pixelSize - 1; + for (x = 0; x < blockPtr->width; x++) { + if (*pixelPtr != 255) { + alphaOffset = 3; break; + } + pixelPtr += blockPtr->pixelSize; + } + if (alphaOffset) break; + } + if (!alphaOffset) { + blockPtr->pixelPtr--; + blockPtr->offset[0]++; + blockPtr->offset[1]++; + blockPtr->offset[2]++; + } + greenOffset = blockPtr->offset[1] - blockPtr->offset[0]; + blueOffset = blockPtr->offset[2] - blockPtr->offset[0]; + if (((optPtr->options & OPT_BACKGROUND) && alphaOffset) || + ((optPtr->options & OPT_GRAYSCALE) && (greenOffset || blueOffset))) { + int newPixelSize,x,y; + unsigned char *srcPtr, *destPtr; + char *data; + + newPixelSize = (!(optPtr->options & OPT_BACKGROUND) && alphaOffset) ? 2 : 1; + if ((greenOffset || blueOffset) && !(optPtr->options & OPT_GRAYSCALE)) { + newPixelSize += 2; + } + data = ckalloc((unsigned int) (newPixelSize * + blockPtr->width * blockPtr->height)); + srcPtr = blockPtr->pixelPtr + blockPtr->offset[0]; + destPtr = (unsigned char *) data; + if (!greenOffset && !blueOffset) { + for (y = blockPtr->height; y > 0; y--) { + for (x = blockPtr->width; x > 0; x--) { + *destPtr = *srcPtr; + srcPtr += blockPtr->pixelSize; + destPtr += newPixelSize; + } + srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize); + } + } else if (optPtr->options & OPT_GRAYSCALE) { + for (y = blockPtr->height; y > 0; y--) { + for (x = blockPtr->width; x > 0; x--) { + *destPtr = (unsigned char) ((srcPtr[0] * 11 + srcPtr[1] * 16 + + srcPtr[2] * 5 + 16) >> 5); + srcPtr += blockPtr->pixelSize; + destPtr += newPixelSize; + } + srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize); + } + } else { + for (y = blockPtr->height; y > 0; y--) { + for (x = blockPtr->width; x > 0; x--) { + destPtr[0] = srcPtr[0]; + destPtr[1] = srcPtr[1]; + destPtr[2] = srcPtr[2]; + srcPtr += blockPtr->pixelSize; + destPtr += newPixelSize; + } + srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize); + } + } + srcPtr = blockPtr->pixelPtr + alphaOffset; + destPtr = (unsigned char *) data; + if (!alphaOffset) { + /* nothing to be done */ + } else if (optPtr->options & OPT_BACKGROUND) { + if (newPixelSize > 2) { + int red = optPtr->background->red>>8; + int green = optPtr->background->green>>8; + int blue = optPtr->background->blue>>8; + for (y = blockPtr->height; y > 0; y--) { + for (x = blockPtr->width; x > 0; x--) { + destPtr[0] += (unsigned char) (((255 - *srcPtr) * + (red-destPtr[0])) / 255); + destPtr[1] += (unsigned char) (((255 - *srcPtr) * + (green-destPtr[1])) / 255); + destPtr[2] += (unsigned char) (((255 - *srcPtr) * + (blue-destPtr[2])) / 255); + srcPtr += blockPtr->pixelSize; + destPtr += newPixelSize; + } + srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize); + } + } else { + int gray = (unsigned char) (((optPtr->background->red>>8) * 11 + + (optPtr->background->green>>8) * 16 + + (optPtr->background->blue>>8) * 5 + 16) >> 5); + for (y = blockPtr->height; y > 0; y--) { + for (x = blockPtr->width; x > 0; x--) { + destPtr[0] += ((255 - *srcPtr) * + (gray-destPtr[0])) / 255; + srcPtr += blockPtr->pixelSize; + destPtr += newPixelSize; + } + srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize); + } + } + } else { + destPtr += newPixelSize-1; + for (y = blockPtr->height; y > 0; y--) { + for (x = blockPtr->width; x > 0; x--) { + *destPtr = *srcPtr; + srcPtr += blockPtr->pixelSize; + destPtr += newPixelSize; + } + srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize); + } + } + blockPtr->pixelPtr = (unsigned char *) data; + blockPtr->pixelSize = newPixelSize; + blockPtr->pitch = newPixelSize * blockPtr->width; + blockPtr->offset[0] = 0; + if (newPixelSize>2) { + blockPtr->offset[1]= 1; + blockPtr->offset[2]= 2; + } else { + blockPtr->offset[1]= 0; + blockPtr->offset[2]= 0; + } + return data; + } + return NULL; +} + +/* + *---------------------------------------------------------------------- + * + * ImgStringWrite -- + * + * Default string write function. The data is formatted in + * the default format as accepted by the "<img> put" command. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +ImgStringWrite(interp, dataPtr, formatString, blockPtr) + Tcl_Interp *interp; + Tcl_DString *dataPtr; + Tcl_Obj *formatString; + Tk_PhotoImageBlock *blockPtr; +{ + int row,col; + char *line, *linePtr; + unsigned char *pixelPtr; + int greenOffset, blueOffset; + + greenOffset = blockPtr->offset[1] - blockPtr->offset[0]; + blueOffset = blockPtr->offset[2] - blockPtr->offset[0]; + + if ((blockPtr->width > 0) && (blockPtr->height > 0)) { + line = (char *) ckalloc((unsigned int) ((8 * blockPtr->width) + 2)); + for (row=0; row<blockPtr->height; row++) { + pixelPtr = blockPtr->pixelPtr + blockPtr->offset[0] + + row * blockPtr->pitch; + linePtr = line; + for (col=0; col<blockPtr->width; col++) { + sprintf(linePtr, " #%02x%02x%02x", *pixelPtr, + pixelPtr[greenOffset], pixelPtr[blueOffset]); + pixelPtr += blockPtr->pixelSize; + linePtr += 8; + } + Tcl_DStringAppendElement(dataPtr, line+1); + } + ckfree (line); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * * Tk_PhotoGetImage -- * * This procedure is called to obtain image data from a photo @@ -4169,11 +4936,11 @@ Tk_PhotoGetImage(handle, blockPtr) blockPtr->pixelPtr = masterPtr->pix24; blockPtr->width = masterPtr->width; blockPtr->height = masterPtr->height; - blockPtr->pitch = masterPtr->width * 3; - blockPtr->pixelSize = 3; + blockPtr->pitch = masterPtr->width * 4; + blockPtr->pixelSize = 4; blockPtr->offset[0] = 0; blockPtr->offset[1] = 1; blockPtr->offset[2] = 2; - blockPtr->offset[3] = 0; + blockPtr->offset[3] = 3; return 1; } |