2 "$Id: png.c 9195 2008-06-01 15:36:42Z anmaster $";
42 #include <X11/Xutil.h>
53 #define PNGX_OUTOFMEM 2
59 static void user_read_data(png_structp png_ptr, png_bytep data, png_size_t length) {
68 static png_bytepp rows=NULL;
69 static int rows_byte=0;
73 int bit_depth, color_type, interlace_type, compression_type, y;
79 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
85 info_ptr = png_create_info_struct (png_ptr);
88 png_destroy_read_struct (&png_ptr, NULL, NULL);
91 if (setjmp (png_ptr->jmpbuf)) {
92 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
97 png_read_info (png_ptr, info_ptr);
102 *width = png_get_image_width(png_ptr, info_ptr);
103 *height = png_get_image_height(png_ptr, info_ptr);
104 bit_depth = png_get_bit_depth(png_ptr, info_ptr);
105 color_type = png_get_color_type(png_ptr, info_ptr);
106 interlace_type = png_get_interlace_type(png_ptr, info_ptr);
107 compression_type = png_get_compression_type(png_ptr, info_ptr);
109 if (color_type == PNG_COLOR_TYPE_PALETTE &&
113 png_set_expand (png_ptr);
115 }
else if (color_type == PNG_COLOR_TYPE_GRAY &&
119 png_set_expand (png_ptr);
121 }
else if (png_get_valid (png_ptr,
122 info_ptr, PNG_INFO_tRNS)) {
126 png_set_expand(png_ptr);
128 }
else if (bit_depth < 8) {
131 png_set_expand(png_ptr);
139 if (bit_depth == 16) {
140 png_set_strip_16(png_ptr);
144 if (color_type == PNG_COLOR_TYPE_GRAY ||
145 color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
146 png_set_gray_to_rgb(png_ptr);
150 if (interlace_type != PNG_INTERLACE_NONE) {
151 png_set_interlace_handling(png_ptr);
155 if (!(color_type & PNG_COLOR_MASK_ALPHA))
156 png_set_filler(png_ptr, 255, PNG_FILLER_AFTER);
159 png_read_update_info(png_ptr, info_ptr);
165 *width = png_get_image_width(png_ptr, info_ptr);
166 *height = png_get_image_height(png_ptr, info_ptr);
167 bit_depth = png_get_bit_depth(png_ptr, info_ptr);
168 color_type = png_get_color_type(png_ptr, info_ptr);
169 interlace_type = png_get_interlace_type(png_ptr, info_ptr);
170 compression_type = png_get_compression_type(png_ptr, info_ptr);
172 pixels = (
uint8*)malloc(*width * *height * 4);
175 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
176 fprintf(stderr,
"Out of memory - exiting\n");
181 if (rows_byte == 0) {
182 rows =(png_bytepp) malloc(
sizeof(
char*) * *
height);
184 }
else if (*height > rows_byte) {
185 rows =(png_bytepp) realloc(rows,
sizeof(
char*) * *
height);
189 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
194 rows[y] = pixels + y * *width * 4;
196 png_read_image(png_ptr, rows);
197 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
235 #define MAX_IMAGE_WIDTH 1024
236 #define MAX_IMAGE_HEIGHT 1024
245 int new_width = *width * scale /
RATIO, new_height = *height * scale /
RATIO;
247 int sourcerow=0, ytoleft, ytofill, xtoleft, xtofill, dest_column=0, source_column=0, needcol,
256 fprintf(stderr,
"Image too big\n");
261 memset(yrow, 0,
sizeof(
int) * *height *
BPP);
263 ndata = (
uint8*)malloc(new_width * new_height * BPP);
265 for (y=0; y<new_height; y++)
266 nrows[y] = (png_bytep) (ndata + y * new_width *
BPP);
271 for (y=0,sourcerow=0; y < new_height; y++) {
272 memset(xrow, 0,
sizeof(
int) * *width * BPP);
273 while (ytoleft < ytofill) {
274 for (x=0; x< *
width; ++x) {
279 if (data[(sourcerow * *width + x)*BPP+3] > 0 ) {
280 yrow[x*
BPP] += ytoleft * data[(sourcerow * *width + x)*BPP]/
RATIO;
281 yrow[x*BPP+1] += ytoleft * data[(sourcerow * *width + x)*BPP+1]/
RATIO;
282 yrow[x*BPP+2] += ytoleft * data[(sourcerow * *width + x)*BPP+2]/
RATIO;
287 if (data[(sourcerow * *width + x)*BPP+3] > yrow[x*BPP+3])
288 yrow[x*BPP+3] = data[(sourcerow * *width + x)*BPP+3];
292 if (sourcerow < *height)
296 for (x=0; x < *
width; ++x) {
297 if (data[(sourcerow * *width + x)*BPP+3] > 0 ) {
298 xrow[x*
BPP] = yrow[x*
BPP] + ytofill * data[(sourcerow * *width + x)*BPP] /
RATIO;
299 xrow[x*BPP+1] = yrow[x*BPP+1] + ytofill * data[(sourcerow * *width + x)*BPP+1] /
RATIO;
300 xrow[x*BPP+2] = yrow[x*BPP+2] + ytofill * data[(sourcerow * *width + x)*BPP+2] /
RATIO;
302 if (data[(sourcerow * *width + x)*BPP+3] > xrow[x*BPP+3])
303 xrow[x*BPP+3] = data[(sourcerow * *width + x)*BPP+3];
304 yrow[x*
BPP]=0; yrow[x*BPP+1]=0; yrow[x*BPP+2]=0; yrow[x*BPP+3]=0;
310 if (sourcerow < *height)
321 for (x=0; x< *
width; x++) {
324 while (xtoleft >= xtofill) {
330 if (xrow[source_column*BPP+3] > 0) {
331 r += xtofill * xrow[source_column*
BPP] /
RATIO;
332 g += xtofill * xrow[1+source_column*
BPP] /
RATIO;
333 b += xtofill * xrow[2+source_column*
BPP] /
RATIO;
335 if (xrow[3+source_column*BPP] > a)
336 a = xrow[3+source_column*
BPP];
338 nrows[destrow][dest_column *
BPP] = r;
339 nrows[destrow][1+dest_column *
BPP] = g;
340 nrows[destrow][2+dest_column *
BPP] = b;
341 nrows[destrow][3+dest_column *
BPP] = a;
354 if (xrow[3+source_column*BPP] > 0) {
355 r += xtoleft * xrow[source_column*
BPP] /
RATIO;
356 g += xtoleft * xrow[1+source_column*
BPP] /
RATIO;
357 b += xtoleft * xrow[2+source_column*
BPP] /
RATIO;
359 if (xrow[3+source_column*BPP] > a)
360 a = xrow[3+source_column*
BPP];
369 if (xrow[3+source_column*BPP] > 0) {
370 r += xtofill * xrow[source_column*
BPP] /
RATIO;
371 g += xtofill * xrow[1+source_column*
BPP] /
RATIO;
372 b += xtofill * xrow[2+source_column*
BPP] /
RATIO;
374 if (xrow[3+source_column*BPP] > a)
375 a = xrow[3+source_column*
BPP];
383 if (!needcol && (dest_column < new_width)) {
384 nrows[destrow][dest_column *
BPP] = r;
385 nrows[destrow][1+dest_column *
BPP] = g;
386 nrows[destrow][2+dest_column *
BPP] = b;
387 nrows[destrow][3+dest_column *
BPP] = a;
392 *height = new_height;
406 #define COLOR_FACTOR 3
407 #define BRIGHTNESS_FACTOR 1
419 int i, closeness=0xffffff, close_entry=-1, tmpclose;
436 if (tmpclose < closeness) {
437 closeness = tmpclose;
449 scolor.red = (red << 8) + red;
450 scolor.green = (green << 8) + green;
451 scolor.blue = (blue << 8) + blue;
455 if (!XAllocColor(display, *cmap, &scolor)) {
457 fprintf(stderr,
"Going to private colormap after %d allocs\n", colors_alloced);
458 *cmap = XCopyColormapAndFree(display, *cmap);
464 fprintf(stderr,
"Unable to allocate color %d %d %d, %d colors alloced, will use closenss value %d\n",
465 red, green, blue, colors_alloced, closeness);
485 XVisualInfo xvinfo, *xvret;
488 depth = DefaultDepth(display, DefaultScreen(display));
489 visual = DefaultVisual(display, DefaultScreen(display));
490 xvinfo.visualid = XVisualIDFromVisual(visual);
491 xvret = XGetVisualInfo(display, VisualIDMask, &xvinfo, &pad);
493 fprintf(stderr,
"XGetVisual found %d matching visuals?\n", pad);
496 rmask = xvret -> red_mask;
497 gmask = xvret -> green_mask;
498 bmask = xvret -> blue_mask;
542 if (xvret->class==PseudoColor) {
544 if (xvret->colormap_size>256) {
545 fprintf(stderr,
"One a pseudocolor visual, but colormap has %d entries?\n", xvret->colormap_size);
552 if (depth>16) pad = 32;
553 else if (depth > 8) pad = 16;
556 ximage = XCreateImage(display, visual,
561 fprintf(stderr,
"Failed to create Ximage\n");
566 fprintf(stderr,
"Failed to create Ximage data\n");
574 Pixmap *pix, Pixmap *
mask, Colormap *cmap,
577 static uint8 *pixels=NULL;
578 static int pixels_byte=0, rows_byte=0;
579 static png_bytepp rows=NULL;
581 png_structp png_ptr=NULL;
582 png_infop info_ptr=NULL;
583 int bit_depth, color_type, interlace_type, compression_type,
584 red,green,blue, lastred=-1, lastgreen=-1, lastblue=-1,alpha,bpp, x,y,
585 has_alpha, cmask, lastcmask, lastcolor;
592 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
597 info_ptr = png_create_info_struct (png_ptr);
600 png_destroy_read_struct (&png_ptr, NULL, NULL);
603 if (setjmp (png_ptr->jmpbuf)) {
604 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
616 png_read_info (png_ptr, info_ptr);
622 *width = png_get_image_width(png_ptr, info_ptr);
623 *height = png_get_image_height(png_ptr, info_ptr);
624 bit_depth = png_get_bit_depth(png_ptr, info_ptr);
625 color_type = png_get_color_type(png_ptr, info_ptr);
626 interlace_type = png_get_interlace_type(png_ptr, info_ptr);
627 compression_type = png_get_compression_type(png_ptr, info_ptr);
629 if (color_type == PNG_COLOR_TYPE_PALETTE &&
633 png_set_expand (png_ptr);
635 }
else if (color_type == PNG_COLOR_TYPE_GRAY &&
639 png_set_expand (png_ptr);
641 }
else if (png_get_valid (png_ptr,
642 info_ptr, PNG_INFO_tRNS)) {
646 png_set_expand(png_ptr);
648 }
else if (bit_depth < 8) {
651 png_set_expand(png_ptr);
659 if (bit_depth == 16) {
660 png_set_strip_16(png_ptr);
664 if (color_type == PNG_COLOR_TYPE_GRAY ||
665 color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
666 png_set_gray_to_rgb(png_ptr);
670 if (interlace_type != PNG_INTERLACE_NONE) {
671 png_set_interlace_handling(png_ptr);
675 png_read_update_info(png_ptr, info_ptr);
682 *width = png_get_image_width(png_ptr, info_ptr);
683 *height = png_get_image_height(png_ptr, info_ptr);
684 bit_depth = png_get_bit_depth(png_ptr, info_ptr);
685 color_type = png_get_color_type(png_ptr, info_ptr);
686 interlace_type = png_get_interlace_type(png_ptr, info_ptr);
687 compression_type = png_get_compression_type(png_ptr, info_ptr);
689 if (color_type & PNG_COLOR_MASK_ALPHA)
697 if (pixels_byte==0) {
698 pixels_byte =*width * *height * bpp;
699 pixels = (
uint8*)malloc(pixels_byte);
700 }
else if ((*width * *height * bpp) > pixels_byte) {
701 pixels_byte =*width * *height * bpp;
702 pixels=realloc(pixels, pixels_byte);
707 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
710 if (rows_byte == 0) {
711 rows =(png_bytepp) malloc(
sizeof(
char*) * *
height);
713 }
else if (*height > rows_byte) {
714 rows =(png_bytepp) realloc(rows,
sizeof(
char*) * *
height);
719 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
724 rows[y] = pixels + y * (*width) * bpp;
726 png_read_image(png_ptr, rows);
728 fprintf(stderr,
"image is %d X %d, bpp=%d, color_type=%d\n",
729 *width, *height, bpp, color_type);
732 *pix = XCreatePixmap(display, draw, *width, *height,
733 DefaultDepth(display, DefaultScreen(display)));
735 gc=XCreateGC(display, *pix, 0, NULL);
736 XSetFunction(display, gc, GXcopy);
737 XSetPlaneMask(display, gc, AllPlanes);
739 if (color_type & PNG_COLOR_MASK_ALPHA) {
747 *mask=XCreatePixmap(display ,draw, *width, *height,1);
748 gc_alpha=XCreateGC(display, *mask, 0, NULL);
749 XSetFunction(display, gc_alpha, GXcopy);
750 XSetPlaneMask(display, gc_alpha, AllPlanes);
751 XSetForeground(display, gc_alpha, 1);
752 XFillRectangle(display, *mask, gc_alpha, 0, 0, *width, *height);
753 XSetForeground(display, gc_alpha, 0);
761 for (y=0; y<*
height; y++) {
762 for (x=0; x<*
width; x++) {
764 green=rows[y][x*bpp+1];
765 blue=rows[y][x*bpp+2];
767 alpha = rows[y][x*bpp+3];
770 XDrawPoint(display, *mask, gc_alpha, x, y);
777 if ((lastred != red) && (lastgreen != green) && (lastblue != blue)) {
781 XPutPixel(
ximage, x, y, lastcolor);
783 if ((lastred != red) && (lastgreen != green) && (lastblue != blue)) {
793 XPutPixel(
ximage, x, y, cmask);
798 XPutImage(display, *pix, gc,
ximage, 0, 0, 0, 0, 32, 32);
800 XFreeGC(display, gc_alpha);
801 XFreeGC(display, gc);
802 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
812 Pixmap *pix, Pixmap *
mask, Colormap *cmap,
815 int red,green,blue, lastred=-1, lastgreen=-1, lastblue=-1,alpha,x,y,
816 cmask=-1, lastcmask, lastcolor=-1;
819 *pix = XCreatePixmap(display, draw, width, height,
820 DefaultDepth(display, DefaultScreen(display)));
822 gc=XCreateGC(display, *pix, 0, NULL);
823 XSetFunction(display, gc, GXcopy);
824 XSetPlaneMask(display, gc, AllPlanes);
834 *mask=XCreatePixmap(display ,draw, width, height,1);
835 gc_alpha=XCreateGC(display, *mask, 0, NULL);
836 XSetFunction(display, gc_alpha, GXcopy);
837 XSetPlaneMask(display, gc_alpha, AllPlanes);
838 XSetForeground(display, gc_alpha, 1);
839 XFillRectangle(display, *mask, gc_alpha, 0, 0, width, height);
840 XSetForeground(display, gc_alpha, 0);
842 for (y=0; y<
height; y++) {
843 for (x=0; x<
width; x++) {
844 red= pixels[(y * width + x)*4];
845 green= pixels[(y * width + x)*4 + 1];
846 blue= pixels[(y * width + x)*4 + 2];
847 alpha = pixels[(y * width + x)*4 + 3];
849 XDrawPoint(display, *mask, gc_alpha, x, y);
855 if ((lastred != red) && (lastgreen != green) && (lastblue != blue)) {
859 XPutPixel(
ximage, x, y, lastcolor);
861 if ((lastred != red) && (lastgreen != green) && (lastblue != blue)) {
871 XPutPixel(
ximage, x, y, cmask);
876 XPutImage(display, *pix, gc,
ximage, 0, 0, 0, 0, width, height);
877 XFreeGC(display, gc_alpha);
878 XFreeGC(display, gc);
945 int main(
int argc,
char *argv[])
948 char data[256],buf[1024*1024];
952 XSetWindowAttributes wattrs;
957 fprintf(stderr,
"Usage: %s <filename>\n", argv[0]);
961 if (!(disp=XOpenDisplay(NULL))) {
962 fprintf(stderr,
"Unable to open display\n");
966 wattrs.backing_store = WhenMapped;
967 wattrs.background_pixel = WhitePixel(disp, DefaultScreen(disp));
969 window=XCreateWindow(disp, DefaultRootWindow(disp), 0, 0,
970 32, 32, 0, CopyFromParent, InputOutput, CopyFromParent,
971 CWBackingStore|CWBackPixel, &wattrs);
973 i = open(argv[1], O_RDONLY);
974 z=read(i, buf, 1024*1024);
976 fprintf(stderr,
"Read %d bytes from %s\n", z, argv[1]);
977 png_to_xpixmap(disp, window, buf, z, &pix, &mask, DefaultColormap(disp,
978 DefaultScreen(disp)), &width, &height);
979 XResizeWindow(disp, window, width, height);
981 fprintf(stderr,
"Unable to create window\n");
984 if (mask) XShapeCombineMask(disp,window,ShapeBounding,0,0,mask,ShapeSet);
985 XMapWindow(disp, window);
987 gc=XCreateGC(disp, pix, 0, NULL);
989 XSetClipMask(disp, gc, mask);
994 for (i=0; i<30; i++) {
995 XCopyArea(disp, pix, window, gc, 0, 0, width, height, 0 , 0);
long pngx_find_color(Display *display, Colormap *cmap, int red, int green, int blue)
int init_pngx_loader(Display *display)
uint8 * png_to_data(uint8 *data, int len, uint32 *width, uint32 *height)
static void user_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
static unsigned char * data_cp
PixmapInfo * pixmaps[MAXPIXMAPNUM]
struct Pngx_Color_Values * color_values
int rgba_to_xpixmap(Display *display, Drawable draw, uint8 *pixels, Pixmap *pix, Pixmap *mask, Colormap *cmap, unsigned long width, unsigned long height)
int png_to_xpixmap(Display *display, Drawable draw, unsigned char *data, int len, Pixmap *pix, Pixmap *mask, Colormap *cmap, unsigned long *width, unsigned long *height)
int create_and_rescale_image_from_data(Cache_Entry *ce, int pixmap_num, uint8 *rgba_data, int width, int height)
uint8 * rescale_rgba_data(uint8 *data, int *width, int *height, int scale)
#define BRIGHTNESS_FACTOR
static int need_color_alloc
void get_map_image_size(int face, uint8 *w, uint8 *h)
static int colors_alloced
const char * rcsid_x11_png_c