From b78b8e9087ca140b6d5beecd4026c501cac5ff24 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 7 Mar 2001 17:16:38 +0000 Subject: [PATCH] Berni - Wed Mar 7 09:18:02 PST 2001 * Added initial GIMP XCF support (disabled by default) --- CHANGES | 2 + IMG.c | 1 + IMG_xcf.c | 796 +++++++++++++++++++++++++++++++++++++++++++++++++++ Makefile.am | 1 + SDL_image.h | 2 + configure.in | 6 + 6 files changed, 808 insertions(+) create mode 100644 IMG_xcf.c diff --git a/CHANGES b/CHANGES index 61222e5f..9ebbb2e0 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,7 @@ 1.1.1: +Berni - Wed Mar 7 09:18:02 PST 2001 + * Added initial GIMP XCF support (disabled by default) Mattias Engdegård - Wed Mar 7 09:01:49 PST 2001 * Added general PNM (PPM/PGM/PBM) support Mattias Engdegård - Sun Mar 4 14:23:42 PST 2001 diff --git a/IMG.c b/IMG.c index 97729be9..baaf7f27 100644 --- a/IMG.c +++ b/IMG.c @@ -43,6 +43,7 @@ static struct { { "BMP", IMG_isBMP, IMG_LoadBMP_RW }, { "PNM", IMG_isPNM, IMG_LoadPNM_RW }, /* P[BGP]M share code */ { "XPM", IMG_isXPM, IMG_LoadXPM_RW }, + { "XCF", IMG_isXCF, IMG_LoadXCF_RW }, { "PCX", IMG_isPCX, IMG_LoadPCX_RW }, { "GIF", IMG_isGIF, IMG_LoadGIF_RW }, { "JPG", IMG_isJPG, IMG_LoadJPG_RW }, diff --git a/IMG_xcf.c b/IMG_xcf.c new file mode 100644 index 00000000..541e7dc2 --- /dev/null +++ b/IMG_xcf.c @@ -0,0 +1,796 @@ +/* + IMGLIB: An example image loading library for use with SDL + Copyright (C) 1999 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + 5635-34 Springhouse Dr. + Pleasanton, CA 94588 (USA) + slouken@devolution.com + + XCF support by Bernhard J. Pietsch +*/ + +/* This is a XCF image file loading framework */ + +#include +#include +#include + +#include "SDL_image.h" + +#ifdef LOAD_XCF + +static char prop_names [][30] = { + "end", + "colormap", + "active_layer", + "active_channel", + "selection", + "floating_selection", + "opacity", + "mode", + "visible", + "linked", + "preserve_transparency", + "apply_mask", + "edit_mask", + "show_mask", + "show_masked", + "offsets", + "color", + "compression", + "guides", + "resolution", + "tattoo", + "parasites", + "unit", + "paths", + "user_unit" +}; + +typedef enum +{ + PROP_END = 0, + PROP_COLORMAP = 1, + PROP_ACTIVE_LAYER = 2, + PROP_ACTIVE_CHANNEL = 3, + PROP_SELECTION = 4, + PROP_FLOATING_SELECTION = 5, + PROP_OPACITY = 6, + PROP_MODE = 7, + PROP_VISIBLE = 8, + PROP_LINKED = 9, + PROP_PRESERVE_TRANSPARENCY = 10, + PROP_APPLY_MASK = 11, + PROP_EDIT_MASK = 12, + PROP_SHOW_MASK = 13, + PROP_SHOW_MASKED = 14, + PROP_OFFSETS = 15, + PROP_COLOR = 16, + PROP_COMPRESSION = 17, + PROP_GUIDES = 18, + PROP_RESOLUTION = 19, + PROP_TATTOO = 20, + PROP_PARASITES = 21, + PROP_UNIT = 22, + PROP_PATHS = 23, + PROP_USER_UNIT = 24 +} xcf_prop_type; + +typedef enum { + COMPR_NONE = 0, + COMPR_RLE = 1, + COMPR_ZLIB = 2, + COMPR_FRACTAL = 3 +} xcf_compr_type; + +typedef enum { + IMAGE_RGB = 0, + IMAGE_GREYSCALE = 1, + IMAGE_INDEXED = 2 +} xcf_image_type; + +typedef struct { + Uint32 id; + Uint32 length; + union { + struct { + Uint32 num; + char * cmap; + } colormap; // 1 + struct { + Uint32 drawable_offset; + } floating_selection; // 5 + Sint32 opacity; + Sint32 mode; + int visible; + int linked; + int preserve_transparency; + int apply_mask; + int show_mask; + struct { + Sint32 x; + Sint32 y; + } offset; + unsigned char color [3]; + Uint8 compression; + struct { + Sint32 x; + Sint32 y; + } resolution; + struct { + char * name; + Uint32 flags; + Uint32 size; + char * data; + } parasite; + } data; +} xcf_prop; + +typedef struct { + char sign [14]; + Uint32 width; + Uint32 height; + Sint32 image_type; + xcf_prop * properties; + + Uint32 * layer_file_offsets; + Uint32 * channel_file_offsets; + + xcf_compr_type compr; + Uint32 cm_num; + unsigned char * cm_map; +} xcf_header; + +typedef struct { + Uint32 width; + Uint32 height; + Sint32 layer_type; + char * name; + xcf_prop * properties; + + Uint32 hierarchy_file_offset; + Uint32 layer_mask_offset; + + Uint32 offset_x; + Uint32 offset_y; +} xcf_layer; + +typedef struct { + Uint32 width; + Uint32 height; + char * name; + xcf_prop * properties; + + Uint32 hierarchy_file_offset; + + Uint32 color; + Uint32 opacity; + int selection : 1; +} xcf_channel; + +typedef struct { + Uint32 width; + Uint32 height; + Uint32 bpp; + + Uint32 * level_file_offsets; +} xcf_hierarchy; + +typedef struct { + Uint32 width; + Uint32 height; + + Uint32 * tile_file_offsets; +} xcf_level; + +typedef unsigned char * xcf_tile; + +typedef unsigned char * (* load_tile_type) (SDL_RWops *, Uint32, int, int, int); + + +/* See if an image is contained in a data source */ +int IMG_isXCF(SDL_RWops *src) { + int is_XCF; + char magic[14]; + + is_XCF = 0; + if ( SDL_RWread(src, magic, 14, 1) ) { + if (strncmp(magic, "gimp xcf ", 9) == 0) { + is_XCF = 1; + } + } + + return(is_XCF); +} + +static char * read_string (SDL_RWops * src) { + Uint32 tmp; + char * data; + + tmp = SDL_ReadBE32 (src); + if (tmp > 0) { + data = (char *) malloc (sizeof (char) * tmp); + SDL_RWread (src, data, tmp, 1); + } + else { + data = NULL; + } + + return data; +} + + +static Uint32 Swap32 (Uint32 v) { + return + ((v & 0x000000FF) << 16) + | ((v & 0x0000FF00)) + | ((v & 0x00FF0000) >> 16) + | ((v & 0xFF000000)); +} + +void xcf_read_property (SDL_RWops * src, xcf_prop * prop) { + prop->id = SDL_ReadBE32 (src); + prop->length = SDL_ReadBE32 (src); + + printf ("%.8X: %s: %d\n", SDL_RWtell (src), prop->id < 25 ? prop_names [prop->id] : "unknown", prop->length); + + switch (prop->id) { + case PROP_COLORMAP: + prop->data.colormap.num = SDL_ReadBE32 (src); + prop->data.colormap.cmap = (char *) malloc (sizeof (char) * prop->data.colormap.num * 3); + SDL_RWread (src, prop->data.colormap.cmap, prop->data.colormap.num*3, 1); + break; + + case PROP_OFFSETS: + prop->data.offset.x = SDL_ReadBE32 (src); + prop->data.offset.y = SDL_ReadBE32 (src); + break; + case PROP_OPACITY: + prop->data.opacity = SDL_ReadBE32 (src); + break; + case PROP_COMPRESSION: + case PROP_COLOR: + SDL_RWread (src, &prop->data, prop->length, 1); + break; + default: + // SDL_RWread (src, &prop->data, prop->length, 1); + SDL_RWseek (src, prop->length, SEEK_CUR); + } +} + +void free_xcf_header (xcf_header * h) { + if (h->cm_num) + free (h->cm_map); + + free (h); +} + +xcf_header * read_xcf_header (SDL_RWops * src) { + xcf_header * h; + xcf_prop prop; + + h = (xcf_header *) malloc (sizeof (xcf_header)); + SDL_RWread (src, h->sign, 14, 1); + h->width = SDL_ReadBE32 (src); + h->height = SDL_ReadBE32 (src); + h->image_type = SDL_ReadBE32 (src); + + h->properties = NULL; + h->compr = COMPR_NONE; + h->cm_num = 0; + h->cm_map = NULL; + + // Just read, don't save + do { + xcf_read_property (src, &prop); + if (prop.id == PROP_COMPRESSION) + h->compr = prop.data.compression; + else if (prop.id == PROP_COLORMAP) { + int i; + + h->cm_num = prop.data.colormap.num; + h->cm_map = (char *) malloc (sizeof (char) * 3 * h->cm_num); + memcpy (h->cm_map, prop.data.colormap.cmap, 3*sizeof (char)*h->cm_num); + free (prop.data.colormap.cmap); + } + } while (prop.id != PROP_END); + + return h; +} + +void free_xcf_layer (xcf_layer * l) { + free (l->name); + free (l); +} + +xcf_layer * read_xcf_layer (SDL_RWops * src) { + xcf_layer * l; + xcf_prop prop; + + l = (xcf_layer *) malloc (sizeof (xcf_layer)); + l->width = SDL_ReadBE32 (src); + l->height = SDL_ReadBE32 (src); + l->layer_type = SDL_ReadBE32 (src); + + l->name = read_string (src); + + do { + xcf_read_property (src, &prop); + if (prop.id == PROP_OFFSETS) { + l->offset_x = prop.data.offset.x; + l->offset_y = prop.data.offset.y; + } + } while (prop.id != PROP_END); + + l->hierarchy_file_offset = SDL_ReadBE32 (src); + l->layer_mask_offset = SDL_ReadBE32 (src); + + return l; +} + +void free_xcf_channel (xcf_channel * c) { + free (c->name); + free (c); +} + +xcf_channel * read_xcf_channel (SDL_RWops * src) { + xcf_channel * l; + xcf_prop prop; + + l = (xcf_channel *) malloc (sizeof (xcf_channel)); + l->width = SDL_ReadBE32 (src); + l->height = SDL_ReadBE32 (src); + + l->name = read_string (src); + + l->selection = 0; + do { + xcf_read_property (src, &prop); + switch (prop.id) { + case PROP_OPACITY: + l->opacity = prop.data.opacity << 24; + break; + case PROP_COLOR: + l->color = ((Uint32) prop.data.color[0] << 16) + | ((Uint32) prop.data.color[1] << 8) + | ((Uint32) prop.data.color[2]); + break; + case PROP_SELECTION: + l->selection = 1; + break; + default: + } + } while (prop.id != PROP_END); + + l->hierarchy_file_offset = SDL_ReadBE32 (src); + + return l; +} + +void free_xcf_hierarchy (xcf_hierarchy * h) { + free (h->level_file_offsets); + free (h); +} + +xcf_hierarchy * read_xcf_hierarchy (SDL_RWops * src) { + xcf_hierarchy * h; + int i; + + h = (xcf_hierarchy *) malloc (sizeof (xcf_hierarchy)); + h->width = SDL_ReadBE32 (src); + h->height = SDL_ReadBE32 (src); + h->bpp = SDL_ReadBE32 (src); + + h->level_file_offsets = NULL; + i = 0; + do { + h->level_file_offsets = (Uint32 *) realloc (h->level_file_offsets, sizeof (Uint32) * (i+1)); + h->level_file_offsets [i] = SDL_ReadBE32 (src); + } while (h->level_file_offsets [i++]); + + return h; +} + +void free_xcf_level (xcf_level * l) { + free (l->tile_file_offsets); + free (l); +} + +xcf_level * read_xcf_level (SDL_RWops * src) { + xcf_level * l; + int i; + + l = (xcf_level *) malloc (sizeof (xcf_level)); + l->width = SDL_ReadBE32 (src); + l->height = SDL_ReadBE32 (src); + + l->tile_file_offsets = NULL; + i = 0; + do { + l->tile_file_offsets = (Uint32 *) realloc (l->tile_file_offsets, sizeof (Uint32) * (i+1)); + l->tile_file_offsets [i] = SDL_ReadBE32 (src); + } while (l->tile_file_offsets [i++]); + + return l; +} + +void free_xcf_tile (unsigned char * t) { + free (t); +} + +unsigned char * load_xcf_tile_none (SDL_RWops * src, Uint32 len, int bpp, int x, int y) { + unsigned char * load; + + load = (char *) malloc (len); // expect this is okay + SDL_RWread (src, load, len, 1); + + return load; +} + +unsigned char * load_xcf_tile_rle (SDL_RWops * src, Uint32 len, int bpp, int x, int y) { + unsigned char * load, * t, * data, * d; + Uint32 reallen; + int i, size, count, j, length; + unsigned char val; + + t = load = (char *) malloc (len); + reallen = SDL_RWread (src, t, 1, len); + + data = (char *) malloc (x*y*bpp); + for (i = 0; i < bpp; i++) { + d = data + i; + size = x*y; + count = 0; + + while (size > 0) { + val = *t++; + + length = val; + if (length >= 128) { + length = 255 - (length - 1); + if (length == 128) { + length = (*t << 8) + t[1]; + t += 2; + } + + count += length; + size -= length; + + while (length-- > 0) { + *d = *t++; + d += bpp; + } + } + else { + length += 1; + if (length == 128) { + length = (*t << 8) + t[1]; + t += 2; + } + + count += length; + size -= length; + + val = *t++; + + for (j = 0; j < length; j++) { + *d = val; + d += bpp; + } + } + } + } + + free (load); + return (data); +} + +static Uint32 rgb2grey (Uint32 a) { + Uint8 l; + l = 0.2990 * ((a && 0x00FF0000) >> 16) + + 0.5870 * ((a && 0x0000FF00) >> 8) + + 0.1140 * ((a && 0x000000FF)); + + return (l << 16) | (l << 8) | l; +} + +void create_channel_surface (SDL_Surface * surf, xcf_image_type itype, Uint32 color, Uint32 opacity) { + Uint32 c; + + switch (itype) { + case IMAGE_RGB: + case IMAGE_INDEXED: + c = opacity | color; + break; + case IMAGE_GREYSCALE: + c = opacity | rgb2grey (color); + break; + } + SDL_FillRect (surf, NULL, c); +} + +int do_layer_surface (SDL_Surface * surface, SDL_RWops * src, xcf_header * head, xcf_layer * layer, load_tile_type load_tile) { + xcf_hierarchy * hierarchy; + xcf_level * level; + unsigned char * tile; + Uint8 * p8; + Uint16 * p16; + Uint32 * p; + int x, y, tx, ty, ox, oy, width, height, i, j; + Uint32 *row; + + SDL_RWseek (src, layer->hierarchy_file_offset, SEEK_SET); + hierarchy = read_xcf_hierarchy (src); + + level = NULL; + for (i = 0; hierarchy->level_file_offsets [i]; i++) { + SDL_RWseek (src, hierarchy->level_file_offsets [i], SEEK_SET); + level = read_xcf_level (src); + + ty = tx = 0; + for (j = 0; level->tile_file_offsets [j]; j++) { + SDL_RWseek (src, level->tile_file_offsets [j], SEEK_SET); + ox = tx+64 > level->width ? level->width % 64 : 64; + oy = ty+64 > level->height ? level->height % 64 : 64; + + if (level->tile_file_offsets [j+1]) { + tile = load_tile + (src, + level->tile_file_offsets [j+1] - level->tile_file_offsets [j], + hierarchy->bpp, + ox, oy); + } + else { + tile = load_tile + (src, + ox*oy*6, + hierarchy->bpp, + ox, oy); + } + + p8 = tile; + p16 = (Uint16 *) p8; + p = (Uint32 *) p8; + for (y=ty; y < ty+oy; y++) { + row = (Uint32 *)((Uint8 *)surface->pixels + y*surface->pitch + tx*4); + switch (hierarchy->bpp) { + case 4: + for (x=tx; x < tx+ox; x++) + *row++ = Swap32 (*p++); + break; + case 3: + for (x=tx; x < tx+ox; x++) { + *row = 0xFF000000; + *row |= ((Uint32) *(p8++) << 16); + *row |= ((Uint32) *(p8++) << 8); + *row |= ((Uint32) *(p8++) << 0); + row++; + } + break; + case 2: // Indexed/Greyscale + Alpha + switch (head->image_type) { + case IMAGE_INDEXED: + for (x=tx; x < tx+ox; x++) { + *row = ((Uint32) (head->cm_map [*p8*3]) << 16); + *row |= ((Uint32) (head->cm_map [*p8*3+1]) << 8); + *row |= ((Uint32) (head->cm_map [*p8++*3+2]) << 0); + *row |= ((Uint32) *p8++ << 24);; + row++; + } + break; + case IMAGE_GREYSCALE: + for (x=tx; x < tx+ox; x++) { + *row = ((Uint32) *p8 << 16); + *row |= ((Uint32) *p8 << 8); + *row |= ((Uint32) *p8++ << 0); + *row |= ((Uint32) *p8++ << 24);; + row++; + } + break; + default: + fprintf (stderr, "Unknown Gimp image type (%d)\n", head->image_type); + return 1; + } + break; + case 1: // Indexed/Greyscale + switch (head->image_type) { + case IMAGE_INDEXED: + for (x = tx; x < tx+ox; x++) { + *row++ = 0xFF000000 + | ((Uint32) (head->cm_map [*p8*3]) << 16) + | ((Uint32) (head->cm_map [*p8*3+1]) << 8) + | ((Uint32) (head->cm_map [*p8*3+2]) << 0); + p8++; + } + break; + case IMAGE_GREYSCALE: + for (x=tx; x < tx+ox; x++) { + *row++ = 0xFF000000 + | (((Uint32) (*p8)) << 16) + | (((Uint32) (*p8)) << 8) + | (((Uint32) (*p8++)) << 0); + } + break; + default: + fprintf (stderr, "Unknown Gimp image type (%d)\n", head->image_type); + return 1; + } + break; + } + } + tx += 64; + if (tx >= level->width) { + tx = 0; + ty += 64; + } + if (ty >= level->height) { + break; + } + + free_xcf_tile (tile); + } + free_xcf_level (level); + } + + free_xcf_hierarchy (hierarchy); +} + +SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src) { + SDL_Surface *surface, *lays; + xcf_header * head; + xcf_layer * layer; + xcf_channel ** channel; + int read_error, chnls, i, offsets; + Uint32 offset, fp; + + unsigned char * (* load_tile) (SDL_RWops *, Uint32, int, int, int); + + /* Initialize the data we will clean up when we're done */ + surface = NULL; + read_error = 0; + + /* Check to make sure we have something to do */ + if ( ! src ) { + goto done; + } + + head = read_xcf_header (src); + + switch (head->compr) { + case COMPR_NONE: + load_tile = load_xcf_tile_none; + break; + case COMPR_RLE: + load_tile = load_xcf_tile_rle; + break; + default: + fprintf (stderr, "Unsupported Compression.\n"); + free_xcf_header (head); + return NULL; + } + + /* Create the surface of the appropriate type */ + surface = SDL_AllocSurface(SDL_SWSURFACE, head->width, head->height, 32, + 0x00FF0000,0x0000FF00,0x000000FF,0xFF000000); + + if ( surface == NULL ) { + IMG_SetError("Out of memory"); + goto done; + } + + head->layer_file_offsets = NULL; + offsets = 0; + + while (offset = SDL_ReadBE32 (src)) { + head->layer_file_offsets = (Uint32 *) realloc (head->layer_file_offsets, sizeof (Uint32) * (offsets+1)); + head->layer_file_offsets [offsets] = offset; + offsets++; + } + fp = SDL_RWtell (src); + + lays = SDL_AllocSurface(SDL_SWSURFACE, head->width, head->height, 32, + 0x00FF0000,0x0000FF00,0x000000FF,0xFF000000); + + if ( lays == NULL ) { + IMG_SetError("Out of memory"); + goto done; + } + + // Blit layers backwards, because Gimp saves them highest first + for (i = offsets; i > 0; i--) { + SDL_Rect rs, rd; + SDL_RWseek (src, head->layer_file_offsets [i-1], SEEK_SET); + + layer = read_xcf_layer (src); + do_layer_surface (lays, src, head, layer, load_tile); + rs.x = 0; + rs.y = 0; + rs.w = layer->width; + rs.h = layer->height; + rd.x = layer->offset_x; + rd.y = layer->offset_y; + rd.w = layer->width; + rd.h = layer->height; + free_xcf_layer (layer); + + SDL_BlitSurface (lays, &rs, surface, &rd); + } + + SDL_FreeSurface (lays); + + SDL_RWseek (src, fp, SEEK_SET); + + // read channels + channel = NULL; + chnls = 0; + while (offset = SDL_ReadBE32 (src)) { + channel = (xcf_channel **) realloc (channel, sizeof (xcf_channel *) * (chnls+1)); + fp = SDL_RWtell (src); + SDL_RWseek (src, offset, SEEK_SET); + channel [chnls++] = (read_xcf_channel (src)); + SDL_RWseek (src, fp, SEEK_SET); + } + + if (chnls) { + SDL_Surface * chs; + + chs = SDL_AllocSurface(SDL_SWSURFACE, head->width, head->height, 32, + 0x00FF0000,0x0000FF00,0x000000FF,0xFF000000); + + if (chs == NULL) { + IMG_SetError("Out of memory"); + goto done; + } + for (i = 0; i < chnls; i++) { + // printf ("CNLBLT %i\n", i); + if (!channel [i]->selection) { + create_channel_surface (chs, head->image_type, channel [i]->color, channel [i]->opacity); + SDL_BlitSurface (chs, NULL, surface, NULL); + } + free_xcf_channel (channel [i]); + } + + SDL_FreeSurface (chs); + } + + done: + free_xcf_header (head); + if ( read_error ) { + SDL_FreeSurface(surface); + IMG_SetError("Error reading XCF data"); + surface = NULL; + } + + return(surface); +} + +#else + +/* See if an image is contained in a data source */ +int IMG_isXCF(SDL_RWops *src) +{ + return(0); +} + +/* Load a XCF type image from an SDL datasource */ +SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src) +{ + return(NULL); +} + +#endif /* LOAD_XCF */ diff --git a/Makefile.am b/Makefile.am index 6f081511..6b5fe067 100644 --- a/Makefile.am +++ b/Makefile.am @@ -16,6 +16,7 @@ libSDL_image_la_SOURCES = \ IMG_pnm.c \ IMG_tga.c \ IMG_tif.c \ + IMG_xcf.c \ IMG_xpm.c EXTRA_DIST = \ diff --git a/SDL_image.h b/SDL_image.h index f4164921..5b002bdf 100644 --- a/SDL_image.h +++ b/SDL_image.h @@ -58,6 +58,7 @@ extern DECLSPEC int IMG_InvertAlpha(int on); extern DECLSPEC int IMG_isBMP(SDL_RWops *src); extern DECLSPEC int IMG_isPNM(SDL_RWops *src); extern DECLSPEC int IMG_isXPM(SDL_RWops *src); +extern DECLSPEC int IMG_isXCF(SDL_RWops *src); extern DECLSPEC int IMG_isPCX(SDL_RWops *src); extern DECLSPEC int IMG_isGIF(SDL_RWops *src); extern DECLSPEC int IMG_isJPG(SDL_RWops *src); @@ -68,6 +69,7 @@ extern DECLSPEC int IMG_isPNG(SDL_RWops *src); extern DECLSPEC SDL_Surface *IMG_LoadBMP_RW(SDL_RWops *src); extern DECLSPEC SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src); extern DECLSPEC SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src); extern DECLSPEC SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src); extern DECLSPEC SDL_Surface *IMG_LoadGIF_RW(SDL_RWops *src); extern DECLSPEC SDL_Surface *IMG_LoadJPG_RW(SDL_RWops *src); diff --git a/configure.in b/configure.in index 970cb711..a24619e6 100644 --- a/configure.in +++ b/configure.in @@ -158,6 +158,12 @@ if test x$enable_tif = xyes; then AC_MSG_WARN([TIF image loading disabled]) fi fi +AC_ARG_ENABLE(xcf, +[ --enable-xcf support loading XCF images [default=no]], + , enable_xcf=no) +if test x$enable_xcf = xyes; then + CFLAGS="$CFLAGS -DLOAD_XCF" +fi AC_ARG_ENABLE(xpm, [ --enable-xpm support loading XPM images [default=yes]], , enable_xpm=yes)