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 againpil-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
|
} |