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