[Freeciv-Dev] Re: (PR#2269) PNG for freeciv
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Raimar Falke via RT wrote:
> On Mon, Nov 04, 2002 at 03:04:06AM -0800, Jason Short via RT wrote:
>
>>Attached is an update of Vasco's patch for PNG under XAW. See
>>http://lists.complete.org/freeciv-dev@xxxxxxxxxxx/2001/10/msg00797.html.gz.
>>
>>I've added minimal autoconf support, but we will need real support
>>before we go further. A patch would be welcome.
>>
>>Now, this patch *replaces* XPM support with (limited) PNG support.
>>There's nothing wrong with that (IMO), but it means when the patch is
>>applied the xaw client will no longer be able to use XPMs.
>
>
> So what does Xaw+this patch support and what is missing? Do all images
> have to have the same palette (as mentioned before)?
Well, I can't answer this definitively; perhaps Vasco can. I don't even
know if PNG has the concept of the "same palette"; if all images use the
same 32 colors it might all just work out.
I suspect that in Trident's case there will be no problem anyway - since
trident uses so few colors. For tilesets with more colors I don't know.
> Also the patch violates a lot of the coding style guide points.
Fixed; new patch attached.
jason
Index: client/gui-xaw/graphics.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-xaw/graphics.c,v
retrieving revision 1.39
diff -u -r1.39 graphics.c
--- client/gui-xaw/graphics.c 2002/08/07 11:21:43 1.39
+++ client/gui-xaw/graphics.c 2002/11/04 20:22:23
@@ -17,15 +17,13 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <ctype.h>
+#include <limits.h>
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
-#ifdef XPM_H_NO_X11
-#include <xpm.h>
-#else
-#include <X11/xpm.h>
-#endif
+#include <png.h>
#include "fcintl.h"
#include "game.h"
@@ -62,6 +60,7 @@
Cursor nuke_cursor;
Cursor patrol_cursor;
+static struct Sprite *ctor_sprite(Pixmap mypixmap, int width, int height);
static struct Sprite *ctor_sprite_mask(Pixmap mypixmap, Pixmap mask,
int width, int height);
@@ -167,22 +166,27 @@
struct Sprite *crop_sprite(struct Sprite *source,
int x, int y, int width, int height)
{
- GC plane_gc;
- Pixmap mypixmap, mask;
+ Pixmap mypixmap;
mypixmap = XCreatePixmap(display, root_window,
width, height, display_depth);
XCopyArea(display, source->pixmap, mypixmap, civ_gc,
x, y, width, height, 0, 0);
-
- mask = XCreatePixmap(display, root_window, width, height, 1);
- plane_gc = XCreateGC(display, mask, 0, NULL);
- XCopyArea(display, source->mask, mask, plane_gc,
- x, y, width, height, 0, 0);
- XFreeGC(display, plane_gc);
-
- return ctor_sprite_mask(mypixmap, mask, width, height);
+ if (source->has_mask) {
+ GC plane_gc;
+ Pixmap mask;
+
+ mask = XCreatePixmap(display, root_window, width, height, 1);
+
+ plane_gc = XCreateGC(display, mask, 0, NULL);
+ XCopyArea(display, source->mask, mask, plane_gc,
+ x, y, width, height, 0, 0);
+ XFreeGC(display, plane_gc);
+ return ctor_sprite_mask(mypixmap, mask, width, height);
+ } else {
+ return ctor_sprite(mypixmap, width, height);
+ }
}
/***************************************************************************
@@ -257,7 +261,6 @@
XFreePixmap(display, mask);
}
-#ifdef UNUSED
/***************************************************************************
...
***************************************************************************/
@@ -270,7 +273,6 @@
mysprite->has_mask=0;
return mysprite;
}
-#endif
/***************************************************************************
...
@@ -290,23 +292,7 @@
-#ifdef UNUSED
/***************************************************************************
-...
-***************************************************************************/
-void dtor_sprite(struct Sprite *mysprite)
-{
- XFreePixmap(display, mysprite->pixmap);
- if(mysprite->has_mask)
- XFreePixmap(display, mysprite->mask);
- free_colors(mysprite->pcolorarray, mysprite->ncols);
- free(mysprite->pcolorarray);
- free(mysprite);
-
-}
-#endif
-
-/***************************************************************************
Returns the filename extensions the client supports
Order is important.
***************************************************************************/
@@ -314,60 +300,231 @@
{
static char *ext[] =
{
- "xpm",
+ "png",
NULL
};
return ext;
}
+
+
/***************************************************************************
...
***************************************************************************/
+static bool is_transparent(png_byte index, png_bytep trans, int ntrans)
+{
+ int i;
+
+ for (i = 0; i < ntrans; i++) {
+ if (index == trans[i]) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/***************************************************************************
+...
+***************************************************************************/
+static Pixmap image2pixmap(XImage *xi)
+{
+ Pixmap ret;
+ XGCValues values;
+ GC gc;
+
+ ret = XCreatePixmap(display, root_window,
+ xi->width, xi->height, xi->depth);
+
+ values.foreground = 1;
+ values.background = 0;
+ gc = XCreateGC(display, ret, GCForeground | GCBackground, &values);
+
+ XPutImage(display, ret, gc, xi, 0, 0, 0, 0, xi->width, xi->height);
+ XFreeGC(display, gc);
+ return ret;
+}
+
+/***************************************************************************
+...
+***************************************************************************/
struct Sprite *load_gfxfile(const char *filename)
{
+ png_structp pngp;
+ png_infop infop;
+ png_uint_32 sig_read=0;
+ png_int_32 width, height, row, col;
+ int bit_depth, color_type, interlace_type;
+ FILE *fp;
+ int npalette, ntrans;
+ png_colorp palette;
+ png_bytep trans;
+ unsigned long *pcolorarray;
+ png_bytep *row_pointers;
struct Sprite *mysprite;
- Pixmap mypixmap, mask_bitmap;
- int err;
- XpmAttributes attributes;
-
- attributes.extensions = NULL;
- attributes.valuemask = XpmCloseness|XpmColormap;
- attributes.colormap = cmap;
- attributes.closeness = 40000;
+ XImage *xi;
+ int has_mask;
+
+ fp = fopen(filename, "rb");
+ if (!fp) {
+ freelog(LOG_FATAL, _("Failed reading PNG file: %s"), filename);
+ exit(EXIT_FAILURE);
+ }
+
+ pngp = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!pngp) {
+ freelog(LOG_FATAL, _("Failed creating PNG struct"));
+ exit(EXIT_FAILURE);
+ }
-again:
+ infop=png_create_info_struct(pngp);
+ if (!infop) {
+ freelog(LOG_FATAL, _("Failed creating PNG struct"));
+ exit(EXIT_FAILURE);
+ }
- if((err=XpmReadFileToPixmap(display, root_window, (char*)filename,
&mypixmap,
- &mask_bitmap, &attributes))!=XpmSuccess) {
- if(err==XpmColorError || err==XpmColorFailed) {
- color_error();
- goto again;
+ if (setjmp(pngp->jmpbuf)) {
+ freelog(LOG_FATAL, _("Failed while reading PNG file: %s"), filename);
+ exit(EXIT_FAILURE);
+ }
+
+ png_init_io(pngp, fp);
+ png_set_sig_bytes(pngp, sig_read);
+
+ png_read_info(pngp, infop);
+ png_get_IHDR(pngp, infop, &width, &height, &bit_depth, &color_type,
+ &interlace_type, NULL, NULL);
+
+ png_set_strip_16(pngp);
+ png_set_packing(pngp);
+
+ if (png_get_PLTE(pngp, infop, &palette, &npalette)) {
+ int i;
+
+ pcolorarray = fc_malloc(npalette * sizeof(unsigned long));
+
+ for (i = 0; i < npalette; i++) {
+ XColor mycolor;
+
+ mycolor.red = palette[i].red << 8;
+ mycolor.green = palette[i].green << 8;
+ mycolor.blue = palette[i].blue << 8;
+
+ if (XAllocColor(display, cmap, &mycolor)) {
+ pcolorarray[i] = mycolor.pixel;
+ } else {
+ XColor *cols;
+ int ncols, j;
+
+ ncols = DefaultVisual(display, screen_number)->map_entries;
+ cols = fc_malloc(sizeof(XColor) * ncols);
+
+ for (j = 0; j < ncols; j++) {
+ cols[j].pixel = j;
+ }
+ XQueryColors(display, cmap, cols, ncols);
+
+ for (; i < npalette; i++) {
+ int best = INT_MAX;
+ unsigned long pixel=0;
+
+ for (j = 0; j < ncols; j++) {
+ int rd, gd, bd, dist;
+
+ rd = (cols[j].red >> 8) - palette[i].red;
+ gd = (cols[j].green >> 8) - palette[i].green;
+ bd = (cols[j].blue >> 8) - palette[i].blue;
+ dist = rd * rd + gd * gd + bd * bd;
+
+ if (dist < best) {
+ best = dist;
+ pixel = j;
+ }
+ }
+ pcolorarray[i] = pixel;
+ }
+ free(cols);
+ break;
+ }
}
- freelog(LOG_FATAL, _("Failed reading XPM file: %s"), filename);
+ } else {
+ freelog(LOG_FATAL, _("PNG file has no palette: %s"), filename);
exit(EXIT_FAILURE);
}
+ png_read_update_info(pngp, infop);
+ has_mask = png_get_tRNS(pngp, infop, &trans, &ntrans, NULL);
+
+ row_pointers = fc_malloc(sizeof(png_bytep) * height);
+
+ for (row = 0; row < height; row++) {
+ row_pointers[row] = fc_malloc(png_get_rowbytes(pngp, infop));
+ }
+
+ png_read_image(pngp, row_pointers);
+ png_read_end(pngp, infop);
+ fclose(fp);
+
mysprite=fc_malloc(sizeof(struct Sprite));
+ mysprite->pixmap = 0;
+ mysprite->mask = 0;
- mysprite->pixmap=mypixmap;
- mysprite->mask=mask_bitmap;
- mysprite->has_mask=(mask_bitmap!=0);
- mysprite->width=attributes.width;
- mysprite->height=attributes.height;
+ xi = XCreateImage(display, DefaultVisual(display, screen_number),
+ display_depth, ZPixmap, 0, NULL, width, height, 32, 0);
+ xi->data = fc_calloc(xi->bytes_per_line * xi->height, 1);
+
+ for (row = 0; row < height; row++) {
+ for (col = 0; col < width; col++) {
+ XPutPixel(xi, col, row, pcolorarray[row_pointers[row][col]]);
+ }
+ }
+ mysprite->pixmap = image2pixmap(xi);
+ XDestroyImage(xi);
+ if (has_mask) {
+ XImage *xm;
+
+ xm = XCreateImage(display, DefaultVisual(display, screen_number),
+ 1, XYBitmap, 0, NULL, width, height, 8, 0);
+ xm->data = fc_calloc(xm->bytes_per_line * xm->height, 1);
+
+ for (row = 0; row < height; row++) {
+ for (col = 0; col < width; col++) {
+ XPutPixel(xm, col, row,
+ !is_transparent(row_pointers[row][col], trans, ntrans));
+ }
+ }
+ mysprite->mask = image2pixmap(xm);
+ XDestroyImage(xm);
+ }
+
+ mysprite->has_mask = has_mask;
+ mysprite->width = width;
+ mysprite->height = height;
+ mysprite->pcolorarray = pcolorarray;
+ mysprite->ncols = npalette;
+
+ for (row = 0; row < height; row++) {
+ free(row_pointers[row]);
+ }
+ free(row_pointers);
+ png_destroy_read_struct(&pngp, &infop, NULL);
return mysprite;
}
/***************************************************************************
Deletes a sprite. These things can use a lot of memory.
-
- (How/why does this differ from dtor_sprite() ? --dwp)
***************************************************************************/
void free_sprite(struct Sprite *s)
{
- if(s->pixmap) XFreePixmap(display,s->pixmap);
- if(s->has_mask) XFreePixmap(display,s->mask);
+ XFreePixmap(display, s->pixmap);
+ if (s->has_mask) {
+ XFreePixmap(display, s->mask);
+ }
+#if 0
+ free_colors(s->pcolorarray, s->ncols);
+#endif
+ free(s->pcolorarray);
free(s);
}
Index: configure.ac
===================================================================
RCS file: /home/freeciv/CVS/freeciv/configure.ac,v
retrieving revision 1.23
diff -u -r1.23 configure.ac
--- configure.ac 2002/10/11 23:45:46 1.23
+++ configure.ac 2002/11/04 20:22:31
@@ -351,6 +351,9 @@
dnl Checks for X:
AC_PATH_XTRA
+ # FIXME: check for libpng, and make sure we have libz
+ LDFLAGS="$LDFLAGS -lpng"
+
dnl Determine the Xfuncproto control definitions:
FC_CHECK_X_PROTO_DEFINE(FUNCPROTO)
if test -n "$fc_x_proto_value"; then
Message not available
|
|