1 |
|
---|
2 | /*
|
---|
3 | * bltWinImage.c --
|
---|
4 | *
|
---|
5 | * This module implements image processing procedures for the BLT
|
---|
6 | * toolkit.
|
---|
7 | *
|
---|
8 | * Copyright 1997-1998 Lucent Technologies, Inc.
|
---|
9 | *
|
---|
10 | * Permission to use, copy, modify, and distribute this software and
|
---|
11 | * its documentation for any purpose and without fee is hereby
|
---|
12 | * granted, provided that the above copyright notice appear in all
|
---|
13 | * copies and that both that the copyright notice and warranty
|
---|
14 | * disclaimer appear in supporting documentation, and that the names
|
---|
15 | * of Lucent Technologies any of their entities not be used in
|
---|
16 | * advertising or publicity pertaining to distribution of the software
|
---|
17 | * without specific, written prior permission.
|
---|
18 | *
|
---|
19 | * Lucent Technologies disclaims all warranties with regard to this
|
---|
20 | * software, including all implied warranties of merchantability and
|
---|
21 | * fitness. In no event shall Lucent Technologies be liable for any
|
---|
22 | * special, indirect or consequential damages or any damages
|
---|
23 | * whatsoever resulting from loss of use, data or profits, whether in
|
---|
24 | * an action of contract, negligence or other tortuous action, arising
|
---|
25 | * out of or in connection with the use or performance of this
|
---|
26 | * software.
|
---|
27 | */
|
---|
28 |
|
---|
29 | #include "bltInt.h"
|
---|
30 | #include "bltImage.h"
|
---|
31 | #include <X11/Xutil.h>
|
---|
32 |
|
---|
33 | #define CLAMP(c) ((((c) < 0.0) ? 0.0 : ((c) > 255.0) ? 255.0 : (c)))
|
---|
34 |
|
---|
35 | #define GetBit(x, y) \
|
---|
36 | srcBits[(srcBytesPerRow * (srcHeight - y - 1)) + (x>>3)] & (0x80 >> (x&7))
|
---|
37 | #define SetBit(x, y) \
|
---|
38 | destBits[(destBytesPerRow * (destHeight - y - 1)) + (x>>3)] |= (0x80 >>(x&7))
|
---|
39 |
|
---|
40 | /*
|
---|
41 | *----------------------------------------------------------------------
|
---|
42 | *
|
---|
43 | * Blt_ColorImageToPixmap --
|
---|
44 | *
|
---|
45 | * Converts a color image into a pixmap.
|
---|
46 | *
|
---|
47 | * Right now this only handles TrueColor visuals.
|
---|
48 | *
|
---|
49 | * Results:
|
---|
50 | * The new pixmap is returned.
|
---|
51 | *
|
---|
52 | *----------------------------------------------------------------------
|
---|
53 | */
|
---|
54 | Pixmap
|
---|
55 | Blt_ColorImageToPixmap(
|
---|
56 | Tcl_Interp *interp,
|
---|
57 | Tk_Window tkwin,
|
---|
58 | Blt_ColorImage image,
|
---|
59 | ColorTable *colorTablePtr) /* Points to array of colormap indices */
|
---|
60 | {
|
---|
61 | HDC pixmapDC;
|
---|
62 | TkWinDCState state;
|
---|
63 | Display *display;
|
---|
64 | int width, height, depth;
|
---|
65 | Pixmap pixmap;
|
---|
66 | register int x, y;
|
---|
67 | register Pix32 *srcPtr;
|
---|
68 | COLORREF rgb;
|
---|
69 |
|
---|
70 | *colorTablePtr = NULL;
|
---|
71 | width = Blt_ColorImageWidth(image);
|
---|
72 | height = Blt_ColorImageHeight(image);
|
---|
73 | display = Tk_Display(tkwin);
|
---|
74 | depth = Tk_Depth(tkwin);
|
---|
75 |
|
---|
76 | pixmap = Tk_GetPixmap(display, Tk_WindowId(tkwin), width, height, depth);
|
---|
77 | pixmapDC = TkWinGetDrawableDC(display, pixmap, &state);
|
---|
78 |
|
---|
79 | srcPtr = Blt_ColorImageBits(image);
|
---|
80 | for (y = 0; y < height; y++) {
|
---|
81 | for (x = 0; x < width; x++) {
|
---|
82 | rgb = PALETTERGB(srcPtr->Red, srcPtr->Green, srcPtr->Blue);
|
---|
83 | SetPixelV(pixmapDC, x, y, rgb);
|
---|
84 | srcPtr++;
|
---|
85 | }
|
---|
86 | }
|
---|
87 | TkWinReleaseDrawableDC(pixmap, pixmapDC, &state);
|
---|
88 | return pixmap;
|
---|
89 | }
|
---|
90 |
|
---|
91 | /*
|
---|
92 | *----------------------------------------------------------------------
|
---|
93 | *
|
---|
94 | * Blt_ColorImageToPixmap2 --
|
---|
95 | *
|
---|
96 | * Converts a color image into a pixmap.
|
---|
97 | *
|
---|
98 | * Right now this only handles TrueColor visuals.
|
---|
99 | *
|
---|
100 | * Results:
|
---|
101 | * The new pixmap is returned.
|
---|
102 | *
|
---|
103 | *----------------------------------------------------------------------
|
---|
104 | */
|
---|
105 | Pixmap
|
---|
106 | Blt_ColorImageToPixmap2(
|
---|
107 | Display *display,
|
---|
108 | int depth,
|
---|
109 | Blt_ColorImage image,
|
---|
110 | ColorTable *colorTablePtr) /* Points to array of colormap indices */
|
---|
111 | {
|
---|
112 | BITMAP bm;
|
---|
113 | HBITMAP hBitmap;
|
---|
114 | TkWinBitmap *twdPtr;
|
---|
115 | int width, height;
|
---|
116 | register Pix32 *srcPtr;
|
---|
117 | register int x, y;
|
---|
118 | register unsigned char *destPtr;
|
---|
119 | unsigned char *bits;
|
---|
120 |
|
---|
121 | *colorTablePtr = NULL;
|
---|
122 | width = Blt_ColorImageWidth(image);
|
---|
123 | height = Blt_ColorImageHeight(image);
|
---|
124 |
|
---|
125 | /*
|
---|
126 | * Copy the color image RGB data into the DIB. The DIB scanlines
|
---|
127 | * are stored bottom-to-top and the order of the RGB color
|
---|
128 | * components is BGR. Who says Win32 GDI programming isn't
|
---|
129 | * backwards?
|
---|
130 | */
|
---|
131 | bits = Blt_Malloc(width * height * sizeof(unsigned char));
|
---|
132 | assert(bits);
|
---|
133 | srcPtr = Blt_ColorImageBits(image);
|
---|
134 | for (y = height - 1; y >= 0; y--) {
|
---|
135 | destPtr = bits + (y * width);
|
---|
136 | for (x = 0; x < width; x++) {
|
---|
137 | *destPtr++ = srcPtr->Blue;
|
---|
138 | *destPtr++ = srcPtr->Green;
|
---|
139 | *destPtr++ = srcPtr->Red;
|
---|
140 | *destPtr++ = (unsigned char)-1;
|
---|
141 | srcPtr++;
|
---|
142 | }
|
---|
143 | }
|
---|
144 | bm.bmType = 0;
|
---|
145 | bm.bmWidth = width;
|
---|
146 | bm.bmHeight = height;
|
---|
147 | bm.bmWidthBytes = width;
|
---|
148 | bm.bmPlanes = 1;
|
---|
149 | bm.bmBitsPixel = 32;
|
---|
150 | bm.bmBits = bits;
|
---|
151 | hBitmap = CreateBitmapIndirect(&bm);
|
---|
152 |
|
---|
153 | /* Create a windows version of a drawable. */
|
---|
154 | twdPtr = Blt_Malloc(sizeof(TkWinBitmap));
|
---|
155 | assert(twdPtr);
|
---|
156 | twdPtr->type = TWD_BITMAP;
|
---|
157 | twdPtr->handle = hBitmap;
|
---|
158 | twdPtr->depth = depth;
|
---|
159 | twdPtr->colormap = DefaultColormap(display, DefaultScreen(display));
|
---|
160 | return (Pixmap)twdPtr;
|
---|
161 | }
|
---|
162 |
|
---|
163 | /*
|
---|
164 | *----------------------------------------------------------------------
|
---|
165 | *
|
---|
166 | * Blt_DrawableToColorImage --
|
---|
167 | *
|
---|
168 | * Takes a snapshot of an X drawable (pixmap or window) and
|
---|
169 | * converts it to a color image.
|
---|
170 | *
|
---|
171 | * Results:
|
---|
172 | * Returns a color image of the drawable. If an error occurred,
|
---|
173 | * NULL is returned.
|
---|
174 | *
|
---|
175 | *----------------------------------------------------------------------
|
---|
176 | */
|
---|
177 | Blt_ColorImage
|
---|
178 | Blt_DrawableToColorImage(
|
---|
179 | Tk_Window tkwin,
|
---|
180 | Drawable drawable,
|
---|
181 | int x, int y,
|
---|
182 | int width, int height, /* Dimension of the drawable. */
|
---|
183 | double inputGamma)
|
---|
184 | {
|
---|
185 | void *data;
|
---|
186 | BITMAPINFO info;
|
---|
187 | DIBSECTION ds;
|
---|
188 | HBITMAP hBitmap, oldBitmap;
|
---|
189 | HPALETTE hPalette;
|
---|
190 | HDC memDC;
|
---|
191 | unsigned char *srcArr;
|
---|
192 | register unsigned char *srcPtr;
|
---|
193 | HDC hDC;
|
---|
194 | TkWinDCState state;
|
---|
195 | register Pix32 *destPtr;
|
---|
196 | Blt_ColorImage image;
|
---|
197 | unsigned char lut[256];
|
---|
198 |
|
---|
199 | hDC = TkWinGetDrawableDC(Tk_Display(tkwin), drawable, &state);
|
---|
200 |
|
---|
201 | /* Create the intermediate drawing surface at window resolution. */
|
---|
202 | ZeroMemory(&info, sizeof(info));
|
---|
203 | info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
---|
204 | info.bmiHeader.biWidth = width;
|
---|
205 | info.bmiHeader.biHeight = height;
|
---|
206 | info.bmiHeader.biPlanes = 1;
|
---|
207 | info.bmiHeader.biBitCount = 32;
|
---|
208 | info.bmiHeader.biCompression = BI_RGB;
|
---|
209 | hBitmap = CreateDIBSection(hDC, &info, DIB_RGB_COLORS, &data, NULL, 0);
|
---|
210 | memDC = CreateCompatibleDC(hDC);
|
---|
211 | oldBitmap = SelectBitmap(memDC, hBitmap);
|
---|
212 |
|
---|
213 | hPalette = Blt_GetSystemPalette();
|
---|
214 | if (hPalette != NULL) {
|
---|
215 | SelectPalette(hDC, hPalette, FALSE);
|
---|
216 | RealizePalette(hDC);
|
---|
217 | SelectPalette(memDC, hPalette, FALSE);
|
---|
218 | RealizePalette(memDC);
|
---|
219 | }
|
---|
220 | image = NULL;
|
---|
221 | /* Copy the window contents to the memory surface. */
|
---|
222 | if (!BitBlt(memDC, 0, 0, width, height, hDC, x, y, SRCCOPY)) {
|
---|
223 | #ifdef notdef
|
---|
224 | PurifyPrintf("can't blit: %s\n", Blt_LastError());
|
---|
225 | #endif
|
---|
226 | goto done;
|
---|
227 | }
|
---|
228 | if (GetObject(hBitmap, sizeof(DIBSECTION), &ds) == 0) {
|
---|
229 | #ifdef notdef
|
---|
230 | PurifyPrintf("can't get object: %s\n", Blt_LastError());
|
---|
231 | #endif
|
---|
232 | goto done;
|
---|
233 | }
|
---|
234 | srcArr = (unsigned char *)ds.dsBm.bmBits;
|
---|
235 | image = Blt_CreateColorImage(width, height);
|
---|
236 | destPtr = Blt_ColorImageBits(image);
|
---|
237 |
|
---|
238 | {
|
---|
239 | register int i;
|
---|
240 | double value;
|
---|
241 |
|
---|
242 | for (i = 0; i < 256; i++) {
|
---|
243 | value = pow(i / 255.0, inputGamma) * 255.0 + 0.5;
|
---|
244 | lut[i] = (unsigned char)CLAMP(value);
|
---|
245 | }
|
---|
246 | }
|
---|
247 |
|
---|
248 | /*
|
---|
249 | * Copy the DIB RGB data into the color image. The DIB scanlines
|
---|
250 | * are stored bottom-to-top and the order of the RGB color
|
---|
251 | * components is BGR. Who says Win32 GDI programming isn't
|
---|
252 | * backwards?
|
---|
253 | */
|
---|
254 |
|
---|
255 | for (y = height - 1; y >= 0; y--) {
|
---|
256 | srcPtr = srcArr + (y * ds.dsBm.bmWidthBytes);
|
---|
257 | for (x = 0; x < width; x++) {
|
---|
258 | destPtr->Blue = lut[*srcPtr++];
|
---|
259 | destPtr->Green = lut[*srcPtr++];
|
---|
260 | destPtr->Red = lut[*srcPtr++];
|
---|
261 | destPtr->Alpha = (unsigned char)-1;
|
---|
262 | destPtr++;
|
---|
263 | srcPtr++;
|
---|
264 | }
|
---|
265 | }
|
---|
266 | done:
|
---|
267 | DeleteBitmap(SelectBitmap(memDC, oldBitmap));
|
---|
268 | DeleteDC(memDC);
|
---|
269 | TkWinReleaseDrawableDC(drawable, hDC, &state);
|
---|
270 | if (hPalette != NULL) {
|
---|
271 | DeletePalette(hPalette);
|
---|
272 | }
|
---|
273 | return image;
|
---|
274 | }
|
---|
275 |
|
---|
276 |
|
---|
277 | Pixmap
|
---|
278 | Blt_PhotoImageMask(
|
---|
279 | Tk_Window tkwin,
|
---|
280 | Tk_PhotoImageBlock src)
|
---|
281 | {
|
---|
282 | TkWinBitmap *twdPtr;
|
---|
283 | int offset, count;
|
---|
284 | register int x, y;
|
---|
285 | unsigned char *srcPtr;
|
---|
286 | int destBytesPerRow;
|
---|
287 | int destHeight;
|
---|
288 | unsigned char *destBits;
|
---|
289 |
|
---|
290 | destBytesPerRow = ((src.width + 31) & ~31) / 8;
|
---|
291 | destBits = Blt_Calloc(src.height, destBytesPerRow);
|
---|
292 | destHeight = src.height;
|
---|
293 |
|
---|
294 | offset = count = 0;
|
---|
295 | /* FIXME: figure out why this is so! */
|
---|
296 | for (y = src.height - 1; y >= 0; y--) {
|
---|
297 | srcPtr = src.pixelPtr + offset;
|
---|
298 | for (x = 0; x < src.width; x++) {
|
---|
299 | if (srcPtr[src.offset[3]] == 0x00) {
|
---|
300 | SetBit(x, y);
|
---|
301 | count++;
|
---|
302 | }
|
---|
303 | srcPtr += src.pixelSize;
|
---|
304 | }
|
---|
305 | offset += src.pitch;
|
---|
306 | }
|
---|
307 | if (count > 0) {
|
---|
308 | HBITMAP hBitmap;
|
---|
309 | BITMAP bm;
|
---|
310 |
|
---|
311 | bm.bmType = 0;
|
---|
312 | bm.bmWidth = src.width;
|
---|
313 | bm.bmHeight = src.height;
|
---|
314 | bm.bmWidthBytes = destBytesPerRow;
|
---|
315 | bm.bmPlanes = 1;
|
---|
316 | bm.bmBitsPixel = 1;
|
---|
317 | bm.bmBits = destBits;
|
---|
318 | hBitmap = CreateBitmapIndirect(&bm);
|
---|
319 |
|
---|
320 | twdPtr = Blt_Malloc(sizeof(TkWinBitmap));
|
---|
321 | assert(twdPtr);
|
---|
322 | twdPtr->type = TWD_BITMAP;
|
---|
323 | twdPtr->handle = hBitmap;
|
---|
324 | twdPtr->depth = 1;
|
---|
325 | if (Tk_WindowId(tkwin) == None) {
|
---|
326 | twdPtr->colormap = DefaultColormap(Tk_Display(tkwin),
|
---|
327 | DefaultScreen(Tk_Display(tkwin)));
|
---|
328 | } else {
|
---|
329 | twdPtr->colormap = Tk_Colormap(tkwin);
|
---|
330 | }
|
---|
331 | } else {
|
---|
332 | twdPtr = NULL;
|
---|
333 | }
|
---|
334 | if (destBits != NULL) {
|
---|
335 | Blt_Free(destBits);
|
---|
336 | }
|
---|
337 | return (Pixmap)twdPtr;
|
---|
338 | }
|
---|
339 |
|
---|
340 | Pixmap
|
---|
341 | Blt_ColorImageMask(
|
---|
342 | Tk_Window tkwin,
|
---|
343 | Blt_ColorImage image)
|
---|
344 | {
|
---|
345 | TkWinBitmap *twdPtr;
|
---|
346 | int count;
|
---|
347 | register int x, y;
|
---|
348 | Pix32 *srcPtr;
|
---|
349 | int destBytesPerRow;
|
---|
350 | int destWidth, destHeight;
|
---|
351 | unsigned char *destBits;
|
---|
352 |
|
---|
353 | destWidth = Blt_ColorImageWidth(image);
|
---|
354 | destHeight = Blt_ColorImageHeight(image);
|
---|
355 | destBytesPerRow = ((destWidth + 31) & ~31) / 8;
|
---|
356 | destBits = Blt_Calloc(destHeight, destBytesPerRow);
|
---|
357 | count = 0;
|
---|
358 | srcPtr = Blt_ColorImageBits(image);
|
---|
359 | for (y = 0; y < destHeight; y++) {
|
---|
360 | for (x = 0; x < destWidth; x++) {
|
---|
361 | if (srcPtr->Alpha == 0x00) {
|
---|
362 | SetBit(x, y);
|
---|
363 | count++;
|
---|
364 | }
|
---|
365 | srcPtr++;
|
---|
366 | }
|
---|
367 | }
|
---|
368 | if (count > 0) {
|
---|
369 | HBITMAP hBitmap;
|
---|
370 | BITMAP bm;
|
---|
371 |
|
---|
372 | bm.bmType = 0;
|
---|
373 | bm.bmWidth = Blt_ColorImageWidth(image);
|
---|
374 | bm.bmHeight = Blt_ColorImageHeight(image);
|
---|
375 | bm.bmWidthBytes = destBytesPerRow;
|
---|
376 | bm.bmPlanes = 1;
|
---|
377 | bm.bmBitsPixel = 1;
|
---|
378 | bm.bmBits = destBits;
|
---|
379 | hBitmap = CreateBitmapIndirect(&bm);
|
---|
380 |
|
---|
381 | twdPtr = Blt_Malloc(sizeof(TkWinBitmap));
|
---|
382 | assert(twdPtr);
|
---|
383 | twdPtr->type = TWD_BITMAP;
|
---|
384 | twdPtr->handle = hBitmap;
|
---|
385 | twdPtr->depth = 1;
|
---|
386 | if (Tk_WindowId(tkwin) == None) {
|
---|
387 | twdPtr->colormap = DefaultColormap(Tk_Display(tkwin),
|
---|
388 | DefaultScreen(Tk_Display(tkwin)));
|
---|
389 | } else {
|
---|
390 | twdPtr->colormap = Tk_Colormap(tkwin);
|
---|
391 | }
|
---|
392 | } else {
|
---|
393 | twdPtr = NULL;
|
---|
394 | }
|
---|
395 | if (destBits != NULL) {
|
---|
396 | Blt_Free(destBits);
|
---|
397 | }
|
---|
398 | return (Pixmap)twdPtr;
|
---|
399 | }
|
---|
400 |
|
---|
401 | /*
|
---|
402 | * -----------------------------------------------------------------
|
---|
403 | *
|
---|
404 | * Blt_RotateBitmap --
|
---|
405 | *
|
---|
406 | * Creates a new bitmap containing the rotated image of the given
|
---|
407 | * bitmap. We also need a special GC of depth 1, so that we do
|
---|
408 | * not need to rotate more than one plane of the bitmap.
|
---|
409 | *
|
---|
410 | * Note that under Windows, monochrome bitmaps are stored
|
---|
411 | * bottom-to-top. This is why the right angle rotations 0/180
|
---|
412 | * and 90/270 look reversed.
|
---|
413 | *
|
---|
414 | * Results:
|
---|
415 | * Returns a new bitmap containing the rotated image.
|
---|
416 | *
|
---|
417 | * -----------------------------------------------------------------
|
---|
418 | */
|
---|
419 | Pixmap
|
---|
420 | Blt_RotateBitmap(
|
---|
421 | Tk_Window tkwin,
|
---|
422 | Pixmap srcBitmap, /* Source bitmap to be rotated */
|
---|
423 | int srcWidth,
|
---|
424 | int srcHeight, /* Width and height of the source bitmap */
|
---|
425 | double theta, /* Right angle rotation to perform */
|
---|
426 | int *destWidthPtr,
|
---|
427 | int *destHeightPtr)
|
---|
428 | {
|
---|
429 | Display *display; /* X display */
|
---|
430 | Window root; /* Root window drawable */
|
---|
431 | Pixmap destBitmap;
|
---|
432 | double rotWidth, rotHeight;
|
---|
433 | HDC hDC;
|
---|
434 | TkWinDCState state;
|
---|
435 | register int x, y; /* Destination bitmap coordinates */
|
---|
436 | register int sx, sy; /* Source bitmap coordinates */
|
---|
437 | unsigned long pixel;
|
---|
438 | HBITMAP hBitmap;
|
---|
439 | int result;
|
---|
440 | struct MonoBitmap {
|
---|
441 | BITMAPINFOHEADER bi;
|
---|
442 | RGBQUAD colors[2];
|
---|
443 | } mb;
|
---|
444 | int srcBytesPerRow, destBytesPerRow;
|
---|
445 | int destWidth, destHeight;
|
---|
446 | unsigned char *srcBits, *destBits;
|
---|
447 |
|
---|
448 | display = Tk_Display(tkwin);
|
---|
449 | root = RootWindow(Tk_Display(tkwin), Tk_ScreenNumber(tkwin));
|
---|
450 | Blt_GetBoundingBox(srcWidth, srcHeight, theta, &rotWidth, &rotHeight,
|
---|
451 | (Point2D *)NULL);
|
---|
452 |
|
---|
453 | destWidth = (int)ceil(rotWidth);
|
---|
454 | destHeight = (int)ceil(rotHeight);
|
---|
455 | destBitmap = Tk_GetPixmap(display, root, destWidth, destHeight, 1);
|
---|
456 | if (destBitmap == None) {
|
---|
457 | return None; /* Can't allocate pixmap. */
|
---|
458 | }
|
---|
459 | srcBits = Blt_GetBitmapData(display, srcBitmap, srcWidth, srcHeight,
|
---|
460 | &srcBytesPerRow);
|
---|
461 | if (srcBits == NULL) {
|
---|
462 | OutputDebugString("Blt_GetBitmapData failed");
|
---|
463 | return None;
|
---|
464 | }
|
---|
465 | destBytesPerRow = ((destWidth + 31) & ~31) / 8;
|
---|
466 | destBits = Blt_Calloc(destHeight, destBytesPerRow);
|
---|
467 |
|
---|
468 | theta = FMOD(theta, 360.0);
|
---|
469 | if (FMOD(theta, (double)90.0) == 0.0) {
|
---|
470 | int quadrant;
|
---|
471 |
|
---|
472 | /* Handle right-angle rotations specially. */
|
---|
473 |
|
---|
474 | quadrant = (int)(theta / 90.0);
|
---|
475 | switch (quadrant) {
|
---|
476 | case ROTATE_270: /* 270 degrees */
|
---|
477 | for (y = 0; y < destHeight; y++) {
|
---|
478 | sx = y;
|
---|
479 | for (x = 0; x < destWidth; x++) {
|
---|
480 | sy = destWidth - x - 1;
|
---|
481 | pixel = GetBit(sx, sy);
|
---|
482 | if (pixel) {
|
---|
483 | SetBit(x, y);
|
---|
484 | }
|
---|
485 | }
|
---|
486 | }
|
---|
487 | break;
|
---|
488 |
|
---|
489 | case ROTATE_180: /* 180 degrees */
|
---|
490 | for (y = 0; y < destHeight; y++) {
|
---|
491 | sy = destHeight - y - 1;
|
---|
492 | for (x = 0; x < destWidth; x++) {
|
---|
493 | sx = destWidth - x - 1;
|
---|
494 | pixel = GetBit(sx, sy);
|
---|
495 | if (pixel) {
|
---|
496 | SetBit(x, y);
|
---|
497 | }
|
---|
498 | }
|
---|
499 | }
|
---|
500 | break;
|
---|
501 |
|
---|
502 | case ROTATE_90: /* 90 degrees */
|
---|
503 | for (y = 0; y < destHeight; y++) {
|
---|
504 | sx = destHeight - y - 1;
|
---|
505 | for (x = 0; x < destWidth; x++) {
|
---|
506 | sy = x;
|
---|
507 | pixel = GetBit(sx, sy);
|
---|
508 | if (pixel) {
|
---|
509 | SetBit(x, y);
|
---|
510 | }
|
---|
511 | }
|
---|
512 | }
|
---|
513 | break;
|
---|
514 |
|
---|
515 | case ROTATE_0: /* 0 degrees */
|
---|
516 | for (y = 0; y < destHeight; y++) {
|
---|
517 | for (x = 0; x < destWidth; x++) {
|
---|
518 | pixel = GetBit(x, y);
|
---|
519 | if (pixel) {
|
---|
520 | SetBit(x, y);
|
---|
521 | }
|
---|
522 | }
|
---|
523 | }
|
---|
524 | break;
|
---|
525 |
|
---|
526 | default:
|
---|
527 | /* The calling routine should never let this happen. */
|
---|
528 | break;
|
---|
529 | }
|
---|
530 | } else {
|
---|
531 | double radians, sinTheta, cosTheta;
|
---|
532 | double srcCX, srcCY; /* Center of source rectangle */
|
---|
533 | double destCX, destCY; /* Center of destination rectangle */
|
---|
534 | double tx, ty;
|
---|
535 | double rx, ry; /* Angle of rotation for x and y coordinates */
|
---|
536 |
|
---|
537 | radians = (theta / 180.0) * M_PI;
|
---|
538 | sinTheta = sin(radians), cosTheta = cos(radians);
|
---|
539 |
|
---|
540 | /*
|
---|
541 | * Coordinates of the centers of the source and destination rectangles
|
---|
542 | */
|
---|
543 | srcCX = srcWidth * 0.5;
|
---|
544 | srcCY = srcHeight * 0.5;
|
---|
545 | destCX = destWidth * 0.5;
|
---|
546 | destCY = destHeight * 0.5;
|
---|
547 |
|
---|
548 | /* Rotate each pixel of dest image, placing results in source image */
|
---|
549 |
|
---|
550 | for (y = 0; y < destHeight; y++) {
|
---|
551 | ty = y - destCY;
|
---|
552 | for (x = 0; x < destWidth; x++) {
|
---|
553 |
|
---|
554 | /* Translate origin to center of destination image */
|
---|
555 | tx = x - destCX;
|
---|
556 |
|
---|
557 | /* Rotate the coordinates about the origin */
|
---|
558 | rx = (tx * cosTheta) - (ty * sinTheta);
|
---|
559 | ry = (tx * sinTheta) + (ty * cosTheta);
|
---|
560 |
|
---|
561 | /* Translate back to the center of the source image */
|
---|
562 | rx += srcCX;
|
---|
563 | ry += srcCY;
|
---|
564 |
|
---|
565 | sx = ROUND(rx);
|
---|
566 | sy = ROUND(ry);
|
---|
567 |
|
---|
568 | /*
|
---|
569 | * Verify the coordinates, since the destination image can be
|
---|
570 | * bigger than the source
|
---|
571 | */
|
---|
572 |
|
---|
573 | if ((sx >= srcWidth) || (sx < 0) || (sy >= srcHeight) ||
|
---|
574 | (sy < 0)) {
|
---|
575 | continue;
|
---|
576 | }
|
---|
577 | pixel = GetBit(sx, sy);
|
---|
578 | if (pixel) {
|
---|
579 | SetBit(x, y);
|
---|
580 | }
|
---|
581 | }
|
---|
582 | }
|
---|
583 | }
|
---|
584 | hBitmap = ((TkWinDrawable *)destBitmap)->bitmap.handle;
|
---|
585 | ZeroMemory(&mb, sizeof(mb));
|
---|
586 | mb.bi.biSize = sizeof(BITMAPINFOHEADER);
|
---|
587 | mb.bi.biPlanes = 1;
|
---|
588 | mb.bi.biBitCount = 1;
|
---|
589 | mb.bi.biCompression = BI_RGB;
|
---|
590 | mb.bi.biWidth = destWidth;
|
---|
591 | mb.bi.biHeight = destHeight;
|
---|
592 | mb.bi.biSizeImage = destBytesPerRow * destHeight;
|
---|
593 | mb.colors[0].rgbBlue = mb.colors[0].rgbRed = mb.colors[0].rgbGreen = 0x0;
|
---|
594 | mb.colors[1].rgbBlue = mb.colors[1].rgbRed = mb.colors[1].rgbGreen = 0xFF;
|
---|
595 | hDC = TkWinGetDrawableDC(display, destBitmap, &state);
|
---|
596 | result = SetDIBits(hDC, hBitmap, 0, destHeight, (LPVOID)destBits,
|
---|
597 | (BITMAPINFO *)&mb, DIB_RGB_COLORS);
|
---|
598 | TkWinReleaseDrawableDC(destBitmap, hDC, &state);
|
---|
599 | if (!result) {
|
---|
600 | #if WINDEBUG
|
---|
601 | PurifyPrintf("can't setDIBits: %s\n", Blt_LastError());
|
---|
602 | #endif
|
---|
603 | destBitmap = None;
|
---|
604 | }
|
---|
605 | if (destBits != NULL) {
|
---|
606 | Blt_Free(destBits);
|
---|
607 | }
|
---|
608 | if (srcBits != NULL) {
|
---|
609 | Blt_Free(srcBits);
|
---|
610 | }
|
---|
611 |
|
---|
612 | *destWidthPtr = destWidth;
|
---|
613 | *destHeightPtr = destHeight;
|
---|
614 | return destBitmap;
|
---|
615 | }
|
---|
616 |
|
---|
617 | /*
|
---|
618 | * -----------------------------------------------------------------------
|
---|
619 | *
|
---|
620 | * Blt_ScaleBitmap --
|
---|
621 | *
|
---|
622 | * Creates a new scaled bitmap from another bitmap.
|
---|
623 | *
|
---|
624 | * Results:
|
---|
625 | * The new scaled bitmap is returned.
|
---|
626 | *
|
---|
627 | * Side Effects:
|
---|
628 | * A new pixmap is allocated. The caller must release this.
|
---|
629 | *
|
---|
630 | * -----------------------------------------------------------------------
|
---|
631 | */
|
---|
632 | Pixmap
|
---|
633 | Blt_ScaleBitmap(
|
---|
634 | Tk_Window tkwin,
|
---|
635 | Pixmap srcBitmap,
|
---|
636 | int srcWidth,
|
---|
637 | int srcHeight,
|
---|
638 | int destWidth,
|
---|
639 | int destHeight)
|
---|
640 | {
|
---|
641 | TkWinDCState srcState, destState;
|
---|
642 | HDC src, dest;
|
---|
643 | Pixmap destBitmap;
|
---|
644 | Window root;
|
---|
645 | Display *display;
|
---|
646 |
|
---|
647 | /* Create a new bitmap the size of the region and clear it */
|
---|
648 |
|
---|
649 | display = Tk_Display(tkwin);
|
---|
650 | root = RootWindow(Tk_Display(tkwin), Tk_ScreenNumber(tkwin));
|
---|
651 | destBitmap = Tk_GetPixmap(display, root, destWidth, destHeight, 1);
|
---|
652 | if (destBitmap == None) {
|
---|
653 | return None;
|
---|
654 | }
|
---|
655 | src = TkWinGetDrawableDC(display, srcBitmap, &srcState);
|
---|
656 | dest = TkWinGetDrawableDC(display, destBitmap, &destState);
|
---|
657 |
|
---|
658 | StretchBlt(dest, 0, 0, destWidth, destHeight, src, 0, 0,
|
---|
659 | srcWidth, srcHeight, SRCCOPY);
|
---|
660 |
|
---|
661 | TkWinReleaseDrawableDC(srcBitmap, src, &srcState);
|
---|
662 | TkWinReleaseDrawableDC(destBitmap, dest, &destState);
|
---|
663 | return destBitmap;
|
---|
664 | }
|
---|
665 |
|
---|
666 | /*
|
---|
667 | * -----------------------------------------------------------------------
|
---|
668 | *
|
---|
669 | * Blt_ScaleRotateBitmapRegion --
|
---|
670 | *
|
---|
671 | * Creates a scaled and rotated bitmap from a given bitmap. The
|
---|
672 | * caller also provides (offsets and dimensions) the region of
|
---|
673 | * interest in the destination bitmap. This saves having to
|
---|
674 | * process the entire destination bitmap is only part of it is
|
---|
675 | * showing in the viewport.
|
---|
676 | *
|
---|
677 | * This uses a simple rotation/scaling of each pixel in the
|
---|
678 | * destination image. For each pixel, the corresponding
|
---|
679 | * pixel in the source bitmap is used. This means that
|
---|
680 | * destination coordinates are first scaled to the size of
|
---|
681 | * the rotated source bitmap. These coordinates are then
|
---|
682 | * rotated back to their original orientation in the source.
|
---|
683 | *
|
---|
684 | * Results:
|
---|
685 | * The new rotated and scaled bitmap is returned.
|
---|
686 | *
|
---|
687 | * Side Effects:
|
---|
688 | * A new pixmap is allocated. The caller must release this.
|
---|
689 | *
|
---|
690 | * -----------------------------------------------------------------------
|
---|
691 | */
|
---|
692 | Pixmap
|
---|
693 | Blt_ScaleRotateBitmapRegion(
|
---|
694 | Tk_Window tkwin,
|
---|
695 | Pixmap srcBitmap, /* Source bitmap. */
|
---|
696 | unsigned int srcWidth,
|
---|
697 | unsigned int srcHeight, /* Size of source bitmap */
|
---|
698 | int regionX,
|
---|
699 | int regionY, /* Offset of region in virtual
|
---|
700 | * destination bitmap. */
|
---|
701 | unsigned int regionWidth,
|
---|
702 | unsigned int regionHeight, /* Desire size of bitmap region. */
|
---|
703 | unsigned int virtWidth,
|
---|
704 | unsigned int virtHeight, /* Virtual size of destination bitmap. */
|
---|
705 | double theta) /* Angle to rotate bitmap. */
|
---|
706 | {
|
---|
707 | Display *display; /* X display */
|
---|
708 | HBITMAP hBitmap;
|
---|
709 | HDC hDC;
|
---|
710 | Pixmap destBitmap;
|
---|
711 | TkWinDCState state;
|
---|
712 | Window root; /* Root window drawable */
|
---|
713 | double rotWidth, rotHeight;
|
---|
714 | double xScale, yScale;
|
---|
715 | int srcBytesPerRow, destBytesPerRow;
|
---|
716 | int destHeight;
|
---|
717 | int result;
|
---|
718 | register int sx, sy; /* Source bitmap coordinates */
|
---|
719 | register int x, y; /* Destination bitmap coordinates */
|
---|
720 | unsigned char *srcBits, *destBits;
|
---|
721 | unsigned long pixel;
|
---|
722 | struct MonoBitmap {
|
---|
723 | BITMAPINFOHEADER bi;
|
---|
724 | RGBQUAD colors[2];
|
---|
725 | } mb;
|
---|
726 |
|
---|
727 | display = Tk_Display(tkwin);
|
---|
728 | root = RootWindow(Tk_Display(tkwin), Tk_ScreenNumber(tkwin));
|
---|
729 |
|
---|
730 | /* Create a bitmap and image big enough to contain the rotated text */
|
---|
731 | destBitmap = Tk_GetPixmap(display, root, regionWidth, regionHeight, 1);
|
---|
732 | if (destBitmap == None) {
|
---|
733 | return None; /* Can't allocate pixmap. */
|
---|
734 | }
|
---|
735 | srcBits = Blt_GetBitmapData(display, srcBitmap, srcWidth, srcHeight,
|
---|
736 | &srcBytesPerRow);
|
---|
737 | if (srcBits == NULL) {
|
---|
738 | OutputDebugString("Blt_GetBitmapData failed");
|
---|
739 | return None;
|
---|
740 | }
|
---|
741 | destBytesPerRow = ((regionWidth + 31) & ~31) / 8;
|
---|
742 | destBits = Blt_Calloc(regionHeight, destBytesPerRow);
|
---|
743 | destHeight = regionHeight;
|
---|
744 |
|
---|
745 | theta = FMOD(theta, 360.0);
|
---|
746 | Blt_GetBoundingBox(srcWidth, srcHeight, theta, &rotWidth, &rotHeight,
|
---|
747 | (Point2D *)NULL);
|
---|
748 | xScale = rotWidth / (double)virtWidth;
|
---|
749 | yScale = rotHeight / (double)virtHeight;
|
---|
750 |
|
---|
751 | if (FMOD(theta, (double)90.0) == 0.0) {
|
---|
752 | int quadrant;
|
---|
753 |
|
---|
754 | /* Handle right-angle rotations specifically */
|
---|
755 |
|
---|
756 | quadrant = (int)(theta / 90.0);
|
---|
757 | switch (quadrant) {
|
---|
758 | case ROTATE_270: /* 270 degrees */
|
---|
759 | for (y = 0; y < (int)regionHeight; y++) {
|
---|
760 | sx = (int)(yScale * (double)(y+regionY));
|
---|
761 | for (x = 0; x < (int)regionWidth; x++) {
|
---|
762 | sy = (int)(xScale *(double)(virtWidth - (x+regionX) - 1));
|
---|
763 | pixel = GetBit(sx, sy);
|
---|
764 | if (pixel) {
|
---|
765 | SetBit(x, y);
|
---|
766 | }
|
---|
767 | }
|
---|
768 | }
|
---|
769 | break;
|
---|
770 |
|
---|
771 | case ROTATE_180: /* 180 degrees */
|
---|
772 | for (y = 0; y < (int)regionHeight; y++) {
|
---|
773 | sy = (int)(yScale * (double)(virtHeight - (y + regionY) - 1));
|
---|
774 | for (x = 0; x < (int)regionWidth; x++) {
|
---|
775 | sx = (int)(xScale *(double)(virtWidth - (x+regionX) - 1));
|
---|
776 | pixel = GetBit(sx, sy);
|
---|
777 | if (pixel) {
|
---|
778 | SetBit(x, y);
|
---|
779 | }
|
---|
780 | }
|
---|
781 | }
|
---|
782 | break;
|
---|
783 |
|
---|
784 | case ROTATE_90: /* 90 degrees */
|
---|
785 | for (y = 0; y < (int)regionHeight; y++) {
|
---|
786 | sx = (int)(yScale * (double)(virtHeight - (y + regionY) - 1));
|
---|
787 | for (x = 0; x < (int)regionWidth; x++) {
|
---|
788 | sy = (int)(xScale * (double)(x + regionX));
|
---|
789 | pixel = GetBit(sx, sy);
|
---|
790 | if (pixel) {
|
---|
791 | SetBit(x, y);
|
---|
792 | }
|
---|
793 | }
|
---|
794 | }
|
---|
795 | break;
|
---|
796 |
|
---|
797 | case ROTATE_0: /* 0 degrees */
|
---|
798 | for (y = 0; y < (int)regionHeight; y++) {
|
---|
799 | sy = (int)(yScale * (double)(y + regionY));
|
---|
800 | for (x = 0; x < (int)regionWidth; x++) {
|
---|
801 | sx = (int)(xScale * (double)(x + regionX));
|
---|
802 | pixel = GetBit(sx, sy);
|
---|
803 | if (pixel) {
|
---|
804 | SetBit(x, y);
|
---|
805 | }
|
---|
806 | }
|
---|
807 | }
|
---|
808 | break;
|
---|
809 |
|
---|
810 | default:
|
---|
811 | /* The calling routine should never let this happen. */
|
---|
812 | break;
|
---|
813 | }
|
---|
814 | } else {
|
---|
815 | double radians, sinTheta, cosTheta;
|
---|
816 | double scx, scy; /* Offset from the center of the
|
---|
817 | * source rectangle. */
|
---|
818 | double rcx, rcy; /* Offset to the center of the
|
---|
819 | * rotated rectangle. */
|
---|
820 | double tx, ty; /* Translated coordinates from center */
|
---|
821 | double rx, ry; /* Angle of rotation for x and y coordinates */
|
---|
822 |
|
---|
823 | radians = (theta / 180.0) * M_PI;
|
---|
824 | sinTheta = sin(radians), cosTheta = cos(radians);
|
---|
825 |
|
---|
826 | /*
|
---|
827 | * Coordinates of the centers of the source and destination rectangles
|
---|
828 | */
|
---|
829 | scx = srcWidth * 0.5;
|
---|
830 | scy = srcHeight * 0.5;
|
---|
831 | rcx = rotWidth * 0.5;
|
---|
832 | rcy = rotHeight * 0.5;
|
---|
833 |
|
---|
834 | /* For each pixel of the destination image, transform back to the
|
---|
835 | * associated pixel in the source image. */
|
---|
836 |
|
---|
837 | for (y = 0; y < (int)regionHeight; y++) {
|
---|
838 | ty = (yScale * (double)(y + regionY)) - rcy;
|
---|
839 | for (x = 0; x < (int)regionWidth; x++) {
|
---|
840 |
|
---|
841 | /* Translate origin to center of destination image. */
|
---|
842 | tx = (xScale * (double)(x + regionX)) - rcx;
|
---|
843 |
|
---|
844 | /* Rotate the coordinates about the origin. */
|
---|
845 | rx = (tx * cosTheta) - (ty * sinTheta);
|
---|
846 | ry = (tx * sinTheta) + (ty * cosTheta);
|
---|
847 |
|
---|
848 | /* Translate back to the center of the source image. */
|
---|
849 | rx += scx;
|
---|
850 | ry += scy;
|
---|
851 |
|
---|
852 | sx = ROUND(rx);
|
---|
853 | sy = ROUND(ry);
|
---|
854 |
|
---|
855 | /*
|
---|
856 | * Verify the coordinates, since the destination image can be
|
---|
857 | * bigger than the source.
|
---|
858 | */
|
---|
859 |
|
---|
860 | if ((sx >= (int)srcWidth) || (sx < 0) ||
|
---|
861 | (sy >= (int)srcHeight) || (sy < 0)) {
|
---|
862 | continue;
|
---|
863 | }
|
---|
864 | pixel = GetBit(sx, sy);
|
---|
865 | if (pixel) {
|
---|
866 | SetBit(x, y);
|
---|
867 | }
|
---|
868 | }
|
---|
869 | }
|
---|
870 | }
|
---|
871 | /* Write the rotated image into the destination bitmap. */
|
---|
872 | hBitmap = ((TkWinDrawable *)destBitmap)->bitmap.handle;
|
---|
873 | ZeroMemory(&mb, sizeof(mb));
|
---|
874 | mb.bi.biSize = sizeof(BITMAPINFOHEADER);
|
---|
875 | mb.bi.biPlanes = 1;
|
---|
876 | mb.bi.biBitCount = 1;
|
---|
877 | mb.bi.biCompression = BI_RGB;
|
---|
878 | mb.bi.biWidth = regionWidth;
|
---|
879 | mb.bi.biHeight = regionHeight;
|
---|
880 | mb.bi.biSizeImage = destBytesPerRow * regionHeight;
|
---|
881 | mb.colors[0].rgbBlue = mb.colors[0].rgbRed = mb.colors[0].rgbGreen = 0x0;
|
---|
882 | mb.colors[1].rgbBlue = mb.colors[1].rgbRed = mb.colors[1].rgbGreen = 0xFF;
|
---|
883 | hDC = TkWinGetDrawableDC(display, destBitmap, &state);
|
---|
884 | result = SetDIBits(hDC, hBitmap, 0, regionHeight, (LPVOID)destBits,
|
---|
885 | (BITMAPINFO *)&mb, DIB_RGB_COLORS);
|
---|
886 | TkWinReleaseDrawableDC(destBitmap, hDC, &state);
|
---|
887 | if (!result) {
|
---|
888 | #if WINDEBUG
|
---|
889 | PurifyPrintf("can't setDIBits: %s\n", Blt_LastError());
|
---|
890 | #endif
|
---|
891 | destBitmap = None;
|
---|
892 | }
|
---|
893 | if (destBits != NULL) {
|
---|
894 | Blt_Free(destBits);
|
---|
895 | }
|
---|
896 | if (srcBits != NULL) {
|
---|
897 | Blt_Free(srcBits);
|
---|
898 | }
|
---|
899 | return destBitmap;
|
---|
900 | }
|
---|
901 |
|
---|
902 | #ifdef notdef
|
---|
903 | /*
|
---|
904 | *----------------------------------------------------------------------
|
---|
905 | *
|
---|
906 | * Blt_BlendColorImage --
|
---|
907 | *
|
---|
908 | * Takes a snapshot of an X drawable (pixmap or window) and
|
---|
909 | * converts it to a color image.
|
---|
910 | *
|
---|
911 | * Results:
|
---|
912 | * Returns a color image of the drawable. If an error occurred,
|
---|
913 | * NULL is returned.
|
---|
914 | *
|
---|
915 | *----------------------------------------------------------------------
|
---|
916 | */
|
---|
917 | void
|
---|
918 | Blt_BlendColorImage(
|
---|
919 | Tk_Window tkwin,
|
---|
920 | Drawable drawable,
|
---|
921 | int width, int height, /* Dimension of the drawable. */
|
---|
922 | Region2D *regionPtr) /* Region to be snapped. */
|
---|
923 | {
|
---|
924 | void *data;
|
---|
925 | BITMAPINFO info;
|
---|
926 | DIBSECTION ds;
|
---|
927 | HBITMAP hBitmap, oldBitmap;
|
---|
928 | HPALETTE hPalette;
|
---|
929 | HDC memDC;
|
---|
930 | unsigned char *srcArr;
|
---|
931 | register unsigned char *srcPtr;
|
---|
932 | HDC hDC;
|
---|
933 | TkWinDCState state;
|
---|
934 | register Pix32 *destPtr;
|
---|
935 | Blt_ColorImage image;
|
---|
936 | register int x, y;
|
---|
937 |
|
---|
938 | if (regionPtr == NULL) {
|
---|
939 | regionPtr = Blt_SetRegion(0, 0, ColorImageWidth(image),
|
---|
940 | ColorImageHeight(image), ®ion);
|
---|
941 | }
|
---|
942 | if (regionPtr->left < 0) {
|
---|
943 | regionPtr->left = 0;
|
---|
944 | }
|
---|
945 | if (regionPtr->right >= destWidth) {
|
---|
946 | regionPtr->right = destWidth - 1;
|
---|
947 | }
|
---|
948 | if (regionPtr->top < 0) {
|
---|
949 | regionPtr->top = 0;
|
---|
950 | }
|
---|
951 | if (regionPtr->bottom >= destHeight) {
|
---|
952 | regionPtr->bottom = destHeight - 1;
|
---|
953 | }
|
---|
954 | width = RegionWidth(regionPtr);
|
---|
955 | height = RegionHeight(regionPtr);
|
---|
956 |
|
---|
957 | hDC = TkWinGetDrawableDC(display, drawable, &state);
|
---|
958 |
|
---|
959 | /* Create the intermediate drawing surface at window resolution. */
|
---|
960 | ZeroMemory(&info, sizeof(info));
|
---|
961 | info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
---|
962 | info.bmiHeader.biWidth = width;
|
---|
963 | info.bmiHeader.biHeight = height;
|
---|
964 | info.bmiHeader.biPlanes = 1;
|
---|
965 | info.bmiHeader.biBitCount = 32;
|
---|
966 | info.bmiHeader.biCompression = BI_RGB;
|
---|
967 | hBitmap = CreateDIBSection(hDC, &info, DIB_RGB_COLORS, &data, NULL, 0);
|
---|
968 | memDC = CreateCompatibleDC(hDC);
|
---|
969 | oldBitmap = SelectBitmap(memDC, hBitmap);
|
---|
970 |
|
---|
971 | hPalette = Blt_GetSystemPalette();
|
---|
972 | if (hPalette != NULL) {
|
---|
973 | SelectPalette(hDC, hPalette, FALSE);
|
---|
974 | RealizePalette(hDC);
|
---|
975 | SelectPalette(memDC, hPalette, FALSE);
|
---|
976 | RealizePalette(memDC);
|
---|
977 | }
|
---|
978 | image = NULL;
|
---|
979 | /* Copy the window contents to the memory surface. */
|
---|
980 | if (!BitBlt(memDC, 0, 0, width, height, hDC, regionPtr->left,
|
---|
981 | regionPtr->top, SRCCOPY)) {
|
---|
982 | #ifdef notdef
|
---|
983 | PurifyPrintf("can't blit: %s\n", Blt_LastError());
|
---|
984 | #endif
|
---|
985 | goto done;
|
---|
986 | }
|
---|
987 | if (GetObject(hBitmap, sizeof(DIBSECTION), &ds) == 0) {
|
---|
988 | #ifdef notdef
|
---|
989 | PurifyPrintf("can't get object: %s\n", Blt_LastError());
|
---|
990 | #endif
|
---|
991 | goto done;
|
---|
992 | }
|
---|
993 | srcArr = (unsigned char *)ds.dsBm.bmBits;
|
---|
994 | image = Blt_CreateColorImage(width, height);
|
---|
995 | destPtr = Blt_ColorImageBits(image);
|
---|
996 |
|
---|
997 | /*
|
---|
998 | * Copy the DIB RGB data into the color image. The DIB scanlines
|
---|
999 | * are stored bottom-to-top and the order of the RGBA color
|
---|
1000 | * components is BGRA. Who says Win32 GDI programming isn't
|
---|
1001 | * backwards?
|
---|
1002 | */
|
---|
1003 | for (y = height - 1; y >= 0; y--) {
|
---|
1004 | srcPtr = srcArr + (y * ds.dsBm.bmWidthBytes);
|
---|
1005 | for (x = 0; x < width; x++) {
|
---|
1006 | if (destPtr->Alpha > 0) {
|
---|
1007 | /* Blend colorimage with background. */
|
---|
1008 | destPtr->Blue = *srcPtr++;
|
---|
1009 | destPtr->Green = *srcPtr++;
|
---|
1010 | destPtr->Red = *srcPtr++;
|
---|
1011 | destPtr->Alpha = (unsigned char)-1;
|
---|
1012 | srcPtr++;
|
---|
1013 | }
|
---|
1014 | destPtr++;
|
---|
1015 | }
|
---|
1016 | }
|
---|
1017 | done:
|
---|
1018 | DeleteBitmap(SelectBitmap(memDC, oldBitmap));
|
---|
1019 | DeleteDC(memDC);
|
---|
1020 | TkWinReleaseDrawableDC(drawable, hDC, &state);
|
---|
1021 | if (hPalette != NULL) {
|
---|
1022 | DeletePalette(hPalette);
|
---|
1023 | }
|
---|
1024 | return image;
|
---|
1025 | }
|
---|
1026 | #endif
|
---|
1027 |
|
---|
1028 | #ifdef HAVE_IJL_H
|
---|
1029 |
|
---|
1030 | #include <ijl.h>
|
---|
1031 |
|
---|
1032 | Blt_ColorImage
|
---|
1033 | Blt_JPEGToColorImage(interp, fileName)
|
---|
1034 | Tcl_Interp *interp;
|
---|
1035 | char *fileName;
|
---|
1036 | {
|
---|
1037 | JPEG_CORE_PROPERTIES jpgProps;
|
---|
1038 | Blt_ColorImage image;
|
---|
1039 |
|
---|
1040 | ZeroMemory(&jpgProps, sizeof(JPEG_CORE_PROPERTIES));
|
---|
1041 | if(ijlInit(&jpgProps) != IJL_OK) {
|
---|
1042 | Tcl_AppendResult(interp, "can't initialize Intel JPEG library",
|
---|
1043 | (char *)NULL);
|
---|
1044 | return NULL;
|
---|
1045 | }
|
---|
1046 | jpgProps.JPGFile = fileName;
|
---|
1047 | if (ijlRead(&jpgProps, IJL_JFILE_READPARAMS) != IJL_OK) {
|
---|
1048 | Tcl_AppendResult(interp, "can't read JPEG file header from \"",
|
---|
1049 | fileName, "\" file.", (char *)NULL);
|
---|
1050 | goto error;
|
---|
1051 | }
|
---|
1052 |
|
---|
1053 | // !dudnik: to fix bug case 584680, [OT:287A305B]
|
---|
1054 | // Set the JPG color space ... this will always be
|
---|
1055 | // somewhat of an educated guess at best because JPEG
|
---|
1056 | // is "color blind" (i.e., nothing in the bit stream
|
---|
1057 | // tells you what color space the data was encoded from).
|
---|
1058 | // However, in this example we assume that we are
|
---|
1059 | // reading JFIF files which means that 3 channel images
|
---|
1060 | // are in the YCbCr color space and 1 channel images are
|
---|
1061 | // in the Y color space.
|
---|
1062 | switch(jpgProps.JPGChannels) {
|
---|
1063 | case 1:
|
---|
1064 | jpgProps.JPGColor = IJL_G;
|
---|
1065 | jpgProps.DIBChannels = 4;
|
---|
1066 | jpgProps.DIBColor = IJL_RGBA_FPX;
|
---|
1067 | break;
|
---|
1068 |
|
---|
1069 | case 3:
|
---|
1070 | jpgProps.JPGColor = IJL_YCBCR;
|
---|
1071 | jpgProps.DIBChannels = 4;
|
---|
1072 | jpgProps.DIBColor = IJL_RGBA_FPX;
|
---|
1073 | break;
|
---|
1074 |
|
---|
1075 | case 4:
|
---|
1076 | jpgProps.JPGColor = IJL_YCBCRA_FPX;
|
---|
1077 | jpgProps.DIBChannels = 4;
|
---|
1078 | jpgProps.DIBColor = IJL_RGBA_FPX;
|
---|
1079 | break;
|
---|
1080 |
|
---|
1081 | default:
|
---|
1082 | /* This catches everything else, but no color twist will be
|
---|
1083 | performed by the IJL. */
|
---|
1084 | jpgProps.DIBColor = (IJL_COLOR)IJL_OTHER;
|
---|
1085 | jpgProps.JPGColor = (IJL_COLOR)IJL_OTHER;
|
---|
1086 | jpgProps.DIBChannels = jpgProps.JPGChannels;
|
---|
1087 | break;
|
---|
1088 | }
|
---|
1089 |
|
---|
1090 | jpgProps.DIBWidth = jpgProps.JPGWidth;
|
---|
1091 | jpgProps.DIBHeight = jpgProps.JPGHeight;
|
---|
1092 | jpgProps.DIBPadBytes = IJL_DIB_PAD_BYTES(jpgProps.DIBWidth,
|
---|
1093 | jpgProps.DIBChannels);
|
---|
1094 |
|
---|
1095 | image = Blt_CreateColorImage(jpgProps.JPGWidth, jpgProps.JPGHeight);
|
---|
1096 |
|
---|
1097 | jpgProps.DIBBytes = (BYTE *)Blt_ColorImageBits(image);
|
---|
1098 | if (ijlRead(&jpgProps, IJL_JFILE_READWHOLEIMAGE) != IJL_OK) {
|
---|
1099 | Tcl_AppendResult(interp, "can't read image data from \"", fileName,
|
---|
1100 | "\"", (char *)NULL);
|
---|
1101 | goto error;
|
---|
1102 | }
|
---|
1103 | if (ijlFree(&jpgProps) != IJL_OK) {
|
---|
1104 | fprintf(stderr, "can't free Intel(R) JPEG library\n");
|
---|
1105 | }
|
---|
1106 | return image;
|
---|
1107 |
|
---|
1108 | error:
|
---|
1109 | ijlFree(&jpgProps);
|
---|
1110 | if (image != NULL) {
|
---|
1111 | Blt_FreeColorImage(image);
|
---|
1112 | }
|
---|
1113 | ijlFree(&jpgProps);
|
---|
1114 | return NULL;
|
---|
1115 | }
|
---|
1116 |
|
---|
1117 | #else
|
---|
1118 |
|
---|
1119 | #ifdef HAVE_JPEGLIB_H
|
---|
1120 |
|
---|
1121 | #undef HAVE_STDLIB_H
|
---|
1122 | #undef EXTERN
|
---|
1123 | #ifdef WIN32
|
---|
1124 | #define XMD_H 1
|
---|
1125 | #endif
|
---|
1126 | #include "jpeglib.h"
|
---|
1127 | #include <setjmp.h>
|
---|
1128 |
|
---|
1129 | typedef struct {
|
---|
1130 | struct jpeg_error_mgr pub; /* "public" fields */
|
---|
1131 | jmp_buf jmpBuf;
|
---|
1132 | Tcl_DString dString;
|
---|
1133 | } ReaderHandler;
|
---|
1134 |
|
---|
1135 | static void ErrorProc _ANSI_ARGS_((j_common_ptr jpegInfo));
|
---|
1136 | static void MessageProc _ANSI_ARGS_((j_common_ptr jpegInfo));
|
---|
1137 |
|
---|
1138 | /*
|
---|
1139 | * Here's the routine that will replace the standard error_exit method:
|
---|
1140 | */
|
---|
1141 |
|
---|
1142 | static void
|
---|
1143 | ErrorProc(jpgPtr)
|
---|
1144 | j_common_ptr jpgPtr;
|
---|
1145 | {
|
---|
1146 | ReaderHandler *handlerPtr = (ReaderHandler *)jpgPtr->err;
|
---|
1147 |
|
---|
1148 | (*handlerPtr->pub.output_message) (jpgPtr);
|
---|
1149 | longjmp(handlerPtr->jmpBuf, 1);
|
---|
1150 | }
|
---|
1151 |
|
---|
1152 | static void
|
---|
1153 | MessageProc(jpgPtr)
|
---|
1154 | j_common_ptr jpgPtr;
|
---|
1155 | {
|
---|
1156 | ReaderHandler *handlerPtr = (ReaderHandler *)jpgPtr->err;
|
---|
1157 | char buffer[JMSG_LENGTH_MAX];
|
---|
1158 |
|
---|
1159 | /* Create the message and append it into the dynamic string. */
|
---|
1160 | (*handlerPtr->pub.format_message) (jpgPtr, buffer);
|
---|
1161 | Tcl_DStringAppend(&(handlerPtr->dString), " ", -1);
|
---|
1162 | Tcl_DStringAppend(&(handlerPtr->dString), buffer, -1);
|
---|
1163 | }
|
---|
1164 |
|
---|
1165 | /*
|
---|
1166 | *----------------------------------------------------------------------
|
---|
1167 | *
|
---|
1168 | * Blt_JPEGToColorImage --
|
---|
1169 | *
|
---|
1170 | * Reads a JPEG file and converts it into a color image.
|
---|
1171 | *
|
---|
1172 | * Results:
|
---|
1173 | * The color image is returned. If an error occured, such
|
---|
1174 | * as the designated file could not be opened, NULL is returned.
|
---|
1175 | *
|
---|
1176 | *----------------------------------------------------------------------
|
---|
1177 | */
|
---|
1178 | Blt_ColorImage
|
---|
1179 | Blt_JPEGToColorImage(interp, fileName)
|
---|
1180 | Tcl_Interp *interp;
|
---|
1181 | char *fileName;
|
---|
1182 | {
|
---|
1183 | struct jpeg_decompress_struct jpg;
|
---|
1184 | Blt_ColorImage image;
|
---|
1185 | unsigned int imageWidth, imageHeight;
|
---|
1186 | register Pix32 *destPtr;
|
---|
1187 | ReaderHandler handler;
|
---|
1188 | FILE *f;
|
---|
1189 | JSAMPLE **readBuffer;
|
---|
1190 | int row_stride;
|
---|
1191 | register int i;
|
---|
1192 | register JSAMPLE *bufPtr;
|
---|
1193 |
|
---|
1194 | f = fopen(fileName, "rb");
|
---|
1195 | if (f == NULL) {
|
---|
1196 | Tcl_AppendResult(interp, "can't open \"", fileName, "\":",
|
---|
1197 | Tcl_PosixError(interp), (char *)NULL);
|
---|
1198 | return NULL;
|
---|
1199 | }
|
---|
1200 | image = NULL;
|
---|
1201 |
|
---|
1202 | /* Step 1: allocate and initialize JPEG decompression object */
|
---|
1203 |
|
---|
1204 | /* We set up the normal JPEG error routines, then override error_exit. */
|
---|
1205 | jpg.dct_method = JDCT_IFAST;
|
---|
1206 | jpg.err = jpeg_std_error(&handler.pub);
|
---|
1207 | handler.pub.error_exit = ErrorProc;
|
---|
1208 | handler.pub.output_message = MessageProc;
|
---|
1209 |
|
---|
1210 | Tcl_DStringInit(&handler.dString);
|
---|
1211 | Tcl_DStringAppend(&handler.dString, "error reading \"", -1);
|
---|
1212 | Tcl_DStringAppend(&handler.dString, fileName, -1);
|
---|
1213 | Tcl_DStringAppend(&handler.dString, "\": ", -1);
|
---|
1214 |
|
---|
1215 | if (setjmp(handler.jmpBuf)) {
|
---|
1216 | jpeg_destroy_decompress(&jpg);
|
---|
1217 | fclose(f);
|
---|
1218 | Tcl_DStringResult(interp, &(handler.dString));
|
---|
1219 | return NULL;
|
---|
1220 | }
|
---|
1221 | jpeg_create_decompress(&jpg);
|
---|
1222 | jpeg_stdio_src(&jpg, f);
|
---|
1223 |
|
---|
1224 | jpeg_read_header(&jpg, TRUE); /* Step 3: read file parameters */
|
---|
1225 |
|
---|
1226 | jpeg_start_decompress(&jpg); /* Step 5: Start decompressor */
|
---|
1227 | imageWidth = jpg.output_width;
|
---|
1228 | imageHeight = jpg.output_height;
|
---|
1229 | if ((imageWidth < 1) || (imageHeight < 1)) {
|
---|
1230 | Tcl_AppendResult(interp, "bad JPEG image size", (char *)NULL);
|
---|
1231 | fclose(f);
|
---|
1232 | return NULL;
|
---|
1233 | }
|
---|
1234 | /* JSAMPLEs per row in output buffer */
|
---|
1235 | row_stride = imageWidth * jpg.output_components;
|
---|
1236 |
|
---|
1237 | /* Make a one-row-high sample array that will go away when done
|
---|
1238 | * with image */
|
---|
1239 | readBuffer = (*jpg.mem->alloc_sarray) ((j_common_ptr)&jpg, JPOOL_IMAGE,
|
---|
1240 | row_stride, 1);
|
---|
1241 | image = Blt_CreateColorImage(imageWidth, imageHeight);
|
---|
1242 | destPtr = Blt_ColorImageBits(image);
|
---|
1243 |
|
---|
1244 | if (jpg.output_components == 1) {
|
---|
1245 | while (jpg.output_scanline < imageHeight) {
|
---|
1246 | jpeg_read_scanlines(&jpg, readBuffer, 1);
|
---|
1247 | bufPtr = readBuffer[0];
|
---|
1248 | for (i = 0; i < (int)imageWidth; i++) {
|
---|
1249 | destPtr->Red = destPtr->Green = destPtr->Blue = *bufPtr++;
|
---|
1250 | destPtr->Alpha = (unsigned char)-1;
|
---|
1251 | destPtr++;
|
---|
1252 | }
|
---|
1253 | }
|
---|
1254 | } else {
|
---|
1255 | while (jpg.output_scanline < imageHeight) {
|
---|
1256 | jpeg_read_scanlines(&jpg, readBuffer, 1);
|
---|
1257 | bufPtr = readBuffer[0];
|
---|
1258 | for (i = 0; i < (int)imageWidth; i++) {
|
---|
1259 | destPtr->Red = *bufPtr++;
|
---|
1260 | destPtr->Green = *bufPtr++;
|
---|
1261 | destPtr->Blue = *bufPtr++;
|
---|
1262 | destPtr->Alpha = (unsigned char)-1;
|
---|
1263 | destPtr++;
|
---|
1264 | }
|
---|
1265 | }
|
---|
1266 | }
|
---|
1267 | jpeg_finish_decompress(&jpg); /* We can ignore the return value
|
---|
1268 | * since suspension is not
|
---|
1269 | * possible with the stdio data
|
---|
1270 | * source. */
|
---|
1271 | jpeg_destroy_decompress(&jpg);
|
---|
1272 |
|
---|
1273 |
|
---|
1274 | /*
|
---|
1275 | * After finish_decompress, we can close the input file. Here we
|
---|
1276 | * postpone it until after no more JPEG errors are possible, so as
|
---|
1277 | * to simplify the setjmp error logic above. (Actually, I don't
|
---|
1278 | * think that jpeg_destroy can do an error exit, but why assume
|
---|
1279 | * anything...)
|
---|
1280 | */
|
---|
1281 | fclose(f);
|
---|
1282 |
|
---|
1283 | /*
|
---|
1284 | * At this point you may want to check to see whether any corrupt-data
|
---|
1285 | * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
|
---|
1286 | */
|
---|
1287 | if (handler.pub.num_warnings > 0) {
|
---|
1288 | Tcl_SetErrorCode(interp, "IMAGE", "JPEG",
|
---|
1289 | Tcl_DStringValue(&(handler.dString)), (char *)NULL);
|
---|
1290 | } else {
|
---|
1291 | Tcl_SetErrorCode(interp, "NONE", (char *)NULL);
|
---|
1292 | }
|
---|
1293 | /*
|
---|
1294 | * We're ready to call the Tk_Photo routines. They'll take the RGB
|
---|
1295 | * array we've processed to build the Tk image of the JPEG.
|
---|
1296 | */
|
---|
1297 | Tcl_DStringFree(&(handler.dString));
|
---|
1298 | return image;
|
---|
1299 | }
|
---|
1300 |
|
---|
1301 | #endif /* HAVE_JPEGLIB_H */
|
---|
1302 | #endif /* HAVE_IJL_H */
|
---|
1303 |
|
---|