📄 rpng2-x.c
字号:
r1 = rgb[bg[pat].rgb1_max].r;
g1 = rgb[bg[pat].rgb1_max].g;
b1 = rgb[bg[pat].rgb1_max].b;
r2 = rgb[bg[pat].rgb2_max].r;
g2 = rgb[bg[pat].rgb2_max].g;
b2 = rgb[bg[pat].rgb2_max].b;
for (row = 0; row < rpng2_info.height; ++row) {
yidx = row % bgscale;
if (yidx > hmax)
yidx = bgscale-1 - yidx;
dest = bg_data + row*bg_rowbytes;
for (i = 0; i < rpng2_info.width; ++i) {
xidx = i % bgscale;
if (xidx > hmax)
xidx = bgscale-1 - xidx;
k = xidx + yidx;
*dest++ = (k*r1 + (max-k)*r2) / max;
*dest++ = (k*g1 + (max-k)*g2) / max;
*dest++ = (k*b1 + (max-k)*b2) / max;
}
}
/*---------------------------------------------------------------------------
Radial "starburst" with azimuthal sinusoids; [eventually number of sinu-
soids will equal bgscale?]. This one is slow but very cool. Code con-
tributed by Pieter S. van der Meulen (originally in Smalltalk).
---------------------------------------------------------------------------*/
} else if ((bg[pat].type & 0x07) == 2) {
uch ch;
int ii, x, y, hw, hh, grayspot;
double freq, rotate, saturate, gray, intensity;
double angle=0.0, aoffset=0.0, maxDist, dist;
double red=0.0, green=0.0, blue=0.0, hue, s, v, f, p, q, t;
fprintf(stderr, "%s: computing radial background...",
PROGNAME);
fflush(stderr);
hh = rpng2_info.height / 2;
hw = rpng2_info.width / 2;
/* variables for radial waves:
* aoffset: number of degrees to rotate hue [CURRENTLY NOT USED]
* freq: number of color beams originating from the center
* grayspot: size of the graying center area (anti-alias)
* rotate: rotation of the beams as a function of radius
* saturate: saturation of beams' shape azimuthally
*/
angle = CLIP(angle, 0.0, 360.0);
grayspot = CLIP(bg[pat].bg_gray, 1, (hh + hw));
freq = MAX((double)bg[pat].bg_freq, 0.0);
saturate = (double)bg[pat].bg_bsat * 0.1;
rotate = (double)bg[pat].bg_brot * 0.1;
gray = 0.0;
intensity = 0.0;
maxDist = (double)((hw*hw) + (hh*hh));
for (row = 0; row < rpng2_info.height; ++row) {
y = row - hh;
dest = bg_data + row*bg_rowbytes;
for (i = 0; i < rpng2_info.width; ++i) {
x = i - hw;
angle = (x == 0)? PI_2 : atan((double)y / (double)x);
gray = (double)MAX(ABS(y), ABS(x)) / grayspot;
gray = MIN(1.0, gray);
dist = (double)((x*x) + (y*y)) / maxDist;
intensity = cos((angle+(rotate*dist*PI)) * freq) *
gray * saturate;
intensity = (MAX(MIN(intensity,1.0),-1.0) + 1.0) * 0.5;
hue = (angle + PI) * INV_PI_360 + aoffset;
s = gray * ((double)(ABS(x)+ABS(y)) / (double)(hw + hh));
s = MIN(MAX(s,0.0), 1.0);
v = MIN(MAX(intensity,0.0), 1.0);
if (s == 0.0) {
ch = (uch)(v * 255.0);
*dest++ = ch;
*dest++ = ch;
*dest++ = ch;
} else {
if ((hue < 0.0) || (hue >= 360.0))
hue -= (((int)(hue / 360.0)) * 360.0);
hue /= 60.0;
ii = (int)hue;
f = hue - (double)ii;
p = (1.0 - s) * v;
q = (1.0 - (s * f)) * v;
t = (1.0 - (s * (1.0 - f))) * v;
if (ii == 0) { red = v; green = t; blue = p; }
else if (ii == 1) { red = q; green = v; blue = p; }
else if (ii == 2) { red = p; green = v; blue = t; }
else if (ii == 3) { red = p; green = q; blue = v; }
else if (ii == 4) { red = t; green = p; blue = v; }
else if (ii == 5) { red = v; green = p; blue = q; }
*dest++ = (uch)(red * 255.0);
*dest++ = (uch)(green * 255.0);
*dest++ = (uch)(blue * 255.0);
}
}
}
fprintf(stderr, "done.\n");
fflush(stderr);
}
/*---------------------------------------------------------------------------
Blast background image to display buffer before beginning PNG decode.
---------------------------------------------------------------------------*/
if (depth == 24 || depth == 32) {
ulg red, green, blue;
for (row = 0; row < rpng2_info.height; ++row) {
src = bg_data + row*bg_rowbytes;
dest = ximage->data + row*ximage_rowbytes;
for (i = rpng2_info.width; i > 0; --i) {
red = *src++;
green = *src++;
blue = *src++;
pixel = (red << RPixelShift) |
(green << GPixelShift) |
(blue << BPixelShift);
/* recall that we set ximage->byte_order = MSBFirst above */
*dest++ = ((uch *)&pixel)[3];
*dest++ = ((uch *)&pixel)[2];
*dest++ = ((uch *)&pixel)[1];
*dest++ = ((uch *)&pixel)[0];
}
}
} else if (depth == 16) {
ush red, green, blue;
for (row = 0; row < rpng2_info.height; ++row) {
src = bg_data + row*bg_rowbytes;
dest = ximage->data + row*ximage_rowbytes;
for (i = rpng2_info.width; i > 0; --i) {
red = ((ush)(*src) << 8);
++src;
green = ((ush)(*src) << 8);
++src;
blue = ((ush)(*src) << 8);
++src;
pixel = ((red >> RPixelShift) & RedMask) |
((green >> GPixelShift) & GreenMask) |
((blue >> BPixelShift) & BlueMask);
/* recall that we set ximage->byte_order = MSBFirst above */
*dest++ = ((uch *)&pixel)[1];
*dest++ = ((uch *)&pixel)[0];
}
}
} else /* depth == 8 */ {
/* GRR: add 8-bit support */
}
XPutImage(display, window, gc, ximage, 0, 0, 0, 0, rpng2_info.width,
rpng2_info.height);
return 0;
} /* end function rpng2_x_load_bg_image() */
static void rpng2_x_display_row(ulg row)
{
uch bg_red = rpng2_info.bg_red;
uch bg_green = rpng2_info.bg_green;
uch bg_blue = rpng2_info.bg_blue;
uch *src, *src2=NULL, *dest;
uch r, g, b, a;
int ximage_rowbytes = ximage->bytes_per_line;
ulg i, pixel;
static int rows=0;
static ulg firstrow;
/*---------------------------------------------------------------------------
rows and firstrow simply track how many rows (and which ones) have not
yet been displayed; alternatively, we could call XPutImage() for every
row and not bother with the records-keeping.
---------------------------------------------------------------------------*/
Trace((stderr, "beginning rpng2_x_display_row()\n"))
if (rows == 0)
firstrow = row; /* first row not yet displayed */
++rows; /* count of rows received but not yet displayed */
/*---------------------------------------------------------------------------
Aside from the use of the rpng2_info struct, the lack of an outer loop
(over rows) and moving the XPutImage() call outside the "if (depth)"
tests, this routine is identical to rpng_x_display_image() in the non-
progressive version of the program.
---------------------------------------------------------------------------*/
if (depth == 24 || depth == 32) {
ulg red, green, blue;
src = rpng2_info.image_data + row*rpng2_info.rowbytes;
if (bg_image)
src2 = bg_data + row*bg_rowbytes;
dest = ximage->data + row*ximage_rowbytes;
if (rpng2_info.channels == 3) {
for (i = rpng2_info.width; i > 0; --i) {
red = *src++;
green = *src++;
blue = *src++;
pixel = (red << RPixelShift) |
(green << GPixelShift) |
(blue << BPixelShift);
/* recall that we set ximage->byte_order = MSBFirst */
*dest++ = ((uch *)&pixel)[3];
*dest++ = ((uch *)&pixel)[2];
*dest++ = ((uch *)&pixel)[1];
*dest++ = ((uch *)&pixel)[0];
}
} else /* if (rpng2_info.channels == 4) */ {
for (i = rpng2_info.width; i > 0; --i) {
r = *src++;
g = *src++;
b = *src++;
a = *src++;
if (bg_image) {
bg_red = *src2++;
bg_green = *src2++;
bg_blue = *src2++;
}
if (a == 255) {
red = r;
green = g;
blue = b;
} else if (a == 0) {
red = bg_red;
green = bg_green;
blue = bg_blue;
} else {
/* this macro (from png.h) composites the foreground
* and background values and puts the result into the
* first argument */
alpha_composite(red, r, a, bg_red);
alpha_composite(green, g, a, bg_green);
alpha_composite(blue, b, a, bg_blue);
}
pixel = (red << RPixelShift) |
(green << GPixelShift) |
(blue << BPixelShift);
/* recall that we set ximage->byte_order = MSBFirst */
*dest++ = ((uch *)&pixel)[3];
*dest++ = ((uch *)&pixel)[2];
*dest++ = ((uch *)&pixel)[1];
*dest++ = ((uch *)&pixel)[0];
}
}
} else if (depth == 16) {
ush red, green, blue;
src = rpng2_info.row_pointers[row];
if (bg_image)
src2 = bg_data + row*bg_rowbytes;
dest = ximage->data + row*ximage_rowbytes;
if (rpng2_info.channels == 3) {
for (i = rpng2_info.width; i > 0; --i) {
red = ((ush)(*src) << 8);
++src;
green = ((ush)(*src) << 8);
++src;
blue = ((ush)(*src) << 8);
++src;
pixel = ((red >> RPixelShift) & RedMask) |
((green >> GPixelShift) & GreenMask) |
((blue >> BPixelShift) & BlueMask);
/* recall that we set ximage->byte_order = MSBFirst */
*dest++ = ((uch *)&pixel)[1];
*dest++ = ((uch *)&pixel)[0];
}
} else /* if (rpng2_info.channels == 4) */ {
for (i = rpng2_info.width; i > 0; --i) {
r = *src++;
g = *src++;
b = *src++;
a = *src++;
if (bg_image) {
bg_red = *src2++;
bg_green = *src2++;
bg_blue = *src2++;
}
if (a == 255) {
red = ((ush)r << 8);
green = ((ush)g << 8);
blue = ((ush)b << 8);
} else if (a == 0) {
red = ((ush)bg_red << 8);
green = ((ush)bg_green << 8);
blue = ((ush)bg_blue << 8);
} else {
/* this macro (from png.h) composites the foreground
* and background values and puts the result back into
* the first argument (== fg byte here: safe) */
alpha_composite(r, r, a, bg_red);
alpha_composite(g, g, a, bg_green);
alpha_composite(b, b, a, bg_blue);
red = ((ush)r << 8);
green = ((ush)g << 8);
blue = ((ush)b << 8);
}
pixel = ((red >> RPixelShift) & RedMask) |
((green >> GPixelShift) & GreenMask) |
((blue >> BPixelShift) & BlueMask);
/* recall that we set ximage->byte_order = MSBFirst */
*dest++ = ((uch *)&pixel)[1];
*dest++ = ((uch *)&pixel)[0];
}
}
} else /* depth == 8 */ {
/* GRR: add 8-bit support */
}
/*---------------------------------------------------------------------------
Display after every 16 rows or when on last row. (Region may include
previously displayed lines due to interlacing--i.e., not contiguous.)
---------------------------------------------------------------------------*/
if ((rows & 0xf) == 0 || row == rpng2_info.height-1) {
XPutImage(display, window, gc, ximage, 0, firstrow, 0, firstrow,
rpng2_info.width, row - firstrow + 1);
XFlush(display);
rows = 0;
}
}
static void rpng2_x_finish_display()
{
Trace((stderr, "beginning rpng2_x_finish_display()\n"))
/* last row has already been displayed by rpng2_x_display_row(), so we
* have nothing to do here except set a flag and let the user know that
* the image is done */
rpng2_info.done = TRUE;
printf("Done. Press Q, Esc or mouse button 1 to quit.\n");
}
static void rpng2_x_cleanup()
{
if (bg_image && bg_data) {
free(bg_data);
bg_data = NULL;
}
if (rpng2_info.image_data) {
free(rpng2_info.image_data);
rpng2_info.image_data = NULL;
}
if (rpng2_info.row_pointers) {
free(rpng2_info.row_pointers);
rpng2_info.row_pointers = NULL;
}
if (ximage) {
if (ximage->data) {
free(ximage->data); /* we allocated it, so we free it */
ximage->data = (char *)NULL; /* instead of XDestroyImage() */
}
XDestroyImage(ximage);
ximage = NULL;
}
XFreeGC(display, gc);
if (have_window)
XDestroyWindow(display, window);
if (have_colormap)
XFreeColormap(display, colormap);
}
static int rpng2_x_msb(ulg u32val)
{
int i;
for (i = 31; i >= 0; --i) {
if (u32val & 0x80000000L)
break;
u32val <<= 1;
}
return i;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -