diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/rpng-win.c | 728 |
1 files changed, 728 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/rpng-win.c b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/rpng-win.c new file mode 100644 index 0000000..1c22282 --- /dev/null +++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/rpng-win.c | |||
@@ -0,0 +1,728 @@ | |||
1 | /*--------------------------------------------------------------------------- | ||
2 | |||
3 | rpng - simple PNG display program rpng-win.c | ||
4 | |||
5 | This program decodes and displays PNG images, with gamma correction and | ||
6 | optionally with a user-specified background color (in case the image has | ||
7 | transparency). It is very nearly the most basic PNG viewer possible. | ||
8 | This version is for 32-bit Windows; it may compile under 16-bit Windows | ||
9 | with a little tweaking (or maybe not). | ||
10 | |||
11 | to do: | ||
12 | - handle quoted command-line args (especially filenames with spaces) | ||
13 | - have minimum window width: oh well | ||
14 | - use %.1023s to simplify truncation of title-bar string? | ||
15 | |||
16 | --------------------------------------------------------------------------- | ||
17 | |||
18 | Changelog: | ||
19 | - 1.00: initial public release | ||
20 | - 1.01: modified to allow abbreviated options; fixed long/ulong mis- | ||
21 | match; switched to png_jmpbuf() macro | ||
22 | - 1.02: added extra set of parentheses to png_jmpbuf() macro; fixed | ||
23 | command-line parsing bug | ||
24 | - 1.10: enabled "message window"/console (thanks to David Geldreich) | ||
25 | - 2.00: dual-licensed (added GNU GPL) | ||
26 | - 2.01: fixed improper display of usage screen on PNG error(s) | ||
27 | |||
28 | --------------------------------------------------------------------------- | ||
29 | |||
30 | Copyright (c) 1998-2008 Greg Roelofs. All rights reserved. | ||
31 | |||
32 | This software is provided "as is," without warranty of any kind, | ||
33 | express or implied. In no event shall the author or contributors | ||
34 | be held liable for any damages arising in any way from the use of | ||
35 | this software. | ||
36 | |||
37 | The contents of this file are DUAL-LICENSED. You may modify and/or | ||
38 | redistribute this software according to the terms of one of the | ||
39 | following two licenses (at your option): | ||
40 | |||
41 | |||
42 | LICENSE 1 ("BSD-like with advertising clause"): | ||
43 | |||
44 | Permission is granted to anyone to use this software for any purpose, | ||
45 | including commercial applications, and to alter it and redistribute | ||
46 | it freely, subject to the following restrictions: | ||
47 | |||
48 | 1. Redistributions of source code must retain the above copyright | ||
49 | notice, disclaimer, and this list of conditions. | ||
50 | 2. Redistributions in binary form must reproduce the above copyright | ||
51 | notice, disclaimer, and this list of conditions in the documenta- | ||
52 | tion and/or other materials provided with the distribution. | ||
53 | 3. All advertising materials mentioning features or use of this | ||
54 | software must display the following acknowledgment: | ||
55 | |||
56 | This product includes software developed by Greg Roelofs | ||
57 | and contributors for the book, "PNG: The Definitive Guide," | ||
58 | published by O'Reilly and Associates. | ||
59 | |||
60 | |||
61 | LICENSE 2 (GNU GPL v2 or later): | ||
62 | |||
63 | This program is free software; you can redistribute it and/or modify | ||
64 | it under the terms of the GNU General Public License as published by | ||
65 | the Free Software Foundation; either version 2 of the License, or | ||
66 | (at your option) any later version. | ||
67 | |||
68 | This program is distributed in the hope that it will be useful, | ||
69 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
70 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
71 | GNU General Public License for more details. | ||
72 | |||
73 | You should have received a copy of the GNU General Public License | ||
74 | along with this program; if not, write to the Free Software Foundation, | ||
75 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
76 | |||
77 | ---------------------------------------------------------------------------*/ | ||
78 | |||
79 | #define PROGNAME "rpng-win" | ||
80 | #define LONGNAME "Simple PNG Viewer for Windows" | ||
81 | #define VERSION "2.01 of 16 March 2008" | ||
82 | |||
83 | #include <stdio.h> | ||
84 | #include <stdlib.h> | ||
85 | #include <string.h> | ||
86 | #include <time.h> | ||
87 | #include <windows.h> | ||
88 | #ifdef __CYGWIN__ | ||
89 | /* getch replacement. Turns out, we don't really need this, | ||
90 | * but leave it here if we ever enable any of the uses of | ||
91 | * _getch in the main code | ||
92 | */ | ||
93 | #include <unistd.h> | ||
94 | #include <termio.h> | ||
95 | #include <sys/ioctl.h> | ||
96 | int repl_getch( void ) | ||
97 | { | ||
98 | char ch; | ||
99 | int fd = fileno(stdin); | ||
100 | struct termio old_tty, new_tty; | ||
101 | |||
102 | ioctl(fd, TCGETA, &old_tty); | ||
103 | new_tty = old_tty; | ||
104 | new_tty.c_lflag &= ~(ICANON | ECHO | ISIG); | ||
105 | ioctl(fd, TCSETA, &new_tty); | ||
106 | fread(&ch, 1, sizeof(ch), stdin); | ||
107 | ioctl(fd, TCSETA, &old_tty); | ||
108 | |||
109 | return ch; | ||
110 | } | ||
111 | #define _getch repl_getch | ||
112 | #else | ||
113 | #include <conio.h> /* only for _getch() */ | ||
114 | #endif | ||
115 | |||
116 | /* #define DEBUG : this enables the Trace() macros */ | ||
117 | |||
118 | #include "readpng.h" /* typedefs, common macros, readpng prototypes */ | ||
119 | |||
120 | |||
121 | /* could just include png.h, but this macro is the only thing we need | ||
122 | * (name and typedefs changed to local versions); note that side effects | ||
123 | * only happen with alpha (which could easily be avoided with | ||
124 | * "ush acopy = (alpha);") */ | ||
125 | |||
126 | #define alpha_composite(composite, fg, alpha, bg) { \ | ||
127 | ush temp = ((ush)(fg)*(ush)(alpha) + \ | ||
128 | (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128); \ | ||
129 | (composite) = (uch)((temp + (temp >> 8)) >> 8); \ | ||
130 | } | ||
131 | |||
132 | |||
133 | /* local prototypes */ | ||
134 | static int rpng_win_create_window(HINSTANCE hInst, int showmode); | ||
135 | static int rpng_win_display_image(void); | ||
136 | static void rpng_win_cleanup(void); | ||
137 | LRESULT CALLBACK rpng_win_wndproc(HWND, UINT, WPARAM, LPARAM); | ||
138 | |||
139 | |||
140 | static char titlebar[1024]; | ||
141 | static char *progname = PROGNAME; | ||
142 | static char *appname = LONGNAME; | ||
143 | static char *filename; | ||
144 | static FILE *infile; | ||
145 | |||
146 | static char *bgstr; | ||
147 | static uch bg_red=0, bg_green=0, bg_blue=0; | ||
148 | |||
149 | static double display_exponent; | ||
150 | |||
151 | static ulg image_width, image_height, image_rowbytes; | ||
152 | static int image_channels; | ||
153 | static uch *image_data; | ||
154 | |||
155 | /* Windows-specific variables */ | ||
156 | static ulg wimage_rowbytes; | ||
157 | static uch *dib; | ||
158 | static uch *wimage_data; | ||
159 | static BITMAPINFOHEADER *bmih; | ||
160 | |||
161 | static HWND global_hwnd; | ||
162 | |||
163 | |||
164 | |||
165 | |||
166 | int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) | ||
167 | { | ||
168 | char *args[1024]; /* arbitrary limit, but should suffice */ | ||
169 | char *p, *q, **argv = args; | ||
170 | int argc = 0; | ||
171 | int rc, alen, flen; | ||
172 | int error = 0; | ||
173 | int have_bg = FALSE; | ||
174 | double LUT_exponent; /* just the lookup table */ | ||
175 | double CRT_exponent = 2.2; /* just the monitor */ | ||
176 | double default_display_exponent; /* whole display system */ | ||
177 | MSG msg; | ||
178 | |||
179 | |||
180 | filename = (char *)NULL; | ||
181 | |||
182 | #ifndef __CYGWIN__ | ||
183 | /* First reenable console output, which normally goes to the bit bucket | ||
184 | * for windowed apps. Closing the console window will terminate the | ||
185 | * app. Thanks to David.Geldreich@realviz.com for supplying the magical | ||
186 | * incantation. */ | ||
187 | |||
188 | AllocConsole(); | ||
189 | freopen("CONOUT$", "a", stderr); | ||
190 | freopen("CONOUT$", "a", stdout); | ||
191 | #endif | ||
192 | |||
193 | |||
194 | /* Next set the default value for our display-system exponent, i.e., | ||
195 | * the product of the CRT exponent and the exponent corresponding to | ||
196 | * the frame-buffer's lookup table (LUT), if any. This is not an | ||
197 | * exhaustive list of LUT values (e.g., OpenStep has a lot of weird | ||
198 | * ones), but it should cover 99% of the current possibilities. And | ||
199 | * yes, these ifdefs are completely wasted in a Windows program... */ | ||
200 | |||
201 | #if defined(NeXT) | ||
202 | LUT_exponent = 1.0 / 2.2; | ||
203 | /* | ||
204 | if (some_next_function_that_returns_gamma(&next_gamma)) | ||
205 | LUT_exponent = 1.0 / next_gamma; | ||
206 | */ | ||
207 | #elif defined(sgi) | ||
208 | LUT_exponent = 1.0 / 1.7; | ||
209 | /* there doesn't seem to be any documented function to get the | ||
210 | * "gamma" value, so we do it the hard way */ | ||
211 | infile = fopen("/etc/config/system.glGammaVal", "r"); | ||
212 | if (infile) { | ||
213 | double sgi_gamma; | ||
214 | |||
215 | fgets(tmpline, 80, infile); | ||
216 | fclose(infile); | ||
217 | sgi_gamma = atof(tmpline); | ||
218 | if (sgi_gamma > 0.0) | ||
219 | LUT_exponent = 1.0 / sgi_gamma; | ||
220 | } | ||
221 | #elif defined(Macintosh) | ||
222 | LUT_exponent = 1.8 / 2.61; | ||
223 | /* | ||
224 | if (some_mac_function_that_returns_gamma(&mac_gamma)) | ||
225 | LUT_exponent = mac_gamma / 2.61; | ||
226 | */ | ||
227 | #else | ||
228 | LUT_exponent = 1.0; /* assume no LUT: most PCs */ | ||
229 | #endif | ||
230 | |||
231 | /* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */ | ||
232 | default_display_exponent = LUT_exponent * CRT_exponent; | ||
233 | |||
234 | |||
235 | /* If the user has set the SCREEN_GAMMA environment variable as suggested | ||
236 | * (somewhat imprecisely) in the libpng documentation, use that; otherwise | ||
237 | * use the default value we just calculated. Either way, the user may | ||
238 | * override this via a command-line option. */ | ||
239 | |||
240 | if ((p = getenv("SCREEN_GAMMA")) != NULL) | ||
241 | display_exponent = atof(p); | ||
242 | else | ||
243 | display_exponent = default_display_exponent; | ||
244 | |||
245 | |||
246 | /* Windows really hates command lines, so we have to set up our own argv. | ||
247 | * Note that we do NOT bother with quoted arguments here, so don't use | ||
248 | * filenames with spaces in 'em! */ | ||
249 | |||
250 | argv[argc++] = PROGNAME; | ||
251 | p = cmd; | ||
252 | for (;;) { | ||
253 | if (*p == ' ') | ||
254 | while (*++p == ' ') | ||
255 | ; | ||
256 | /* now p points at the first non-space after some spaces */ | ||
257 | if (*p == '\0') | ||
258 | break; /* nothing after the spaces: done */ | ||
259 | argv[argc++] = q = p; | ||
260 | while (*q && *q != ' ') | ||
261 | ++q; | ||
262 | /* now q points at a space or the end of the string */ | ||
263 | if (*q == '\0') | ||
264 | break; /* last argv already terminated; quit */ | ||
265 | *q = '\0'; /* change space to terminator */ | ||
266 | p = q + 1; | ||
267 | } | ||
268 | argv[argc] = NULL; /* terminate the argv array itself */ | ||
269 | |||
270 | |||
271 | /* Now parse the command line for options and the PNG filename. */ | ||
272 | |||
273 | while (*++argv && !error) { | ||
274 | if (!strncmp(*argv, "-gamma", 2)) { | ||
275 | if (!*++argv) | ||
276 | ++error; | ||
277 | else { | ||
278 | display_exponent = atof(*argv); | ||
279 | if (display_exponent <= 0.0) | ||
280 | ++error; | ||
281 | } | ||
282 | } else if (!strncmp(*argv, "-bgcolor", 2)) { | ||
283 | if (!*++argv) | ||
284 | ++error; | ||
285 | else { | ||
286 | bgstr = *argv; | ||
287 | if (strlen(bgstr) != 7 || bgstr[0] != '#') | ||
288 | ++error; | ||
289 | else | ||
290 | have_bg = TRUE; | ||
291 | } | ||
292 | } else { | ||
293 | if (**argv != '-') { | ||
294 | filename = *argv; | ||
295 | if (argv[1]) /* shouldn't be any more args after filename */ | ||
296 | ++error; | ||
297 | } else | ||
298 | ++error; /* not expecting any other options */ | ||
299 | } | ||
300 | } | ||
301 | |||
302 | if (!filename) | ||
303 | ++error; | ||
304 | |||
305 | |||
306 | /* print usage screen if any errors up to this point */ | ||
307 | |||
308 | if (error) { | ||
309 | #ifndef __CYGWIN__ | ||
310 | int ch; | ||
311 | #endif | ||
312 | |||
313 | fprintf(stderr, "\n%s %s: %s\n\n", PROGNAME, VERSION, appname); | ||
314 | readpng_version_info(); | ||
315 | fprintf(stderr, "\n" | ||
316 | "Usage: %s [-gamma exp] [-bgcolor bg] file.png\n" | ||
317 | " exp \ttransfer-function exponent (``gamma'') of the display\n" | ||
318 | "\t\t system in floating-point format (e.g., ``%.1f''); equal\n" | ||
319 | "\t\t to the product of the lookup-table exponent (varies)\n" | ||
320 | "\t\t and the CRT exponent (usually 2.2); must be positive\n" | ||
321 | " bg \tdesired background color in 7-character hex RGB format\n" | ||
322 | "\t\t (e.g., ``#ff7700'' for orange: same as HTML colors);\n" | ||
323 | "\t\t used with transparent images\n" | ||
324 | "\nPress Q, Esc or mouse button 1 after image is displayed to quit.\n" | ||
325 | #ifndef __CYGWIN__ | ||
326 | "Press Q or Esc to quit this usage screen.\n" | ||
327 | #endif | ||
328 | "\n", PROGNAME, default_display_exponent); | ||
329 | #ifndef __CYGWIN__ | ||
330 | do | ||
331 | ch = _getch(); | ||
332 | while (ch != 'q' && ch != 'Q' && ch != 0x1B); | ||
333 | #endif | ||
334 | exit(1); | ||
335 | } | ||
336 | |||
337 | |||
338 | if (!(infile = fopen(filename, "rb"))) { | ||
339 | fprintf(stderr, PROGNAME ": can't open PNG file [%s]\n", filename); | ||
340 | ++error; | ||
341 | } else { | ||
342 | if ((rc = readpng_init(infile, &image_width, &image_height)) != 0) { | ||
343 | switch (rc) { | ||
344 | case 1: | ||
345 | fprintf(stderr, PROGNAME | ||
346 | ": [%s] is not a PNG file: incorrect signature\n", | ||
347 | filename); | ||
348 | break; | ||
349 | case 2: | ||
350 | fprintf(stderr, PROGNAME | ||
351 | ": [%s] has bad IHDR (libpng longjmp)\n", filename); | ||
352 | break; | ||
353 | case 4: | ||
354 | fprintf(stderr, PROGNAME ": insufficient memory\n"); | ||
355 | break; | ||
356 | default: | ||
357 | fprintf(stderr, PROGNAME | ||
358 | ": unknown readpng_init() error\n"); | ||
359 | break; | ||
360 | } | ||
361 | ++error; | ||
362 | } | ||
363 | if (error) | ||
364 | fclose(infile); | ||
365 | } | ||
366 | |||
367 | |||
368 | if (error) { | ||
369 | #ifndef __CYGWIN__ | ||
370 | int ch; | ||
371 | #endif | ||
372 | |||
373 | fprintf(stderr, PROGNAME ": aborting.\n"); | ||
374 | #ifndef __CYGWIN__ | ||
375 | do | ||
376 | ch = _getch(); | ||
377 | while (ch != 'q' && ch != 'Q' && ch != 0x1B); | ||
378 | #endif | ||
379 | exit(2); | ||
380 | } else { | ||
381 | fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, appname); | ||
382 | #ifndef __CYGWIN__ | ||
383 | fprintf(stderr, | ||
384 | "\n [console window: closing this window will terminate %s]\n\n", | ||
385 | PROGNAME); | ||
386 | #endif | ||
387 | } | ||
388 | |||
389 | |||
390 | /* set the title-bar string, but make sure buffer doesn't overflow */ | ||
391 | |||
392 | alen = strlen(appname); | ||
393 | flen = strlen(filename); | ||
394 | if (alen + flen + 3 > 1023) | ||
395 | sprintf(titlebar, "%s: ...%s", appname, filename+(alen+flen+6-1023)); | ||
396 | else | ||
397 | sprintf(titlebar, "%s: %s", appname, filename); | ||
398 | |||
399 | |||
400 | /* if the user didn't specify a background color on the command line, | ||
401 | * check for one in the PNG file--if not, the initialized values of 0 | ||
402 | * (black) will be used */ | ||
403 | |||
404 | if (have_bg) { | ||
405 | unsigned r, g, b; /* this approach quiets compiler warnings */ | ||
406 | |||
407 | sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b); | ||
408 | bg_red = (uch)r; | ||
409 | bg_green = (uch)g; | ||
410 | bg_blue = (uch)b; | ||
411 | } else if (readpng_get_bgcolor(&bg_red, &bg_green, &bg_blue) > 1) { | ||
412 | readpng_cleanup(TRUE); | ||
413 | fprintf(stderr, PROGNAME | ||
414 | ": libpng error while checking for background color\n"); | ||
415 | exit(2); | ||
416 | } | ||
417 | |||
418 | |||
419 | /* do the basic Windows initialization stuff, make the window and fill it | ||
420 | * with the background color */ | ||
421 | |||
422 | if (rpng_win_create_window(hInst, showmode)) | ||
423 | exit(2); | ||
424 | |||
425 | |||
426 | /* decode the image, all at once */ | ||
427 | |||
428 | Trace((stderr, "calling readpng_get_image()\n")) | ||
429 | image_data = readpng_get_image(display_exponent, &image_channels, | ||
430 | &image_rowbytes); | ||
431 | Trace((stderr, "done with readpng_get_image()\n")) | ||
432 | |||
433 | |||
434 | /* done with PNG file, so clean up to minimize memory usage (but do NOT | ||
435 | * nuke image_data!) */ | ||
436 | |||
437 | readpng_cleanup(FALSE); | ||
438 | fclose(infile); | ||
439 | |||
440 | if (!image_data) { | ||
441 | fprintf(stderr, PROGNAME ": unable to decode PNG image\n"); | ||
442 | exit(3); | ||
443 | } | ||
444 | |||
445 | |||
446 | /* display image (composite with background if requested) */ | ||
447 | |||
448 | Trace((stderr, "calling rpng_win_display_image()\n")) | ||
449 | if (rpng_win_display_image()) { | ||
450 | free(image_data); | ||
451 | exit(4); | ||
452 | } | ||
453 | Trace((stderr, "done with rpng_win_display_image()\n")) | ||
454 | |||
455 | |||
456 | /* wait for the user to tell us when to quit */ | ||
457 | |||
458 | printf( | ||
459 | #ifndef __CYGWIN__ | ||
460 | "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n" | ||
461 | #else | ||
462 | "Done. Press mouse button 1 (within image window) to quit.\n" | ||
463 | #endif | ||
464 | ); | ||
465 | fflush(stdout); | ||
466 | |||
467 | while (GetMessage(&msg, NULL, 0, 0)) { | ||
468 | TranslateMessage(&msg); | ||
469 | DispatchMessage(&msg); | ||
470 | } | ||
471 | |||
472 | |||
473 | /* OK, we're done: clean up all image and Windows resources and go away */ | ||
474 | |||
475 | rpng_win_cleanup(); | ||
476 | |||
477 | return msg.wParam; | ||
478 | } | ||
479 | |||
480 | |||
481 | |||
482 | |||
483 | |||
484 | static int rpng_win_create_window(HINSTANCE hInst, int showmode) | ||
485 | { | ||
486 | uch *dest; | ||
487 | int extra_width, extra_height; | ||
488 | ulg i, j; | ||
489 | WNDCLASSEX wndclass; | ||
490 | |||
491 | |||
492 | /*--------------------------------------------------------------------------- | ||
493 | Allocate memory for the display-specific version of the image (round up | ||
494 | to multiple of 4 for Windows DIB). | ||
495 | ---------------------------------------------------------------------------*/ | ||
496 | |||
497 | wimage_rowbytes = ((3*image_width + 3L) >> 2) << 2; | ||
498 | |||
499 | if (!(dib = (uch *)malloc(sizeof(BITMAPINFOHEADER) + | ||
500 | wimage_rowbytes*image_height))) | ||
501 | { | ||
502 | return 4; /* fail */ | ||
503 | } | ||
504 | |||
505 | /*--------------------------------------------------------------------------- | ||
506 | Initialize the DIB. Negative height means to use top-down BMP ordering | ||
507 | (must be uncompressed, but that's what we want). Bit count of 1, 4 or 8 | ||
508 | implies a colormap of RGBX quads, but 24-bit BMPs just use B,G,R values | ||
509 | directly => wimage_data begins immediately after BMP header. | ||
510 | ---------------------------------------------------------------------------*/ | ||
511 | |||
512 | memset(dib, 0, sizeof(BITMAPINFOHEADER)); | ||
513 | bmih = (BITMAPINFOHEADER *)dib; | ||
514 | bmih->biSize = sizeof(BITMAPINFOHEADER); | ||
515 | bmih->biWidth = image_width; | ||
516 | bmih->biHeight = -((long)image_height); | ||
517 | bmih->biPlanes = 1; | ||
518 | bmih->biBitCount = 24; | ||
519 | bmih->biCompression = 0; | ||
520 | wimage_data = dib + sizeof(BITMAPINFOHEADER); | ||
521 | |||
522 | /*--------------------------------------------------------------------------- | ||
523 | Fill in background color (black by default); data are in BGR order. | ||
524 | ---------------------------------------------------------------------------*/ | ||
525 | |||
526 | for (j = 0; j < image_height; ++j) { | ||
527 | dest = wimage_data + j*wimage_rowbytes; | ||
528 | for (i = image_width; i > 0; --i) { | ||
529 | *dest++ = bg_blue; | ||
530 | *dest++ = bg_green; | ||
531 | *dest++ = bg_red; | ||
532 | } | ||
533 | } | ||
534 | |||
535 | /*--------------------------------------------------------------------------- | ||
536 | Set the window parameters. | ||
537 | ---------------------------------------------------------------------------*/ | ||
538 | |||
539 | memset(&wndclass, 0, sizeof(wndclass)); | ||
540 | |||
541 | wndclass.cbSize = sizeof(wndclass); | ||
542 | wndclass.style = CS_HREDRAW | CS_VREDRAW; | ||
543 | wndclass.lpfnWndProc = rpng_win_wndproc; | ||
544 | wndclass.hInstance = hInst; | ||
545 | wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); | ||
546 | wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); | ||
547 | wndclass.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH); | ||
548 | wndclass.lpszMenuName = NULL; | ||
549 | wndclass.lpszClassName = progname; | ||
550 | wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); | ||
551 | |||
552 | RegisterClassEx(&wndclass); | ||
553 | |||
554 | /*--------------------------------------------------------------------------- | ||
555 | Finally, create the window. | ||
556 | ---------------------------------------------------------------------------*/ | ||
557 | |||
558 | extra_width = 2*(GetSystemMetrics(SM_CXBORDER) + | ||
559 | GetSystemMetrics(SM_CXDLGFRAME)); | ||
560 | extra_height = 2*(GetSystemMetrics(SM_CYBORDER) + | ||
561 | GetSystemMetrics(SM_CYDLGFRAME)) + | ||
562 | GetSystemMetrics(SM_CYCAPTION); | ||
563 | |||
564 | global_hwnd = CreateWindow(progname, titlebar, WS_OVERLAPPEDWINDOW, | ||
565 | CW_USEDEFAULT, CW_USEDEFAULT, image_width+extra_width, | ||
566 | image_height+extra_height, NULL, NULL, hInst, NULL); | ||
567 | |||
568 | ShowWindow(global_hwnd, showmode); | ||
569 | UpdateWindow(global_hwnd); | ||
570 | |||
571 | return 0; | ||
572 | |||
573 | } /* end function rpng_win_create_window() */ | ||
574 | |||
575 | |||
576 | |||
577 | |||
578 | |||
579 | static int rpng_win_display_image() | ||
580 | { | ||
581 | uch *src, *dest; | ||
582 | uch r, g, b, a; | ||
583 | ulg i, row, lastrow; | ||
584 | RECT rect; | ||
585 | |||
586 | |||
587 | Trace((stderr, "beginning display loop (image_channels == %d)\n", | ||
588 | image_channels)) | ||
589 | Trace((stderr, "(width = %ld, rowbytes = %ld, wimage_rowbytes = %d)\n", | ||
590 | image_width, image_rowbytes, wimage_rowbytes)) | ||
591 | |||
592 | |||
593 | /*--------------------------------------------------------------------------- | ||
594 | Blast image data to buffer. This whole routine takes place before the | ||
595 | message loop begins, so there's no real point in any pseudo-progressive | ||
596 | display... | ||
597 | ---------------------------------------------------------------------------*/ | ||
598 | |||
599 | for (lastrow = row = 0; row < image_height; ++row) { | ||
600 | src = image_data + row*image_rowbytes; | ||
601 | dest = wimage_data + row*wimage_rowbytes; | ||
602 | if (image_channels == 3) { | ||
603 | for (i = image_width; i > 0; --i) { | ||
604 | r = *src++; | ||
605 | g = *src++; | ||
606 | b = *src++; | ||
607 | *dest++ = b; | ||
608 | *dest++ = g; /* note reverse order */ | ||
609 | *dest++ = r; | ||
610 | } | ||
611 | } else /* if (image_channels == 4) */ { | ||
612 | for (i = image_width; i > 0; --i) { | ||
613 | r = *src++; | ||
614 | g = *src++; | ||
615 | b = *src++; | ||
616 | a = *src++; | ||
617 | if (a == 255) { | ||
618 | *dest++ = b; | ||
619 | *dest++ = g; | ||
620 | *dest++ = r; | ||
621 | } else if (a == 0) { | ||
622 | *dest++ = bg_blue; | ||
623 | *dest++ = bg_green; | ||
624 | *dest++ = bg_red; | ||
625 | } else { | ||
626 | /* this macro (copied from png.h) composites the | ||
627 | * foreground and background values and puts the | ||
628 | * result into the first argument; there are no | ||
629 | * side effects with the first argument */ | ||
630 | alpha_composite(*dest++, b, a, bg_blue); | ||
631 | alpha_composite(*dest++, g, a, bg_green); | ||
632 | alpha_composite(*dest++, r, a, bg_red); | ||
633 | } | ||
634 | } | ||
635 | } | ||
636 | /* display after every 16 lines */ | ||
637 | if (((row+1) & 0xf) == 0) { | ||
638 | rect.left = 0L; | ||
639 | rect.top = (LONG)lastrow; | ||
640 | rect.right = (LONG)image_width; /* possibly off by one? */ | ||
641 | rect.bottom = (LONG)lastrow + 16L; /* possibly off by one? */ | ||
642 | InvalidateRect(global_hwnd, &rect, FALSE); | ||
643 | UpdateWindow(global_hwnd); /* similar to XFlush() */ | ||
644 | lastrow = row + 1; | ||
645 | } | ||
646 | } | ||
647 | |||
648 | Trace((stderr, "calling final image-flush routine\n")) | ||
649 | if (lastrow < image_height) { | ||
650 | rect.left = 0L; | ||
651 | rect.top = (LONG)lastrow; | ||
652 | rect.right = (LONG)image_width; /* possibly off by one? */ | ||
653 | rect.bottom = (LONG)image_height; /* possibly off by one? */ | ||
654 | InvalidateRect(global_hwnd, &rect, FALSE); | ||
655 | UpdateWindow(global_hwnd); /* similar to XFlush() */ | ||
656 | } | ||
657 | |||
658 | /* | ||
659 | last param determines whether or not background is wiped before paint | ||
660 | InvalidateRect(global_hwnd, NULL, TRUE); | ||
661 | UpdateWindow(global_hwnd); | ||
662 | */ | ||
663 | |||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | |||
668 | |||
669 | |||
670 | |||
671 | static void rpng_win_cleanup() | ||
672 | { | ||
673 | if (image_data) { | ||
674 | free(image_data); | ||
675 | image_data = NULL; | ||
676 | } | ||
677 | |||
678 | if (dib) { | ||
679 | free(dib); | ||
680 | dib = NULL; | ||
681 | } | ||
682 | } | ||
683 | |||
684 | |||
685 | |||
686 | |||
687 | |||
688 | LRESULT CALLBACK rpng_win_wndproc(HWND hwnd, UINT iMsg, WPARAM wP, LPARAM lP) | ||
689 | { | ||
690 | HDC hdc; | ||
691 | PAINTSTRUCT ps; | ||
692 | int rc; | ||
693 | |||
694 | switch (iMsg) { | ||
695 | case WM_CREATE: | ||
696 | /* one-time processing here, if any */ | ||
697 | return 0; | ||
698 | |||
699 | case WM_PAINT: | ||
700 | hdc = BeginPaint(hwnd, &ps); | ||
701 | /* dest */ | ||
702 | rc = StretchDIBits(hdc, 0, 0, image_width, image_height, | ||
703 | /* source */ | ||
704 | 0, 0, image_width, image_height, | ||
705 | wimage_data, (BITMAPINFO *)bmih, | ||
706 | /* iUsage: no clue */ | ||
707 | 0, SRCCOPY); | ||
708 | EndPaint(hwnd, &ps); | ||
709 | return 0; | ||
710 | |||
711 | /* wait for the user to tell us when to quit */ | ||
712 | case WM_CHAR: | ||
713 | switch (wP) { /* only need one, so ignore repeat count */ | ||
714 | case 'q': | ||
715 | case 'Q': | ||
716 | case 0x1B: /* Esc key */ | ||
717 | PostQuitMessage(0); | ||
718 | } | ||
719 | return 0; | ||
720 | |||
721 | case WM_LBUTTONDOWN: /* another way of quitting */ | ||
722 | case WM_DESTROY: | ||
723 | PostQuitMessage(0); | ||
724 | return 0; | ||
725 | } | ||
726 | |||
727 | return DefWindowProc(hwnd, iMsg, wP, lP); | ||
728 | } | ||