95 #define PROGNAME "rpng2-x" 96 #define LONGNAME "Progressive PNG Viewer for X" 97 #define VERSION "2.02 of 16 March 2008" 98 #define RESNAME "rpng2" 99 #define RESCLASS "Rpng" 108 #include <X11/Xlib.h> 109 #include <X11/Xutil.h> 111 #include <X11/keysym.h> 119 # define PI 3.141592653589793238 121 #define PI_2 (PI*0.5) 122 #define INV_PI_360 (360.0 / PI) 123 #define MAX(a,b) (a>b?a:b) 124 #define MIN(a,b) (a<b?a:b) 125 #define CLIP(a,min,max) MAX(min,MIN((a),max)) 126 #define ABS(a) ((a)<0?-(a):(a)) 127 #define CLIP8P(c) MAX(0,(MIN((c),255))) 128 #define ROUNDF(f) ((int)(f + 0.5)) 130 #define QUIT(e,k) ((e.type == ButtonPress && e.xbutton.button == Button1) || \ 131 (e.type == KeyPress && \ 132 ((k = XLookupKeysym(&e.xkey, 0)) == XK_q || k == XK_Escape))) 134 #define NO_24BIT_MASKS 136 #define rgb1_max bg_freq 137 #define rgb1_min bg_gray 138 #define rgb2_max bg_bsat 139 #define rgb2_min bg_brot 151 #define alpha_composite(composite, fg, alpha, bg) { \ 152 ush temp = ((ush)(fg)*(ush)(alpha) + \ 153 (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128); \ 154 (composite) = (uch)((temp + (temp >> 8)) >> 8); \ 158 #define INBUFSIZE 4096 165 static void rpng2_x_init (
void);
166 static int rpng2_x_create_window (
void);
167 static int rpng2_x_load_bg_image (
void);
168 static void rpng2_x_display_row (
ulg row);
169 static void rpng2_x_finish_display (
void);
170 static void rpng2_x_redisplay_image (
ulg startcol,
ulg startrow,
173 static void rpng2_x_reload_bg_image (
void);
174 static int is_number (
char *
p);
176 static void rpng2_x_cleanup (
void);
177 static int rpng2_x_msb (
ulg u32val);
180 static char titlebar[1024], *window_name = titlebar;
183 static char *res_name =
RESNAME;
194 static int bg_image = 0;
195 static int bgscale, bgscale_default = 16;
196 static ulg bg_rowbytes;
203 static struct rgb_color {
245 static struct background_pattern {
265 {2, 16, 256, 100, 250},
266 {2, 10000, 256, 11, 0}
268 static int num_bgpat =
sizeof(bg) /
sizeof(
struct background_pattern);
272 static char *displayname;
273 static XImage *ximage;
274 static Display *display;
276 static Visual *visual;
277 static XVisualInfo *visual_list;
278 static int RShift, GShift, BShift;
279 static ulg RMask, GMask, BMask;
280 static Window window;
282 static Colormap colormap;
284 static int have_nondefault_visual =
FALSE;
285 static int have_colormap =
FALSE;
286 static int have_window =
FALSE;
287 static int have_gc =
FALSE;
292 int main(
int argc,
char **argv)
297 char *
p, *bgstr =
NULL;
304 long loop_interval = -1;
307 double CRT_exponent = 2.2;
308 double default_display_exponent;
317 displayname = (
char *)
NULL;
330 LUT_exponent = 1.0 / 2.2;
336 LUT_exponent = 1.0 / 1.7;
339 infile = fopen(
"/etc/config/system.glGammaVal",
"r");
343 fgets(tmpline, 80,
infile);
345 sgi_gamma = atof(tmpline);
347 LUT_exponent = 1.0 / sgi_gamma;
349 #elif defined(Macintosh) 350 LUT_exponent = 1.8 / 2.61;
360 default_display_exponent = LUT_exponent * CRT_exponent;
368 if ((p = getenv(
"SCREEN_GAMMA")) !=
NULL)
376 while (*++argv && !error) {
377 if (!strncmp(*argv,
"-display", 2)) {
382 }
else if (!strncmp(*argv,
"-gamma", 2)) {
390 }
else if (!strncmp(*argv,
"-bgcolor", 4)) {
395 if (strlen(bgstr) != 7 || bgstr[0] !=
'#')
402 }
else if (!strncmp(*argv,
"-bgpat", 4)) {
407 if (pat >= 0 && pat < num_bgpat) {
413 }
else if (!strncmp(*argv,
"-usleep", 2)) {
420 }
else if (!strncmp(*argv,
"-pause", 2)) {
422 }
else if (!strncmp(*argv,
"-timing", 2)) {
425 }
else if (!strncmp(*argv,
"-loop", 2)) {
427 if (!argv[1] || !is_number(argv[1]))
431 loop_interval = atol(*argv);
432 if (loop_interval < 0)
434 else if (loop_interval > 100000)
435 loop_interval = 100000;
438 #if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__)) 439 }
else if (!strncmp(*argv,
"-nommxfilters", 7)) {
440 rpng2_info.nommxfilters =
TRUE;
441 }
else if (!strncmp(*argv,
"-nommxcombine", 7)) {
442 rpng2_info.nommxcombine =
TRUE;
443 }
else if (!strncmp(*argv,
"-nommxinterlace", 7)) {
444 rpng2_info.nommxinterlace =
TRUE;
445 }
else if (!strcmp(*argv,
"-nommx")) {
446 rpng2_info.nommxfilters =
TRUE;
447 rpng2_info.nommxcombine =
TRUE;
448 rpng2_info.nommxinterlace =
TRUE;
470 "Usage: %s [-display xdpy] [-gamma exp] [-bgcolor bg | -bgpat pat]\n" 471 #
if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__))
472 " %*s [[-nommxfilters] [-nommxcombine] [-nommxinterlace] | -nommx]\n" 475 " %*s [-usleep dur | -timing] [-pause] [-loop [sec]] file.png\n\n" 477 " %*s [-usleep dur | -timing] [-pause] file.png\n\n" 479 " xdpy\tname of the target X display (e.g., ``hostname:0'')\n" 480 " exp \ttransfer-function exponent (``gamma'') of the display\n" 481 "\t\t system in floating-point format (e.g., ``%.1f''); equal\n" 482 "\t\t to the product of the lookup-table exponent (varies)\n" 483 "\t\t and the CRT exponent (usually 2.2); must be positive\n" 484 " bg \tdesired background color in 7-character hex RGB format\n" 485 "\t\t (e.g., ``#ff7700'' for orange: same as HTML colors);\n" 486 "\t\t used with transparent images; overrides -bgpat\n" 487 " pat \tdesired background pattern number (0-%d); used with\n" 488 "\t\t transparent images; overrides -bgcolor\n" 490 " -loop\tloops through background images after initial display\n" 491 "\t\t is complete (depends on -bgpat)\n" 492 " sec \tseconds to display each background image (default = 2)\n" 494 #
if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__))
495 " -nommx*\tdisable optimized MMX routines for decoding row filters,\n" 496 "\t\t combining rows, and expanding interlacing, respectively\n" 498 " dur \tduration in microseconds to wait after displaying each\n" 499 "\t\t row (for demo purposes)\n" 500 " -timing\tenables delay for every block read, to simulate modem\n" 501 "\t\t download of image (~36 Kbps)\n" 502 " -pause\tpauses after displaying each pass until mouse clicked\n" 503 "\nPress Q, Esc or mouse button 1 (within image window, after image\n" 504 "is displayed) to quit.\n" 506 #
if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__))
509 (
int)strlen(
PROGNAME),
" ", default_display_exponent, num_bgpat-1);
521 ": [%s] is not a PNG file: incorrect signature\n",
528 ": [%s] has bad IHDR (libpng longjmp)\n",
filename);
531 fprintf(stderr,
PROGNAME ": insufficient memory\n");
535 ": unknown readpng2_init() error\n");
540 Trace((stderr,
"about to call XOpenDisplay()\n"))
541 display = XOpenDisplay(displayname);
544 fprintf(stderr,
PROGNAME ": can't open X display [%s]\n",
545 displayname? displayname :
"default");
555 fprintf(stderr,
PROGNAME ": aborting.\n");
562 alen = strlen(appname);
564 if (alen + flen + 3 > 1023)
565 sprintf(titlebar,
"%s: ...%s", appname,
filename+(alen+flen+6-1023));
567 sprintf(titlebar,
"%s: %s", appname,
filename);
575 sscanf(bgstr+1,
"%2x%2x%2x", &r, &g, &b);
598 Trace((stderr,
"about to call readpng2_decode_data()\n"))
601 Trace((stderr,
"done with readpng2_decode_data()\n"))
605 Trace((stderr,
"done decoding PNG image\n"))
606 }
else if (ferror(
infile)) {
608 ": error while reading PNG image file\n");
610 }
else if (feof(
infile)) {
611 fprintf(stderr,
PROGNAME ": end of file reached " 612 "(unexpectedly) while reading PNG image file\n");
630 Trace((stderr,
"about to call readpng2_cleanup()\n"))
634 fprintf(stderr,
PROGNAME ": libpng error while decoding PNG image\n");
641 if (loop && bg_image) {
642 Trace((stderr,
"entering -loop loop (FEATURE_LOOP)\n"))
645 struct timeval now, then;
648 if (gettimeofday(&then,
NULL) == 0) {
649 then.tv_sec += loop_interval;
656 if (XCheckMaskEvent(display, KeyPressMask | ButtonPressMask, &e))
661 if (++pat >= num_bgpat)
663 rpng2_x_reload_bg_image();
666 if (use_sleep || gettimeofday(&now,
NULL) != 0) {
667 for (i = loop_interval; i > 0; --
i) {
670 if (XCheckMaskEvent(display, KeyPressMask | ButtonPressMask,
676 if (now.tv_sec < then.tv_sec ||
677 (now.tv_sec == then.tv_sec && now.tv_usec < then.tv_usec))
680 long seconds_to_go = then.tv_sec - now.tv_sec;
688 while (seconds_to_go-- > 1) {
689 int seconds_done = 0;
691 for (i = seconds_to_go; i > 0 && !
quit; --
i) {
694 if (XCheckMaskEvent(display, KeyPressMask |
695 ButtonPressMask, &e) &&
QUIT(e,k))
697 if (++seconds_done > 1000)
705 if (gettimeofday(&now,
NULL) == 0) {
706 if (now.tv_sec >= then.tv_sec)
708 seconds_to_go = then.tv_sec - now.tv_sec;
718 if (gettimeofday(&now,
NULL) == 0) {
719 usleep_usec = 1000000L*(then.tv_sec - now.tv_sec) +
720 then.tv_usec - now.tv_usec;
722 usleep((
ulg)usleep_usec);
729 rpng2_x_redisplay_image (0, 0, rpng2_info.
width, rpng2_info.
height);
739 Trace((stderr,
"entering final wait-for-quit-event loop\n"))
741 XNextEvent(display, &e);
742 if (e.type == Expose) {
743 XExposeEvent *ex = (XExposeEvent *)&e;
744 rpng2_x_redisplay_image (ex->x, ex->y, ex->width, ex->height);
746 }
while (!
QUIT(e,k));
748 fprintf(stderr,
PROGNAME ": init callback never called: probable " 749 "libpng error while decoding PNG metadata\n");
756 Trace((stderr,
"about to call rpng2_x_cleanup()\n"))
770 static void rpng2_x_init(
void)
775 Trace((stderr,
"beginning rpng2_x_init()\n"))
777 Trace((stderr,
" width = %ld\n", rpng2_info.
width))
778 Trace((stderr,
" height = %ld\n", rpng2_info.
height))
794 for (i = 0; i < rpng2_info.
height; ++
i)
802 if (rpng2_x_create_window()) {
821 static int rpng2_x_create_window(
void)
828 int need_colormap =
FALSE;
834 XSetWindowAttributes attr;
835 XTextProperty windowName, *pWindowName = &windowName;
836 XTextProperty iconName, *pIconName = &iconName;
837 XVisualInfo visual_info;
838 XSizeHints *size_hints;
840 XClassHint *class_hints;
843 Trace((stderr,
"beginning rpng2_x_create_window()\n"))
845 screen = DefaultScreen(display);
846 depth = DisplayPlanes(display, screen);
847 root = RootWindow(display, screen);
850 XSynchronize(display, True);
854 int visuals_matched = 0;
856 Trace((stderr,
"default depth is %d: checking other visuals\n",
860 visual_info.screen = screen;
861 visual_info.depth = 24;
862 visual_list = XGetVisualInfo(display,
863 VisualScreenMask | VisualDepthMask, &visual_info, &visuals_matched);
864 if (visuals_matched == 0) {
866 fprintf(stderr,
"default screen depth %d not supported, and no" 867 " 24-bit visuals found\n",
depth);
870 Trace((stderr,
"XGetVisualInfo() returned %d 24-bit visuals\n",
872 visual = visual_list[0].visual;
873 depth = visual_list[0].depth;
879 have_nondefault_visual =
TRUE;
880 need_colormap =
TRUE;
882 XMatchVisualInfo(display, screen,
depth, TrueColor, &visual_info);
883 visual = visual_info.visual;
886 RMask = visual->red_mask;
887 GMask = visual->green_mask;
888 BMask = visual->blue_mask;
891 if (
depth == 8 || need_colormap) {
892 colormap = XCreateColormap(display, root, visual, AllocNone);
894 fprintf(stderr,
"XCreateColormap() failed\n");
897 have_colormap =
TRUE;
902 RShift = 15 - rpng2_x_msb(RMask);
903 GShift = 15 - rpng2_x_msb(GMask);
904 BShift = 15 - rpng2_x_msb(BMask);
905 }
else if (
depth > 16) {
906 RShift = rpng2_x_msb(RMask) - 7;
907 GShift = rpng2_x_msb(GMask) - 7;
908 BShift = rpng2_x_msb(BMask) - 7;
910 if (
depth >= 15 && (RShift < 0 || GShift < 0 || BShift < 0)) {
911 fprintf(stderr,
"rpng2 internal logic error: negative X shift(s)!\n");
919 attr.backing_store = Always;
920 attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask;
921 attrmask = CWBackingStore | CWEventMask;
922 if (have_nondefault_visual) {
923 attr.colormap = colormap;
924 attr.background_pixel = 0;
925 attr.border_pixel = 1;
926 attrmask |= CWColormap | CWBackPixel | CWBorderPixel;
929 window = XCreateWindow(display, root, 0, 0, rpng2_info.
width,
930 rpng2_info.
height, 0,
depth, InputOutput, visual, attrmask, &attr);
932 if (window == None) {
933 fprintf(stderr,
"XCreateWindow() failed\n");
939 XSetWindowColormap(display, window, colormap);
941 if (!XStringListToTextProperty(&window_name, 1, pWindowName))
943 if (!XStringListToTextProperty(&icon_name, 1, pIconName))
948 if ((size_hints = XAllocSizeHints()) !=
NULL) {
950 size_hints->flags = PMinSize | PMaxSize;
951 size_hints->min_width = size_hints->max_width = (
int)rpng2_info.
width;
952 size_hints->min_height = size_hints->max_height =
956 if ((wm_hints = XAllocWMHints()) !=
NULL) {
957 wm_hints->initial_state = NormalState;
958 wm_hints->input = True;
960 wm_hints->flags = StateHint | InputHint ;
963 if ((class_hints = XAllocClassHint()) !=
NULL) {
964 class_hints->res_name = res_name;
965 class_hints->res_class = res_class;
968 XSetWMProperties(display, window, pWindowName, pIconName,
NULL, 0,
969 size_hints, wm_hints, class_hints);
973 XFree(pWindowName->value);
975 XFree(pIconName->value);
983 XMapWindow(display, window);
985 gc = XCreateGC(display, window, 0, &gcvalues);
995 }
else if (
depth == 16) {
1004 fprintf(stderr,
PROGNAME ": unable to allocate image memory\n");
1008 ximage = XCreateImage(display, visual,
depth, ZPixmap, 0,
1009 (
char *)xdata, rpng2_info.
width, rpng2_info.
height, pad, 0);
1012 fprintf(stderr,
PROGNAME ": XCreateImage() failed\n");
1033 rpng2_x_load_bg_image();
1037 bg_pixel = (bg_red << RShift) |
1038 (bg_green << GShift) |
1039 (bg_blue << BShift);
1040 }
else if (
depth == 16) {
1041 bg_pixel = (((bg_red << 8) >> RShift) & RMask) |
1042 (((bg_green << 8) >> GShift) & GMask) |
1043 (((bg_blue << 8) >> BShift) & BMask);
1049 XSetForeground(display, gc, bg_pixel);
1050 XFillRectangle(display, window, gc, 0, 0, rpng2_info.
width,
1059 XNextEvent(display, &e);
1060 while (e.type != Expose || e.xexpose.count);
1072 static int rpng2_x_load_bg_image(
void)
1076 uch r1, r2, g1, g2, b1, b2;
1077 uch r1_inv, r2_inv, g1_inv, g2_inv, b1_inv, b2_inv;
1079 int xidx, yidx, yidx_max;
1080 int even_odd_vert, even_odd_horiz, even_odd;
1081 int invert_gradient2 = (bg[pat].type & 0x08);
1083 int ximage_rowbytes = ximage->bytes_per_line;
1092 bg_rowbytes = 3 * rpng2_info.
width;
1096 ": unable to allocate memory for background image\n");
1101 bgscale = (pat == 0)? 8 : bgscale_default;
1102 yidx_max = bgscale - 1;
1109 if ((bg[pat].
type & 0x07) == 0) {
1110 uch r1_min = rgb[bg[pat].rgb1_min].r;
1111 uch g1_min = rgb[bg[pat].rgb1_min].g;
1112 uch b1_min = rgb[bg[pat].rgb1_min].b;
1113 uch r2_min = rgb[bg[pat].rgb2_min].r;
1114 uch g2_min = rgb[bg[pat].rgb2_min].g;
1115 uch b2_min = rgb[bg[pat].rgb2_min].b;
1116 int r1_diff = rgb[bg[pat].rgb1_max].r - r1_min;
1117 int g1_diff = rgb[bg[pat].rgb1_max].g - g1_min;
1118 int b1_diff = rgb[bg[pat].rgb1_max].b - b1_min;
1119 int r2_diff = rgb[bg[pat].rgb2_max].r - r2_min;
1120 int g2_diff = rgb[bg[pat].rgb2_max].g - g2_min;
1121 int b2_diff = rgb[bg[pat].rgb2_max].b - b2_min;
1123 for (row = 0; row < rpng2_info.
height; ++
row) {
1124 yidx = (
int)(row % bgscale);
1125 even_odd_vert = (
int)((row / bgscale) & 1);
1127 r1 = r1_min + (r1_diff * yidx) / yidx_max;
1128 g1 = g1_min + (g1_diff * yidx) / yidx_max;
1129 b1 = b1_min + (b1_diff * yidx) / yidx_max;
1130 r1_inv = r1_min + (r1_diff * (yidx_max-yidx)) / yidx_max;
1131 g1_inv = g1_min + (g1_diff * (yidx_max-yidx)) / yidx_max;
1132 b1_inv = b1_min + (b1_diff * (yidx_max-yidx)) / yidx_max;
1134 r2 = r2_min + (r2_diff * yidx) / yidx_max;
1135 g2 = g2_min + (g2_diff * yidx) / yidx_max;
1136 b2 = b2_min + (b2_diff * yidx) / yidx_max;
1137 r2_inv = r2_min + (r2_diff * (yidx_max-yidx)) / yidx_max;
1138 g2_inv = g2_min + (g2_diff * (yidx_max-yidx)) / yidx_max;
1139 b2_inv = b2_min + (b2_diff * (yidx_max-yidx)) / yidx_max;
1141 dest = (
char *)bg_data + row*bg_rowbytes;
1142 for (i = 0; i < rpng2_info.
width; ++
i) {
1143 even_odd_horiz = (
int)((i / bgscale) & 1);
1144 even_odd = even_odd_vert ^ even_odd_horiz;
1146 (even_odd_horiz && (bg[pat].type & 0x10));
1147 if (even_odd == 0) {
1148 if (invert_column) {
1158 if ((invert_column && invert_gradient2) ||
1159 (!invert_column && !invert_gradient2))
1178 }
else if ((bg[pat].
type & 0x07) == 1) {
1180 hmax = (bgscale-1)/2;
1183 r1 = rgb[bg[pat].rgb1_max].r;
1184 g1 = rgb[bg[pat].rgb1_max].g;
1185 b1 = rgb[bg[pat].rgb1_max].b;
1186 r2 = rgb[bg[pat].rgb2_max].r;
1187 g2 = rgb[bg[pat].rgb2_max].g;
1188 b2 = rgb[bg[pat].rgb2_max].b;
1190 for (row = 0; row < rpng2_info.
height; ++
row) {
1191 yidx = (
int)(row % bgscale);
1193 yidx = bgscale-1 - yidx;
1194 dest = (
char *)bg_data + row*bg_rowbytes;
1195 for (i = 0; i < rpng2_info.
width; ++
i) {
1196 xidx = (
int)(i % bgscale);
1198 xidx = bgscale-1 - xidx;
1200 *dest++ = (k*r1 + (max-k)*r2) /
max;
1201 *dest++ = (k*g1 + (max-k)*g2) /
max;
1202 *dest++ = (k*b1 + (max-k)*b2) /
max;
1212 }
else if ((bg[pat].
type & 0x07) == 2) {
1214 int ii,
x,
y, hw, hh, grayspot;
1215 double freq,
rotate, saturate, gray, intensity;
1216 double angle=0.0, aoffset=0.0, maxDist, dist;
1219 fprintf(stderr,
"%s: computing radial background...",
1233 angle =
CLIP(angle, 0.0, 360.0);
1234 grayspot =
CLIP(bg[pat].bg_gray, 1, (hh + hw));
1235 freq =
MAX((
double)bg[pat].bg_freq, 0.0);
1236 saturate = (double)bg[pat].bg_bsat * 0.1;
1237 rotate = (double)bg[pat].bg_brot * 0.1;
1240 maxDist = (double)((hw*hw) + (hh*hh));
1242 for (row = 0; row < rpng2_info.
height; ++
row) {
1243 y = (
int)(row - hh);
1244 dest = (
char *)bg_data + row*bg_rowbytes;
1245 for (i = 0; i < rpng2_info.
width; ++
i) {
1247 angle = (x == 0)?
PI_2 :
atan((
double)y / (double)x);
1248 gray = (double)
MAX(
ABS(y),
ABS(x)) / grayspot;
1249 gray =
MIN(1.0, gray);
1250 dist = (double)((x*x) + (y*
y)) / maxDist;
1251 intensity =
cos((angle+(rotate*dist*
PI)) * freq) *
1253 intensity = (
MAX(
MIN(intensity,1.0),-1.0) + 1.0) * 0.5;
1255 s = gray * ((double)(
ABS(x)+
ABS(y)) / (
double)(hw + hh));
1256 s =
MIN(
MAX(s,0.0), 1.0);
1257 v =
MIN(
MAX(intensity,0.0), 1.0);
1260 ch = (
uch)(v * 255.0);
1265 if ((hue < 0.0) || (hue >= 360.0))
1266 hue -= (((
int)(hue / 360.0)) * 360.0);
1269 f = hue - (double)ii;
1271 q = (1.0 - (s *
f)) *
v;
1272 t = (1.0 - (s * (1.0 -
f))) * v;
1279 *dest++ = (
uch)(red * 255.0);
1281 *dest++ = (
uch)(
blue * 255.0);
1285 fprintf(stderr,
"done.\n");
1295 int bpp = ximage->bits_per_pixel;
1297 for (row = 0; row < rpng2_info.
height; ++
row) {
1298 src = bg_data + row*bg_rowbytes;
1299 dest = ximage->data + row*ximage_rowbytes;
1301 for (i = rpng2_info.
width; i > 0; --i) {
1305 pixel = (red << RShift) |
1309 *dest++ = (char)((pixel >> 24) & 0xff);
1310 *dest++ = (char)((pixel >> 16) & 0xff);
1311 *dest++ = (char)((pixel >> 8) & 0xff);
1312 *dest++ = (char)( pixel & 0xff);
1315 for (i = rpng2_info.
width; i > 0; --i) {
1319 pixel = (red << RShift) |
1325 *dest++ = (char)((pixel >> 16) & 0xff);
1326 *dest++ = (char)((pixel >> 8) & 0xff);
1327 *dest++ = (char)( pixel & 0xff);
1332 }
else if (
depth == 16) {
1335 for (row = 0; row < rpng2_info.
height; ++
row) {
1336 src = bg_data + row*bg_rowbytes;
1337 dest = ximage->data + row*ximage_rowbytes;
1338 for (i = rpng2_info.
width; i > 0; --i) {
1339 red = ((
ush)(*src) << 8); ++
src;
1340 green = ((
ush)(*src) << 8); ++
src;
1341 blue = ((
ush)(*src) << 8); ++
src;
1342 pixel = ((red >> RShift) & RMask) |
1343 ((green >> GShift) & GMask) |
1344 ((blue >> BShift) & BMask);
1346 *dest++ = (char)((pixel >> 8) & 0xff);
1347 *dest++ = (char)( pixel & 0xff);
1357 XPutImage(display, window, gc, ximage, 0, 0, 0, 0, rpng2_info.
width,
1368 static void rpng2_x_display_row(
ulg row)
1376 int ximage_rowbytes = ximage->bytes_per_line;
1378 static int rows=0, prevpass=(-1);
1379 static ulg firstrow;
1387 Trace((stderr,
"beginning rpng2_x_display_row()\n"))
1389 if (rpng2_info.
pass != prevpass) {
1395 "%s: end of pass %d of 7; click in image window to continue\n",
1398 XNextEvent(display, &e);
1401 fprintf(stderr,
"%s: pass %d of 7\r",
PROGNAME, rpng2_info.
pass + 1);
1403 prevpass = rpng2_info.
pass;
1420 int bpp = ximage->bits_per_pixel;
1424 src2 = bg_data + row*bg_rowbytes;
1425 dest = ximage->data + row*ximage_rowbytes;
1427 for (i = rpng2_info.
width; i > 0; --i) {
1431 pixel = (red << RShift) |
1436 *dest++ = (char)((pixel >> 24) & 0xff);
1437 *dest++ = (char)((pixel >> 16) & 0xff);
1438 *dest++ = (char)((pixel >> 8) & 0xff);
1439 *dest++ = (char)( pixel & 0xff);
1443 *dest++ = (char)((pixel >> 16) & 0xff);
1444 *dest++ = (char)((pixel >> 8) & 0xff);
1445 *dest++ = (char)( pixel & 0xff);
1449 for (i = rpng2_info.
width; i > 0; --i) {
1463 }
else if (a == 0) {
1475 pixel = (red << RShift) |
1480 *dest++ = (char)((pixel >> 24) & 0xff);
1481 *dest++ = (char)((pixel >> 16) & 0xff);
1482 *dest++ = (char)((pixel >> 8) & 0xff);
1483 *dest++ = (char)( pixel & 0xff);
1487 *dest++ = (char)((pixel >> 16) & 0xff);
1488 *dest++ = (char)((pixel >> 8) & 0xff);
1489 *dest++ = (char)( pixel & 0xff);
1494 }
else if (
depth == 16) {
1499 src2 = bg_data + row*bg_rowbytes;
1500 dest = ximage->data + row*ximage_rowbytes;
1502 for (i = rpng2_info.
width; i > 0; --i) {
1503 red = ((
ush)(*src) << 8);
1505 green = ((
ush)(*src) << 8);
1507 blue = ((
ush)(*src) << 8);
1509 pixel = ((red >> RShift) & RMask) |
1510 ((green >> GShift) & GMask) |
1511 ((blue >> BShift) & BMask);
1513 *dest++ = (char)((pixel >> 8) & 0xff);
1514 *dest++ = (char)( pixel & 0xff);
1517 for (i = rpng2_info.
width; i > 0; --i) {
1528 red = ((
ush)r << 8);
1529 green = ((
ush)g << 8);
1530 blue = ((
ush)b << 8);
1531 }
else if (a == 0) {
1532 red = ((
ush)bg_red << 8);
1533 green = ((
ush)bg_green << 8);
1534 blue = ((
ush)bg_blue << 8);
1542 red = ((
ush)r << 8);
1543 green = ((
ush)g << 8);
1544 blue = ((
ush)b << 8);
1546 pixel = ((red >> RShift) & RMask) |
1547 ((green >> GShift) & GMask) |
1548 ((blue >> BShift) & BMask);
1550 *dest++ = (char)((pixel >> 8) & 0xff);
1551 *dest++ = (char)( pixel & 0xff);
1571 XPutImage(display, window, gc, ximage, 0, (
int)firstrow, 0,
1572 (
int)firstrow, rpng2_info.
width, row - firstrow + 1);
1578 XPutImage(display, window, gc, ximage, 0, (
int)firstrow, 0,
1579 (
int)firstrow, rpng2_info.
width, row - firstrow + 1);
1590 static void rpng2_x_finish_display(
void)
1592 Trace((stderr,
"beginning rpng2_x_finish_display()\n"))
1600 "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n");
1608 static void rpng2_x_redisplay_image(
ulg startcol,
ulg startrow,
1619 int ximage_rowbytes = ximage->bytes_per_line;
1622 Trace((stderr,
"beginning display loop (image_channels == %d)\n",
1624 Trace((stderr,
" (width = %ld, rowbytes = %d, ximage_rowbytes = %d)\n",
1626 Trace((stderr,
" (bpp = %d)\n", ximage->bits_per_pixel))
1627 Trace((stderr,
" (byte_order = %s)\n", ximage->byte_order ==
MSBFirst?
1628 "MSBFirst" : (ximage->byte_order ==
LSBFirst?
"LSBFirst" :
"unknown")))
1640 int bpp = ximage->bits_per_pixel;
1642 for (lastrow = row = startrow; row < startrow+
height; ++
row) {
1645 src2 = bg_data + row*bg_rowbytes;
1646 dest = ximage->data + row*ximage_rowbytes;
1648 for (i = rpng2_info.
width; i > 0; --i) {
1652 #ifdef NO_24BIT_MASKS 1653 pixel = (red << RShift) |
1658 *dest++ = (char)((pixel >> 24) & 0xff);
1659 *dest++ = (char)((pixel >> 16) & 0xff);
1660 *dest++ = (char)((pixel >> 8) & 0xff);
1661 *dest++ = (char)( pixel & 0xff);
1665 *dest++ = (char)((pixel >> 16) & 0xff);
1666 *dest++ = (char)((pixel >> 8) & 0xff);
1667 *dest++ = (char)( pixel & 0xff);
1670 red = (RShift < 0)? red << (-RShift) : red >> RShift;
1671 green = (GShift < 0)? green << (-GShift) : green >> GShift;
1672 blue = (BShift < 0)? blue << (-BShift) : blue >> BShift;
1673 pixel = (red & RMask) | (green & GMask) | (blue & BMask);
1676 *dest++ = (char)((pixel >> 24) & 0xff);
1677 *dest++ = (char)((pixel >> 16) & 0xff);
1678 *dest++ = (char)((pixel >> 8) & 0xff);
1679 *dest++ = (char)( pixel & 0xff);
1684 *dest++ = (char)((pixel >> 16) & 0xff);
1685 *dest++ = (char)((pixel >> 8) & 0xff);
1686 *dest++ = (char)( pixel & 0xff);
1692 for (i = rpng2_info.
width; i > 0; --i) {
1706 }
else if (a == 0) {
1718 #ifdef NO_24BIT_MASKS 1719 pixel = (red << RShift) |
1724 *dest++ = (char)((pixel >> 24) & 0xff);
1725 *dest++ = (char)((pixel >> 16) & 0xff);
1726 *dest++ = (char)((pixel >> 8) & 0xff);
1727 *dest++ = (char)( pixel & 0xff);
1731 *dest++ = (char)((pixel >> 16) & 0xff);
1732 *dest++ = (char)((pixel >> 8) & 0xff);
1733 *dest++ = (char)( pixel & 0xff);
1736 red = (RShift < 0)? red << (-RShift) : red >> RShift;
1737 green = (GShift < 0)? green << (-GShift) : green >> GShift;
1738 blue = (BShift < 0)? blue << (-BShift) : blue >> BShift;
1739 pixel = (red & RMask) | (green & GMask) | (blue & BMask);
1742 *dest++ = (char)((pixel >> 24) & 0xff);
1743 *dest++ = (char)((pixel >> 16) & 0xff);
1744 *dest++ = (char)((pixel >> 8) & 0xff);
1745 *dest++ = (char)( pixel & 0xff);
1750 *dest++ = (char)((pixel >> 16) & 0xff);
1751 *dest++ = (char)((pixel >> 8) & 0xff);
1752 *dest++ = (char)( pixel & 0xff);
1758 if (((row+1) & 0xf) == 0) {
1759 XPutImage(display, window, gc, ximage, 0, (
int)lastrow, 0,
1760 (
int)lastrow, rpng2_info.
width, 16);
1766 }
else if (
depth == 16) {
1769 for (lastrow = row = startrow; row < startrow+
height; ++
row) {
1772 src2 = bg_data + row*bg_rowbytes;
1773 dest = ximage->data + row*ximage_rowbytes;
1775 for (i = rpng2_info.
width; i > 0; --i) {
1776 red = ((
ush)(*src) << 8);
1778 green = ((
ush)(*src) << 8);
1780 blue = ((
ush)(*src) << 8);
1782 pixel = ((red >> RShift) & RMask) |
1783 ((green >> GShift) & GMask) |
1784 ((blue >> BShift) & BMask);
1786 *dest++ = (char)((pixel >> 8) & 0xff);
1787 *dest++ = (char)( pixel & 0xff);
1790 for (i = rpng2_info.
width; i > 0; --i) {
1801 red = ((
ush)r << 8);
1802 green = ((
ush)g << 8);
1803 blue = ((
ush)b << 8);
1804 }
else if (a == 0) {
1805 red = ((
ush)bg_red << 8);
1806 green = ((
ush)bg_green << 8);
1807 blue = ((
ush)bg_blue << 8);
1815 red = ((
ush)r << 8);
1816 green = ((
ush)g << 8);
1817 blue = ((
ush)b << 8);
1819 pixel = ((red >> RShift) & RMask) |
1820 ((green >> GShift) & GMask) |
1821 ((blue >> BShift) & BMask);
1823 *dest++ = (char)((pixel >> 8) & 0xff);
1824 *dest++ = (char)( pixel & 0xff);
1828 if (((row+1) & 0xf) == 0) {
1829 XPutImage(display, window, gc, ximage, 0, (
int)lastrow, 0,
1830 (
int)lastrow, rpng2_info.
width, 16);
1842 Trace((stderr,
"calling final XPutImage()\n"))
1843 if (lastrow < startrow+height) {
1844 XPutImage(display, window, gc, ximage, 0, (
int)lastrow, 0,
1845 (
int)lastrow, rpng2_info.
width, rpng2_info.
height-lastrow);
1857 static void rpng2_x_reload_bg_image(
void)
1860 uch r1, r2, g1, g2, b1, b2;
1861 uch r1_inv, r2_inv, g1_inv, g2_inv, b1_inv, b2_inv;
1863 int xidx, yidx, yidx_max;
1864 int even_odd_vert, even_odd_horiz, even_odd;
1865 int invert_gradient2 = (bg[pat].type & 0x08);
1870 bgscale = (pat == 0)? 8 : bgscale_default;
1871 yidx_max = bgscale - 1;
1878 if ((bg[pat].
type & 0x07) == 0) {
1879 uch r1_min = rgb[bg[pat].rgb1_min].r;
1880 uch g1_min = rgb[bg[pat].rgb1_min].g;
1881 uch b1_min = rgb[bg[pat].rgb1_min].b;
1882 uch r2_min = rgb[bg[pat].rgb2_min].r;
1883 uch g2_min = rgb[bg[pat].rgb2_min].g;
1884 uch b2_min = rgb[bg[pat].rgb2_min].b;
1885 int r1_diff = rgb[bg[pat].rgb1_max].r - r1_min;
1886 int g1_diff = rgb[bg[pat].rgb1_max].g - g1_min;
1887 int b1_diff = rgb[bg[pat].rgb1_max].b - b1_min;
1888 int r2_diff = rgb[bg[pat].rgb2_max].r - r2_min;
1889 int g2_diff = rgb[bg[pat].rgb2_max].g - g2_min;
1890 int b2_diff = rgb[bg[pat].rgb2_max].b - b2_min;
1892 for (row = 0; row < rpng2_info.
height; ++
row) {
1893 yidx = (
int)(row % bgscale);
1894 even_odd_vert = (
int)((row / bgscale) & 1);
1896 r1 = r1_min + (r1_diff * yidx) / yidx_max;
1897 g1 = g1_min + (g1_diff * yidx) / yidx_max;
1898 b1 = b1_min + (b1_diff * yidx) / yidx_max;
1899 r1_inv = r1_min + (r1_diff * (yidx_max-yidx)) / yidx_max;
1900 g1_inv = g1_min + (g1_diff * (yidx_max-yidx)) / yidx_max;
1901 b1_inv = b1_min + (b1_diff * (yidx_max-yidx)) / yidx_max;
1903 r2 = r2_min + (r2_diff * yidx) / yidx_max;
1904 g2 = g2_min + (g2_diff * yidx) / yidx_max;
1905 b2 = b2_min + (b2_diff * yidx) / yidx_max;
1906 r2_inv = r2_min + (r2_diff * (yidx_max-yidx)) / yidx_max;
1907 g2_inv = g2_min + (g2_diff * (yidx_max-yidx)) / yidx_max;
1908 b2_inv = b2_min + (b2_diff * (yidx_max-yidx)) / yidx_max;
1910 dest = (
char *)bg_data + row*bg_rowbytes;
1911 for (i = 0; i < rpng2_info.
width; ++
i) {
1912 even_odd_horiz = (
int)((i / bgscale) & 1);
1913 even_odd = even_odd_vert ^ even_odd_horiz;
1915 (even_odd_horiz && (bg[pat].type & 0x10));
1916 if (even_odd == 0) {
1917 if (invert_column) {
1927 if ((invert_column && invert_gradient2) ||
1928 (!invert_column && !invert_gradient2))
1947 }
else if ((bg[pat].
type & 0x07) == 1) {
1949 hmax = (bgscale-1)/2;
1952 r1 = rgb[bg[pat].rgb1_max].r;
1953 g1 = rgb[bg[pat].rgb1_max].g;
1954 b1 = rgb[bg[pat].rgb1_max].b;
1955 r2 = rgb[bg[pat].rgb2_max].r;
1956 g2 = rgb[bg[pat].rgb2_max].g;
1957 b2 = rgb[bg[pat].rgb2_max].b;
1959 for (row = 0; row < rpng2_info.
height; ++
row) {
1960 yidx = (
int)(row % bgscale);
1962 yidx = bgscale-1 - yidx;
1963 dest = (
char *)bg_data + row*bg_rowbytes;
1964 for (i = 0; i < rpng2_info.
width; ++
i) {
1965 xidx = (
int)(i % bgscale);
1967 xidx = bgscale-1 - xidx;
1969 *dest++ = (k*r1 + (max-k)*r2) /
max;
1970 *dest++ = (k*g1 + (max-k)*g2) /
max;
1971 *dest++ = (k*b1 + (max-k)*b2) /
max;
1981 }
else if ((bg[pat].
type & 0x07) == 2) {
1983 int ii,
x,
y, hw, hh, grayspot;
1984 double freq,
rotate, saturate, gray, intensity;
1985 double angle=0.0, aoffset=0.0, maxDist, dist;
1998 angle =
CLIP(angle, 0.0, 360.0);
1999 grayspot =
CLIP(bg[pat].bg_gray, 1, (hh + hw));
2000 freq =
MAX((
double)bg[pat].bg_freq, 0.0);
2001 saturate = (double)bg[pat].bg_bsat * 0.1;
2002 rotate = (double)bg[pat].bg_brot * 0.1;
2005 maxDist = (double)((hw*hw) + (hh*hh));
2007 for (row = 0; row < rpng2_info.
height; ++
row) {
2008 y = (
int)(row - hh);
2009 dest = (
char *)bg_data + row*bg_rowbytes;
2010 for (i = 0; i < rpng2_info.
width; ++
i) {
2012 angle = (x == 0)?
PI_2 :
atan((
double)y / (double)x);
2013 gray = (double)
MAX(
ABS(y),
ABS(x)) / grayspot;
2014 gray =
MIN(1.0, gray);
2015 dist = (double)((x*x) + (y*
y)) / maxDist;
2016 intensity =
cos((angle+(rotate*dist*
PI)) * freq) *
2018 intensity = (
MAX(
MIN(intensity,1.0),-1.0) + 1.0) * 0.5;
2020 s = gray * ((double)(
ABS(x)+
ABS(y)) / (
double)(hw + hh));
2021 s =
MIN(
MAX(s,0.0), 1.0);
2022 v =
MIN(
MAX(intensity,0.0), 1.0);
2025 ch = (
uch)(v * 255.0);
2030 if ((hue < 0.0) || (hue >= 360.0))
2031 hue -= (((
int)(hue / 360.0)) * 360.0);
2034 f = hue - (double)ii;
2036 q = (1.0 - (s *
f)) *
v;
2037 t = (1.0 - (s * (1.0 -
f))) * v;
2044 *dest++ = (
uch)(red * 255.0);
2046 *dest++ = (
uch)(
blue * 255.0);
2058 static int is_number(
char *
p)
2074 static void rpng2_x_cleanup(
void)
2076 if (bg_image && bg_data) {
2094 ximage->data = (
char *)
NULL;
2096 XDestroyImage(ximage);
2101 XFreeGC(display, gc);
2104 XDestroyWindow(display, window);
2107 XFreeColormap(display, colormap);
2109 if (have_nondefault_visual)
2117 static int rpng2_x_msb(
ulg u32val)
2121 for (i = 31; i >= 0; --
i) {
2122 if (u32val & 0x80000000L)
#define alpha_composite(composite, fg, alpha, bg)
GLint GLint GLsizei GLsizei height
GLboolean GLboolean GLboolean GLboolean a
GLint GLint GLsizei GLsizei GLsizei depth
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 GLsizei width
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]
int main(int argc, char **argv)
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)
void(* mainprog_display_row)(ulg row_num)
#define CLIP(a, min, max)
local void quit(char *why)