VirtualBox

source: vbox/trunk/src/libs/libpng-1.2.8/contrib/gregbook/rpng-x.c@ 11115

Last change on this file since 11115 was 6395, checked in by vboxsync, 17 years ago

export libpng and zlib so Windows and OS/2 build cleanly.

  • Property svn:eol-style set to native
File size: 28.3 KB
Line 
1/*---------------------------------------------------------------------------
2
3 rpng - simple PNG display program rpng-x.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 the X Window System (tested by author under Unix and
9 by Martin Zinser under OpenVMS; may work under OS/2 with some tweaking).
10
11 to do:
12 - 8-bit support
13 - use %.1023s to simplify truncation of title-bar string?
14
15 ---------------------------------------------------------------------------
16
17 Changelog:
18 - 1.01: initial public release
19 - 1.02: modified to allow abbreviated options; fixed long/ulong mis-
20 match; switched to png_jmpbuf() macro
21 - 1.10: added support for non-default visuals; fixed X pixel-conversion
22 - 1.11: added extra set of parentheses to png_jmpbuf() macro; fixed
23 command-line parsing bug
24 - 1.12: fixed small X memory leak (thanks to Francois Petitjean)
25 - 1.13: fixed XFreeGC() crash bug
26
27 ---------------------------------------------------------------------------
28
29 Copyright (c) 1998-2001 Greg Roelofs. All rights reserved.
30
31 This software is provided "as is," without warranty of any kind,
32 express or implied. In no event shall the author or contributors
33 be held liable for any damages arising in any way from the use of
34 this software.
35
36 Permission is granted to anyone to use this software for any purpose,
37 including commercial applications, and to alter it and redistribute
38 it freely, subject to the following restrictions:
39
40 1. Redistributions of source code must retain the above copyright
41 notice, disclaimer, and this list of conditions.
42 2. Redistributions in binary form must reproduce the above copyright
43 notice, disclaimer, and this list of conditions in the documenta-
44 tion and/or other materials provided with the distribution.
45 3. All advertising materials mentioning features or use of this
46 software must display the following acknowledgment:
47
48 This product includes software developed by Greg Roelofs
49 and contributors for the book, "PNG: The Definitive Guide,"
50 published by O'Reilly and Associates.
51
52 ---------------------------------------------------------------------------*/
53
54#define PROGNAME "rpng-x"
55#define LONGNAME "Simple PNG Viewer for X"
56#define VERSION "1.13 of 16 August 2001"
57
58#include <stdio.h>
59#include <stdlib.h>
60#include <string.h>
61#include <time.h>
62#include <X11/Xlib.h>
63#include <X11/Xutil.h>
64#include <X11/Xos.h>
65#include <X11/keysym.h>
66
67/* #define DEBUG : this enables the Trace() macros */
68
69#include "readpng.h" /* typedefs, common macros, readpng prototypes */
70
71
72/* could just include png.h, but this macro is the only thing we need
73 * (name and typedefs changed to local versions); note that side effects
74 * only happen with alpha (which could easily be avoided with
75 * "ush acopy = (alpha);") */
76
77#define alpha_composite(composite, fg, alpha, bg) { \
78 ush temp = ((ush)(fg)*(ush)(alpha) + \
79 (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128); \
80 (composite) = (uch)((temp + (temp >> 8)) >> 8); \
81}
82
83
84/* local prototypes */
85static int rpng_x_create_window(void);
86static int rpng_x_display_image(void);
87static void rpng_x_cleanup(void);
88static int rpng_x_msb(ulg u32val);
89
90
91static char titlebar[1024], *window_name = titlebar;
92static char *appname = LONGNAME;
93static char *icon_name = PROGNAME;
94static char *filename;
95static FILE *infile;
96
97static char *bgstr;
98static uch bg_red=0, bg_green=0, bg_blue=0;
99
100static double display_exponent;
101
102static ulg image_width, image_height, image_rowbytes;
103static int image_channels;
104static uch *image_data;
105
106/* X-specific variables */
107static char *displayname;
108static XImage *ximage;
109static Display *display;
110static int depth;
111static Visual *visual;
112static XVisualInfo *visual_list;
113static int RShift, GShift, BShift;
114static ulg RMask, GMask, BMask;
115static Window window;
116static GC gc;
117static Colormap colormap;
118
119static int have_nondefault_visual = FALSE;
120static int have_colormap = FALSE;
121static int have_window = FALSE;
122static int have_gc = FALSE;
123/*
124ulg numcolors=0, pixels[256];
125ush reds[256], greens[256], blues[256];
126 */
127
128
129
130
131int main(int argc, char **argv)
132{
133#ifdef sgi
134 char tmpline[80];
135#endif
136 char *p;
137 int rc, alen, flen;
138 int error = 0;
139 int have_bg = FALSE;
140 double LUT_exponent; /* just the lookup table */
141 double CRT_exponent = 2.2; /* just the monitor */
142 double default_display_exponent; /* whole display system */
143 XEvent e;
144 KeySym k;
145
146
147 displayname = (char *)NULL;
148 filename = (char *)NULL;
149
150
151 /* First set the default value for our display-system exponent, i.e.,
152 * the product of the CRT exponent and the exponent corresponding to
153 * the frame-buffer's lookup table (LUT), if any. This is not an
154 * exhaustive list of LUT values (e.g., OpenStep has a lot of weird
155 * ones), but it should cover 99% of the current possibilities. */
156
157#if defined(NeXT)
158 LUT_exponent = 1.0 / 2.2;
159 /*
160 if (some_next_function_that_returns_gamma(&next_gamma))
161 LUT_exponent = 1.0 / next_gamma;
162 */
163#elif defined(sgi)
164 LUT_exponent = 1.0 / 1.7;
165 /* there doesn't seem to be any documented function to get the
166 * "gamma" value, so we do it the hard way */
167 infile = fopen("/etc/config/system.glGammaVal", "r");
168 if (infile) {
169 double sgi_gamma;
170
171 fgets(tmpline, 80, infile);
172 fclose(infile);
173 sgi_gamma = atof(tmpline);
174 if (sgi_gamma > 0.0)
175 LUT_exponent = 1.0 / sgi_gamma;
176 }
177#elif defined(Macintosh)
178 LUT_exponent = 1.8 / 2.61;
179 /*
180 if (some_mac_function_that_returns_gamma(&mac_gamma))
181 LUT_exponent = mac_gamma / 2.61;
182 */
183#else
184 LUT_exponent = 1.0; /* assume no LUT: most PCs */
185#endif
186
187 /* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */
188 default_display_exponent = LUT_exponent * CRT_exponent;
189
190
191 /* If the user has set the SCREEN_GAMMA environment variable as suggested
192 * (somewhat imprecisely) in the libpng documentation, use that; otherwise
193 * use the default value we just calculated. Either way, the user may
194 * override this via a command-line option. */
195
196 if ((p = getenv("SCREEN_GAMMA")) != NULL)
197 display_exponent = atof(p);
198 else
199 display_exponent = default_display_exponent;
200
201
202 /* Now parse the command line for options and the PNG filename. */
203
204 while (*++argv && !error) {
205 if (!strncmp(*argv, "-display", 2)) {
206 if (!*++argv)
207 ++error;
208 else
209 displayname = *argv;
210 } else if (!strncmp(*argv, "-gamma", 2)) {
211 if (!*++argv)
212 ++error;
213 else {
214 display_exponent = atof(*argv);
215 if (display_exponent <= 0.0)
216 ++error;
217 }
218 } else if (!strncmp(*argv, "-bgcolor", 2)) {
219 if (!*++argv)
220 ++error;
221 else {
222 bgstr = *argv;
223 if (strlen(bgstr) != 7 || bgstr[0] != '#')
224 ++error;
225 else
226 have_bg = TRUE;
227 }
228 } else {
229 if (**argv != '-') {
230 filename = *argv;
231 if (argv[1]) /* shouldn't be any more args after filename */
232 ++error;
233 } else
234 ++error; /* not expecting any other options */
235 }
236 }
237
238 if (!filename) {
239 ++error;
240 } else if (!(infile = fopen(filename, "rb"))) {
241 fprintf(stderr, PROGNAME ": can't open PNG file [%s]\n", filename);
242 ++error;
243 } else {
244 if ((rc = readpng_init(infile, &image_width, &image_height)) != 0) {
245 switch (rc) {
246 case 1:
247 fprintf(stderr, PROGNAME
248 ": [%s] is not a PNG file: incorrect signature\n",
249 filename);
250 break;
251 case 2:
252 fprintf(stderr, PROGNAME
253 ": [%s] has bad IHDR (libpng longjmp)\n",
254 filename);
255 break;
256 case 4:
257 fprintf(stderr, PROGNAME ": insufficient memory\n");
258 break;
259 default:
260 fprintf(stderr, PROGNAME
261 ": unknown readpng_init() error\n");
262 break;
263 }
264 ++error;
265 } else {
266 display = XOpenDisplay(displayname);
267 if (!display) {
268 readpng_cleanup(TRUE);
269 fprintf(stderr, PROGNAME ": can't open X display [%s]\n",
270 displayname? displayname : "default");
271 ++error;
272 }
273 }
274 if (error)
275 fclose(infile);
276 }
277
278
279 /* usage screen */
280
281 if (error) {
282 fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, appname);
283 readpng_version_info();
284 fprintf(stderr, "\n"
285 "Usage: %s [-display xdpy] [-gamma exp] [-bgcolor bg] file.png\n"
286 " xdpy\tname of the target X display (e.g., ``hostname:0'')\n"
287 " exp \ttransfer-function exponent (``gamma'') of the display\n"
288 "\t\t system in floating-point format (e.g., ``%.1f''); equal\n"
289 "\t\t to the product of the lookup-table exponent (varies)\n"
290 "\t\t and the CRT exponent (usually 2.2); must be positive\n"
291 " bg \tdesired background color in 7-character hex RGB format\n"
292 "\t\t (e.g., ``#ff7700'' for orange: same as HTML colors);\n"
293 "\t\t used with transparent images\n"
294 "\nPress Q, Esc or mouse button 1 (within image window, after image\n"
295 "is displayed) to quit.\n"
296 "\n", PROGNAME, default_display_exponent);
297 exit(1);
298 }
299
300
301 /* set the title-bar string, but make sure buffer doesn't overflow */
302
303 alen = strlen(appname);
304 flen = strlen(filename);
305 if (alen + flen + 3 > 1023)
306 sprintf(titlebar, "%s: ...%s", appname, filename+(alen+flen+6-1023));
307 else
308 sprintf(titlebar, "%s: %s", appname, filename);
309
310
311 /* if the user didn't specify a background color on the command line,
312 * check for one in the PNG file--if not, the initialized values of 0
313 * (black) will be used */
314
315 if (have_bg) {
316 unsigned r, g, b; /* this approach quiets compiler warnings */
317
318 sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b);
319 bg_red = (uch)r;
320 bg_green = (uch)g;
321 bg_blue = (uch)b;
322 } else if (readpng_get_bgcolor(&bg_red, &bg_green, &bg_blue) > 1) {
323 readpng_cleanup(TRUE);
324 fprintf(stderr, PROGNAME
325 ": libpng error while checking for background color\n");
326 exit(2);
327 }
328
329
330 /* do the basic X initialization stuff, make the window and fill it
331 * with the background color */
332
333 if (rpng_x_create_window())
334 exit(2);
335
336
337 /* decode the image, all at once */
338
339 Trace((stderr, "calling readpng_get_image()\n"))
340 image_data = readpng_get_image(display_exponent, &image_channels,
341 &image_rowbytes);
342 Trace((stderr, "done with readpng_get_image()\n"))
343
344
345 /* done with PNG file, so clean up to minimize memory usage (but do NOT
346 * nuke image_data!) */
347
348 readpng_cleanup(FALSE);
349 fclose(infile);
350
351 if (!image_data) {
352 fprintf(stderr, PROGNAME ": unable to decode PNG image\n");
353 exit(3);
354 }
355
356
357 /* display image (composite with background if requested) */
358
359 Trace((stderr, "calling rpng_x_display_image()\n"))
360 if (rpng_x_display_image()) {
361 free(image_data);
362 exit(4);
363 }
364 Trace((stderr, "done with rpng_x_display_image()\n"))
365
366
367 /* wait for the user to tell us when to quit */
368
369 printf(
370 "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n");
371 fflush(stdout);
372
373 do
374 XNextEvent(display, &e);
375 while (!(e.type == ButtonPress && e.xbutton.button == Button1) &&
376 !(e.type == KeyPress && /* v--- or 1 for shifted keys */
377 ((k = XLookupKeysym(&e.xkey, 0)) == XK_q || k == XK_Escape) ));
378
379
380 /* OK, we're done: clean up all image and X resources and go away */
381
382 rpng_x_cleanup();
383
384 return 0;
385}
386
387
388
389
390
391static int rpng_x_create_window(void)
392{
393 uch *xdata;
394 int need_colormap = FALSE;
395 int screen, pad;
396 ulg bg_pixel = 0L;
397 ulg attrmask;
398 Window root;
399 XEvent e;
400 XGCValues gcvalues;
401 XSetWindowAttributes attr;
402 XSizeHints *size_hints;
403 XTextProperty windowName, *pWindowName = &windowName;
404 XTextProperty iconName, *pIconName = &iconName;
405 XVisualInfo visual_info;
406 XWMHints *wm_hints;
407
408
409 screen = DefaultScreen(display);
410 depth = DisplayPlanes(display, screen);
411 root = RootWindow(display, screen);
412
413#ifdef DEBUG
414 XSynchronize(display, True);
415#endif
416
417#if 0
418/* GRR: add 8-bit support */
419 if (/* depth != 8 && */ depth != 16 && depth != 24 && depth != 32) {
420 fprintf(stderr,
421 "screen depth %d not supported (only 16-, 24- or 32-bit TrueColor)\n",
422 depth);
423 return 2;
424 }
425
426 XMatchVisualInfo(display, screen, depth,
427 (depth == 8)? PseudoColor : TrueColor, &visual_info);
428 visual = visual_info.visual;
429#else
430 if (depth != 16 && depth != 24 && depth != 32) {
431 int visuals_matched = 0;
432
433 Trace((stderr, "default depth is %d: checking other visuals\n",
434 depth))
435
436 /* 24-bit first */
437 visual_info.screen = screen;
438 visual_info.depth = 24;
439 visual_list = XGetVisualInfo(display,
440 VisualScreenMask | VisualDepthMask, &visual_info, &visuals_matched);
441 if (visuals_matched == 0) {
442/* GRR: add 15-, 16- and 32-bit TrueColor visuals (also DirectColor?) */
443 fprintf(stderr, "default screen depth %d not supported, and no"
444 " 24-bit visuals found\n", depth);
445 return 2;
446 }
447 Trace((stderr, "XGetVisualInfo() returned %d 24-bit visuals\n",
448 visuals_matched))
449 visual = visual_list[0].visual;
450 depth = visual_list[0].depth;
451/*
452 colormap_size = visual_list[0].colormap_size;
453 visual_class = visual->class;
454 visualID = XVisualIDFromVisual(visual);
455 */
456 have_nondefault_visual = TRUE;
457 need_colormap = TRUE;
458 } else {
459 XMatchVisualInfo(display, screen, depth, TrueColor, &visual_info);
460 visual = visual_info.visual;
461 }
462#endif
463
464 RMask = visual->red_mask;
465 GMask = visual->green_mask;
466 BMask = visual->blue_mask;
467
468/* GRR: add/check 8-bit support */
469 if (depth == 8 || need_colormap) {
470 colormap = XCreateColormap(display, root, visual, AllocNone);
471 if (!colormap) {
472 fprintf(stderr, "XCreateColormap() failed\n");
473 return 2;
474 }
475 have_colormap = TRUE;
476 }
477 if (depth == 15 || depth == 16) {
478 RShift = 15 - rpng_x_msb(RMask); /* these are right-shifts */
479 GShift = 15 - rpng_x_msb(GMask);
480 BShift = 15 - rpng_x_msb(BMask);
481 } else if (depth > 16) {
482#define NO_24BIT_MASKS
483#ifdef NO_24BIT_MASKS
484 RShift = rpng_x_msb(RMask) - 7; /* these are left-shifts */
485 GShift = rpng_x_msb(GMask) - 7;
486 BShift = rpng_x_msb(BMask) - 7;
487#else
488 RShift = 7 - rpng_x_msb(RMask); /* these are right-shifts, too */
489 GShift = 7 - rpng_x_msb(GMask);
490 BShift = 7 - rpng_x_msb(BMask);
491#endif
492 }
493 if (depth >= 15 && (RShift < 0 || GShift < 0 || BShift < 0)) {
494 fprintf(stderr, "rpng internal logic error: negative X shift(s)!\n");
495 return 2;
496 }
497
498/*---------------------------------------------------------------------------
499 Finally, create the window.
500 ---------------------------------------------------------------------------*/
501
502 attr.backing_store = Always;
503 attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask;
504 attrmask = CWBackingStore | CWEventMask;
505 if (have_nondefault_visual) {
506 attr.colormap = colormap;
507 attr.background_pixel = 0;
508 attr.border_pixel = 1;
509 attrmask |= CWColormap | CWBackPixel | CWBorderPixel;
510 }
511
512 window = XCreateWindow(display, root, 0, 0, image_width, image_height, 0,
513 depth, InputOutput, visual, attrmask, &attr);
514
515 if (window == None) {
516 fprintf(stderr, "XCreateWindow() failed\n");
517 return 2;
518 } else
519 have_window = TRUE;
520
521 if (depth == 8)
522 XSetWindowColormap(display, window, colormap);
523
524 if (!XStringListToTextProperty(&window_name, 1, pWindowName))
525 pWindowName = NULL;
526 if (!XStringListToTextProperty(&icon_name, 1, pIconName))
527 pIconName = NULL;
528
529 /* OK if either hints allocation fails; XSetWMProperties() allows NULLs */
530
531 if ((size_hints = XAllocSizeHints()) != NULL) {
532 /* window will not be resizable */
533 size_hints->flags = PMinSize | PMaxSize;
534 size_hints->min_width = size_hints->max_width = (int)image_width;
535 size_hints->min_height = size_hints->max_height = (int)image_height;
536 }
537
538 if ((wm_hints = XAllocWMHints()) != NULL) {
539 wm_hints->initial_state = NormalState;
540 wm_hints->input = True;
541 /* wm_hints->icon_pixmap = icon_pixmap; */
542 wm_hints->flags = StateHint | InputHint /* | IconPixmapHint */ ;
543 }
544
545 XSetWMProperties(display, window, pWindowName, pIconName, NULL, 0,
546 size_hints, wm_hints, NULL);
547
548 /* various properties and hints no longer needed; free memory */
549 if (pWindowName)
550 XFree(pWindowName->value);
551 if (pIconName)
552 XFree(pIconName->value);
553 if (size_hints)
554 XFree(size_hints);
555 if (wm_hints)
556 XFree(wm_hints);
557
558 XMapWindow(display, window);
559
560 gc = XCreateGC(display, window, 0, &gcvalues);
561 have_gc = TRUE;
562
563/*---------------------------------------------------------------------------
564 Fill window with the specified background color.
565 ---------------------------------------------------------------------------*/
566
567 if (depth == 24 || depth == 32) {
568 bg_pixel = ((ulg)bg_red << RShift) |
569 ((ulg)bg_green << GShift) |
570 ((ulg)bg_blue << BShift);
571 } else if (depth == 16) {
572 bg_pixel = ((((ulg)bg_red << 8) >> RShift) & RMask) |
573 ((((ulg)bg_green << 8) >> GShift) & GMask) |
574 ((((ulg)bg_blue << 8) >> BShift) & BMask);
575 } else /* depth == 8 */ {
576
577 /* GRR: add 8-bit support */
578
579 }
580
581 XSetForeground(display, gc, bg_pixel);
582 XFillRectangle(display, window, gc, 0, 0, image_width, image_height);
583
584/*---------------------------------------------------------------------------
585 Wait for first Expose event to do any drawing, then flush.
586 ---------------------------------------------------------------------------*/
587
588 do
589 XNextEvent(display, &e);
590 while (e.type != Expose || e.xexpose.count);
591
592 XFlush(display);
593
594/*---------------------------------------------------------------------------
595 Allocate memory for the X- and display-specific version of the image.
596 ---------------------------------------------------------------------------*/
597
598 if (depth == 24 || depth == 32) {
599 xdata = (uch *)malloc(4*image_width*image_height);
600 pad = 32;
601 } else if (depth == 16) {
602 xdata = (uch *)malloc(2*image_width*image_height);
603 pad = 16;
604 } else /* depth == 8 */ {
605 xdata = (uch *)malloc(image_width*image_height);
606 pad = 8;
607 }
608
609 if (!xdata) {
610 fprintf(stderr, PROGNAME ": unable to allocate image memory\n");
611 return 4;
612 }
613
614 ximage = XCreateImage(display, visual, depth, ZPixmap, 0,
615 (char *)xdata, image_width, image_height, pad, 0);
616
617 if (!ximage) {
618 fprintf(stderr, PROGNAME ": XCreateImage() failed\n");
619 free(xdata);
620 return 3;
621 }
622
623 /* to avoid testing the byte order every pixel (or doubling the size of
624 * the drawing routine with a giant if-test), we arbitrarily set the byte
625 * order to MSBFirst and let Xlib worry about inverting things on little-
626 * endian machines (like Linux/x86, old VAXen, etc.)--this is not the most
627 * efficient approach (the giant if-test would be better), but in the
628 * interest of clarity, we take the easy way out... */
629
630 ximage->byte_order = MSBFirst;
631
632 return 0;
633
634} /* end function rpng_x_create_window() */
635
636
637
638
639
640static int rpng_x_display_image(void)
641{
642 uch *src;
643 char *dest;
644 uch r, g, b, a;
645 ulg i, row, lastrow = 0;
646 ulg pixel;
647 int ximage_rowbytes = ximage->bytes_per_line;
648/* int bpp = ximage->bits_per_pixel; */
649
650
651 Trace((stderr, "beginning display loop (image_channels == %d)\n",
652 image_channels))
653 Trace((stderr, " (width = %ld, rowbytes = %ld, ximage_rowbytes = %d)\n",
654 image_width, image_rowbytes, ximage_rowbytes))
655 Trace((stderr, " (bpp = %d)\n", ximage->bits_per_pixel))
656 Trace((stderr, " (byte_order = %s)\n", ximage->byte_order == MSBFirst?
657 "MSBFirst" : (ximage->byte_order == LSBFirst? "LSBFirst" : "unknown")))
658
659 if (depth == 24 || depth == 32) {
660 ulg red, green, blue;
661
662 for (lastrow = row = 0; row < image_height; ++row) {
663 src = image_data + row*image_rowbytes;
664 dest = ximage->data + row*ximage_rowbytes;
665 if (image_channels == 3) {
666 for (i = image_width; i > 0; --i) {
667 red = *src++;
668 green = *src++;
669 blue = *src++;
670#ifdef NO_24BIT_MASKS
671 pixel = (red << RShift) |
672 (green << GShift) |
673 (blue << BShift);
674 /* recall that we set ximage->byte_order = MSBFirst above */
675 /* GRR BUG: this assumes bpp == 32, but may be 24: */
676 *dest++ = (char)((pixel >> 24) & 0xff);
677 *dest++ = (char)((pixel >> 16) & 0xff);
678 *dest++ = (char)((pixel >> 8) & 0xff);
679 *dest++ = (char)( pixel & 0xff);
680#else
681 red = (RShift < 0)? red << (-RShift) : red >> RShift;
682 green = (GShift < 0)? green << (-GShift) : green >> GShift;
683 blue = (BShift < 0)? blue << (-BShift) : blue >> BShift;
684 pixel = (red & RMask) | (green & GMask) | (blue & BMask);
685 /* recall that we set ximage->byte_order = MSBFirst above */
686 *dest++ = (char)((pixel >> 24) & 0xff);
687 *dest++ = (char)((pixel >> 16) & 0xff);
688 *dest++ = (char)((pixel >> 8) & 0xff);
689 *dest++ = (char)( pixel & 0xff);
690#endif
691 }
692 } else /* if (image_channels == 4) */ {
693 for (i = image_width; i > 0; --i) {
694 r = *src++;
695 g = *src++;
696 b = *src++;
697 a = *src++;
698 if (a == 255) {
699 red = r;
700 green = g;
701 blue = b;
702 } else if (a == 0) {
703 red = bg_red;
704 green = bg_green;
705 blue = bg_blue;
706 } else {
707 /* this macro (from png.h) composites the foreground
708 * and background values and puts the result into the
709 * first argument */
710 alpha_composite(red, r, a, bg_red);
711 alpha_composite(green, g, a, bg_green);
712 alpha_composite(blue, b, a, bg_blue);
713 }
714 pixel = (red << RShift) |
715 (green << GShift) |
716 (blue << BShift);
717 /* recall that we set ximage->byte_order = MSBFirst above */
718 *dest++ = (char)((pixel >> 24) & 0xff);
719 *dest++ = (char)((pixel >> 16) & 0xff);
720 *dest++ = (char)((pixel >> 8) & 0xff);
721 *dest++ = (char)( pixel & 0xff);
722 }
723 }
724 /* display after every 16 lines */
725 if (((row+1) & 0xf) == 0) {
726 XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
727 (int)lastrow, image_width, 16);
728 XFlush(display);
729 lastrow = row + 1;
730 }
731 }
732
733 } else if (depth == 16) {
734 ush red, green, blue;
735
736 for (lastrow = row = 0; row < image_height; ++row) {
737 src = image_data + row*image_rowbytes;
738 dest = ximage->data + row*ximage_rowbytes;
739 if (image_channels == 3) {
740 for (i = image_width; i > 0; --i) {
741 red = ((ush)(*src) << 8);
742 ++src;
743 green = ((ush)(*src) << 8);
744 ++src;
745 blue = ((ush)(*src) << 8);
746 ++src;
747 pixel = ((red >> RShift) & RMask) |
748 ((green >> GShift) & GMask) |
749 ((blue >> BShift) & BMask);
750 /* recall that we set ximage->byte_order = MSBFirst above */
751 *dest++ = (char)((pixel >> 8) & 0xff);
752 *dest++ = (char)( pixel & 0xff);
753 }
754 } else /* if (image_channels == 4) */ {
755 for (i = image_width; i > 0; --i) {
756 r = *src++;
757 g = *src++;
758 b = *src++;
759 a = *src++;
760 if (a == 255) {
761 red = ((ush)r << 8);
762 green = ((ush)g << 8);
763 blue = ((ush)b << 8);
764 } else if (a == 0) {
765 red = ((ush)bg_red << 8);
766 green = ((ush)bg_green << 8);
767 blue = ((ush)bg_blue << 8);
768 } else {
769 /* this macro (from png.h) composites the foreground
770 * and background values and puts the result back into
771 * the first argument (== fg byte here: safe) */
772 alpha_composite(r, r, a, bg_red);
773 alpha_composite(g, g, a, bg_green);
774 alpha_composite(b, b, a, bg_blue);
775 red = ((ush)r << 8);
776 green = ((ush)g << 8);
777 blue = ((ush)b << 8);
778 }
779 pixel = ((red >> RShift) & RMask) |
780 ((green >> GShift) & GMask) |
781 ((blue >> BShift) & BMask);
782 /* recall that we set ximage->byte_order = MSBFirst above */
783 *dest++ = (char)((pixel >> 8) & 0xff);
784 *dest++ = (char)( pixel & 0xff);
785 }
786 }
787 /* display after every 16 lines */
788 if (((row+1) & 0xf) == 0) {
789 XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
790 (int)lastrow, image_width, 16);
791 XFlush(display);
792 lastrow = row + 1;
793 }
794 }
795
796 } else /* depth == 8 */ {
797
798 /* GRR: add 8-bit support */
799
800 }
801
802 Trace((stderr, "calling final XPutImage()\n"))
803 if (lastrow < image_height) {
804 XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
805 (int)lastrow, image_width, image_height-lastrow);
806 XFlush(display);
807 }
808
809 return 0;
810}
811
812
813
814
815static void rpng_x_cleanup(void)
816{
817 if (image_data) {
818 free(image_data);
819 image_data = NULL;
820 }
821
822 if (ximage) {
823 if (ximage->data) {
824 free(ximage->data); /* we allocated it, so we free it */
825 ximage->data = (char *)NULL; /* instead of XDestroyImage() */
826 }
827 XDestroyImage(ximage);
828 ximage = NULL;
829 }
830
831 if (have_gc)
832 XFreeGC(display, gc);
833
834 if (have_window)
835 XDestroyWindow(display, window);
836
837 if (have_colormap)
838 XFreeColormap(display, colormap);
839
840 if (have_nondefault_visual)
841 XFree(visual_list);
842}
843
844
845
846
847
848static int rpng_x_msb(ulg u32val)
849{
850 int i;
851
852 for (i = 31; i >= 0; --i) {
853 if (u32val & 0x80000000L)
854 break;
855 u32val <<= 1;
856 }
857 return i;
858}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette