Fredrik Lundh is sharing code with you

Bitbucket is a code hosting site. Unlimited public and private repositories. Free for small teams.

Don't show this again

effbot / pil-2009-raclette http://effbot.org/zone/pil-index.htm

Work repository for PIL 1.1.7 and beyond. The "default" branch should be fairly solid, the other branches less so. For production use, see the pil-117 repository.

Clone this repository (size: 1.6 MB): HTTPS / SSH
hg clone https://bitbucket.org/effbot/pil-2009-raclette
hg clone ssh://hg@bitbucket.org/effbot/pil-2009-raclette

pil-2009-raclette / Tk / tkImaging.c

commit
454b4d2672f3
parent
64f9636f4d92
branch
default
tags
pil-117-20090317, pil-117a1-20090317

Don't try to open files twice if plugins are already loaded.

1
770a9717f387
/*
2
770a9717f387
 * The Python Imaging Library.
3
2717f05122cd
 * $Id$
4
770a9717f387
 *
5
770a9717f387
 * TK interface for Python Imaging objects
6
770a9717f387
 *
7
770a9717f387
 * Copies (parts of) a named display memory to a photo image object.
8
770a9717f387
 * Also contains code to create an display memory.  Under Tk, a
9
770a9717f387
 * display memory is simply an "L" or "RGB" image memory that is
10
770a9717f387
 * allocated in a single block.
11
770a9717f387
 *
12
2717f05122cd
 * To use this module, import the _imagingtk module (ImageTk does
13
2717f05122cd
 * this for you).
14
2717f05122cd
 * 
15
2717f05122cd
 * If you're using Python in an embedded context, you can add the
16
2717f05122cd
 * following lines to your Tcl_AppInit function (in tkappinit.c)
17
2717f05122cd
 * instead.  Put them after the calls to Tcl_Init and Tk_Init:
18
770a9717f387
 *	
19
770a9717f387
 *	{
20
770a9717f387
 *          extern void TkImaging_Init(Tcl_Interp* interp);
21
770a9717f387
 *          TkImaging_Init(interp);
22
770a9717f387
 *      }
23
770a9717f387
 *
24
2717f05122cd
 * This registers a Tcl command called "PyImagingPhoto", which is used
25
2717f05122cd
 * to communicate between PIL and Tk's PhotoImage handler.
26
770a9717f387
 *
27
2717f05122cd
 * Compile and link tkImaging.c with tkappinit.c and _tkinter (see the
28
2717f05122cd
 * Setup file for details on how to use tkappinit.c).  Note that
29
2717f05122cd
 * _tkinter.c must be compiled with WITH_APPINIT.
30
770a9717f387
 *
31
770a9717f387
 * History:
32
770a9717f387
 * 1995-09-12 fl  Created
33
770a9717f387
 * 1996-04-08 fl  Ready for release
34
770a9717f387
 * 1997-05-09 fl  Use command instead of image type
35
770a9717f387
 * 2001-03-18 fl  Initialize alpha layer pointer (struct changed in 8.3)
36
770a9717f387
 * 2003-04-23 fl  Fixed building for Tk 8.4.1 and later (Jack Jansen)
37
770a9717f387
 * 2004-06-24 fl  Fixed building for Tk 8.4.6 and later.
38
770a9717f387
 *
39
770a9717f387
 * Copyright (c) 1997-2004 by Secret Labs AB
40
770a9717f387
 * Copyright (c) 1995-2004 by Fredrik Lundh
41
770a9717f387
 *
42
770a9717f387
 * See the README file for information on usage and redistribution.
43
770a9717f387
 */
44
770a9717f387
45
b3bbcf67b769
#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
46
770a9717f387
47
770a9717f387
/* This is needed for (at least) Tk 8.4.6 and later, to avoid warnings
48
770a9717f387
   for the Tcl_CreateCommand command. */
49
770a9717f387
#define USE_COMPAT_CONST
50
770a9717f387
51
770a9717f387
#include "tk.h"
52
770a9717f387
53
770a9717f387
#include "Imaging.h"
54
770a9717f387
55
770a9717f387
#include <stdlib.h>
56
770a9717f387
57
770a9717f387
58
770a9717f387
static Imaging
59
770a9717f387
ImagingFind(const char* name)
60
770a9717f387
{
61
770a9717f387
    long id;
62
770a9717f387
63
770a9717f387
    /* FIXME: use CObject instead? */
64
770a9717f387
    id = atol(name);
65
770a9717f387
    if (!id)
66
770a9717f387
	return NULL;
67
770a9717f387
68
770a9717f387
    return (Imaging) id;
69
770a9717f387
}
70
770a9717f387
71
770a9717f387
72
770a9717f387
static int
73
770a9717f387
PyImagingPhotoPut(ClientData clientdata, Tcl_Interp* interp,
74
770a9717f387
               int argc, char **argv)
75
770a9717f387
{
76
770a9717f387
    Imaging im;
77
770a9717f387
    Tk_PhotoHandle photo;
78
770a9717f387
    Tk_PhotoImageBlock block;
79
770a9717f387
80
770a9717f387
    if (argc != 3) {
81
770a9717f387
        Tcl_AppendResult(interp, "usage: ", argv[0],
82
770a9717f387
                         " destPhoto srcImage", (char *) NULL);
83
770a9717f387
        return TCL_ERROR;
84
770a9717f387
    }
85
770a9717f387
86
770a9717f387
    /* get Tcl PhotoImage handle */
87
770a9717f387
    photo = Tk_FindPhoto(interp, argv[1]);
88
770a9717f387
    if (photo == NULL) {
89
770a9717f387
        Tcl_AppendResult(
90
770a9717f387
            interp, "destination photo must exist", (char *) NULL
91
770a9717f387
            );
92
770a9717f387
        return TCL_ERROR;
93
770a9717f387
    }
94
770a9717f387
95
770a9717f387
    /* get PIL Image handle */
96
770a9717f387
    im = ImagingFind(argv[2]);
97
770a9717f387
    if (!im) {
98
770a9717f387
	Tcl_AppendResult(interp, "bad name", (char*) NULL);
99
770a9717f387
	return TCL_ERROR;
100
770a9717f387
    }
101
770a9717f387
    if (!im->block) {
102
770a9717f387
	Tcl_AppendResult(interp, "bad display memory", (char*) NULL);
103
770a9717f387
	return TCL_ERROR;
104
770a9717f387
    }
105
770a9717f387
106
770a9717f387
    /* Active region */
107
770a9717f387
#if 0
108
770a9717f387
    if (src_xoffset + xsize > im->xsize)
109
770a9717f387
	xsize = im->xsize - src_xoffset;
110
770a9717f387
    if (src_yoffset + ysize > im->ysize)
111
770a9717f387
	ysize = im->ysize - src_yoffset;
112
770a9717f387
    if (xsize < 0 || ysize < 0
113
770a9717f387
	|| src_xoffset >= im->xsize
114
770a9717f387
	|| src_yoffset >= im->ysize)
115
770a9717f387
	return TCL_OK;
116
770a9717f387
#endif
117
770a9717f387
118
770a9717f387
    /* Mode */
119
770a9717f387
120
770a9717f387
    if (strcmp(im->mode, "1") == 0 || strcmp(im->mode, "L") == 0) {
121
770a9717f387
	block.pixelSize = 1;
122
770a9717f387
	block.offset[0] = block.offset[1] = block.offset[2] = 0;
123
770a9717f387
    } else if (strncmp(im->mode, "RGB", 3) == 0) {
124
770a9717f387
	block.pixelSize = 4;
125
770a9717f387
	block.offset[0] = 0;
126
770a9717f387
	block.offset[1] = 1;
127
770a9717f387
	block.offset[2] = 2;
128
b3bbcf67b769
        if (strcmp(im->mode, "RGBA") == 0)
129
b3bbcf67b769
            block.offset[3] = 3; /* alpha (or reserved, under 8.2) */
130
b3bbcf67b769
        else
131
b3bbcf67b769
            block.offset[3] = 0; /* no alpha */
132
770a9717f387
    } else {
133
770a9717f387
        Tcl_AppendResult(interp, "Bad mode", (char*) NULL);
134
770a9717f387
	return TCL_ERROR;
135
770a9717f387
    }
136
770a9717f387
137
770a9717f387
    block.width = im->xsize;
138
770a9717f387
    block.height = im->ysize;
139
770a9717f387
    block.pitch = im->linesize;
140
770a9717f387
    block.pixelPtr = (unsigned char*) im->block;
141
770a9717f387
#if 0
142
770a9717f387
    block.pixelPtr = (unsigned char*) im->block +
143
770a9717f387
	             src_yoffset * im->linesize +
144
770a9717f387
	             src_xoffset * im->pixelsize;
145
770a9717f387
#endif
146
770a9717f387
147
b3bbcf67b769
#if TKMAJORMINOR < 8004 /* Tk < 8.4.0 */
148
770a9717f387
    if (strcmp(im->mode, "RGBA") == 0) {
149
770a9717f387
        /* Copy non-transparent pixels to photo image */
150
770a9717f387
        int x, y;
151
770a9717f387
        Tk_PhotoImageBlock run;
152
770a9717f387
153
770a9717f387
        /* Clear current contents */
154
770a9717f387
        Tk_PhotoBlank(photo);
155
770a9717f387
156
770a9717f387
        /* Setup run descriptor */
157
770a9717f387
        run.height = 1;
158
770a9717f387
        run.pitch = block.pitch;
159
770a9717f387
        run.pixelSize = block.pixelSize;
160
770a9717f387
        run.offset[0] = 0;
161
770a9717f387
        run.offset[1] = 1;
162
770a9717f387
        run.offset[2] = 2;
163
770a9717f387
	run.offset[3] = 0; /* no alpha (or reserved, under 8.2) */
164
770a9717f387
165
2717f05122cd
	/* FIXME: handle compositing support under 8.4 and later */
166
2717f05122cd
167
770a9717f387
        /* Copy opaque runs to photo image */
168
770a9717f387
        for (y = 0; y < block.height; y++) {
169
770a9717f387
            unsigned char* p = block.pixelPtr + y*block.pitch;
170
770a9717f387
            unsigned char* s = p;
171
770a9717f387
            int   w = 0;
172
770a9717f387
            for (x = 0; x < block.width; x++) {
173
770a9717f387
                if (p[3]) {
174
770a9717f387
                    /* opaque: add pixel to current run */
175
770a9717f387
                    if (w == 0)
176
770a9717f387
                        s = p;
177
770a9717f387
                    w = w + 1;
178
770a9717f387
                } else if (s) {
179
770a9717f387
                    /* copy run to photo image */
180
770a9717f387
                    if (w > 0) {
181
770a9717f387
                        run.width = w;
182
770a9717f387
                        run.pixelPtr = s;
183
770a9717f387
                        Tk_PhotoPutBlock(photo, &run, x-w, y, run.width, 1);
184
770a9717f387
                    }
185
770a9717f387
                    w = 0;
186
770a9717f387
                }
187
770a9717f387
                p += block.pixelSize;
188
770a9717f387
            }
189
770a9717f387
            if (w > 0) {
190
770a9717f387
                /* copy final run, if any */
191
770a9717f387
                run.width = w;
192
770a9717f387
                run.pixelPtr = s;
193
770a9717f387
                Tk_PhotoPutBlock(photo, &run, x-w, y, run.width, 1);
194
770a9717f387
          }
195
770a9717f387
        }
196
770a9717f387
197
770a9717f387
    } else
198
770a9717f387
199
770a9717f387
        /* Copy opaque block to photo image, and leave the rest to TK */
200
770a9717f387
        Tk_PhotoPutBlock(photo, &block, 0, 0, block.width, block.height);
201
770a9717f387
202
b3bbcf67b769
#else /* Tk >= 8.4.0 */
203
b3bbcf67b769
    Tk_PhotoPutBlock(photo, &block, 0, 0, block.width, block.height,
204
b3bbcf67b769
                     TK_PHOTO_COMPOSITE_SET);
205
b3bbcf67b769
    if (strcmp(im->mode, "RGBA") == 0)
206
b3bbcf67b769
        /* Tk workaround: we need apply ToggleComplexAlphaIfNeeded */
207
b3bbcf67b769
        /* (fixed in Tk 8.5a3) */
208
b3bbcf67b769
        Tk_PhotoSetSize(photo, block.width, block.height);
209
b3bbcf67b769
#endif
210
b3bbcf67b769
211
770a9717f387
    return TCL_OK;
212
770a9717f387
}
213
770a9717f387
214
770a9717f387
215
770a9717f387
static int
216
770a9717f387
PyImagingPhotoGet(ClientData clientdata, Tcl_Interp* interp,
217
770a9717f387
               int argc, char **argv)
218
770a9717f387
{
219
770a9717f387
    Tk_PhotoHandle photo;
220
770a9717f387
    Tk_PhotoImageBlock block;
221
770a9717f387
222
770a9717f387
    if (argc != 2) {
223
770a9717f387
        Tcl_AppendResult(interp, "usage: ", argv[0],
224
770a9717f387
                         " srcPhoto", (char *) NULL);
225
770a9717f387
        return TCL_ERROR;
226
770a9717f387
    }
227
770a9717f387
228
770a9717f387
    /* get Tcl PhotoImage handle */
229
770a9717f387
    photo = Tk_FindPhoto(interp, argv[1]);
230
770a9717f387
    if (photo == NULL) {
231
770a9717f387
        Tcl_AppendResult(
232
770a9717f387
            interp, "source photo must exist", (char *) NULL
233
770a9717f387
            );
234
770a9717f387
        return TCL_ERROR;
235
770a9717f387
    }
236
770a9717f387
237
770a9717f387
    Tk_PhotoGetImage(photo, &block);
238
770a9717f387
239
770a9717f387
    printf("pixelPtr = %p\n", block.pixelPtr);
240
770a9717f387
    printf("width = %d\n", block.width);
241
770a9717f387
    printf("height = %d\n", block.height);
242
770a9717f387
    printf("pitch = %d\n", block.pitch);
243
770a9717f387
    printf("pixelSize = %d\n", block.pixelSize);
244
770a9717f387
    printf("offset = %d %d %d %d\n", block.offset[0], block.offset[1],
245
770a9717f387
           block.offset[2], block.offset[3]);
246
770a9717f387
247
770a9717f387
    Tcl_AppendResult(
248
2717f05122cd
        interp, "this function is not yet supported", (char *) NULL
249
770a9717f387
        );
250
770a9717f387
251
770a9717f387
    return TCL_ERROR;
252
770a9717f387
}
253
770a9717f387
254
770a9717f387
255
770a9717f387
void
256
770a9717f387
TkImaging_Init(Tcl_Interp* interp)
257
770a9717f387
{
258
770a9717f387
    Tcl_CreateCommand(interp, "PyImagingPhoto", PyImagingPhotoPut,
259
770a9717f387
                      (ClientData) 0, (Tcl_CmdDeleteProc*) NULL);
260
770a9717f387
    Tcl_CreateCommand(interp, "PyImagingPhotoGet", PyImagingPhotoGet,
261
770a9717f387
                      (ClientData) 0, (Tcl_CmdDeleteProc*) NULL);
262
770a9717f387
}