|
Packit |
b099d7 |
#include <stdio.h>
|
|
Packit |
b099d7 |
#include <stdlib.h>
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
#include <png.h>
|
|
Packit |
b099d7 |
#include "PngI.h"
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
static double get_display_exponent(void);
|
|
Packit |
b099d7 |
static int png_process_image(Screen *screen,
|
|
Packit |
b099d7 |
XImage *ximage, int image_rowbytes,
|
|
Packit |
b099d7 |
int image_channels, unsigned char bg_red,
|
|
Packit |
b099d7 |
unsigned char bg_green,
|
|
Packit |
b099d7 |
unsigned char bg_blue,
|
|
Packit |
b099d7 |
unsigned char *image_data);
|
|
Packit |
b099d7 |
static int png_msb(unsigned long u32val);
|
|
Packit |
b099d7 |
static int png_load_file(FILE *infile, unsigned long *pWidth,
|
|
Packit |
b099d7 |
unsigned long *pHeight, unsigned char *red,
|
|
Packit |
b099d7 |
unsigned char *green, unsigned char *blue,
|
|
Packit |
b099d7 |
int *pChannels, unsigned long *pRowbytes,
|
|
Packit |
b099d7 |
unsigned char **image_data);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
int
|
|
Packit |
b099d7 |
_XmPngGetImage(Screen *screen, FILE *infile, Pixel background,
|
|
Packit |
b099d7 |
XImage **ximage)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
XColor xcolor;
|
|
Packit |
b099d7 |
int image_channels;
|
|
Packit |
b099d7 |
unsigned char bg_red = 0, bg_green = 0, bg_blue = 0;
|
|
Packit |
b099d7 |
unsigned char *image_data = NULL;
|
|
Packit |
b099d7 |
unsigned long image_width, image_height, image_rowbytes;
|
|
Packit |
b099d7 |
unsigned char *xdata;
|
|
Packit |
b099d7 |
int pad;
|
|
Packit |
b099d7 |
int rc;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
xcolor.pixel = background;
|
|
Packit |
b099d7 |
XQueryColor(screen->display, screen->cmap, &xcolor);
|
|
Packit |
b099d7 |
bg_red = xcolor.red;
|
|
Packit |
b099d7 |
bg_green = xcolor.green;
|
|
Packit |
b099d7 |
bg_blue = xcolor.blue;
|
|
Packit |
b099d7 |
rc = png_load_file(infile,
|
|
Packit |
b099d7 |
&image_width, &image_height,
|
|
Packit |
b099d7 |
NULL, NULL, NULL,
|
|
Packit |
b099d7 |
&image_channels, &image_rowbytes, &image_data);
|
|
Packit |
b099d7 |
/* XXX if background is XmINSPECIFIED_PIXEL, we cat try
|
|
Packit |
b099d7 |
to get background from the PNG image, but I can
|
|
Packit |
b099d7 |
doesn't have this information.
|
|
Packit |
b099d7 |
rc = readpng_load_file(infile,
|
|
Packit |
b099d7 |
&image_width, &image_height,
|
|
Packit |
b099d7 |
&bg_red, &bg_green, &bg_blue,
|
|
Packit |
b099d7 |
&image_channels, &image_rowbytes, &image_data);
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
if (rc) return rc;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if (screen->root_depth == 24 || screen->root_depth == 32) {
|
|
Packit |
b099d7 |
xdata = (unsigned char *) malloc(4 * image_width * image_height);
|
|
Packit |
b099d7 |
pad = 32;
|
|
Packit |
b099d7 |
} else if (screen->root_depth == 16) {
|
|
Packit |
b099d7 |
xdata = (unsigned char *) malloc(2 * image_width * image_height);
|
|
Packit |
b099d7 |
pad = 16;
|
|
Packit |
b099d7 |
} else { /* depth == 8 */
|
|
Packit |
b099d7 |
xdata = (unsigned char *) malloc(image_width * image_height);
|
|
Packit |
b099d7 |
pad = 8;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if (!xdata)
|
|
Packit |
b099d7 |
return 4;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
*ximage =
|
|
Packit |
b099d7 |
XCreateImage(screen->display, screen->root_visual,
|
|
Packit |
b099d7 |
screen->root_depth, ZPixmap, 0, (char *) xdata,
|
|
Packit |
b099d7 |
image_width, image_height, pad, 0);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if (!*ximage) {
|
|
Packit |
b099d7 |
free(xdata);
|
|
Packit |
b099d7 |
return 4;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
(*ximage)->byte_order = MSBFirst;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
rc = png_process_image(screen, *ximage, image_rowbytes,
|
|
Packit |
b099d7 |
image_channels, bg_red, bg_green, bg_blue,
|
|
Packit |
b099d7 |
image_data);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if (image_data) {
|
|
Packit |
b099d7 |
free(image_data);
|
|
Packit |
b099d7 |
image_data = NULL;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
return rc;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
static double
|
|
Packit |
b099d7 |
get_display_exponent(void)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
double LUT_exponent; /* just the lookup table */
|
|
Packit |
b099d7 |
double CRT_exponent = 2.2; /* just the monitor */
|
|
Packit |
b099d7 |
double default_display_exponent; /* whole display system */
|
|
Packit |
b099d7 |
char *p;
|
|
Packit |
b099d7 |
double display_exponent;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* First set the default value for our display-system exponent, i.e.,
|
|
Packit |
b099d7 |
* the product of the CRT exponent and the exponent corresponding to
|
|
Packit |
b099d7 |
* the frame-buffer's lookup table (LUT), if any. This is not an
|
|
Packit |
b099d7 |
* exhaustive list of LUT values (e.g., OpenStep has a lot of weird
|
|
Packit |
b099d7 |
* ones), but it should cover 99% of the current possibilities. */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
LUT_exponent = 1.0; /* assume no LUT: most PCs */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */
|
|
Packit |
b099d7 |
default_display_exponent = LUT_exponent * CRT_exponent;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* If the user has set the SCREEN_GAMMA environment variable as suggested
|
|
Packit |
b099d7 |
* (somewhat imprecisely) in the libpng documentation, use that; otherwise
|
|
Packit |
b099d7 |
* use the default value we just calculated. Either way, the user may
|
|
Packit |
b099d7 |
* override this via a command-line option. */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if ((p = getenv("SCREEN_GAMMA")) != NULL)
|
|
Packit |
b099d7 |
display_exponent = atof(p);
|
|
Packit |
b099d7 |
else
|
|
Packit |
b099d7 |
display_exponent = default_display_exponent;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
return display_exponent;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* return value = 0 for success, 1 for bad sig, 2 for bad struct (IHDR or kBGD),
|
|
Packit |
b099d7 |
4 for no mem 5 if fails due to no bKGD chunk */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
static int
|
|
Packit |
b099d7 |
png_load_file(FILE *infile, unsigned long *pWidth,
|
|
Packit |
b099d7 |
unsigned long *pHeight, unsigned char *red,
|
|
Packit |
b099d7 |
unsigned char *green, unsigned char *blue,
|
|
Packit |
b099d7 |
int *pChannels, unsigned long *pRowbytes,
|
|
Packit |
b099d7 |
unsigned char **image_data)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
png_structp png_ptr = NULL;
|
|
Packit |
b099d7 |
png_infop info_ptr = NULL;
|
|
Packit |
b099d7 |
int bit_depth, color_type;
|
|
Packit |
b099d7 |
png_uint_32 width, height;
|
|
Packit |
b099d7 |
// int rc;
|
|
Packit |
b099d7 |
unsigned char sig[8];
|
|
Packit |
b099d7 |
png_color_16p pBackground;
|
|
Packit |
b099d7 |
double gamma;
|
|
Packit |
b099d7 |
png_uint_32 i, rowbytes;
|
|
Packit |
b099d7 |
png_bytepp row_pointers = NULL;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
fread(sig, 1, 8, infile);
|
|
Packit |
b099d7 |
if (png_sig_cmp(sig, 0, 8))
|
|
Packit |
b099d7 |
return 1; /* bad signature */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
png_ptr =
|
|
Packit |
b099d7 |
png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
|
Packit |
b099d7 |
if (!png_ptr)
|
|
Packit |
b099d7 |
return 4; /* out of memory */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
info_ptr = png_create_info_struct(png_ptr);
|
|
Packit |
b099d7 |
if (!info_ptr) {
|
|
Packit |
b099d7 |
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
|
Packit |
b099d7 |
return 4; /* out of memory */
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* setjmp() must be called in every function that calls a PNG-reading
|
|
Packit |
b099d7 |
* libpng function */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if (setjmp(png_jmpbuf(png_ptr))) {
|
|
Packit |
b099d7 |
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
Packit |
b099d7 |
return 2;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
png_init_io(png_ptr, infile);
|
|
Packit |
b099d7 |
png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
|
|
Packit |
b099d7 |
&color_type, NULL, NULL, NULL);
|
|
Packit |
b099d7 |
if (pWidth)
|
|
Packit |
b099d7 |
*pWidth = width;
|
|
Packit |
b099d7 |
if (pHeight)
|
|
Packit |
b099d7 |
*pHeight = height;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if (red && green && blue) {
|
|
Packit |
b099d7 |
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) {
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
png_get_bKGD(png_ptr, info_ptr, &pBackground);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if (bit_depth == 16) {
|
|
Packit |
b099d7 |
*red = pBackground->red >> 8;
|
|
Packit |
b099d7 |
*green = pBackground->green >> 8;
|
|
Packit |
b099d7 |
*blue = pBackground->blue >> 8;
|
|
Packit |
b099d7 |
} else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
|
|
Packit |
b099d7 |
if (bit_depth == 1)
|
|
Packit |
b099d7 |
*red = *green = *blue = pBackground->gray ? 255 : 0;
|
|
Packit |
b099d7 |
else if (bit_depth == 2)
|
|
Packit |
b099d7 |
*red = *green = *blue = (255 / 3) * pBackground->gray;
|
|
Packit |
b099d7 |
else /* bit_depth == 4 */
|
|
Packit |
b099d7 |
*red = *green = *blue = (255 / 15) * pBackground->gray;
|
|
Packit |
b099d7 |
} else {
|
|
Packit |
b099d7 |
*red = (unsigned char) pBackground->red;
|
|
Packit |
b099d7 |
*green = (unsigned char) pBackground->green;
|
|
Packit |
b099d7 |
*blue = (unsigned char) pBackground->blue;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
|
Packit |
b099d7 |
png_set_expand(png_ptr);
|
|
Packit |
b099d7 |
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 16)
|
|
Packit |
b099d7 |
png_set_expand(png_ptr);
|
|
Packit |
b099d7 |
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
|
Packit |
b099d7 |
png_set_expand(png_ptr);
|
|
Packit |
b099d7 |
if (bit_depth == 16)
|
|
Packit |
b099d7 |
png_set_strip_16(png_ptr);
|
|
Packit |
b099d7 |
if (color_type == PNG_COLOR_TYPE_GRAY ||
|
|
Packit |
b099d7 |
color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
|
Packit |
b099d7 |
png_set_gray_to_rgb(png_ptr);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if (png_get_gAMA(png_ptr, info_ptr, &gamma))
|
|
Packit |
b099d7 |
png_set_gamma(png_ptr, get_display_exponent(), gamma);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* all transformations have been registered; now update info_ptr data,
|
|
Packit |
b099d7 |
* get rowbytes and channels, and allocate image memory */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
png_read_update_info(png_ptr, info_ptr);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
*pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
|
Packit |
b099d7 |
*pChannels = (int) png_get_channels(png_ptr, info_ptr);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if ((*image_data =
|
|
Packit |
b099d7 |
(unsigned char *) malloc(rowbytes * height)) == NULL) {
|
|
Packit |
b099d7 |
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
Packit |
b099d7 |
return 4;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
if ((row_pointers =
|
|
Packit |
b099d7 |
(png_bytepp) malloc(height * sizeof(png_bytep))) == NULL) {
|
|
Packit |
b099d7 |
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
Packit |
b099d7 |
free(*image_data);
|
|
Packit |
b099d7 |
*image_data = NULL;
|
|
Packit |
b099d7 |
return 4;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* set the individual row_pointers to point at the correct offsets */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
for (i = 0; i < height; ++i)
|
|
Packit |
b099d7 |
row_pointers[i] = *image_data + i * rowbytes;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* now we can go ahead and just read the whole image */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
png_read_image(png_ptr, row_pointers);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* and we're done! (png_read_end() can be omitted if no processing of
|
|
Packit |
b099d7 |
* post-IDAT text/time/etc. is desired) */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
free(row_pointers);
|
|
Packit |
b099d7 |
row_pointers = NULL;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
png_read_end(png_ptr, NULL);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if (png_ptr && info_ptr) {
|
|
Packit |
b099d7 |
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
Packit |
b099d7 |
png_ptr = NULL;
|
|
Packit |
b099d7 |
info_ptr = NULL;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
return 0;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
static int
|
|
Packit |
b099d7 |
png_process_image(Screen *screen,
|
|
Packit |
b099d7 |
XImage *ximage, int image_rowbytes,
|
|
Packit |
b099d7 |
int image_channels,
|
|
Packit |
b099d7 |
unsigned char bg_red,
|
|
Packit |
b099d7 |
unsigned char bg_green,
|
|
Packit |
b099d7 |
unsigned char bg_blue, unsigned char *image_data)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
unsigned char *src;
|
|
Packit |
b099d7 |
char *dest;
|
|
Packit |
b099d7 |
unsigned char r, g, b, a;
|
|
Packit |
b099d7 |
unsigned long i, row, lastrow = 0;
|
|
Packit |
b099d7 |
unsigned long pixel;
|
|
Packit |
b099d7 |
int ximage_rowbytes = ximage->bytes_per_line;
|
|
Packit |
b099d7 |
static int RShift, GShift, BShift;
|
|
Packit |
b099d7 |
static unsigned long RMask, GMask, BMask;
|
|
Packit |
b099d7 |
unsigned short red, green, blue;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
RMask = screen->root_visual->red_mask;
|
|
Packit |
b099d7 |
GMask = screen->root_visual->green_mask;
|
|
Packit |
b099d7 |
BMask = screen->root_visual->blue_mask;
|
|
Packit |
b099d7 |
if (screen->root_depth == 15 || screen->root_depth == 16) {
|
|
Packit |
b099d7 |
RShift = 15 - png_msb(RMask);
|
|
Packit |
b099d7 |
GShift = 15 - png_msb(GMask);
|
|
Packit |
b099d7 |
BShift = 15 - png_msb(BMask);
|
|
Packit |
b099d7 |
} else if (screen->root_depth > 16) {
|
|
Packit |
b099d7 |
RShift = png_msb(RMask) - 7;
|
|
Packit |
b099d7 |
GShift = png_msb(GMask) - 7;
|
|
Packit |
b099d7 |
BShift = png_msb(BMask) - 7;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if (screen->root_depth == 24 || screen->root_depth == 32) {
|
|
Packit |
b099d7 |
for (lastrow = row = 0; row < ximage->height; ++row) {
|
|
Packit |
b099d7 |
src = image_data + row * image_rowbytes;
|
|
Packit |
b099d7 |
dest = ximage->data + row * ximage_rowbytes;
|
|
Packit |
b099d7 |
if (image_channels == 3) {
|
|
Packit |
b099d7 |
for (i = ximage->width; i > 0; --i) {
|
|
Packit |
b099d7 |
red = *src++;
|
|
Packit |
b099d7 |
green = *src++;
|
|
Packit |
b099d7 |
blue = *src++;
|
|
Packit |
b099d7 |
#ifdef NO_24BIT_MASKS
|
|
Packit |
b099d7 |
pixel = (red << RShift) |
|
|
Packit |
b099d7 |
(green << GShift) | (blue << BShift);
|
|
Packit |
b099d7 |
/* recall that we set ximage->byte_order = MSBFirst above */
|
|
Packit |
b099d7 |
/* GRR BUG: this assumes bpp == 32, but may be 24: */
|
|
Packit |
b099d7 |
*dest++ = (char) ((pixel >> 24) & 0xff);
|
|
Packit |
b099d7 |
*dest++ = (char) ((pixel >> 16) & 0xff);
|
|
Packit |
b099d7 |
*dest++ = (char) ((pixel >> 8) & 0xff);
|
|
Packit |
b099d7 |
*dest++ = (char) (pixel & 0xff);
|
|
Packit |
b099d7 |
#else
|
|
Packit |
b099d7 |
red = (RShift < 0) ? red << (-RShift) : red >> RShift;
|
|
Packit |
b099d7 |
green =
|
|
Packit |
b099d7 |
(GShift <
|
|
Packit |
b099d7 |
0) ? green << (-GShift) : green >> GShift;
|
|
Packit |
b099d7 |
blue =
|
|
Packit |
b099d7 |
(BShift < 0) ? blue << (-BShift) : blue >> BShift;
|
|
Packit |
b099d7 |
pixel =
|
|
Packit |
b099d7 |
(red & RMask) | (green & GMask) | (blue & BMask);
|
|
Packit |
b099d7 |
/* recall that we set ximage->byte_order = MSBFirst above */
|
|
Packit |
b099d7 |
*dest++ = (char) ((pixel >> 24) & 0xff);
|
|
Packit |
b099d7 |
*dest++ = (char) ((pixel >> 16) & 0xff);
|
|
Packit |
b099d7 |
*dest++ = (char) ((pixel >> 8) & 0xff);
|
|
Packit |
b099d7 |
*dest++ = (char) (pixel & 0xff);
|
|
Packit |
b099d7 |
#endif
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
} else { /* if (image_channels == 4) */
|
|
Packit |
b099d7 |
for (i = ximage->width; i > 0; --i) {
|
|
Packit |
b099d7 |
r = *src++;
|
|
Packit |
b099d7 |
g = *src++;
|
|
Packit |
b099d7 |
b = *src++;
|
|
Packit |
b099d7 |
a = *src++;
|
|
Packit |
b099d7 |
if (a == 255) {
|
|
Packit |
b099d7 |
red = r;
|
|
Packit |
b099d7 |
green = g;
|
|
Packit |
b099d7 |
blue = b;
|
|
Packit |
b099d7 |
} else if (a == 0) {
|
|
Packit |
b099d7 |
red = bg_red;
|
|
Packit |
b099d7 |
green = bg_green;
|
|
Packit |
b099d7 |
blue = bg_blue;
|
|
Packit |
b099d7 |
} else {
|
|
Packit |
b099d7 |
/* this macro (from png.h) composites the foreground
|
|
Packit |
b099d7 |
* and background values and puts the result into the
|
|
Packit |
b099d7 |
* first argument */
|
|
Packit |
b099d7 |
png_composite(red, r, a, bg_red);
|
|
Packit |
b099d7 |
png_composite(green, g, a, bg_green);
|
|
Packit |
b099d7 |
png_composite(blue, b, a, bg_blue);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
pixel = (red << RShift) |
|
|
Packit |
b099d7 |
(green << GShift) | (blue << BShift);
|
|
Packit |
b099d7 |
/* recall that we set ximage->byte_order = MSBFirst above */
|
|
Packit |
b099d7 |
*dest++ = (char) ((pixel >> 24) & 0xff);
|
|
Packit |
b099d7 |
*dest++ = (char) ((pixel >> 16) & 0xff);
|
|
Packit |
b099d7 |
*dest++ = (char) ((pixel >> 8) & 0xff);
|
|
Packit |
b099d7 |
*dest++ = (char) (pixel & 0xff);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
} else if (screen->root_depth == 16) {
|
|
Packit |
b099d7 |
for (lastrow = row = 0; row < ximage->height; ++row) {
|
|
Packit |
b099d7 |
src = image_data + row * image_rowbytes;
|
|
Packit |
b099d7 |
dest = ximage->data + row * ximage_rowbytes;
|
|
Packit |
b099d7 |
if (image_channels == 3) {
|
|
Packit |
b099d7 |
for (i = ximage->width; i > 0; --i) {
|
|
Packit |
b099d7 |
red = ((unsigned short) (*src) << 8);
|
|
Packit |
b099d7 |
++src;
|
|
Packit |
b099d7 |
green = ((unsigned short) (*src) << 8);
|
|
Packit |
b099d7 |
++src;
|
|
Packit |
b099d7 |
blue = ((unsigned short) (*src) << 8);
|
|
Packit |
b099d7 |
++src;
|
|
Packit |
b099d7 |
pixel = ((red >> RShift) & RMask) |
|
|
Packit |
b099d7 |
((green >> GShift) & GMask) |
|
|
Packit |
b099d7 |
((blue >> BShift) & BMask);
|
|
Packit |
b099d7 |
/* recall that we set ximage->byte_order = MSBFirst above */
|
|
Packit |
b099d7 |
*dest++ = (char) ((pixel >> 8) & 0xff);
|
|
Packit |
b099d7 |
*dest++ = (char) (pixel & 0xff);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
} else { /* if (image_channels == 4) */
|
|
Packit |
b099d7 |
for (i = ximage->width; i > 0; --i) {
|
|
Packit |
b099d7 |
r = *src++;
|
|
Packit |
b099d7 |
g = *src++;
|
|
Packit |
b099d7 |
b = *src++;
|
|
Packit |
b099d7 |
a = *src++;
|
|
Packit |
b099d7 |
if (a == 255) {
|
|
Packit |
b099d7 |
red = ((unsigned short) r << 8);
|
|
Packit |
b099d7 |
green = ((unsigned short) g << 8);
|
|
Packit |
b099d7 |
blue = ((unsigned short) b << 8);
|
|
Packit |
b099d7 |
} else if (a == 0) {
|
|
Packit |
b099d7 |
red = ((unsigned short) bg_red << 8);
|
|
Packit |
b099d7 |
green = ((unsigned short) bg_green << 8);
|
|
Packit |
b099d7 |
blue = ((unsigned short) bg_blue << 8);
|
|
Packit |
b099d7 |
} else {
|
|
Packit |
b099d7 |
/* this macro (from png.h) composites the foreground
|
|
Packit |
b099d7 |
* and background values and puts the result back into
|
|
Packit |
b099d7 |
* the first argument (== fg byte here: safe) */
|
|
Packit |
b099d7 |
png_composite(r, r, a, bg_red);
|
|
Packit |
b099d7 |
png_composite(g, g, a, bg_green);
|
|
Packit |
b099d7 |
png_composite(b, b, a, bg_blue);
|
|
Packit |
b099d7 |
red = ((unsigned short) r << 8);
|
|
Packit |
b099d7 |
green = ((unsigned short) g << 8);
|
|
Packit |
b099d7 |
blue = ((unsigned short) b << 8);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
pixel = ((red >> RShift) & RMask) |
|
|
Packit |
b099d7 |
((green >> GShift) & GMask) |
|
|
Packit |
b099d7 |
((blue >> BShift) & BMask);
|
|
Packit |
b099d7 |
/* recall that we set ximage->byte_order = MSBFirst above */
|
|
Packit |
b099d7 |
*dest++ = (char) ((pixel >> 8) & 0xff);
|
|
Packit |
b099d7 |
*dest++ = (char) (pixel & 0xff);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
} else { /* depth == 8 */
|
|
Packit |
b099d7 |
/* XXX: add 8-bit support */
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
return 0;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
static int
|
|
Packit |
b099d7 |
png_msb(unsigned long u32val)
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
int i;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
for (i = 31; i >= 0; --i) {
|
|
Packit |
b099d7 |
if (u32val & 0x80000000L)
|
|
Packit |
b099d7 |
break;
|
|
Packit |
b099d7 |
u32val <<= 1;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
return i;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|