87 #define PROGNAME "rpng2-win" 88 #define LONGNAME "Progressive PNG Viewer for Windows" 89 #define VERSION "2.02 of 16 March 2008" 102 # define PI 3.141592653589793238 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))) 111 #define ROUNDF(f) ((int)(f + 0.5)) 113 #define rgb1_max bg_freq 114 #define rgb1_min bg_gray 115 #define rgb2_max bg_bsat 116 #define rgb2_min bg_brot 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); \ 135 #define INBUFSIZE 4096 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);
151 static char titlebar[1024];
163 static int bg_image = 0;
164 static int bgscale = 16;
165 static ulg bg_rowbytes;
168 static struct rgb_color {
209 static struct background_pattern {
228 {2, 16, 256, 100, 250},
229 {2, 10000, 256, 11, 0}
231 static int num_bgpat =
sizeof(bg) /
sizeof(
struct background_pattern);
235 static ulg wimage_rowbytes;
237 static uch *wimage_data;
238 static BITMAPINFOHEADER *bmih;
240 static HWND global_hwnd;
241 static HINSTANCE global_hInst;
242 static int global_showmode;
247 int WINAPI
WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd,
int showmode)
251 char *
p, *
q, *bgstr =
NULL;
258 double CRT_exponent = 2.2;
259 double default_display_exponent;
267 global_hInst = hInst;
268 global_showmode = showmode;
279 freopen(
"CONOUT$",
"a", stderr);
280 freopen(
"CONOUT$",
"a", stdout);
292 LUT_exponent = 1.0 / 2.2;
298 LUT_exponent = 1.0 / 1.7;
301 infile = fopen(
"/etc/config/system.glGammaVal",
"r");
305 fgets(tmpline, 80,
infile);
307 sgi_gamma = atof(tmpline);
309 LUT_exponent = 1.0 / sgi_gamma;
311 #elif defined(Macintosh) 312 LUT_exponent = 1.8 / 2.61;
322 default_display_exponent = LUT_exponent * CRT_exponent;
330 if ((p = getenv(
"SCREEN_GAMMA")) !=
NULL)
349 argv[argc++] = q =
p;
350 while (*q && *q !=
' ')
363 while (*++argv && !error) {
364 if (!strncmp(*argv,
"-gamma", 2)) {
372 }
else if (!strncmp(*argv,
"-bgcolor", 4)) {
377 if (strlen(bgstr) != 7 || bgstr[0] !=
'#')
384 }
else if (!strncmp(*argv,
"-bgpat", 4)) {
388 pat = atoi(*argv) - 1;
389 if (pat < 0 || pat >= num_bgpat)
396 }
else if (!strncmp(*argv,
"-timing", 2)) {
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;
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" 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" 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. ",
455 #
if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__))
458 (
int)strlen(
PROGNAME),
" ", default_display_exponent, num_bgpat);
462 while (ch !=
'q' && ch !=
'Q' && ch != 0x1B);
474 ": [%s] is not a PNG file: incorrect signature\n",
481 ": [%s] has bad IHDR (libpng longjmp)\n",
filename);
484 fprintf(stderr,
PROGNAME ": insufficient memory\n");
488 ": unknown readpng2_init() error\n");
501 fprintf(stderr,
PROGNAME ": aborting.\n");
504 while (ch !=
'q' && ch !=
'Q' && ch != 0x1B);
509 "\n [console window: closing this window will terminate %s]\n\n",
517 alen = strlen(appname);
519 if (alen + flen + 3 > 1023)
520 sprintf(titlebar,
"%s: ...%s", appname,
filename+(alen+flen+6-1023));
522 sprintf(titlebar,
"%s: %s", appname,
filename);
530 sscanf(bgstr+1,
"%2x%2x%2x", &r, &g, &b);
553 Trace((stderr,
"about to call readpng2_decode_data()\n"))
556 Trace((stderr,
"done with readpng2_decode_data()\n"))
560 Trace((stderr,
"done decoding PNG image\n"))
561 }
else if (ferror(
infile)) {
563 ": error while reading PNG image file\n");
565 }
else if (feof(
infile)) {
566 fprintf(stderr,
PROGNAME ": end of file reached " 567 "(unexpectedly) while reading PNG image file\n");
585 Trace((stderr,
"about to call readpng2_cleanup()\n"))
589 fprintf(stderr,
PROGNAME ": libpng error while decoding PNG image\n");
596 while (GetMessage(&msg,
NULL, 0, 0)) {
597 TranslateMessage(&msg);
598 DispatchMessage(&msg);
604 Trace((stderr,
"about to call rpng2_win_cleanup()\n"))
618 static void rpng2_win_init()
623 Trace((stderr,
"beginning rpng2_win_init()\n"))
625 Trace((stderr,
" width = %ld\n", rpng2_info.
width))
626 Trace((stderr,
" height = %ld\n", rpng2_info.
height))
642 for (i = 0; i < rpng2_info.
height; ++
i)
650 if (rpng2_win_create_window()) {
662 static int rpng2_win_create_window()
668 int extra_width, extra_height;
679 wimage_rowbytes = ((3*rpng2_info.
width + 3L) >> 2) << 2;
681 if (!(dib = (
uch *)
malloc(
sizeof(BITMAPINFOHEADER) +
682 wimage_rowbytes*rpng2_info.
height)))
694 memset(dib, 0,
sizeof(BITMAPINFOHEADER));
695 bmih = (BITMAPINFOHEADER *)dib;
696 bmih->biSize =
sizeof(BITMAPINFOHEADER);
697 bmih->biWidth = rpng2_info.
width;
700 bmih->biBitCount = 24;
701 bmih->biCompression = 0;
702 wimage_data = dib +
sizeof(BITMAPINFOHEADER);
711 memset(wimage_data, 0, wimage_rowbytes*rpng2_info.
height);
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) {
727 memset(&wndclass, 0,
sizeof(wndclass));
729 wndclass.cbSize =
sizeof(wndclass);
730 wndclass.style = CS_HREDRAW | CS_VREDRAW;
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);
740 RegisterClassEx(&wndclass);
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);
752 global_hwnd = CreateWindow(progname, titlebar, WS_OVERLAPPEDWINDOW,
753 CW_USEDEFAULT, CW_USEDEFAULT, rpng2_info.
width+extra_width,
756 ShowWindow(global_hwnd, global_showmode);
757 UpdateWindow(global_hwnd);
765 static const char *
msg =
"Computing background image...";
766 int x,
y,
len = strlen(msg);
767 HDC hdc = GetDC(global_hwnd);
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));
776 TextOut(hdc, ((x < 0)? 0 : x), ((y < 0)? 0 : y), msg, len);
777 ReleaseDC(global_hwnd, hdc);
779 rpng2_win_load_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) {
795 rect.right = (LONG)rpng2_info.
width;
796 rect.bottom = (LONG)rpng2_info.
height;
797 InvalidateRect(global_hwnd, &rect,
FALSE);
798 UpdateWindow(global_hwnd);
808 static int rpng2_win_load_bg_image()
811 uch r1, r2, g1, g2, b1, b2;
812 uch r1_inv, r2_inv, g1_inv, g2_inv, b1_inv, b2_inv;
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);
825 bg_rowbytes = 3 * rpng2_info.
width;
829 ": unable to allocate memory for background image\n");
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;
853 for (row = 0; row < rpng2_info.
height; ++
row) {
854 yidx = row % bgscale;
855 even_odd_vert = (row / bgscale) & 1;
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;
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;
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;
876 (even_odd_horiz && (bg[pat].type & 0x10));
888 if ((invert_column && invert_gradient2) ||
889 (!invert_column && !invert_gradient2))
908 }
else if ((bg[pat].
type & 0x07) == 1) {
910 hmax = (bgscale-1)/2;
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;
920 for (row = 0; row < rpng2_info.
height; ++
row) {
921 yidx = row % bgscale;
923 yidx = bgscale-1 - yidx;
924 dest = bg_data + row*bg_rowbytes;
925 for (i = 0; i < rpng2_info.
width; ++
i) {
928 xidx = bgscale-1 - xidx;
930 *dest++ = (k*r1 + (max-k)*r2) /
max;
931 *dest++ = (k*g1 + (max-k)*g2) /
max;
932 *dest++ = (k*b1 + (max-k)*b2) /
max;
942 }
else if ((bg[pat].
type & 0x07) == 2) {
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;
949 fprintf(stderr,
"%s: computing radial background...",
953 hh = rpng2_info.
height / 2;
954 hw = rpng2_info.
width / 2;
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;
970 maxDist = (double)((hw*hw) + (hh*hh));
972 for (row = 0; row < rpng2_info.
height; ++
row) {
974 dest = bg_data + row*bg_rowbytes;
975 for (i = 0; i < rpng2_info.
width; ++
i) {
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) *
983 intensity = (
MAX(
MIN(intensity,1.0),-1.0) + 1.0) * 0.5;
985 s = gray * ((double)(
ABS(x)+
ABS(y)) / (
double)(hw + hh));
987 v =
MIN(
MAX(intensity,0.0), 1.0);
990 ch = (
uch)(v * 255.0);
995 if ((hue < 0.0) || (hue >= 360.0))
996 hue -= (((
int)(hue / 360.0)) * 360.0);
999 f = hue - (double)ii;
1001 q = (1.0 - (s *
f)) *
v;
1002 t = (1.0 - (s * (1.0 -
f))) * v;
1009 *dest++ = (
uch)(red * 255.0);
1011 *dest++ = (
uch)(
blue * 255.0);
1015 fprintf(stderr,
"done.\n");
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) {
1045 static void rpng2_win_display_row(
ulg row)
1054 static ulg firstrow;
1062 Trace((stderr,
"beginning rpng2_win_display_row()\n"))
1077 src2 = bg_data + row*bg_rowbytes;
1078 dest = wimage_data + row*wimage_rowbytes;
1081 for (i = rpng2_info.
width; i > 0; --i) {
1090 for (i = rpng2_info.
width; i > 0; --i) {
1104 }
else if (a == 0) {
1125 if ((rows & 0xf) == 0 || row == rpng2_info.
height-1) {
1129 rect.top = (LONG)firstrow;
1130 rect.right = (LONG)rpng2_info.
width;
1131 rect.bottom = (LONG)row + 1L;
1132 InvalidateRect(global_hwnd, &rect,
FALSE);
1133 UpdateWindow(global_hwnd);
1143 static void rpng2_win_finish_display()
1145 Trace((stderr,
"beginning rpng2_win_finish_display()\n"))
1153 "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n");
1161 static void rpng2_win_cleanup()
1163 if (bg_image && bg_data) {
1200 hdc = BeginPaint(hwnd, &ps);
1201 rc = StretchDIBits(hdc, 0, 0, rpng2_info.
width, rpng2_info.
height,
1203 wimage_data, (BITMAPINFO *)bmih,
1205 EndPaint(hwnd, &ps);
1218 case WM_LBUTTONDOWN:
1224 return DefWindowProc(hwnd, iMsg, wP, lP);
LRESULT CALLBACK rpng2_win_wndproc(HWND, UINT, WPARAM, LPARAM)
GLboolean GLboolean GLboolean GLboolean a
void(* mainprog_init)(void)
GLint GLint GLint GLint GLint GLint y
int readpng2_check_sig(uch *sig, int num)
GLdouble GLdouble GLdouble GLdouble q
GLint GLint GLint GLint GLint x
local void rotate(unsigned char *list, unsigned len, unsigned rot)
GLboolean GLboolean GLboolean b
void readpng2_version_info(void)
GLenum GLenum GLvoid * row
void readpng2_cleanup(mainprog_info *mainprog_ptr)
void(* mainprog_finish_display)(void)
GLdouble GLdouble GLdouble r
unsigned char inbuf[SIZE]
#define CLIP(a, min, max)
typedef long(ZCALLBACK *tell_file_func) OF((voidpf opaque
#define alpha_composite(composite, fg, alpha, bg)
if(!abbox) return FT_THROW(Invalid_Argument)
int readpng2_decode_data(mainprog_info *mainprog_ptr, uch *rawbuf, ulg length)
int readpng2_init(mainprog_info *mainprog_ptr)
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode)
void(* mainprog_display_row)(ulg row_num)