Visualization Library 2.0.0-b5

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
rpng2-win.c
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------
2 
3  rpng2 - progressive-model PNG display program rpng2-win.c
4 
5  This program decodes and displays PNG files progressively, as if it were
6  a web browser (though the front end is only set up to read from files).
7  It supports gamma correction, user-specified background colors, and user-
8  specified background patterns (for transparent images). This version is
9  for 32-bit Windows; it may compile under 16-bit Windows with a little
10  tweaking (or maybe not). Thanks to Adam Costello and Pieter S. van der
11  Meulen for the "diamond" and "radial waves" patterns, respectively.
12 
13  to do (someday, maybe):
14  - handle quoted command-line args (especially filenames with spaces)
15  - finish resizable checkerboard-gradient (sizes 4-128?)
16  - use %.1023s to simplify truncation of title-bar string?
17  - have minimum window width: oh well
18 
19  ---------------------------------------------------------------------------
20 
21  Changelog:
22  - 1.01: initial public release
23  - 1.02: fixed cut-and-paste error in usage screen (oops...)
24  - 1.03: modified to allow abbreviated options
25  - 1.04: removed bogus extra argument from usage fprintf() [Glenn R-P?];
26  fixed command-line parsing bug
27  - 1.10: enabled "message window"/console (thanks to David Geldreich)
28  - 1.20: added runtime MMX-enabling/disabling and new -mmx* options
29  - 1.21: made minor tweak to usage screen to fit within 25-line console
30  - 1.22: added AMD64/EM64T support (__x86_64__)
31  - 2.00: dual-licensed (added GNU GPL)
32  - 2.01: fixed 64-bit typo in readpng2.c
33  - 2.02: fixed improper display of usage screen on PNG error(s); fixed
34  unexpected-EOF and file-read-error cases
35 
36  ---------------------------------------------------------------------------
37 
38  Copyright (c) 1998-2008 Greg Roelofs. All rights reserved.
39 
40  This software is provided "as is," without warranty of any kind,
41  express or implied. In no event shall the author or contributors
42  be held liable for any damages arising in any way from the use of
43  this software.
44 
45  The contents of this file are DUAL-LICENSED. You may modify and/or
46  redistribute this software according to the terms of one of the
47  following two licenses (at your option):
48 
49 
50  LICENSE 1 ("BSD-like with advertising clause"):
51 
52  Permission is granted to anyone to use this software for any purpose,
53  including commercial applications, and to alter it and redistribute
54  it freely, subject to the following restrictions:
55 
56  1. Redistributions of source code must retain the above copyright
57  notice, disclaimer, and this list of conditions.
58  2. Redistributions in binary form must reproduce the above copyright
59  notice, disclaimer, and this list of conditions in the documenta-
60  tion and/or other materials provided with the distribution.
61  3. All advertising materials mentioning features or use of this
62  software must display the following acknowledgment:
63 
64  This product includes software developed by Greg Roelofs
65  and contributors for the book, "PNG: The Definitive Guide,"
66  published by O'Reilly and Associates.
67 
68 
69  LICENSE 2 (GNU GPL v2 or later):
70 
71  This program is free software; you can redistribute it and/or modify
72  it under the terms of the GNU General Public License as published by
73  the Free Software Foundation; either version 2 of the License, or
74  (at your option) any later version.
75 
76  This program is distributed in the hope that it will be useful,
77  but WITHOUT ANY WARRANTY; without even the implied warranty of
78  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
79  GNU General Public License for more details.
80 
81  You should have received a copy of the GNU General Public License
82  along with this program; if not, write to the Free Software Foundation,
83  Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
84 
85  ---------------------------------------------------------------------------*/
86 
87 #define PROGNAME "rpng2-win"
88 #define LONGNAME "Progressive PNG Viewer for Windows"
89 #define VERSION "2.02 of 16 March 2008"
90 
91 #include <stdio.h>
92 #include <stdlib.h>
93 #include <string.h>
94 #include <setjmp.h> /* for jmpbuf declaration in readpng2.h */
95 #include <time.h>
96 #include <math.h> /* only for PvdM background code */
97 #include <windows.h>
98 #include <conio.h> /* only for _getch() */
99 
100 /* all for PvdM background code: */
101 #ifndef PI
102 # define PI 3.141592653589793238
103 #endif
104 #define PI_2 (PI*0.5)
105 #define INV_PI_360 (360.0 / PI)
106 #define MAX(a,b) (a>b?a:b)
107 #define MIN(a,b) (a<b?a:b)
108 #define CLIP(a,min,max) MAX(min,MIN((a),max))
109 #define ABS(a) ((a)<0?-(a):(a))
110 #define CLIP8P(c) MAX(0,(MIN((c),255))) /* 8-bit pos. integer (uch) */
111 #define ROUNDF(f) ((int)(f + 0.5))
112 
113 #define rgb1_max bg_freq
114 #define rgb1_min bg_gray
115 #define rgb2_max bg_bsat
116 #define rgb2_min bg_brot
117 
118 /* #define DEBUG */ /* this enables the Trace() macros */
119 
120 #include "readpng2.h" /* typedefs, common macros, readpng2 prototypes */
121 
122 
123 /* could just include png.h, but this macro is the only thing we need
124  * (name and typedefs changed to local versions); note that side effects
125  * only happen with alpha (which could easily be avoided with
126  * "ush acopy = (alpha);") */
127 
128 #define alpha_composite(composite, fg, alpha, bg) { \
129  ush temp = ((ush)(fg)*(ush)(alpha) + \
130  (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128); \
131  (composite) = (uch)((temp + (temp >> 8)) >> 8); \
132 }
133 
134 
135 #define INBUFSIZE 4096 /* with pseudo-timing on (1 sec delay/block), this
136  * block size corresponds roughly to a download
137  * speed 10% faster than theoretical 33.6K maximum
138  * (assuming 8 data bits, 1 stop bit and no other
139  * overhead) */
140 
141 /* local prototypes */
142 static void rpng2_win_init(void);
143 static int rpng2_win_create_window(void);
144 static int rpng2_win_load_bg_image(void);
145 static void rpng2_win_display_row(ulg row);
146 static void rpng2_win_finish_display(void);
147 static void rpng2_win_cleanup(void);
148 LRESULT CALLBACK rpng2_win_wndproc(HWND, UINT, WPARAM, LPARAM);
149 
150 
151 static char titlebar[1024];
152 static char *progname = PROGNAME;
153 static char *appname = LONGNAME;
154 static char *filename;
155 static FILE *infile;
156 
157 static mainprog_info rpng2_info;
158 
159 static uch inbuf[INBUFSIZE];
160 static int incount;
161 
162 static int pat = 6; /* must be less than num_bgpat */
163 static int bg_image = 0;
164 static int bgscale = 16;
165 static ulg bg_rowbytes;
166 static uch *bg_data;
167 
168 static struct rgb_color {
169  uch r, g, b;
170 } rgb[] = {
171  { 0, 0, 0}, /* 0: black */
172  {255, 255, 255}, /* 1: white */
173  {173, 132, 57}, /* 2: tan */
174  { 64, 132, 0}, /* 3: medium green */
175  {189, 117, 1}, /* 4: gold */
176  {253, 249, 1}, /* 5: yellow */
177  { 0, 0, 255}, /* 6: blue */
178  { 0, 0, 120}, /* 7: medium blue */
179  {255, 0, 255}, /* 8: magenta */
180  { 64, 0, 64}, /* 9: dark magenta */
181  {255, 0, 0}, /* 10: red */
182  { 64, 0, 0}, /* 11: dark red */
183  {255, 127, 0}, /* 12: orange */
184  {192, 96, 0}, /* 13: darker orange */
185  { 24, 60, 0}, /* 14: dark green-yellow */
186  { 85, 125, 200} /* 15: ice blue */
187 };
188 /* not used for now, but should be for error-checking:
189 static int num_rgb = sizeof(rgb) / sizeof(struct rgb_color);
190  */
191 
192 /*
193  This whole struct is a fairly cheesy way to keep the number of
194  command-line options to a minimum. The radial-waves background
195  type is a particularly poor fit to the integer elements of the
196  struct...but a few macros and a little fixed-point math will do
197  wonders for ya.
198 
199  type bits:
200  F E D C B A 9 8 7 6 5 4 3 2 1 0
201  | | | | |
202  | | +-+-+-- 0 = sharp-edged checkerboard
203  | | 1 = soft diamonds
204  | | 2 = radial waves
205  | | 3-7 = undefined
206  | +-- gradient #2 inverted?
207  +-- alternating columns inverted?
208  */
209 static struct background_pattern {
210  ush type;
211  int rgb1_max, rgb1_min; /* or bg_freq, bg_gray */
212  int rgb2_max, rgb2_min; /* or bg_bsat, bg_brot (both scaled by 10)*/
213 } bg[] = {
214  {0+8, 2,0, 1,15}, /* checkered: tan/black vs. white/ice blue */
215  {0+24, 2,0, 1,0}, /* checkered: tan/black vs. white/black */
216  {0+8, 4,5, 0,2}, /* checkered: gold/yellow vs. black/tan */
217  {0+8, 4,5, 0,6}, /* checkered: gold/yellow vs. black/blue */
218  {0, 7,0, 8,9}, /* checkered: deep blue/black vs. magenta */
219  {0+8, 13,0, 5,14}, /* checkered: orange/black vs. yellow */
220  {0+8, 12,0, 10,11}, /* checkered: orange/black vs. red */
221  {1, 7,0, 8,0}, /* diamonds: deep blue/black vs. magenta */
222  {1, 12,0, 11,0}, /* diamonds: orange vs. dark red */
223  {1, 10,0, 7,0}, /* diamonds: red vs. medium blue */
224  {1, 4,0, 5,0}, /* diamonds: gold vs. yellow */
225  {1, 3,0, 0,0}, /* diamonds: medium green vs. black */
226  {2, 16, 100, 20, 0}, /* radial: ~hard radial color-beams */
227  {2, 18, 100, 10, 2}, /* radial: soft, curved radial color-beams */
228  {2, 16, 256, 100, 250}, /* radial: very tight spiral */
229  {2, 10000, 256, 11, 0} /* radial: dipole-moire' (almost fractal) */
230 };
231 static int num_bgpat = sizeof(bg) / sizeof(struct background_pattern);
232 
233 
234 /* Windows-specific global variables (could go in struct, but messy...) */
235 static ulg wimage_rowbytes;
236 static uch *dib;
237 static uch *wimage_data;
238 static BITMAPINFOHEADER *bmih;
239 
240 static HWND global_hwnd;
241 static HINSTANCE global_hInst;
242 static int global_showmode;
243 
244 
245 
246 
247 int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode)
248 {
249  char *args[1024]; /* arbitrary limit, but should suffice */
250  char **argv = args;
251  char *p, *q, *bgstr = NULL;
252  int argc = 0;
253  int rc, alen, flen;
254  int error = 0;
255  int timing = FALSE;
256  int have_bg = FALSE;
257  double LUT_exponent; /* just the lookup table */
258  double CRT_exponent = 2.2; /* just the monitor */
259  double default_display_exponent; /* whole display system */
260  MSG msg;
261 
262 
263  /* First initialize a few things, just to be sure--memset takes care of
264  * default background color (black), booleans (FALSE), pointers (NULL),
265  * etc. */
266 
267  global_hInst = hInst;
268  global_showmode = showmode;
269  filename = (char *)NULL;
270  memset(&rpng2_info, 0, sizeof(mainprog_info));
271 
272 
273  /* Next reenable console output, which normally goes to the bit bucket
274  * for windowed apps. Closing the console window will terminate the
275  * app. Thanks to David.Geldreich@realviz.com for supplying the magical
276  * incantation. */
277 
278  AllocConsole();
279  freopen("CONOUT$", "a", stderr);
280  freopen("CONOUT$", "a", stdout);
281 
282 
283  /* Set the default value for our display-system exponent, i.e., the
284  * product of the CRT exponent and the exponent corresponding to
285  * the frame-buffer's lookup table (LUT), if any. This is not an
286  * exhaustive list of LUT values (e.g., OpenStep has a lot of weird
287  * ones), but it should cover 99% of the current possibilities. And
288  * yes, these ifdefs are completely wasted in a Windows program... */
289 
290 #if defined(NeXT)
291  /* third-party utilities can modify the default LUT exponent */
292  LUT_exponent = 1.0 / 2.2;
293  /*
294  if (some_next_function_that_returns_gamma(&next_gamma))
295  LUT_exponent = 1.0 / next_gamma;
296  */
297 #elif defined(sgi)
298  LUT_exponent = 1.0 / 1.7;
299  /* there doesn't seem to be any documented function to
300  * get the "gamma" value, so we do it the hard way */
301  infile = fopen("/etc/config/system.glGammaVal", "r");
302  if (infile) {
303  double sgi_gamma;
304 
305  fgets(tmpline, 80, infile);
306  fclose(infile);
307  sgi_gamma = atof(tmpline);
308  if (sgi_gamma > 0.0)
309  LUT_exponent = 1.0 / sgi_gamma;
310  }
311 #elif defined(Macintosh)
312  LUT_exponent = 1.8 / 2.61;
313  /*
314  if (some_mac_function_that_returns_gamma(&mac_gamma))
315  LUT_exponent = mac_gamma / 2.61;
316  */
317 #else
318  LUT_exponent = 1.0; /* assume no LUT: most PCs */
319 #endif
320 
321  /* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */
322  default_display_exponent = LUT_exponent * CRT_exponent;
323 
324 
325  /* If the user has set the SCREEN_GAMMA environment variable as suggested
326  * (somewhat imprecisely) in the libpng documentation, use that; otherwise
327  * use the default value we just calculated. Either way, the user may
328  * override this via a command-line option. */
329 
330  if ((p = getenv("SCREEN_GAMMA")) != NULL)
331  rpng2_info.display_exponent = atof(p);
332  else
333  rpng2_info.display_exponent = default_display_exponent;
334 
335 
336  /* Windows really hates command lines, so we have to set up our own argv.
337  * Note that we do NOT bother with quoted arguments here, so don't use
338  * filenames with spaces in 'em! */
339 
340  argv[argc++] = PROGNAME;
341  p = cmd;
342  for (;;) {
343  if (*p == ' ')
344  while (*++p == ' ')
345  ;
346  /* now p points at the first non-space after some spaces */
347  if (*p == '\0')
348  break; /* nothing after the spaces: done */
349  argv[argc++] = q = p;
350  while (*q && *q != ' ')
351  ++q;
352  /* now q points at a space or the end of the string */
353  if (*q == '\0')
354  break; /* last argv already terminated; quit */
355  *q = '\0'; /* change space to terminator */
356  p = q + 1;
357  }
358  argv[argc] = NULL; /* terminate the argv array itself */
359 
360 
361  /* Now parse the command line for options and the PNG filename. */
362 
363  while (*++argv && !error) {
364  if (!strncmp(*argv, "-gamma", 2)) {
365  if (!*++argv)
366  ++error;
367  else {
368  rpng2_info.display_exponent = atof(*argv);
369  if (rpng2_info.display_exponent <= 0.0)
370  ++error;
371  }
372  } else if (!strncmp(*argv, "-bgcolor", 4)) {
373  if (!*++argv)
374  ++error;
375  else {
376  bgstr = *argv;
377  if (strlen(bgstr) != 7 || bgstr[0] != '#')
378  ++error;
379  else {
380  have_bg = TRUE;
381  bg_image = FALSE;
382  }
383  }
384  } else if (!strncmp(*argv, "-bgpat", 4)) {
385  if (!*++argv)
386  ++error;
387  else {
388  pat = atoi(*argv) - 1;
389  if (pat < 0 || pat >= num_bgpat)
390  ++error;
391  else {
392  bg_image = TRUE;
393  have_bg = FALSE;
394  }
395  }
396  } else if (!strncmp(*argv, "-timing", 2)) {
397  timing = TRUE;
398 #if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__))
399  } else if (!strncmp(*argv, "-nommxfilters", 7)) {
400  rpng2_info.nommxfilters = TRUE;
401  } else if (!strncmp(*argv, "-nommxcombine", 7)) {
402  rpng2_info.nommxcombine = TRUE;
403  } else if (!strncmp(*argv, "-nommxinterlace", 7)) {
404  rpng2_info.nommxinterlace = TRUE;
405  } else if (!strcmp(*argv, "-nommx")) {
406  rpng2_info.nommxfilters = TRUE;
407  rpng2_info.nommxcombine = TRUE;
408  rpng2_info.nommxinterlace = TRUE;
409 #endif
410  } else {
411  if (**argv != '-') {
412  filename = *argv;
413  if (argv[1]) /* shouldn't be any more args after filename */
414  ++error;
415  } else
416  ++error; /* not expecting any other options */
417  }
418  }
419 
420  if (!filename)
421  ++error;
422 
423 
424  /* print usage screen if any errors up to this point */
425 
426  if (error) {
427  int ch;
428 
429  fprintf(stderr, "\n%s %s: %s\n\n", PROGNAME, VERSION, appname);
431  fprintf(stderr, "\n"
432  "Usage: %s [-gamma exp] [-bgcolor bg | -bgpat pat] [-timing]\n"
433 #if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__))
434  " %*s [[-nommxfilters] [-nommxcombine] [-nommxinterlace] | -nommx]\n"
435 #endif
436  " %*s file.png\n\n"
437  " exp \ttransfer-function exponent (``gamma'') of the display\n"
438  "\t\t system in floating-point format (e.g., ``%.1f''); equal\n"
439  "\t\t to the product of the lookup-table exponent (varies)\n"
440  "\t\t and the CRT exponent (usually 2.2); must be positive\n"
441  " bg \tdesired background color in 7-character hex RGB format\n"
442  "\t\t (e.g., ``#ff7700'' for orange: same as HTML colors);\n"
443  "\t\t used with transparent images; overrides -bgpat option\n"
444  " pat \tdesired background pattern number (1-%d); used with\n"
445  "\t\t transparent images; overrides -bgcolor option\n"
446  " -timing\tenables delay for every block read, to simulate modem\n"
447  "\t\t download of image (~36 Kbps)\n"
448 #if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__))
449  " -nommx*\tdisable optimized MMX routines for decoding row filters,\n"
450  "\t\t combining rows, and expanding interlacing, respectively\n"
451 #endif
452  "\nPress Q, Esc or mouse button 1 after image is displayed to quit.\n"
453  "Press Q or Esc to quit this usage screen. ",
454  PROGNAME,
455 #if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__))
456  (int)strlen(PROGNAME), " ",
457 #endif
458  (int)strlen(PROGNAME), " ", default_display_exponent, num_bgpat);
459  fflush(stderr);
460  do
461  ch = _getch();
462  while (ch != 'q' && ch != 'Q' && ch != 0x1B);
463  exit(1);
464  }
465 
466 
467  if (!(infile = fopen(filename, "rb"))) {
468  fprintf(stderr, PROGNAME ": can't open PNG file [%s]\n", filename);
469  ++error;
470  } else {
471  incount = fread(inbuf, 1, INBUFSIZE, infile);
472  if (incount < 8 || !readpng2_check_sig(inbuf, 8)) {
473  fprintf(stderr, PROGNAME
474  ": [%s] is not a PNG file: incorrect signature\n",
475  filename);
476  ++error;
477  } else if ((rc = readpng2_init(&rpng2_info)) != 0) {
478  switch (rc) {
479  case 2:
480  fprintf(stderr, PROGNAME
481  ": [%s] has bad IHDR (libpng longjmp)\n", filename);
482  break;
483  case 4:
484  fprintf(stderr, PROGNAME ": insufficient memory\n");
485  break;
486  default:
487  fprintf(stderr, PROGNAME
488  ": unknown readpng2_init() error\n");
489  break;
490  }
491  ++error;
492  }
493  if (error)
494  fclose(infile);
495  }
496 
497 
498  if (error) {
499  int ch;
500 
501  fprintf(stderr, PROGNAME ": aborting.\n");
502  do
503  ch = _getch();
504  while (ch != 'q' && ch != 'Q' && ch != 0x1B);
505  exit(2);
506  } else {
507  fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, appname);
508  fprintf(stderr,
509  "\n [console window: closing this window will terminate %s]\n\n",
510  PROGNAME);
511  fflush(stderr);
512  }
513 
514 
515  /* set the title-bar string, but make sure buffer doesn't overflow */
516 
517  alen = strlen(appname);
518  flen = strlen(filename);
519  if (alen + flen + 3 > 1023)
520  sprintf(titlebar, "%s: ...%s", appname, filename+(alen+flen+6-1023));
521  else
522  sprintf(titlebar, "%s: %s", appname, filename);
523 
524 
525  /* set some final rpng2_info variables before entering main data loop */
526 
527  if (have_bg) {
528  unsigned r, g, b; /* this approach quiets compiler warnings */
529 
530  sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b);
531  rpng2_info.bg_red = (uch)r;
532  rpng2_info.bg_green = (uch)g;
533  rpng2_info.bg_blue = (uch)b;
534  } else
535  rpng2_info.need_bgcolor = TRUE;
536 
537  rpng2_info.state = kPreInit;
538  rpng2_info.mainprog_init = rpng2_win_init;
539  rpng2_info.mainprog_display_row = rpng2_win_display_row;
540  rpng2_info.mainprog_finish_display = rpng2_win_finish_display;
541 
542 
543  /* OK, this is the fun part: call readpng2_decode_data() at the start of
544  * the loop to deal with our first buffer of data (read in above to verify
545  * that the file is a PNG image), then loop through the file and continue
546  * calling the same routine to handle each chunk of data. It in turn
547  * passes the data to libpng, which will invoke one or more of our call-
548  * backs as decoded data become available. We optionally call Sleep() for
549  * one second per iteration to simulate downloading the image via an analog
550  * modem. */
551 
552  for (;;) {
553  Trace((stderr, "about to call readpng2_decode_data()\n"))
554  if (readpng2_decode_data(&rpng2_info, inbuf, incount))
555  ++error;
556  Trace((stderr, "done with readpng2_decode_data()\n"))
557 
558  if (error || incount != INBUFSIZE || rpng2_info.state == kDone) {
559  if (rpng2_info.state == kDone) {
560  Trace((stderr, "done decoding PNG image\n"))
561  } else if (ferror(infile)) {
562  fprintf(stderr, PROGNAME
563  ": error while reading PNG image file\n");
564  exit(3);
565  } else if (feof(infile)) {
566  fprintf(stderr, PROGNAME ": end of file reached "
567  "(unexpectedly) while reading PNG image file\n");
568  exit(3);
569  } else /* if (error) */ {
570  // will print error message below
571  }
572  break;
573  }
574 
575  if (timing)
576  Sleep(1000L);
577 
578  incount = fread(inbuf, 1, INBUFSIZE, infile);
579  }
580 
581 
582  /* clean up PNG stuff and report any decoding errors */
583 
584  fclose(infile);
585  Trace((stderr, "about to call readpng2_cleanup()\n"))
586  readpng2_cleanup(&rpng2_info);
587 
588  if (error) {
589  fprintf(stderr, PROGNAME ": libpng error while decoding PNG image\n");
590  exit(3);
591  }
592 
593 
594  /* wait for the user to tell us when to quit */
595 
596  while (GetMessage(&msg, NULL, 0, 0)) {
597  TranslateMessage(&msg);
598  DispatchMessage(&msg);
599  }
600 
601 
602  /* we're done: clean up all image and Windows resources and go away */
603 
604  Trace((stderr, "about to call rpng2_win_cleanup()\n"))
605  rpng2_win_cleanup();
606 
607  return msg.wParam;
608 }
609 
610 
611 
612 
613 
614 /* this function is called by readpng2_info_callback() in readpng2.c, which
615  * in turn is called by libpng after all of the pre-IDAT chunks have been
616  * read and processed--i.e., we now have enough info to finish initializing */
617 
618 static void rpng2_win_init()
619 {
620  ulg i;
621  ulg rowbytes = rpng2_info.rowbytes;
622 
623  Trace((stderr, "beginning rpng2_win_init()\n"))
624  Trace((stderr, " rowbytes = %d\n", rpng2_info.rowbytes))
625  Trace((stderr, " width = %ld\n", rpng2_info.width))
626  Trace((stderr, " height = %ld\n", rpng2_info.height))
627 
628  rpng2_info.image_data = (uch *)malloc(rowbytes * rpng2_info.height);
629  if (!rpng2_info.image_data) {
630  readpng2_cleanup(&rpng2_info);
631  return;
632  }
633 
634  rpng2_info.row_pointers = (uch **)malloc(rpng2_info.height * sizeof(uch *));
635  if (!rpng2_info.row_pointers) {
636  free(rpng2_info.image_data);
637  rpng2_info.image_data = NULL;
638  readpng2_cleanup(&rpng2_info);
639  return;
640  }
641 
642  for (i = 0; i < rpng2_info.height; ++i)
643  rpng2_info.row_pointers[i] = rpng2_info.image_data + i*rowbytes;
644 
645 /*---------------------------------------------------------------------------
646  Do the basic Windows initialization stuff, make the window, and fill it
647  with the user-specified, file-specified or default background color.
648  ---------------------------------------------------------------------------*/
649 
650  if (rpng2_win_create_window()) {
651  readpng2_cleanup(&rpng2_info);
652  return;
653  }
654 
655  rpng2_info.state = kWindowInit;
656 }
657 
658 
659 
660 
661 
662 static int rpng2_win_create_window()
663 {
664  uch bg_red = rpng2_info.bg_red;
665  uch bg_green = rpng2_info.bg_green;
666  uch bg_blue = rpng2_info.bg_blue;
667  uch *dest;
668  int extra_width, extra_height;
669  ulg i, j;
670  WNDCLASSEX wndclass;
671  RECT rect;
672 
673 
674 /*---------------------------------------------------------------------------
675  Allocate memory for the display-specific version of the image (round up
676  to multiple of 4 for Windows DIB).
677  ---------------------------------------------------------------------------*/
678 
679  wimage_rowbytes = ((3*rpng2_info.width + 3L) >> 2) << 2;
680 
681  if (!(dib = (uch *)malloc(sizeof(BITMAPINFOHEADER) +
682  wimage_rowbytes*rpng2_info.height)))
683  {
684  return 4; /* fail */
685  }
686 
687 /*---------------------------------------------------------------------------
688  Initialize the DIB. Negative height means to use top-down BMP ordering
689  (must be uncompressed, but that's what we want). Bit count of 1, 4 or 8
690  implies a colormap of RGBX quads, but 24-bit BMPs just use B,G,R values
691  directly => wimage_data begins immediately after BMP header.
692  ---------------------------------------------------------------------------*/
693 
694  memset(dib, 0, sizeof(BITMAPINFOHEADER));
695  bmih = (BITMAPINFOHEADER *)dib;
696  bmih->biSize = sizeof(BITMAPINFOHEADER);
697  bmih->biWidth = rpng2_info.width;
698  bmih->biHeight = -((long)rpng2_info.height);
699  bmih->biPlanes = 1;
700  bmih->biBitCount = 24;
701  bmih->biCompression = 0;
702  wimage_data = dib + sizeof(BITMAPINFOHEADER);
703 
704 /*---------------------------------------------------------------------------
705  Fill window with the specified background color (default is black), but
706  defer loading faked "background image" until window is displayed (may be
707  slow to compute). Data are in BGR order.
708  ---------------------------------------------------------------------------*/
709 
710  if (bg_image) { /* just fill with black for now */
711  memset(wimage_data, 0, wimage_rowbytes*rpng2_info.height);
712  } else {
713  for (j = 0; j < rpng2_info.height; ++j) {
714  dest = wimage_data + j*wimage_rowbytes;
715  for (i = rpng2_info.width; i > 0; --i) {
716  *dest++ = bg_blue;
717  *dest++ = bg_green;
718  *dest++ = bg_red;
719  }
720  }
721  }
722 
723 /*---------------------------------------------------------------------------
724  Set the window parameters.
725  ---------------------------------------------------------------------------*/
726 
727  memset(&wndclass, 0, sizeof(wndclass));
728 
729  wndclass.cbSize = sizeof(wndclass);
730  wndclass.style = CS_HREDRAW | CS_VREDRAW;
731  wndclass.lpfnWndProc = rpng2_win_wndproc;
732  wndclass.hInstance = global_hInst;
733  wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
734  wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
735  wndclass.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH);
736  wndclass.lpszMenuName = NULL;
737  wndclass.lpszClassName = progname;
738  wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
739 
740  RegisterClassEx(&wndclass);
741 
742 /*---------------------------------------------------------------------------
743  Finally, create the window.
744  ---------------------------------------------------------------------------*/
745 
746  extra_width = 2*(GetSystemMetrics(SM_CXBORDER) +
747  GetSystemMetrics(SM_CXDLGFRAME));
748  extra_height = 2*(GetSystemMetrics(SM_CYBORDER) +
749  GetSystemMetrics(SM_CYDLGFRAME)) +
750  GetSystemMetrics(SM_CYCAPTION);
751 
752  global_hwnd = CreateWindow(progname, titlebar, WS_OVERLAPPEDWINDOW,
753  CW_USEDEFAULT, CW_USEDEFAULT, rpng2_info.width+extra_width,
754  rpng2_info.height+extra_height, NULL, NULL, global_hInst, NULL);
755 
756  ShowWindow(global_hwnd, global_showmode);
757  UpdateWindow(global_hwnd);
758 
759 /*---------------------------------------------------------------------------
760  Now compute the background image and display it. If it fails (memory
761  allocation), revert to a plain background color.
762  ---------------------------------------------------------------------------*/
763 
764  if (bg_image) {
765  static const char *msg = "Computing background image...";
766  int x, y, len = strlen(msg);
767  HDC hdc = GetDC(global_hwnd);
768  TEXTMETRIC tm;
769 
770  GetTextMetrics(hdc, &tm);
771  x = (rpng2_info.width - len*tm.tmAveCharWidth)/2;
772  y = (rpng2_info.height - tm.tmHeight)/2;
773  SetBkMode(hdc, TRANSPARENT);
774  SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
775  /* this can still begin out of bounds even if x is positive (???): */
776  TextOut(hdc, ((x < 0)? 0 : x), ((y < 0)? 0 : y), msg, len);
777  ReleaseDC(global_hwnd, hdc);
778 
779  rpng2_win_load_bg_image(); /* resets bg_image if fails */
780  }
781 
782  if (!bg_image) {
783  for (j = 0; j < rpng2_info.height; ++j) {
784  dest = wimage_data + j*wimage_rowbytes;
785  for (i = rpng2_info.width; i > 0; --i) {
786  *dest++ = bg_blue;
787  *dest++ = bg_green;
788  *dest++ = bg_red;
789  }
790  }
791  }
792 
793  rect.left = 0L;
794  rect.top = 0L;
795  rect.right = (LONG)rpng2_info.width; /* possibly off by one? */
796  rect.bottom = (LONG)rpng2_info.height; /* possibly off by one? */
797  InvalidateRect(global_hwnd, &rect, FALSE);
798  UpdateWindow(global_hwnd); /* similar to XFlush() */
799 
800  return 0;
801 
802 } /* end function rpng2_win_create_window() */
803 
804 
805 
806 
807 
808 static int rpng2_win_load_bg_image()
809 {
810  uch *src, *dest;
811  uch r1, r2, g1, g2, b1, b2;
812  uch r1_inv, r2_inv, g1_inv, g2_inv, b1_inv, b2_inv;
813  int k, hmax, max;
814  int xidx, yidx, yidx_max = (bgscale-1);
815  int even_odd_vert, even_odd_horiz, even_odd;
816  int invert_gradient2 = (bg[pat].type & 0x08);
817  int invert_column;
818  ulg i, row;
819 
820 /*---------------------------------------------------------------------------
821  Allocate buffer for fake background image to be used with transparent
822  images; if this fails, revert to plain background color.
823  ---------------------------------------------------------------------------*/
824 
825  bg_rowbytes = 3 * rpng2_info.width;
826  bg_data = (uch *)malloc(bg_rowbytes * rpng2_info.height);
827  if (!bg_data) {
828  fprintf(stderr, PROGNAME
829  ": unable to allocate memory for background image\n");
830  bg_image = 0;
831  return 1;
832  }
833 
834 /*---------------------------------------------------------------------------
835  Vertical gradients (ramps) in NxN squares, alternating direction and
836  colors (N == bgscale).
837  ---------------------------------------------------------------------------*/
838 
839  if ((bg[pat].type & 0x07) == 0) {
840  uch r1_min = rgb[bg[pat].rgb1_min].r;
841  uch g1_min = rgb[bg[pat].rgb1_min].g;
842  uch b1_min = rgb[bg[pat].rgb1_min].b;
843  uch r2_min = rgb[bg[pat].rgb2_min].r;
844  uch g2_min = rgb[bg[pat].rgb2_min].g;
845  uch b2_min = rgb[bg[pat].rgb2_min].b;
846  int r1_diff = rgb[bg[pat].rgb1_max].r - r1_min;
847  int g1_diff = rgb[bg[pat].rgb1_max].g - g1_min;
848  int b1_diff = rgb[bg[pat].rgb1_max].b - b1_min;
849  int r2_diff = rgb[bg[pat].rgb2_max].r - r2_min;
850  int g2_diff = rgb[bg[pat].rgb2_max].g - g2_min;
851  int b2_diff = rgb[bg[pat].rgb2_max].b - b2_min;
852 
853  for (row = 0; row < rpng2_info.height; ++row) {
854  yidx = row % bgscale;
855  even_odd_vert = (row / bgscale) & 1;
856 
857  r1 = r1_min + (r1_diff * yidx) / yidx_max;
858  g1 = g1_min + (g1_diff * yidx) / yidx_max;
859  b1 = b1_min + (b1_diff * yidx) / yidx_max;
860  r1_inv = r1_min + (r1_diff * (yidx_max-yidx)) / yidx_max;
861  g1_inv = g1_min + (g1_diff * (yidx_max-yidx)) / yidx_max;
862  b1_inv = b1_min + (b1_diff * (yidx_max-yidx)) / yidx_max;
863 
864  r2 = r2_min + (r2_diff * yidx) / yidx_max;
865  g2 = g2_min + (g2_diff * yidx) / yidx_max;
866  b2 = b2_min + (b2_diff * yidx) / yidx_max;
867  r2_inv = r2_min + (r2_diff * (yidx_max-yidx)) / yidx_max;
868  g2_inv = g2_min + (g2_diff * (yidx_max-yidx)) / yidx_max;
869  b2_inv = b2_min + (b2_diff * (yidx_max-yidx)) / yidx_max;
870 
871  dest = bg_data + row*bg_rowbytes;
872  for (i = 0; i < rpng2_info.width; ++i) {
873  even_odd_horiz = (i / bgscale) & 1;
874  even_odd = even_odd_vert ^ even_odd_horiz;
875  invert_column =
876  (even_odd_horiz && (bg[pat].type & 0x10));
877  if (even_odd == 0) { /* gradient #1 */
878  if (invert_column) {
879  *dest++ = r1_inv;
880  *dest++ = g1_inv;
881  *dest++ = b1_inv;
882  } else {
883  *dest++ = r1;
884  *dest++ = g1;
885  *dest++ = b1;
886  }
887  } else { /* gradient #2 */
888  if ((invert_column && invert_gradient2) ||
889  (!invert_column && !invert_gradient2))
890  {
891  *dest++ = r2; /* not inverted or */
892  *dest++ = g2; /* doubly inverted */
893  *dest++ = b2;
894  } else {
895  *dest++ = r2_inv;
896  *dest++ = g2_inv; /* singly inverted */
897  *dest++ = b2_inv;
898  }
899  }
900  }
901  }
902 
903 /*---------------------------------------------------------------------------
904  Soft gradient-diamonds with scale = bgscale. Code contributed by Adam
905  M. Costello.
906  ---------------------------------------------------------------------------*/
907 
908  } else if ((bg[pat].type & 0x07) == 1) {
909 
910  hmax = (bgscale-1)/2; /* half the max weight of a color */
911  max = 2*hmax; /* the max weight of a color */
912 
913  r1 = rgb[bg[pat].rgb1_max].r;
914  g1 = rgb[bg[pat].rgb1_max].g;
915  b1 = rgb[bg[pat].rgb1_max].b;
916  r2 = rgb[bg[pat].rgb2_max].r;
917  g2 = rgb[bg[pat].rgb2_max].g;
918  b2 = rgb[bg[pat].rgb2_max].b;
919 
920  for (row = 0; row < rpng2_info.height; ++row) {
921  yidx = row % bgscale;
922  if (yidx > hmax)
923  yidx = bgscale-1 - yidx;
924  dest = bg_data + row*bg_rowbytes;
925  for (i = 0; i < rpng2_info.width; ++i) {
926  xidx = i % bgscale;
927  if (xidx > hmax)
928  xidx = bgscale-1 - xidx;
929  k = xidx + yidx;
930  *dest++ = (k*r1 + (max-k)*r2) / max;
931  *dest++ = (k*g1 + (max-k)*g2) / max;
932  *dest++ = (k*b1 + (max-k)*b2) / max;
933  }
934  }
935 
936 /*---------------------------------------------------------------------------
937  Radial "starburst" with azimuthal sinusoids; [eventually number of sinu-
938  soids will equal bgscale?]. This one is slow but very cool. Code con-
939  tributed by Pieter S. van der Meulen (originally in Smalltalk).
940  ---------------------------------------------------------------------------*/
941 
942  } else if ((bg[pat].type & 0x07) == 2) {
943  uch ch;
944  int ii, x, y, hw, hh, grayspot;
945  double freq, rotate, saturate, gray, intensity;
946  double angle=0.0, aoffset=0.0, maxDist, dist;
947  double red=0.0, green=0.0, blue=0.0, hue, s, v, f, p, q, t;
948 
949  fprintf(stderr, "%s: computing radial background...",
950  PROGNAME);
951  fflush(stderr);
952 
953  hh = rpng2_info.height / 2;
954  hw = rpng2_info.width / 2;
955 
956  /* variables for radial waves:
957  * aoffset: number of degrees to rotate hue [CURRENTLY NOT USED]
958  * freq: number of color beams originating from the center
959  * grayspot: size of the graying center area (anti-alias)
960  * rotate: rotation of the beams as a function of radius
961  * saturate: saturation of beams' shape azimuthally
962  */
963  angle = CLIP(angle, 0.0, 360.0);
964  grayspot = CLIP(bg[pat].bg_gray, 1, (hh + hw));
965  freq = MAX((double)bg[pat].bg_freq, 0.0);
966  saturate = (double)bg[pat].bg_bsat * 0.1;
967  rotate = (double)bg[pat].bg_brot * 0.1;
968  gray = 0.0;
969  intensity = 0.0;
970  maxDist = (double)((hw*hw) + (hh*hh));
971 
972  for (row = 0; row < rpng2_info.height; ++row) {
973  y = row - hh;
974  dest = bg_data + row*bg_rowbytes;
975  for (i = 0; i < rpng2_info.width; ++i) {
976  x = i - hw;
977  angle = (x == 0)? PI_2 : atan((double)y / (double)x);
978  gray = (double)MAX(ABS(y), ABS(x)) / grayspot;
979  gray = MIN(1.0, gray);
980  dist = (double)((x*x) + (y*y)) / maxDist;
981  intensity = cos((angle+(rotate*dist*PI)) * freq) *
982  gray * saturate;
983  intensity = (MAX(MIN(intensity,1.0),-1.0) + 1.0) * 0.5;
984  hue = (angle + PI) * INV_PI_360 + aoffset;
985  s = gray * ((double)(ABS(x)+ABS(y)) / (double)(hw + hh));
986  s = MIN(MAX(s,0.0), 1.0);
987  v = MIN(MAX(intensity,0.0), 1.0);
988 
989  if (s == 0.0) {
990  ch = (uch)(v * 255.0);
991  *dest++ = ch;
992  *dest++ = ch;
993  *dest++ = ch;
994  } else {
995  if ((hue < 0.0) || (hue >= 360.0))
996  hue -= (((int)(hue / 360.0)) * 360.0);
997  hue /= 60.0;
998  ii = (int)hue;
999  f = hue - (double)ii;
1000  p = (1.0 - s) * v;
1001  q = (1.0 - (s * f)) * v;
1002  t = (1.0 - (s * (1.0 - f))) * v;
1003  if (ii == 0) { red = v; green = t; blue = p; }
1004  else if (ii == 1) { red = q; green = v; blue = p; }
1005  else if (ii == 2) { red = p; green = v; blue = t; }
1006  else if (ii == 3) { red = p; green = q; blue = v; }
1007  else if (ii == 4) { red = t; green = p; blue = v; }
1008  else if (ii == 5) { red = v; green = p; blue = q; }
1009  *dest++ = (uch)(red * 255.0);
1010  *dest++ = (uch)(green * 255.0);
1011  *dest++ = (uch)(blue * 255.0);
1012  }
1013  }
1014  }
1015  fprintf(stderr, "done.\n");
1016  fflush(stderr);
1017  }
1018 
1019 /*---------------------------------------------------------------------------
1020  Blast background image to display buffer before beginning PNG decode;
1021  calling function will handle invalidation and UpdateWindow() call.
1022  ---------------------------------------------------------------------------*/
1023 
1024  for (row = 0; row < rpng2_info.height; ++row) {
1025  src = bg_data + row*bg_rowbytes;
1026  dest = wimage_data + row*wimage_rowbytes;
1027  for (i = rpng2_info.width; i > 0; --i) {
1028  r1 = *src++;
1029  g1 = *src++;
1030  b1 = *src++;
1031  *dest++ = b1;
1032  *dest++ = g1; /* note reverse order */
1033  *dest++ = r1;
1034  }
1035  }
1036 
1037  return 0;
1038 
1039 } /* end function rpng2_win_load_bg_image() */
1040 
1041 
1042 
1043 
1044 
1045 static void rpng2_win_display_row(ulg row)
1046 {
1047  uch bg_red = rpng2_info.bg_red;
1048  uch bg_green = rpng2_info.bg_green;
1049  uch bg_blue = rpng2_info.bg_blue;
1050  uch *src, *src2=NULL, *dest;
1051  uch r, g, b, a;
1052  ulg i;
1053  static int rows=0;
1054  static ulg firstrow;
1055 
1056 /*---------------------------------------------------------------------------
1057  rows and firstrow simply track how many rows (and which ones) have not
1058  yet been displayed; alternatively, we could call InvalidateRect() for
1059  every row and not bother with the records-keeping.
1060  ---------------------------------------------------------------------------*/
1061 
1062  Trace((stderr, "beginning rpng2_win_display_row()\n"))
1063 
1064  if (rows == 0)
1065  firstrow = row; /* first row not yet displayed */
1066 
1067  ++rows; /* count of rows received but not yet displayed */
1068 
1069 /*---------------------------------------------------------------------------
1070  Aside from the use of the rpng2_info struct and the lack of an outer
1071  loop (over rows), this routine is identical to rpng_win_display_image()
1072  in the non-progressive version of the program.
1073  ---------------------------------------------------------------------------*/
1074 
1075  src = rpng2_info.image_data + row*rpng2_info.rowbytes;
1076  if (bg_image)
1077  src2 = bg_data + row*bg_rowbytes;
1078  dest = wimage_data + row*wimage_rowbytes;
1079 
1080  if (rpng2_info.channels == 3) {
1081  for (i = rpng2_info.width; i > 0; --i) {
1082  r = *src++;
1083  g = *src++;
1084  b = *src++;
1085  *dest++ = b;
1086  *dest++ = g; /* note reverse order */
1087  *dest++ = r;
1088  }
1089  } else /* if (rpng2_info.channels == 4) */ {
1090  for (i = rpng2_info.width; i > 0; --i) {
1091  r = *src++;
1092  g = *src++;
1093  b = *src++;
1094  a = *src++;
1095  if (bg_image) {
1096  bg_red = *src2++;
1097  bg_green = *src2++;
1098  bg_blue = *src2++;
1099  }
1100  if (a == 255) {
1101  *dest++ = b;
1102  *dest++ = g;
1103  *dest++ = r;
1104  } else if (a == 0) {
1105  *dest++ = bg_blue;
1106  *dest++ = bg_green;
1107  *dest++ = bg_red;
1108  } else {
1109  /* this macro (copied from png.h) composites the
1110  * foreground and background values and puts the
1111  * result into the first argument; there are no
1112  * side effects with the first argument */
1113  alpha_composite(*dest++, b, a, bg_blue);
1114  alpha_composite(*dest++, g, a, bg_green);
1115  alpha_composite(*dest++, r, a, bg_red);
1116  }
1117  }
1118  }
1119 
1120 /*---------------------------------------------------------------------------
1121  Display after every 16 rows or when on last row. (Region may include
1122  previously displayed lines due to interlacing--i.e., not contiguous.)
1123  ---------------------------------------------------------------------------*/
1124 
1125  if ((rows & 0xf) == 0 || row == rpng2_info.height-1) {
1126  RECT rect;
1127 
1128  rect.left = 0L;
1129  rect.top = (LONG)firstrow;
1130  rect.right = (LONG)rpng2_info.width; /* possibly off by one? */
1131  rect.bottom = (LONG)row + 1L; /* possibly off by one? */
1132  InvalidateRect(global_hwnd, &rect, FALSE);
1133  UpdateWindow(global_hwnd); /* similar to XFlush() */
1134  rows = 0;
1135  }
1136 
1137 } /* end function rpng2_win_display_row() */
1138 
1139 
1140 
1141 
1142 
1143 static void rpng2_win_finish_display()
1144 {
1145  Trace((stderr, "beginning rpng2_win_finish_display()\n"))
1146 
1147  /* last row has already been displayed by rpng2_win_display_row(), so
1148  * we have nothing to do here except set a flag and let the user know
1149  * that the image is done */
1150 
1151  rpng2_info.state = kDone;
1152  printf(
1153  "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n");
1154  fflush(stdout);
1155 }
1156 
1157 
1158 
1159 
1160 
1161 static void rpng2_win_cleanup()
1162 {
1163  if (bg_image && bg_data) {
1164  free(bg_data);
1165  bg_data = NULL;
1166  }
1167 
1168  if (rpng2_info.image_data) {
1169  free(rpng2_info.image_data);
1170  rpng2_info.image_data = NULL;
1171  }
1172 
1173  if (rpng2_info.row_pointers) {
1174  free(rpng2_info.row_pointers);
1175  rpng2_info.row_pointers = NULL;
1176  }
1177 
1178  if (dib) {
1179  free(dib);
1180  dib = NULL;
1181  }
1182 }
1183 
1184 
1185 
1186 
1187 
1188 LRESULT CALLBACK rpng2_win_wndproc(HWND hwnd, UINT iMsg, WPARAM wP, LPARAM lP)
1189 {
1190  HDC hdc;
1191  PAINTSTRUCT ps;
1192  int rc;
1193 
1194  switch (iMsg) {
1195  case WM_CREATE:
1196  /* one-time processing here, if any */
1197  return 0;
1198 
1199  case WM_PAINT:
1200  hdc = BeginPaint(hwnd, &ps);
1201  rc = StretchDIBits(hdc, 0, 0, rpng2_info.width, rpng2_info.height,
1202  0, 0, rpng2_info.width, rpng2_info.height,
1203  wimage_data, (BITMAPINFO *)bmih,
1204  0, SRCCOPY);
1205  EndPaint(hwnd, &ps);
1206  return 0;
1207 
1208  /* wait for the user to tell us when to quit */
1209  case WM_CHAR:
1210  switch (wP) { /* only need one, so ignore repeat count */
1211  case 'q':
1212  case 'Q':
1213  case 0x1B: /* Esc key */
1214  PostQuitMessage(0);
1215  }
1216  return 0;
1217 
1218  case WM_LBUTTONDOWN: /* another way of quitting */
1219  case WM_DESTROY:
1220  PostQuitMessage(0);
1221  return 0;
1222  }
1223 
1224  return DefWindowProc(hwnd, iMsg, wP, lP);
1225 }
LRESULT CALLBACK rpng2_win_wndproc(HWND, UINT, WPARAM, LPARAM)
Definition: rpng2-win.c:1188
#define rgb1_max
Definition: rpng2-win.c:113
#define INV_PI_360
Definition: rpng2-win.c:105
#define PI
Definition: rpng2-win.c:102
GLboolean GLboolean GLboolean GLboolean a
GLfloat GLfloat p
void(* mainprog_init)(void)
Definition: readpng2.h:88
#define NULL
Definition: ftobjs.h:61
GLint GLint GLint GLint GLint GLint y
int readpng2_check_sig(uch *sig, int num)
Definition: readpng2.c:160
GLdouble GLdouble GLdouble GLdouble q
char * malloc()
#define ABS(a)
Definition: rpng2-win.c:109
GLint GLint GLint GLint GLint x
local void rotate(unsigned char *list, unsigned len, unsigned rot)
Definition: gzappend.c:123
const char * filename
Definition: ioapi.h:135
GLfloat green
unsigned long ulg
Definition: zutil.h:38
GLboolean GLboolean GLboolean b
void readpng2_version_info(void)
Definition: readpng2.c:74
png_uint_32 i
Definition: png.h:2640
GLenum GLenum GLvoid * row
GLfloat GLfloat blue
#define PI_2
Definition: rpng2-win.c:104
void readpng2_cleanup(mainprog_info *mainprog_ptr)
Definition: readpng2.c:607
GLenum GLsizei len
#define VERSION
Definition: rpng2-win.c:89
unsigned short ush
Definition: zutil.h:36
void(* mainprog_finish_display)(void)
Definition: readpng2.h:90
FT_Error error
Definition: cffdrivr.c:411
const GLdouble * v
#define INBUFSIZE
Definition: rpng2-win.c:135
GLdouble GLdouble GLdouble r
JHUFF_TBL long freq[]
Definition: jchuff.h:47
unsigned char inbuf[SIZE]
Definition: gun.c:161
#define PROGNAME
Definition: rpng2-win.c:87
#define CLIP(a, min, max)
Definition: rpng2-win.c:108
typedef long(ZCALLBACK *tell_file_func) OF((voidpf opaque
#define MIN(a, b)
Definition: rpng2-win.c:107
int free()
#define LONGNAME
Definition: rpng2-win.c:88
GLenum src
GLfloat angle
#define FALSE
Definition: ftobjs.h:57
T atan(T a)
Definition: glsl_math.hpp:277
#define alpha_composite(composite, fg, alpha, bg)
Definition: rpng2-win.c:128
local int max
Definition: enough.c:170
#define CALLBACK
Definition: Tessellator.hpp:41
#define Trace(x)
Definition: zutil.h:197
#define rgb2_max
Definition: rpng2-win.c:115
if(!abbox) return FT_THROW(Invalid_Argument)
GLenum type
int readpng2_decode_data(mainprog_info *mainprog_ptr, uch *rawbuf, ulg length)
Definition: readpng2.c:351
typedef int
Definition: png.h:978
FILE * infile
Definition: cdjpeg.h:141
uch * image_data
Definition: readpng2.h:91
#define rgb1_min
Definition: rpng2-win.c:114
int readpng2_init(mainprog_info *mainprog_ptr)
Definition: readpng2.c:170
double display_exponent
Definition: readpng2.h:83
T cos(T a)
Definition: glsl_math.hpp:225
GLdouble s
GLboolean GLboolean g
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode)
Definition: rpng2-win.c:247
Definition: readpng2.h:75
void(* mainprog_display_row)(ulg row_num)
Definition: readpng2.h:89
int double red
Definition: png.h:1498
GLdouble GLdouble t
int need_bgcolor
Definition: readpng2.h:98
GLfloat f
uch ** row_pointers
Definition: readpng2.h:92
#define rgb2_min
Definition: rpng2-win.c:116
#define TRUE
Definition: ftobjs.h:53
#define MAX(a, b)
Definition: rpng2-win.c:106
unsigned char uch
Definition: zutil.h:34
png_const_charp msg
Definition: PngFile.c:23