summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhobbs <hobbs>1999-10-29 03:57:55 (GMT)
committerhobbs <hobbs>1999-10-29 03:57:55 (GMT)
commit8e52a87a0be5a9969812bdd4c5439688cc5cc9fc (patch)
tree71b94aa4df21cf83d8b4dfaeff16f8c4d6d9bd30
parent62b72b828e6c010209ab75d9d8507adf8f7d6836 (diff)
downloadtk-8e52a87a0be5a9969812bdd4c5439688cc5cc9fc.zip
tk-8e52a87a0be5a9969812bdd4c5439688cc5cc9fc.tar.gz
tk-8e52a87a0be5a9969812bdd4c5439688cc5cc9fc.tar.bz2
* generic/tk.h:
* generic/tkCmds.c: * generic/tkImage.c: * generic/tkImgBmap.c: * generic/tkImgGIF.c: * generic/tkImgPPM.c: * generic/tkImgPhoto.c: * generic/tkInt.h: * generic/tkTest.c: * generic/tkWindow.c: * tests/imgPhoto.test: added Img patch (Nijtmans) with docs, headers #def'd with USE_OLD_IMAGE. Upgrades image stuff to Tcl_Obj API, adds alpha channel (images are now 32 bpp)
-rw-r--r--generic/tk.h47
-rw-r--r--generic/tkCmds.c3
-rw-r--r--generic/tkImage.c201
-rw-r--r--generic/tkImgBmap.c83
-rw-r--r--generic/tkImgGIF.c286
-rw-r--r--generic/tkImgPPM.c4
-rw-r--r--generic/tkImgPhoto.c1205
-rw-r--r--generic/tkInt.h7
-rw-r--r--generic/tkTest.c4
-rw-r--r--generic/tkWindow.c6
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<fileHeight; y++) {
+ for (x=0; x<fileWidth; x++) {
+ if (LWZReadByte(chan, 0, c) < 0) {
+ Tcl_AppendResult(interp,
+ "error reading image data", (char *) NULL);
+ goto error;
+ }
+ }
+ }
+ continue;
+ }
+
if (BitSet(buf[8], LOCALCOLORMAP)) {
if (!ReadColorMap(chan, bitPixel, colorMap)) {
Tcl_AppendResult(interp, "error reading color map",
@@ -327,50 +392,62 @@ FileReadGIF(interp, chan, fileName, formatString, imageHandle, destX, destY,
goto error;
}
}
+
+ index = LM_to_uint(buf[0],buf[1]);
+ srcX -= index;
+ if (srcX<0) {
+ destX -= srcX; width += srcX;
+ srcX = 0;
+ }
+
+ if (width > 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 "<img> put" command.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ImgStringWrite(interp, dataPtr, formatString, blockPtr)
+ Tcl_Interp *interp;
+ Tcl_DString *dataPtr;
+ Tcl_Obj *formatString;
+ Tk_PhotoImageBlock *blockPtr;
+{
+ int row,col;
+ char *line, *linePtr;
+ unsigned char *pixelPtr;
+ int greenOffset, blueOffset;
+
+ greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
+ blueOffset = blockPtr->offset[2] - blockPtr->offset[0];
+
+ if ((blockPtr->width > 0) && (blockPtr->height > 0)) {
+ line = (char *) ckalloc((unsigned int) ((8 * blockPtr->width) + 2));
+ for (row=0; row<blockPtr->height; row++) {
+ pixelPtr = blockPtr->pixelPtr + blockPtr->offset[0] +
+ row * blockPtr->pitch;
+ linePtr = line;
+ for (col=0; col<blockPtr->width; col++) {
+ sprintf(linePtr, " #%02x%02x%02x", *pixelPtr,
+ pixelPtr[greenOffset], pixelPtr[blueOffset]);
+ pixelPtr += blockPtr->pixelSize;
+ linePtr += 8;
+ }
+ Tcl_DStringAppendElement(dataPtr, line+1);
+ }
+ ckfree (line);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tk_PhotoGetImage --
*
* This procedure is called to obtain image data from a photo
@@ -4169,11 +4936,11 @@ Tk_PhotoGetImage(handle, blockPtr)
blockPtr->pixelPtr = masterPtr->pix24;
blockPtr->width = masterPtr->width;
blockPtr->height = masterPtr->height;
- blockPtr->pitch = masterPtr->width * 3;
- blockPtr->pixelSize = 3;
+ blockPtr->pitch = masterPtr->width * 4;
+ blockPtr->pixelSize = 4;
blockPtr->offset[0] = 0;
blockPtr->offset[1] = 1;
blockPtr->offset[2] = 2;
- blockPtr->offset[3] = 0;
+ blockPtr->offset[3] = 3;
return 1;
}
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