summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authordonal.k.fellows@manchester.ac.uk <dkf>2004-03-26 14:34:04 (GMT)
committerdonal.k.fellows@manchester.ac.uk <dkf>2004-03-26 14:34:04 (GMT)
commitfb0df739bfa859239b3caedc7d1954eb08262263 (patch)
tree2e56346380aefd775268df59e1c95838672bceed /generic
parent1c585284aaed11546c54141b5995f5e0f06b37cd (diff)
downloadtk-fb0df739bfa859239b3caedc7d1954eb08262263.zip
tk-fb0df739bfa859239b3caedc7d1954eb08262263.tar.gz
tk-fb0df739bfa859239b3caedc7d1954eb08262263.tar.bz2
Allow old-style image formats to create string representations of photos,
and allow the production of PPM format data in a string. [Bug 923555]
Diffstat (limited to 'generic')
-rw-r--r--generic/tkImgPPM.c110
-rw-r--r--generic/tkImgPhoto.c46
2 files changed, 132 insertions, 24 deletions
diff --git a/generic/tkImgPPM.c b/generic/tkImgPPM.c
index 2abe1fd..48e081e 100644
--- a/generic/tkImgPPM.c
+++ b/generic/tkImgPPM.c
@@ -13,11 +13,9 @@
* Department of Computer Science,
* Australian National University.
*
- * RCS: @(#) $Id: tkImgPPM.c,v 1.11 2003/03/06 15:05:35 dkf Exp $
+ * RCS: @(#) $Id: tkImgPPM.c,v 1.12 2004/03/26 14:34:05 dkf Exp $
*/
-#define USE_OLD_IMAGE
-
#include "tkInt.h"
#include "tkPort.h"
@@ -40,16 +38,19 @@
*/
static int FileMatchPPM _ANSI_ARGS_((Tcl_Channel chan,
- char *fileName, char *formatString,
- int *widthPtr, int *heightPtr));
+ CONST char *fileName, Tcl_Obj *format,
+ int *widthPtr, int *heightPtr,
+ Tcl_Interp *interp));
static int FileReadPPM _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Channel chan, char *fileName,
- char *formatString, Tk_PhotoHandle imageHandle,
+ Tcl_Channel chan, CONST char *fileName,
+ Tcl_Obj *format, Tk_PhotoHandle imageHandle,
int destX, int destY, int width, int height,
int srcX, int srcY));
static int FileWritePPM _ANSI_ARGS_((Tcl_Interp *interp,
- char *fileName, char *formatString,
+ CONST char *fileName, Tcl_Obj *format,
Tk_PhotoImageBlock *blockPtr));
+static int StringWritePPM _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr));
Tk_PhotoImageFormat tkImgFmtPPM = {
"PPM", /* name */
@@ -58,7 +59,7 @@ Tk_PhotoImageFormat tkImgFmtPPM = {
FileReadPPM, /* fileReadProc */
NULL, /* stringReadProc */
FileWritePPM, /* fileWriteProc */
- NULL, /* stringWriteProc */
+ StringWritePPM, /* stringWriteProc */
};
/*
@@ -88,13 +89,14 @@ static int ReadPPMFileHeader _ANSI_ARGS_((Tcl_Channel chan,
*/
static int
-FileMatchPPM(chan, fileName, formatString, widthPtr, heightPtr)
+FileMatchPPM(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. */
+ CONST char *fileName; /* The name of the image file. */
+ Tcl_Obj *format; /* User-specified format string, or NULL. */
int *widthPtr, *heightPtr; /* The dimensions of the image are
* returned here if the file is a valid
* raw PPM file. */
+ Tcl_Interp *interp; /* unused */
{
int dummy;
@@ -122,12 +124,12 @@ FileMatchPPM(chan, fileName, formatString, widthPtr, heightPtr)
*/
static int
-FileReadPPM(interp, chan, fileName, formatString, imageHandle, destX, destY,
+FileReadPPM(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. */
+ CONST char *fileName; /* The name of the image file. */
+ Tcl_Obj *format; /* User-specified format string, or NULL. */
Tk_PhotoHandle imageHandle; /* The photo image to write into. */
int destX, destY; /* Coordinates of top-left pixel in
* photo image to be written to. */
@@ -262,10 +264,10 @@ FileReadPPM(interp, chan, fileName, formatString, imageHandle, destX, destY,
*/
static int
-FileWritePPM(interp, fileName, formatString, blockPtr)
+FileWritePPM(interp, fileName, format, blockPtr)
Tcl_Interp *interp;
- char *fileName;
- char *formatString;
+ CONST char *fileName;
+ Tcl_Obj *format;
Tk_PhotoImageBlock *blockPtr;
{
Tcl_Channel chan;
@@ -335,6 +337,78 @@ FileWritePPM(interp, fileName, formatString, blockPtr)
/*
*----------------------------------------------------------------------
*
+ * StringWritePPM --
+ *
+ * This procedure is invoked to write image data to a string in PPM
+ * format.
+ *
+ * Results:
+ * A standard TCL completion code. If TCL_ERROR is returned
+ * then an error message is left in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+StringWritePPM(interp, format, blockPtr)
+ Tcl_Interp *interp;
+ Tcl_Obj *format;
+ Tk_PhotoImageBlock *blockPtr;
+{
+ int w, h, size, greenOffset, blueOffset;
+ unsigned char *pixLinePtr, *byteArray;
+ char header[16 + TCL_INTEGER_SPACE * 2];
+ Tcl_Obj *byteArrayObj;
+
+ sprintf(header, "P6\n%d %d\n255\n", blockPtr->width, blockPtr->height);
+ /*
+ * Construct a byte array of the right size with the header and
+ * get a pointer to the data part of it.
+ */
+ size = strlen(header);
+ byteArrayObj = Tcl_NewByteArrayObj((unsigned char *)header, size);
+ byteArray = Tcl_SetByteArrayLength(byteArrayObj,
+ size + 3*blockPtr->width*blockPtr->height);
+ byteArray += size;
+
+ pixLinePtr = blockPtr->pixelPtr + blockPtr->offset[0];
+ greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
+ blueOffset = blockPtr->offset[2] - blockPtr->offset[0];
+
+ /*
+ * Check if we can do the data move in single action.
+ */
+ if ((greenOffset == 1) && (blueOffset == 2) && (blockPtr->pixelSize == 3)
+ && (blockPtr->pitch == (blockPtr->width * 3))) {
+ memcpy(byteArray, pixLinePtr,
+ (unsigned)blockPtr->height * blockPtr->pitch);
+ } else {
+ for (h = blockPtr->height; h > 0; h--) {
+ unsigned char *pixelPtr = pixLinePtr;
+
+ for (w = blockPtr->width; w > 0; w--) {
+ *byteArray++ = pixelPtr[0];
+ *byteArray++ = pixelPtr[greenOffset];
+ *byteArray++ = pixelPtr[blueOffset];
+ pixelPtr += blockPtr->pixelSize;
+ }
+ pixLinePtr += blockPtr->pitch;
+ }
+ }
+
+ /*
+ * Return the object in the interpreter result.
+ */
+ Tcl_SetObjResult(interp, byteArrayObj);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* ReadPPMFileHeader --
*
* This procedure reads the PPM header from the beginning of a
diff --git a/generic/tkImgPhoto.c b/generic/tkImgPhoto.c
index d5bf02d..936c4b5 100644
--- a/generic/tkImgPhoto.c
+++ b/generic/tkImgPhoto.c
@@ -17,7 +17,7 @@
* Department of Computer Science,
* Australian National University.
*
- * RCS: @(#) $Id: tkImgPhoto.c,v 1.44 2004/02/09 14:48:20 dkf Exp $
+ * RCS: @(#) $Id: tkImgPhoto.c,v 1.45 2004/03/26 14:34:05 dkf Exp $
*/
#include "tkInt.h"
@@ -934,10 +934,12 @@ ImgPhotoCmd(clientData, interp, objc, objv)
*/
if (options.options & OPT_FORMAT) {
+ matched = 0;
for (imageFormat = tsdPtr->formatList; imageFormat != NULL;
imageFormat = imageFormat->nextPtr) {
if ((strncasecmp(Tcl_GetString(options.format),
imageFormat->name, strlen(imageFormat->name)) == 0)) {
+ matched = 1;
if (imageFormat->stringWriteProc != NULL) {
stringWriteProc = imageFormat->stringWriteProc;
break;
@@ -945,9 +947,25 @@ ImgPhotoCmd(clientData, interp, objc, objv)
}
}
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)) {
+ matched = 1;
+ 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);
+ Tcl_GetString(options.format), "\" is ",
+ (matched ? "not supported" : "unknown"),
+ (char *) NULL);
return TCL_ERROR;
}
} else {
@@ -961,9 +979,25 @@ ImgPhotoCmd(clientData, interp, objc, objv)
data = ImgGetPhoto(masterPtr, &block, &options);
- result = ((int (*) _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *formatString,
- Tk_PhotoImageBlock *blockPtr, VOID *dummy))) stringWriteProc)
- (interp, options.format, &block, (VOID *) NULL);
+ if (oldformat) {
+ Tcl_DString buffer;
+
+ Tcl_DStringInit(&buffer);
+ result = ((int (*) _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_DString *dataPtr, char *formatString,
+ Tk_PhotoImageBlock *blockPtr))) stringWriteProc)
+ (interp, &buffer, Tcl_GetString(options.format), &block);
+ if (result == TCL_OK) {
+ Tcl_DStringResult(interp, &buffer);
+ } else {
+ Tcl_DStringFree(&buffer);
+ }
+ } else {
+ result = ((int (*) _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj *formatString, Tk_PhotoImageBlock *blockPtr,
+ VOID *dummy))) stringWriteProc)
+ (interp, options.format, &block, (VOID *) NULL);
+ }
if (options.background) {
Tk_FreeColor(options.background);
}