From 8e52a87a0be5a9969812bdd4c5439688cc5cc9fc Mon Sep 17 00:00:00 2001 From: hobbs Date: Fri, 29 Oct 1999 03:57:55 +0000 Subject: * 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) --- generic/tk.h | 47 +- generic/tkCmds.c | 3 +- generic/tkImage.c | 201 ++++++--- generic/tkImgBmap.c | 83 ++-- generic/tkImgGIF.c | 286 ++++++++---- generic/tkImgPPM.c | 4 +- generic/tkImgPhoto.c | 1205 +++++++++++++++++++++++++++++++++++++++++--------- generic/tkInt.h | 7 +- generic/tkTest.c | 4 +- generic/tkWindow.c | 6 +- 10 files changed, 1422 insertions(+), 424 deletions(-) diff --git a/generic/tk.h b/generic/tk.h index 974cf53..68b1805 100644 --- a/generic/tk.h +++ b/generic/tk.h @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tk.h,v 1.31 1999/10/01 22:45:16 hobbs Exp $ + * RCS: @(#) $Id: tk.h,v 1.32 1999/10/29 03:57:55 hobbs Exp $ */ #ifndef _TK @@ -978,9 +978,15 @@ typedef struct Tk_CanvasTextInfo { */ typedef struct Tk_ImageType Tk_ImageType; +#ifdef USE_OLD_IMAGE typedef int (Tk_ImageCreateProc) _ANSI_ARGS_((Tcl_Interp *interp, char *name, int argc, char **argv, Tk_ImageType *typePtr, Tk_ImageMaster master, ClientData *masterDataPtr)); +#else +typedef int (Tk_ImageCreateProc) _ANSI_ARGS_((Tcl_Interp *interp, + char *name, int objc, Tcl_Obj *CONST objv[], Tk_ImageType *typePtr, + Tk_ImageMaster master, ClientData *masterDataPtr)); +#endif typedef ClientData (Tk_ImageGetProc) _ANSI_ARGS_((Tk_Window tkwin, ClientData masterData)); typedef void (Tk_ImageDisplayProc) _ANSI_ARGS_((ClientData instanceData, @@ -1055,10 +1061,9 @@ typedef struct Tk_PhotoImageBlock { * pixels in successive lines. */ int pixelSize; /* Address difference between successive * pixels in the same line. */ - int offset[3]; /* Address differences between the red, green - * and blue components of the pixel and the - * pixel as a whole. */ - int reserved; /* Reserved for extensions (dash patch) */ + int offset[4]; /* Address differences between the red, green, + * blue and alpha components of the pixel and + * the pixel as a whole. */ } Tk_PhotoImageBlock; /* @@ -1067,6 +1072,7 @@ typedef struct Tk_PhotoImageBlock { */ typedef struct Tk_PhotoImageFormat Tk_PhotoImageFormat; +#ifdef USE_OLD_IMAGE typedef int (Tk_ImageFileMatchProc) _ANSI_ARGS_((Tcl_Channel chan, char *fileName, char *formatString, int *widthPtr, int *heightPtr)); typedef int (Tk_ImageStringMatchProc) _ANSI_ARGS_((char *string, @@ -1083,6 +1089,26 @@ typedef int (Tk_ImageFileWriteProc) _ANSI_ARGS_((Tcl_Interp *interp, typedef int (Tk_ImageStringWriteProc) _ANSI_ARGS_((Tcl_Interp *interp, Tcl_DString *dataPtr, char *formatString, Tk_PhotoImageBlock *blockPtr)); +#else +typedef int (Tk_ImageFileMatchProc) _ANSI_ARGS_((Tcl_Channel chan, + char *fileName, Tcl_Obj *format, int *widthPtr, + int *heightPtr, Tcl_Interp *interp)); +typedef int (Tk_ImageStringMatchProc) _ANSI_ARGS_((Tcl_Obj *dataObj, + Tcl_Obj *format, int *widthPtr, int *heightPtr, + Tcl_Interp *interp)); +typedef int (Tk_ImageFileReadProc) _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Channel chan, char *fileName, Tcl_Obj *format, + Tk_PhotoHandle imageHandle, int destX, int destY, + int width, int height, int srcX, int srcY)); +typedef int (Tk_ImageStringReadProc) _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *dataObj, Tcl_Obj *format, Tk_PhotoHandle imageHandle, + int destX, int destY, int width, int height, int srcX, int srcY)); +typedef int (Tk_ImageFileWriteProc) _ANSI_ARGS_((Tcl_Interp *interp, + char *fileName, Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr)); +typedef int (Tk_ImageStringWriteProc) _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_DString *dataPtr, Tcl_Obj *format, + Tk_PhotoImageBlock *blockPtr)); +#endif /* * The following structure represents a particular file format for @@ -1117,6 +1143,17 @@ struct Tk_PhotoImageFormat { * currently known. Filled in by Tk, not * by image format handler. */ }; + +EXTERN void Tk_CreateOldImageType _ANSI_ARGS_(( + Tk_ImageType *typePtr)); +EXTERN void Tk_CreateOldPhotoImageFormat _ANSI_ARGS_(( + Tk_PhotoImageFormat *formatPtr)); + +#ifdef USE_OLD_IMAGE +#define Tk_CreateImageType Tk_CreateOldImageType +#define Tk_CreatePhotoImageFormat Tk_CreateOldPhotoImageFormat +#endif + /* *-------------------------------------------------------------- diff --git a/generic/tkCmds.c b/generic/tkCmds.c index b655fc0..c0b8c9e 100644 --- a/generic/tkCmds.c +++ b/generic/tkCmds.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkCmds.c,v 1.6 1999/04/16 01:51:12 stanton Exp $ + * RCS: @(#) $Id: tkCmds.c,v 1.7 1999/10/29 03:57:56 hobbs Exp $ */ #include "tkPort.h" @@ -25,7 +25,6 @@ #include "tkUnixInt.h" #endif - /* * Forward declarations for procedures defined later in this file: */ diff --git a/generic/tkImage.c b/generic/tkImage.c index f9ff2b4..a867594 100644 --- a/generic/tkImage.c +++ b/generic/tkImage.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkImage.c,v 1.3 1999/04/16 01:51:15 stanton Exp $ + * RCS: @(#) $Id: tkImage.c,v 1.4 1999/10/29 03:57:56 hobbs Exp $ */ #include "tkInt.h" @@ -74,6 +74,8 @@ typedef struct ImageMaster { typedef struct ThreadSpecificData { Tk_ImageType *imageTypeList;/* First in a list of all known image * types. */ + Tk_ImageType *oldImageTypeList;/* First in a list of all known old-style image + * types. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; @@ -86,7 +88,7 @@ static void DeleteImage _ANSI_ARGS_((ImageMaster *masterPtr)); /* *---------------------------------------------------------------------- * - * Tk_CreateImageType -- + * Tk_CreateOldImageType, Tk_CreateImageType -- * * This procedure is invoked by an image manager to tell Tk about * a new kind of image and the procedures that manage the new type. @@ -103,6 +105,20 @@ static void DeleteImage _ANSI_ARGS_((ImageMaster *masterPtr)); */ void +Tk_CreateOldImageType(typePtr) + Tk_ImageType *typePtr; /* Structure describing the type. All of + * the fields except "nextPtr" must be filled + * in by caller. Must not have been passed + * to Tk_CreateImageType previously. */ +{ + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + typePtr->nextPtr = tsdPtr->oldImageTypeList; + tsdPtr->oldImageTypeList = typePtr; +} + +void Tk_CreateImageType(typePtr) Tk_ImageType *typePtr; /* Structure describing the type. All of * the fields except "nextPtr" must be filled @@ -119,7 +135,7 @@ Tk_CreateImageType(typePtr) /* *---------------------------------------------------------------------- * - * Tk_ImageCmd -- + * Tk_ImageObjCmd -- * * This procedure is invoked to process the "image" Tcl command. * See the user documentation for details on what it does. @@ -134,15 +150,22 @@ Tk_CreateImageType(typePtr) */ int -Tk_ImageCmd(clientData, interp, argc, argv) +Tk_ImageObjCmd(clientData, interp, objc, objv) ClientData clientData; /* Main window associated with interpreter. */ Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument strings. */ { + static char *imageOptions[] = { + "create", "delete", "height", "names", "type", "types", "width", + (char *) NULL + }; + enum options { + IMAGE_CREATE, IMAGE_DELETE, IMAGE_HEIGHT, IMAGE_NAMES, + IMAGE_TYPE, IMAGE_TYPES, IMAGE_WIDTH + }; TkWindow *winPtr = (TkWindow *) clientData; - int c, i, new, firstOption; - size_t length; + int i, new, firstOption, index; Tk_ImageType *typePtr; ImageMaster *masterPtr; Image *imagePtr; @@ -153,34 +176,49 @@ Tk_ImageCmd(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 ?args?\"", (char *) NULL); + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "option ?args?"); + return TCL_ERROR; + } + + if (Tcl_GetIndexFromObj(interp, objv[1], imageOptions, "option", 0, + &index) != TCL_OK) { return TCL_ERROR; } - c = argv[1][0]; - length = strlen(argv[1]); - if ((c == 'c') && (strncmp(argv[1], "create", length) == 0)) { - if (argc < 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " create type ?name? ?options?\"", (char *) NULL); + switch ((enum options) index) { + case IMAGE_CREATE: { + char *arg; + Tcl_Obj **args; + int oldimage = 0; + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "type ?name? ?options?"); return TCL_ERROR; } - c = argv[2][0]; /* * Look up the image type. */ + arg = Tcl_GetString(objv[2]); for (typePtr = tsdPtr->imageTypeList; typePtr != NULL; typePtr = typePtr->nextPtr) { - if ((c == typePtr->name[0]) - && (strcmp(argv[2], typePtr->name) == 0)) { + if ((*arg == typePtr->name[0]) + && (strcmp(arg, typePtr->name) == 0)) { break; } } if (typePtr == NULL) { - Tcl_AppendResult(interp, "image type \"", argv[2], + oldimage = 1; + for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL; + typePtr = typePtr->nextPtr) { + if ((*arg == typePtr->name[0]) + && (strcmp(arg, typePtr->name) == 0)) { + break; + } + } + } + if (typePtr == NULL) { + Tcl_AppendResult(interp, "image type \"", arg, "\" doesn't exist", (char *) NULL); return TCL_ERROR; } @@ -189,13 +227,14 @@ Tk_ImageCmd(clientData, interp, argc, argv) * Figure out a name to use for the new image. */ - if ((argc == 3) || (argv[3][0] == '-')) { + arg = Tcl_GetString(objv[3]); + if ((objc == 3) || (arg[0] == '-')) { dispPtr->imageId++; sprintf(idString, "image%d", dispPtr->imageId); name = idString; firstOption = 3; } else { - name = argv[3]; + name = arg; firstOption = 4; } @@ -240,12 +279,29 @@ Tk_ImageCmd(clientData, interp, argc, argv) * the image. */ - if ((*typePtr->createProc)(interp, name, argc-firstOption, - argv+firstOption, typePtr, (Tk_ImageMaster) masterPtr, + objv += firstOption; + objc -= firstOption; + args = (Tcl_Obj **) objv; + if (oldimage) { + int i; + args = (Tcl_Obj **) ckalloc((objc+1) * sizeof(char *)); + for (i = 0; i < objc; i++) { + args[i] = (Tcl_Obj *) Tcl_GetString(objv[i]); + } + args[objc] = NULL; + } + if ((*typePtr->createProc)(interp, name, objc, + args, typePtr, (Tk_ImageMaster) masterPtr, &masterPtr->masterData) != TCL_OK) { DeleteImage(masterPtr); + if (oldimage) { + ckfree((char *) args); + } return TCL_ERROR; } + if (oldimage) { + ckfree((char *) args); + } masterPtr->typePtr = typePtr; for (imagePtr = masterPtr->instancePtr; imagePtr != NULL; imagePtr = imagePtr->nextPtr) { @@ -255,38 +311,42 @@ Tk_ImageCmd(clientData, interp, argc, argv) Tcl_SetResult(interp, Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr), TCL_STATIC); - } else if ((c == 'd') && (strncmp(argv[1], "delete", length) == 0)) { - for (i = 2; i < argc; i++) { - hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, argv[i]); + break; + } + case IMAGE_DELETE: { + for (i = 2; i < objc; i++) { + char *arg = Tcl_GetString(objv[i]); + hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg); if (hPtr == NULL) { - Tcl_AppendResult(interp, "image \"", argv[i], + Tcl_AppendResult(interp, "image \"", arg, "\" doesn't exist", (char *) NULL); return TCL_ERROR; } masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); DeleteImage(masterPtr); } - } else if ((c == 'h') && (strncmp(argv[1], "height", length) == 0)) { - char buf[TCL_INTEGER_SPACE]; - - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " height name\"", (char *) NULL); + break; + } + case IMAGE_HEIGHT: { + char *arg; + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "name"); return TCL_ERROR; } - hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, argv[2]); + arg = Tcl_GetString(objv[2]); + hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg); if (hPtr == NULL) { - Tcl_AppendResult(interp, "image \"", argv[2], + Tcl_AppendResult(interp, "image \"", arg, "\" doesn't exist", (char *) NULL); return TCL_ERROR; } masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); - sprintf(buf, "%d", masterPtr->height); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - } else if ((c == 'n') && (strncmp(argv[1], "names", length) == 0)) { - if (argc != 2) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " names\"", (char *) NULL); + Tcl_SetIntObj(Tcl_GetObjResult(interp), masterPtr->height); + break; + } + case IMAGE_NAMES: { + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } for (hPtr = Tcl_FirstHashEntry(&winPtr->mainPtr->imageTable, &search); @@ -294,15 +354,18 @@ Tk_ImageCmd(clientData, interp, argc, argv) Tcl_AppendElement(interp, Tcl_GetHashKey( &winPtr->mainPtr->imageTable, hPtr)); } - } else if ((c == 't') && (strcmp(argv[1], "type") == 0)) { - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " type name\"", (char *) NULL); + break; + } + case IMAGE_TYPE: { + char *arg; + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "name"); return TCL_ERROR; } - hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, argv[2]); + arg = Tcl_GetString(objv[2]); + hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg); if (hPtr == NULL) { - Tcl_AppendResult(interp, "image \"", argv[2], + Tcl_AppendResult(interp, "image \"", arg, "\" doesn't exist", (char *) NULL); return TCL_ERROR; } @@ -310,38 +373,40 @@ Tk_ImageCmd(clientData, interp, argc, argv) if (masterPtr->typePtr != NULL) { Tcl_SetResult(interp, masterPtr->typePtr->name, TCL_STATIC); } - } else if ((c == 't') && (strcmp(argv[1], "types") == 0)) { - if (argc != 2) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " types\"", (char *) NULL); + break; + } + case IMAGE_TYPES: { + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } for (typePtr = tsdPtr->imageTypeList; typePtr != NULL; typePtr = typePtr->nextPtr) { Tcl_AppendElement(interp, typePtr->name); } - } else if ((c == 'w') && (strncmp(argv[1], "width", length) == 0)) { - char buf[TCL_INTEGER_SPACE]; - - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " width name\"", (char *) NULL); + for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL; + typePtr = typePtr->nextPtr) { + Tcl_AppendElement(interp, typePtr->name); + } + break; + } + case IMAGE_WIDTH: { + char *arg; + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "name"); return TCL_ERROR; } - hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, argv[2]); + arg = Tcl_GetString(objv[2]); + hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg); if (hPtr == NULL) { - Tcl_AppendResult(interp, "image \"", argv[2], + Tcl_AppendResult(interp, "image \"", arg, "\" doesn't exist", (char *) NULL); return TCL_ERROR; } masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); - sprintf(buf, "%d", masterPtr->width); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - } else { - Tcl_AppendResult(interp, "bad option \"", argv[1], - "\": must be create, delete, height, names, type, types,", - " or width", (char *) NULL); - return TCL_ERROR; + Tcl_SetIntObj(Tcl_GetObjResult(interp), masterPtr->width); + break; + } } return TCL_OK; } diff --git a/generic/tkImgBmap.c b/generic/tkImgBmap.c index 514e9f2..60b9f39 100644 --- a/generic/tkImgBmap.c +++ b/generic/tkImgBmap.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkImgBmap.c,v 1.9 1999/04/24 01:50:47 stanton Exp $ + * RCS: @(#) $Id: tkImgBmap.c,v 1.10 1999/10/29 03:57:56 hobbs Exp $ */ #include "tkInt.h" @@ -80,7 +80,7 @@ typedef struct BitmapInstance { static int GetByte _ANSI_ARGS_((Tcl_Channel chan)); static int ImgBmapCreate _ANSI_ARGS_((Tcl_Interp *interp, - char *name, int argc, char **argv, + char *name, int argc, Tcl_Obj *CONST objv[], Tk_ImageType *typePtr, Tk_ImageMaster master, ClientData *clientDataPtr)); static ClientData ImgBmapGet _ANSI_ARGS_((Tk_Window tkwin, @@ -150,13 +150,13 @@ typedef struct ParseInfo { */ static int ImgBmapCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); + Tcl_Interp *interp, int argc, Tcl_Obj *CONST objv[])); static void ImgBmapCmdDeletedProc _ANSI_ARGS_(( ClientData clientData)); static void ImgBmapConfigureInstance _ANSI_ARGS_(( BitmapInstance *instancePtr)); static int ImgBmapConfigureMaster _ANSI_ARGS_(( - BitmapMaster *masterPtr, int argc, char **argv, + BitmapMaster *masterPtr, int argc, Tcl_Obj *CONST objv[], int flags)); static int NextBitmapWord _ANSI_ARGS_((ParseInfo *parseInfoPtr)); @@ -184,7 +184,7 @@ ImgBmapCreate(interp, name, argc, argv, typePtr, master, clientDataPtr) * image. */ char *name; /* Name to use for image. */ int argc; /* Number of arguments. */ - char **argv; /* Argument strings for options (doesn't + Tcl_Obj *CONST argv[]; /* 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 @@ -197,7 +197,7 @@ ImgBmapCreate(interp, name, argc, argv, typePtr, master, clientDataPtr) masterPtr = (BitmapMaster *) ckalloc(sizeof(BitmapMaster)); masterPtr->tkMaster = master; masterPtr->interp = interp; - masterPtr->imageCmd = Tcl_CreateCommand(interp, name, ImgBmapCmd, + masterPtr->imageCmd = Tcl_CreateObjCommand(interp, name, ImgBmapCmd, (ClientData) masterPtr, ImgBmapCmdDeletedProc); masterPtr->width = masterPtr->height = 0; masterPtr->data = NULL; @@ -238,22 +238,30 @@ ImgBmapCreate(interp, name, argc, argv, typePtr, master, clientDataPtr) */ static int -ImgBmapConfigureMaster(masterPtr, argc, argv, flags) +ImgBmapConfigureMaster(masterPtr, objc, objv, flags) BitmapMaster *masterPtr; /* Pointer to data structure describing * overall bitmap image to (reconfigure). */ - 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. */ { BitmapInstance *instancePtr; int maskWidth, maskHeight, dummy1, dummy2; + char **argv = (char **) ckalloc((objc+1) * sizeof(char *)); + for (dummy1 = 0; dummy1 < objc; dummy1++) { + argv[dummy1]=Tcl_GetString(objv[dummy1]); + } + argv[objc] = NULL; + if (Tk_ConfigureWidget(masterPtr->interp, Tk_MainWindow(masterPtr->interp), - configSpecs, argc, argv, (char *) masterPtr, flags) + configSpecs, objc, argv, (char *) masterPtr, flags) != TCL_OK) { + ckfree((char *) argv); return TCL_ERROR; } + ckfree((char *) argv); /* * Parse the bitmap and/or mask to create binary data. Make sure that @@ -742,51 +750,52 @@ NextBitmapWord(parseInfoPtr) */ static int -ImgBmapCmd(clientData, interp, argc, argv) +ImgBmapCmd(clientData, interp, objc, objv) ClientData clientData; /* Information about the image 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. */ { + static char *bmapOptions[] = {"cget", "configure", (char *) NULL}; BitmapMaster *masterPtr = (BitmapMaster *) clientData; - int c, code; - size_t length; + int code, index; - 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; + } + if (Tcl_GetIndexFromObj(interp, objv[1], bmapOptions, "option", 0, + &index) != TCL_OK) { return TCL_ERROR; } - c = argv[1][0]; - length = strlen(argv[1]); - if ((c == 'c') && (strncmp(argv[1], "cget", length) == 0) - && (length >= 2)) { - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " cget option\"", - (char *) NULL); + switch (index) { + case 0: { + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option"); return TCL_ERROR; } return Tk_ConfigureValue(interp, Tk_MainWindow(interp), configSpecs, - (char *) masterPtr, argv[2], 0); - } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0) - && (length >= 2)) { - if (argc == 2) { + (char *) masterPtr, Tcl_GetString(objv[2]), 0); + } + case 1: { + if (objc == 2) { code = Tk_ConfigureInfo(interp, Tk_MainWindow(interp), configSpecs, (char *) masterPtr, (char *) NULL, 0); - } else if (argc == 3) { + } else if (objc == 3) { code = Tk_ConfigureInfo(interp, Tk_MainWindow(interp), - configSpecs, (char *) masterPtr, argv[2], 0); + configSpecs, (char *) masterPtr, + Tcl_GetString(objv[2]), 0); } else { - code = ImgBmapConfigureMaster(masterPtr, argc-2, argv+2, + code = ImgBmapConfigureMaster(masterPtr, objc-2, objv+2, TK_CONFIG_ARGV_ONLY); } return code; - } else { - Tcl_AppendResult(interp, "bad option \"", argv[1], - "\": must be cget or configure", (char *) NULL); - return TCL_ERROR; + } + default: { + panic("bad const entries to bmapOptions in ImgBmapCmd"); + } } + return TCL_OK; } /* diff --git a/generic/tkImgGIF.c b/generic/tkImgGIF.c index dc29baa..dc6ec51 100644 --- a/generic/tkImgGIF.c +++ b/generic/tkImgGIF.c @@ -3,13 +3,15 @@ * * A photo image file handler for GIF files. Reads 87a and 89a GIF * files. At present there is no write function. GIF images may be - * read using the -data option of the photo image by representing + * read using the -data option of the photo image. The data may be + * given as a binary string in a Tcl_Obj or by representing * the data as BASE64 encoded ascii. Derived from the giftoppm code * found in the pbmplus package and tkImgFmtPPM.c in the tk4.0b2 * distribution. * * Copyright (c) Reed Wade (wade@cs.utk.edu), University of Tennessee * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright (c) 1997 Australian National University * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. @@ -27,7 +29,7 @@ * | provided "as is" without express or implied warranty. | * +-------------------------------------------------------------------+ * - * RCS: @(#) $Id: tkImgGIF.c,v 1.4 1999/07/01 00:39:44 redman Exp $ + * RCS: @(#) $Id: tkImgGIF.c,v 1.5 1999/10/29 03:57:56 hobbs Exp $ */ /* @@ -63,7 +65,8 @@ typedef struct mFile { /* * HACK ALERT!! HACK ALERT!! HACK ALERT!! * This code is hard-wired for reading from files. In order to read - * from a data stream, we'll trick fread so we can reuse the same code + * from a data stream, we'll trick fread so we can reuse the same code. + * 0==from file; 1==from base64 encoded data; 2==from binary data */ typedef struct ThreadSpecificData { @@ -76,15 +79,17 @@ static Tcl_ThreadDataKey dataKey; */ static int FileMatchGIF _ANSI_ARGS_((Tcl_Channel chan, char *fileName, - char *formatString, int *widthPtr, int *heightPtr)); + Tcl_Obj *format, int *widthPtr, int *heightPtr, + Tcl_Interp *interp)); static int FileReadGIF _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Channel chan, char *fileName, char *formatString, + Tcl_Channel chan, char *fileName, Tcl_Obj *format, Tk_PhotoHandle imageHandle, int destX, int destY, int width, int height, int srcX, int srcY)); -static int StringMatchGIF _ANSI_ARGS_(( char *string, - char *formatString, int *widthPtr, int *heightPtr)); -static int StringReadGIF _ANSI_ARGS_((Tcl_Interp *interp, char *string, - char *formatString, Tk_PhotoHandle imageHandle, +static int StringMatchGIF _ANSI_ARGS_(( Tcl_Obj *dataObj, + Tcl_Obj *format, int *widthPtr, int *heightPtr, + Tcl_Interp *interp)); +static int StringReadGIF _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *dataObj, + Tcl_Obj *format, Tk_PhotoHandle imageHandle, int destX, int destY, int width, int height, int srcX, int srcY)); @@ -165,13 +170,14 @@ static void mInit _ANSI_ARGS_((unsigned char *string, */ static int -FileMatchGIF(chan, fileName, formatString, widthPtr, heightPtr) +FileMatchGIF(chan, fileName, format, widthPtr, heightPtr, interp) 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 *format; /* User-specified format object, or NULL. */ int *widthPtr, *heightPtr; /* The dimensions of the image are * returned here if the file is a valid * raw GIF file. */ + Tcl_Interp *interp; /* not used */ { return ReadGIFHeader(chan, widthPtr, heightPtr); } @@ -197,12 +203,12 @@ FileMatchGIF(chan, fileName, formatString, widthPtr, heightPtr) */ static int -FileReadGIF(interp, chan, fileName, formatString, imageHandle, destX, destY, +FileReadGIF(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 file, open for reading. */ char *fileName; /* The name of the image file. */ - char *formatString; /* User-specified format string, or NULL. */ + 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. */ @@ -212,15 +218,38 @@ FileReadGIF(interp, chan, fileName, formatString, imageHandle, destX, destY, * in image being read. */ { int fileWidth, fileHeight; - int nBytes; + int nBytes, index = 0, argc = 0, i; + Tcl_Obj **objv; Tk_PhotoImageBlock block; unsigned char buf[100]; int bitPixel; unsigned char colorMap[MAXCOLORMAPSIZE][4]; int transparent = -1; + static char *optionStrings[] = { + "-index", NULL + }; + if (format && Tcl_ListObjGetElements(interp, format, + &argc, &objv) != TCL_OK) { + return TCL_ERROR; + } + for (i = 1; i < argc; i++) { + if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option name", 0, + &nBytes) != TCL_OK) { + return TCL_ERROR; + } + if (i == (argc-1)) { + Tcl_AppendResult(interp, "no value given for \"", + Tcl_GetStringFromObj(objv[i], NULL), + "\" option", (char *) NULL); + return TCL_ERROR; + } + if (Tcl_GetIntFromObj(interp, objv[++i], &index) != TCL_OK) { + return TCL_ERROR; + } + } if (!ReadGIFHeader(chan, &fileWidth, &fileHeight)) { - Tcl_AppendResult(interp, "couldn't read GIF header from file \"", + Tcl_AppendResult(interp, "couldn't read GIF header from file \"", fileName, "\"", NULL); return TCL_ERROR; } @@ -263,9 +292,8 @@ FileReadGIF(interp, chan, fileName, formatString, imageHandle, destX, destY, block.offset[0] = 0; block.offset[1] = 1; block.offset[2] = 2; - block.offset[3] = 0; - nBytes = height * block.pitch; - block.pixelPtr = (unsigned char *) ckalloc((unsigned) nBytes); + block.offset[3] = 3; + block.pixelPtr = NULL; while (1) { if (Fread(buf, 1, 1, chan) != 1) { @@ -282,7 +310,9 @@ FileReadGIF(interp, chan, fileName, formatString, imageHandle, destX, destY, * GIF terminator. */ - break; + Tcl_AppendResult(interp,"no image data for this index", + (char *) NULL); + goto error; } if (buf[0] == '!') { @@ -318,8 +348,43 @@ FileReadGIF(interp, chan, fileName, formatString, imageHandle, destX, destY, goto error; } + fileWidth = LM_to_uint(buf[4],buf[5]); + fileHeight = LM_to_uint(buf[6],buf[7]); + bitPixel = 1<<((buf[8]&0x07)+1); + if (index--) { + int x,y; + unsigned char c; + /* this is not the image we want to read: skip it. */ + + if (BitSet(buf[8], LOCALCOLORMAP)) { + if (!ReadColorMap(chan, bitPixel, 0)) { + Tcl_AppendResult(interp, + "error reading color map", (char *) NULL); + goto error; + } + } + + /* read data */ + if (!ReadOK(chan,&c,1)) { + goto error; + } + + LWZReadByte(chan, 1, c); + + for (y=0; y fileWidth) { + width = fileWidth; + } + + index = LM_to_uint(buf[2],buf[3]); + srcY -= index; + if (index > srcY) { + destY -= srcY; height += srcY; + srcY = 0; + } + if (height > fileHeight) { + height = fileHeight; + } + + if ((width <= 0) || (height <= 0)) { + block.pixelPtr = 0; + goto noerror; + } + + block.width = width; + block.height = height; + block.pixelSize = (transparent>=0) ? 4 : 3; + block.offset[3] = (transparent>=0) ? 3 : 0; + block.pitch = block.pixelSize * width; + nBytes = block.pitch * height; + block.pixelPtr = (unsigned char *) ckalloc((unsigned) nBytes); + if (ReadImage(interp, (char *) block.pixelPtr, chan, width, height, colorMap, fileWidth, fileHeight, srcX, srcY, BitSet(buf[8], INTERLACE), transparent) != TCL_OK) { goto error; } break; - } + } - if (transparent == -1) { - Tk_PhotoPutBlock(imageHandle, &block, destX, destY, width, height); - } else { - int x, y, end; - unsigned char *imagePtr, *rowPtr, *pixelPtr; - - imagePtr = rowPtr = block.pixelPtr; - for (y = 0; y < height; y++) { - x = 0; - pixelPtr = rowPtr; - while(x < width) { - /* search for first non-transparent pixel */ - while ((x < width) && !(pixelPtr[CM_ALPHA])) { - x++; pixelPtr += 4; - } - end = x; - /* search for first transparent pixel */ - while ((end < width) && pixelPtr[CM_ALPHA]) { - end++; pixelPtr += 4; - } - if (end > x) { - block.pixelPtr = rowPtr + 4 * x; - Tk_PhotoPutBlock(imageHandle, &block, destX+x, - destY+y, end-x, 1); - } - x = end; - } - rowPtr += block.pitch; - } - block.pixelPtr = imagePtr; + Tk_PhotoPutBlock(imageHandle, &block, destX, destY, width, height); + + noerror: + if (block.pixelPtr) { + ckfree((char *) block.pixelPtr); } - ckfree((char *) block.pixelPtr); + Tcl_AppendResult(interp, tkImgFmtGIF.name, (char *) NULL); return TCL_OK; error: - ckfree((char *) block.pixelPtr); + if (block.pixelPtr) { + ckfree((char *) block.pixelPtr); + } return TCL_ERROR; } @@ -381,10 +458,10 @@ FileReadGIF(interp, chan, fileName, formatString, imageHandle, destX, destY, * StringMatchGIF -- * * This procedure is invoked by the photo image type to see if - * a string contains image data in GIF format. + * an object contains image data in GIF format. * * Results: - * The return value is 1 if the first characters in the string + * The return value is 1 if the first characters in the data are * like GIF data, and 0 otherwise. * * Side effects: @@ -394,21 +471,38 @@ FileReadGIF(interp, chan, fileName, formatString, imageHandle, destX, destY, */ static int -StringMatchGIF(string, formatString, widthPtr, heightPtr) - char *string; /* the string containing the image data */ - char *formatString; /* the image format string */ +StringMatchGIF(dataObj, format, widthPtr, heightPtr, interp) + Tcl_Obj *dataObj; /* the object containing the image data */ + Tcl_Obj *format; /* the image format object, or NULL */ int *widthPtr; /* where to put the string width */ int *heightPtr; /* where to put the string height */ + Tcl_Interp *interp; /* not used */ { - unsigned char header[10]; - int got; + unsigned char *data, header[10]; + int got, length; MFile handle; - mInit((unsigned char *) string, &handle); - got = Mread(header, 10, 1, &handle); - if (got != 10 - || ((strncmp("GIF87a", (char *) header, 6) != 0) - && (strncmp("GIF89a", (char *) header, 6) != 0))) { - return 0; + + data = Tcl_GetByteArrayFromObj(dataObj, &length); + + /* Header is a minimum of 10 bytes */ + if (length < 10) { + return 0; + } + + /* Check whether the data is Base64 encoded */ + + if ((strncmp("\107\111\106\70\67\141", data, 6) != 0) && + (strncmp("\107\111\106\70\71\141", data, 6) != 0)) { + /* Try interpreting the data as Base64 encoded */ + mInit((unsigned char *) data, &handle); + got = Mread(header, 10, 1, &handle); + if (got != 10 + || ((strncmp("\107\111\106\70\67\141", (char *) header, 6) != 0) + && (strncmp("\107\111\106\70\71\141", (char *) header, 6) != 0))) { + return 0; + } + } else { + memcpy((VOID *) header, (VOID *) data, 10); } *widthPtr = LM_to_uint(header[6],header[7]); *heightPtr = LM_to_uint(header[8],header[9]); @@ -421,8 +515,8 @@ StringMatchGIF(string, formatString, widthPtr, heightPtr) * StringReadGif -- -- * * This procedure is called by the photo image type to read - * GIF format data from a base64 encoded string, and give it to - * the photo image. + * GIF format data from an object, optionally base64 encoded, + * and give it to the photo image. * * Results: * A standard TCL completion code. If TCL_ERROR is returned @@ -437,11 +531,11 @@ StringMatchGIF(string, formatString, widthPtr, heightPtr) */ static int -StringReadGIF(interp,string,formatString,imageHandle, +StringReadGIF(interp, dataObj, format, imageHandle, destX, destY, width, height, srcX, srcY) Tcl_Interp *interp; /* interpreter for reporting errors in */ - char *string; /* string containing the image */ - char *formatString; /* format string if any */ + Tcl_Obj *dataObj; /* object containing the image */ + Tcl_Obj *format; /* format object, or NULL */ Tk_PhotoHandle imageHandle; /* the image to write this data into */ int destX, destY; /* The rectangular region of the */ int width, height; /* image to copy */ @@ -451,11 +545,22 @@ StringReadGIF(interp,string,formatString,imageHandle, MFile handle; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - - mInit((unsigned char *)string,&handle); - tsdPtr->fromData = 1; - result = FileReadGIF(interp, (Tcl_Channel) &handle, "inline data", - formatString, imageHandle, destX, destY, width, height, + Tcl_Channel dataSrc; + char *data; + /* Check whether the data is Base64 encoded */ + data = Tcl_GetByteArrayFromObj(dataObj, NULL); + if ((strncmp("\107\111\106\70\67\141", data, 6) != 0) && + (strncmp("\107\111\106\70\71\141", data, 6) != 0)) { + mInit((unsigned char *)data,&handle); + tsdPtr->fromData = 1; + dataSrc = (Tcl_Channel) &handle; + } else { + tsdPtr->fromData = 2; + mInit((unsigned char *)data,&handle); + dataSrc = (Tcl_Channel) &handle; + } + result = FileReadGIF(interp, dataSrc, "inline data", + format, imageHandle, destX, destY, width, height, srcX, srcY); tsdPtr->fromData = 0; return(result); @@ -490,8 +595,8 @@ ReadGIFHeader(chan, widthPtr, heightPtr) unsigned char buf[7]; if ((Fread(buf, 1, 6, chan) != 6) - || ((strncmp("GIF87a", (char *) buf, 6) != 0) - && (strncmp("GIF89a", (char *) buf, 6) != 0))) { + || ((strncmp("\107\111\106\70\67\141", (char *) buf, 6) != 0) + && (strncmp("\107\111\106\70\71\141", (char *) buf, 6) != 0))) { return 0; } @@ -525,10 +630,12 @@ ReadColorMap(chan, number, buffer) return 0; } - buffer[i][CM_RED] = rgb[0] ; - buffer[i][CM_GREEN] = rgb[1] ; - buffer[i][CM_BLUE] = rgb[2] ; - buffer[i][CM_ALPHA] = 255 ; + if (buffer) { + buffer[i][CM_RED] = rgb[0] ; + buffer[i][CM_GREEN] = rgb[1] ; + buffer[i][CM_BLUE] = rgb[2] ; + buffer[i][CM_ALPHA] = 255 ; + } } return 1; } @@ -649,7 +756,9 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap, *pixelPtr++ = cmap[v][CM_RED]; *pixelPtr++ = cmap[v][CM_GREEN]; *pixelPtr++ = cmap[v][CM_BLUE]; - *pixelPtr++ = cmap[v][CM_ALPHA]; + if (transparent >= 0) { + *pixelPtr++ = cmap[v][CM_ALPHA]; + } } ++xpos; @@ -682,7 +791,7 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap, } else { ++ypos; } - pixelPtr = imagePtr + (ypos-srcY) * len * 4; + pixelPtr = imagePtr + (ypos-srcY) * len * ((transparent>=0)?4:3); } if (ypos >= height) break; @@ -1064,10 +1173,17 @@ Fread(dst, hunk, count, chan) { ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + MFile *handle; - if (tsdPtr->fromData) { + switch (tsdPtr->fromData) { + case 1: return(Mread(dst, hunk, count, (MFile *) chan)); - } else { + case 2: + handle = (MFile *) chan; + memcpy((VOID *)dst, (VOID *) handle->data, (size_t) (hunk * count)); + handle->data += hunk * count; + return((int) (hunk * count)); + default: return Tcl_Read(chan, (char *) dst, (int) (hunk * count)); } } diff --git a/generic/tkImgPPM.c b/generic/tkImgPPM.c index a86a254..fe7818f 100644 --- a/generic/tkImgPPM.c +++ b/generic/tkImgPPM.c @@ -13,9 +13,11 @@ * Department of Computer Science, * Australian National University. * - * RCS: @(#) $Id: tkImgPPM.c,v 1.5 1999/07/01 00:39:44 redman Exp $ + * RCS: @(#) $Id: tkImgPPM.c,v 1.6 1999/10/29 03:57:56 hobbs Exp $ */ +#define USE_OLD_IMAGE + #include "tkInt.h" #include "tkPort.h" 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 " 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; rowheight; row++) { + pixelPtr = blockPtr->pixelPtr + blockPtr->offset[0] + + row * blockPtr->pitch; + linePtr = line; + for (col=0; colwidth; 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; } diff --git a/generic/tkInt.h b/generic/tkInt.h index 14be34e..e6a79e1 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: $Id: tkInt.h,v 1.15 1999/06/17 19:58:00 surles Exp $ + * RCS: $Id: tkInt.h,v 1.16 1999/10/29 03:57:57 hobbs Exp $ */ #ifndef _TKINT @@ -927,8 +927,9 @@ EXTERN int Tk_GrabCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int argc, char **argv)); EXTERN int Tk_GridCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int argc, char **argv)); -EXTERN int Tk_ImageCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_ImageObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); EXTERN int Tk_LabelObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); diff --git a/generic/tkTest.c b/generic/tkTest.c index c396345..93965e5 100644 --- a/generic/tkTest.c +++ b/generic/tkTest.c @@ -13,9 +13,11 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkTest.c,v 1.6 1999/06/16 20:11:29 surles Exp $ + * RCS: @(#) $Id: tkTest.c,v 1.7 1999/10/29 03:57:57 hobbs Exp $ */ +#define USE_OLD_IMAGE + #include "tkInt.h" #include "tkPort.h" #include "tkText.h" diff --git a/generic/tkWindow.c b/generic/tkWindow.c index df15d65..20674ba 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWindow.c,v 1.9 1999/09/21 06:42:30 hobbs Exp $ + * RCS: @(#) $Id: tkWindow.c,v 1.10 1999/10/29 03:57:57 hobbs Exp $ */ #include "tkPort.h" @@ -107,7 +107,7 @@ static TkCmd commands[] = { {"font", NULL, Tk_FontObjCmd, 1, 1}, {"grab", Tk_GrabCmd, NULL, 0, 1}, {"grid", Tk_GridCmd, NULL, 1, 1}, - {"image", Tk_ImageCmd, NULL, 1, 1}, + {"image", NULL, Tk_ImageObjCmd, 1, 1}, {"lower", Tk_LowerCmd, NULL, 1, 1}, {"option", Tk_OptionCmd, NULL, 1, 1}, {"pack", Tk_PackCmd, NULL, 1, 1}, @@ -268,7 +268,7 @@ CreateTopLevelWindow(interp, parent, name, screenName) */ Tk_CreatePhotoImageFormat(&tkImgFmtGIF); - Tk_CreatePhotoImageFormat(&tkImgFmtPPM); + Tk_CreateOldPhotoImageFormat(&tkImgFmtPPM); /* * Create exit handler to delete all windows when the application -- cgit v0.12