X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Flibgame%2Fimage.c;h=50dce1d713b0df9c49b12be304610cf013adecdb;hp=836f28435b4b2e2c6380cccd5e61aa3da5d80f09;hb=a8816d6e5319f9ec26a45346b08250f61e95c011;hpb=681721dddc91bcdaef50002d1e861cc8d484e938 diff --git a/src/libgame/image.c b/src/libgame/image.c index 836f2843..50dce1d7 100644 --- a/src/libgame/image.c +++ b/src/libgame/image.c @@ -1,7 +1,7 @@ /*********************************************************** * Artsoft Retro-Game Library * *----------------------------------------------------------* -* (c) 1994-2001 Artsoft Entertainment * +* (c) 1994-2006 Artsoft Entertainment * * Holger Schemel * * Detmolder Strasse 189 * * 33604 Bielefeld * @@ -14,8 +14,13 @@ #include "image.h" #include "pcx.h" #include "misc.h" +#include "setup.h" +/* ========================================================================= */ +/* PLATFORM SPECIFIC IMAGE FUNCTIONS */ +/* ========================================================================= */ + #if defined(TARGET_X11) /* for MS-DOS/Allegro, exclude all except newImage() and freeImage() */ @@ -23,22 +28,24 @@ Image *newImage(unsigned int width, unsigned int height, unsigned int depth) { Image *image; - const unsigned int bytes_per_pixel = 1; + unsigned int bytes_per_pixel = (depth + 7) / 8; int i; - if (depth > 8) - Error(ERR_EXIT, "images with more than 256 colors are not supported"); - - depth = 8; - image = checked_malloc(sizeof(Image)); - image->data = checked_malloc(width * height * bytes_per_pixel); + image = checked_calloc(sizeof(Image)); + image->data = checked_calloc(width * height * bytes_per_pixel); image->width = width; image->height = height; image->depth = depth; + image->bytes_per_pixel = bytes_per_pixel; + image->bytes_per_row = width * bytes_per_pixel; + image->rgb.used = 0; - for (i=0; irgb.color_used[i] = FALSE; + image->type = (depth < 8 ? IMAGETYPE_BITMAP : + depth > 8 ? IMAGETYPE_TRUECOLOR : IMAGETYPE_RGB); + return image; } @@ -53,26 +60,39 @@ void freeImage(Image *image) /* extra colors to try allocating in private color maps to minimize flashing */ #define NOFLASH_COLORS 256 -/* architecture independent value-to-memory conversion +/* architecture independent value <-> memory conversions; note: the internal format is big endian */ -#define value_to_memory(value, ptr, length) ( \ -(length) == 1 ? (*( (byte *)(ptr) ) = ( value ) ) : \ -(length) == 2 ? (*( (byte *)(ptr) ) = (((unsigned long)(value))>> 8), \ - *(((byte *)(ptr))+1) = ( value ) ) : \ -(length) == 3 ? (*( (byte *)(ptr) ) = (((unsigned long)(value))>>16), \ - *(((byte *)(ptr))+1) = (((unsigned long)(value))>> 8), \ - *(((byte *)(ptr))+2) = ( value ) ) : \ - (*( (byte *)(ptr) ) = (((unsigned long)(value))>>24), \ - *(((byte *)(ptr))+1) = (((unsigned long)(value))>>16), \ - *(((byte *)(ptr))+2) = (((unsigned long)(value))>> 8), \ - *(((byte *)(ptr))+3) = ( value ) )) +#define memory_to_value(ptr, len) ( \ +(len) == 1 ? (unsigned int)( *( (byte *)(ptr)) ) : \ +(len) == 2 ? (unsigned int)(((unsigned int)(*( (byte *)(ptr)) ))<< 8) \ + + ( *(((byte *)(ptr))+1) ) : \ +(len) == 3 ? (unsigned int)(((unsigned int)(*( (byte *)(ptr)) ))<<16) \ + + (((unsigned int)(*(((byte *)(ptr))+1)))<< 8) \ + + ( *(((byte *)(ptr))+2) ) : \ + (unsigned int)(((unsigned int)(*( (byte *)(ptr)) ))<<24) \ + + (((unsigned int)(*(((byte *)(ptr))+1)))<<16) \ + + (((unsigned int)(*(((byte *)(ptr))+2)))<< 8) \ + + ( *(((byte *)(ptr))+3) ) ) + + +#define value_to_memory(value, ptr, len) ( \ +(len) == 1 ? (*( (byte *)(ptr) ) = ( value ) ) : \ +(len) == 2 ? (*( (byte *)(ptr) ) = (((unsigned int)(value))>> 8), \ + *(((byte *)(ptr))+1) = ( value ) ) : \ +(len) == 3 ? (*( (byte *)(ptr) ) = (((unsigned int)(value))>>16), \ + *(((byte *)(ptr))+1) = (((unsigned int)(value))>> 8), \ + *(((byte *)(ptr))+2) = ( value ) ) : \ + (*( (byte *)(ptr) ) = (((unsigned int)(value))>>24), \ + *(((byte *)(ptr))+1) = (((unsigned int)(value))>>16), \ + *(((byte *)(ptr))+2) = (((unsigned int)(value))>> 8), \ + *(((byte *)(ptr))+3) = ( value ) )) static Pixmap Image_to_Mask(Image *image, Display *display, Window window) { byte *src_ptr, *dst_ptr, *dst_ptr2; unsigned int bytes_per_row; - unsigned int x, y; + unsigned int x, y, i; byte bitmask; byte *mask_data; Pixmap mask_pixmap; @@ -88,15 +108,78 @@ static Pixmap Image_to_Mask(Image *image, Display *display, Window window) * the corresponding image pixmap */ - for (y=0; yheight; y++) + for (y = 0; y < image->height; y++) + { + bitmask = 0x01; /* start with leftmost bit in the byte */ + dst_ptr2 = dst_ptr; /* start with leftmost byte in the row */ + + for (x = 0; x < image->width; x++) + { + for (i = 0; i < image->bytes_per_pixel; i++) + if (*src_ptr++) /* source pixel solid? (pixel index != 0) */ + *dst_ptr2 |= bitmask; /* then write a bit into the image mask */ + + if ((bitmask <<= 1) == 0) /* bit at rightmost byte position reached? */ + { + bitmask = 0x01; /* start again with leftmost bit position */ + dst_ptr2++; /* continue with next byte in image mask */ + } + } + + dst_ptr += bytes_per_row; /* continue with leftmost byte of next row */ + } + + if ((mask_pixmap = XCreateBitmapFromData(display, window, (char *)mask_data, + image->width, image->height)) + == None) + Error(ERR_EXIT, "Image_to_Mask(): XCreateBitmapFromData() failed"); + + free(mask_data); + + return mask_pixmap; +} + +Pixmap Pixmap_to_Mask(Pixmap src_pixmap, int src_width, int src_height) +{ + XImage *src_ximage; + byte *src_ptr, *dst_ptr, *dst_ptr2; + int bits_per_pixel; + int bytes_per_pixel; + unsigned int bytes_per_row; + unsigned int x, y, i; + byte bitmask; + byte *mask_data; + Pixmap mask_pixmap; + + /* copy source pixmap to temporary image */ + if ((src_ximage = XGetImage(display, src_pixmap, 0, 0, src_width, src_height, + AllPlanes, ZPixmap)) == NULL) + Error(ERR_EXIT, "Pixmap_to_Mask(): XGetImage() failed"); + + bits_per_pixel = src_ximage->bits_per_pixel; + bytes_per_pixel = (bits_per_pixel + 7) / 8; + + bytes_per_row = (src_width + 7) / 8; + mask_data = checked_calloc(bytes_per_row * src_height); + + src_ptr = (byte *)src_ximage->data; + dst_ptr = mask_data; + + /* create bitmap data which can be used by 'XCreateBitmapFromData()' + * directly to create a pixmap of depth 1 for use as a clip mask for + * the corresponding image pixmap + */ + + for (y = 0; y < src_height; y++) { bitmask = 0x01; /* start with leftmost bit in the byte */ dst_ptr2 = dst_ptr; /* start with leftmost byte in the row */ - for (x=0; xwidth; x++) + for (x = 0; x < src_width; x++) { - if (*src_ptr++) /* source pixel solid? (pixel index != 0) */ - *dst_ptr2 |= bitmask; /* then write a bit into the image mask */ + for (i = 0; i < bytes_per_pixel; i++) + if (*src_ptr++) /* source pixel solid? (pixel index != 0) */ + *dst_ptr2 |= bitmask; /* then write a bit into the image mask */ if ((bitmask <<= 1) == 0) /* bit at rightmost byte position reached? */ { @@ -108,8 +191,11 @@ static Pixmap Image_to_Mask(Image *image, Display *display, Window window) dst_ptr += bytes_per_row; /* continue with leftmost byte of next row */ } - mask_pixmap = XCreateBitmapFromData(display, window, (char *)mask_data, - image->width, image->height); + if ((mask_pixmap = XCreateBitmapFromData(display, window->drawable, + (char *)mask_data, + src_width, src_height)) == None) + Error(ERR_EXIT, "Pixmap_to_Mask(): XCreateBitmapFromData() failed"); + free(mask_data); return mask_pixmap; @@ -124,7 +210,7 @@ static int bitsPerPixelAtDepth(Display *display, int screen, int depth) pixmap_format = XListPixmapFormats(display, &num_pixmap_formats); /* find format that matches the given depth */ - for (i=0; itype == IMAGETYPE_TRUECOLOR && depth == 8) + { + SetError(error, "cannot handle true-color images on 8-bit display"); + return NULL; + } if (!global_cmap) { @@ -193,7 +287,7 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, /* calculate number of distinct colors in each band */ redcolors = greencolors = bluecolors = 1; - for (pixval=1; pixval; pixval <<= 1) + for (pixval = 1; pixval; pixval <<= 1) { if (pixval & visual->red_mask) redcolors <<= 1; @@ -214,7 +308,8 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, bluestep = 256 / bluecolors; redbottom = greenbottom = bluebottom = 0; redtop = greentop = bluetop = 0; - for (a=0; amap_entries; a++) + + for (a = 0; a < visual->map_entries; a++) { if (redbottom < 256) redtop = redbottom + redstep; @@ -243,11 +338,13 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, /* something completely unexpected happened */ - fprintf(stderr, "imageToXImage: XAllocColor failed on a TrueColor/Directcolor visual\n"); + fprintf(stderr, "Image_to_Pixmap: XAllocColor failed on a TrueColor/Directcolor visual\n"); + free(redvalue); free(greenvalue); free(bluevalue); free(ximageinfo); + return NULL; } @@ -260,6 +357,7 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, while ((bluebottom < 256) && (bluebottom < bluetop)) bluevalue[bluebottom++] = xcolor.pixel & visual->blue_mask; } + break; } @@ -267,7 +365,7 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, ximageinfo->cmap = global_cmap; - for (a=0; a=0; i--) + for (i = num_cmap_entries - 1; i >= 0; i--) { xcolor2.pixel = *(global_cmap_index + i); xcolor2 = xcolor_private[xcolor2.pixel]; @@ -365,7 +463,10 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, } if (!color_found) /* no more free color cells */ - Error(ERR_EXIT, "cannot allocate enough color cells"); + { + SetError(error, "cannot allocate enough color cells"); + return NULL; + } xcolor.pixel = xcolor2.pixel; xcolor_private[xcolor.pixel] = xcolor; @@ -385,9 +486,10 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, break; default: - Error(ERR_RETURN, "display class not supported"); - Error(ERR_EXIT, "DirectColor, TrueColor or PseudoColor display needed"); - break; + Error(ERR_INFO,"DirectColor, TrueColor or PseudoColor display needed"); + SetError(error, "display class not supported"); + + return NULL; } #if DEBUG_TIMING @@ -396,14 +498,14 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, /* create XImage from internal image structure and convert it to Pixmap */ - bits_per_pixel = bitsPerPixelAtDepth(display, screen, depth); - bytes_per_pixel = (bits_per_pixel + 7) / 8; + display_bits_per_pixel = bitsPerPixelAtDepth(display, screen, depth); + display_bytes_per_pixel = (display_bits_per_pixel + 7) / 8; - ximage = XCreateImage(display, visual, depth, ZPixmap, 0, - NULL, image->width, image->height, - 8, image->width * bytes_per_pixel); + ximage = XCreateImage(display, visual, depth, ZPixmap, + 0, NULL, image->width, image->height, + 8, image->width * display_bytes_per_pixel); ximage->data = - checked_malloc(image->width * image->height * bytes_per_pixel); + checked_malloc(image->width * image->height * display_bytes_per_pixel); ximage->byte_order = MSBFirst; src_ptr = image->data; @@ -416,49 +518,86 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, { Pixel pixval; - for (y=0; yheight; y++) /* general case */ + switch (image->type) { - for (x=0; xwidth; x++) + case IMAGETYPE_RGB: + { + for (y = 0; y < image->height; y++) /* general case */ + { + for (x = 0; x < image->width; x++) + { + pixval = *src_ptr++; + pixval = + redvalue[image->rgb.red[pixval] >> 8] | + greenvalue[image->rgb.green[pixval] >> 8] | + bluevalue[image->rgb.blue[pixval] >> 8]; + value_to_memory(pixval, dst_ptr, display_bytes_per_pixel); + dst_ptr += display_bytes_per_pixel; + } + } + + break; + } + + case IMAGETYPE_TRUECOLOR: { - pixval = *src_ptr++; - pixval = - redvalue[image->rgb.red[pixval] >> 8] | - greenvalue[image->rgb.green[pixval] >> 8] | - bluevalue[image->rgb.blue[pixval] >> 8]; - value_to_memory(pixval, dst_ptr, bytes_per_pixel); - dst_ptr += bytes_per_pixel; + for (y = 0; y < image->height; y++) /* general case */ + { + for (x = 0; x < image->width; x++) + { + pixval = memory_to_value(src_ptr, image->bytes_per_pixel); + pixval = + redvalue[TRUECOLOR_RED(pixval)] | + greenvalue[TRUECOLOR_GREEN(pixval)] | + bluevalue[TRUECOLOR_BLUE(pixval)]; + value_to_memory(pixval, dst_ptr, display_bytes_per_pixel); + src_ptr += image->bytes_per_pixel; + dst_ptr += display_bytes_per_pixel; + } + } + + break; } + + default: + Error(ERR_INFO, "RGB or TrueColor image needed"); + SetError(error, "image type not supported"); + + return NULL; } + break; } case PseudoColor: { - if (bytes_per_pixel == 1) /* (common) special case */ + if (display_bytes_per_pixel == 1) /* special case */ { - for (y=0; yheight; y++) - for (x=0; xwidth; x++) + for (y = 0; y < image->height; y++) + for (x = 0; x < image->width; x++) *dst_ptr++ = ximageinfo->index[c + *src_ptr++]; } else /* general case */ { - for (y=0; yheight; y++) + for (y = 0; y < image->height; y++) { - for (x=0; xwidth; x++) + for (x = 0; x < image->width; x++) { value_to_memory(ximageinfo->index[c + *src_ptr++], - dst_ptr, bytes_per_pixel); - dst_ptr += bytes_per_pixel; + dst_ptr, display_bytes_per_pixel); + dst_ptr += display_bytes_per_pixel; } } } + break; } default: - Error(ERR_RETURN, "display class not supported"); - Error(ERR_EXIT, "DirectColor, TrueColor or PseudoColor display needed"); - break; + Error(ERR_INFO,"DirectColor, TrueColor or PseudoColor display needed"); + SetError(error, "display class not supported"); + + return NULL; } if (redvalue) @@ -479,11 +618,120 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, XPutImage(ximageinfo->display, ximageinfo->pixmap, gc, ximage, 0, 0, 0, 0, ximage->width, ximage->height); - free(ximage->data); - ximage->data = NULL; - XDestroyImage(ximage); + X11DestroyImage(ximage); + + return ximageinfo; +} + +/* + ----------------------------------------------------------------------------- + ZoomPixmap + + Important note: The scaling code currently only supports scaling of the image + up or down by a power of 2 -- other scaling factors currently not supported! + Also not supported is scaling of pixmap masks (with depth 1); to scale them, + better use Pixmap_to_Mask() for now. + ----------------------------------------------------------------------------- +*/ + +void ZoomPixmap(Display *display, GC gc, Pixmap src_pixmap, Pixmap dst_pixmap, + int src_width, int src_height, + int dst_width, int dst_height) +{ + XImage *src_ximage, *dst_ximage; + byte *src_ptr, *dst_ptr; + int bits_per_pixel; + int bytes_per_pixel; + int x, y, xx, yy, i; + int row_skip, col_skip; + int zoom_factor; + boolean scale_down = (src_width > dst_width); + + if (scale_down) + { +#if 1 + zoom_factor = MIN(src_width / dst_width, src_height / dst_height); +#else + zoom_factor = src_width / dst_width; +#endif + + /* adjust source image size to integer multiple of destination size */ + src_width = dst_width * zoom_factor; + src_height = dst_height * zoom_factor; + } + else + { +#if 1 + zoom_factor = MIN(dst_width / src_width, dst_height / src_height); +#else + zoom_factor = dst_width / src_width; +#endif + + /* no adjustment needed when scaling up (some pixels may be left blank) */ + } + + /* copy source pixmap to temporary image */ + if ((src_ximage = XGetImage(display, src_pixmap, 0, 0, src_width, src_height, + AllPlanes, ZPixmap)) == NULL) + Error(ERR_EXIT, "ZoomPixmap(): XGetImage() failed"); + + bits_per_pixel = src_ximage->bits_per_pixel; + bytes_per_pixel = (bits_per_pixel + 7) / 8; + + if ((dst_ximage = XCreateImage(display, visual, src_ximage->depth, ZPixmap, + 0, NULL, dst_width, dst_height, + 8, dst_width * bytes_per_pixel)) == NULL) + Error(ERR_EXIT, "ZoomPixmap(): XCreateImage() failed"); + + dst_ximage->data = + checked_malloc(dst_width * dst_height * bytes_per_pixel); + dst_ximage->byte_order = src_ximage->byte_order; + + src_ptr = (byte *)src_ximage->data; + dst_ptr = (byte *)dst_ximage->data; + + if (scale_down) + { + col_skip = (zoom_factor - 1) * bytes_per_pixel; + row_skip = col_skip * src_width; + + /* scale image down by scaling factor 'zoom_factor' */ + for (y = 0; y < src_height; y += zoom_factor, src_ptr += row_skip) + for (x = 0; x < src_width; x += zoom_factor, src_ptr += col_skip) + for (i = 0; i < bytes_per_pixel; i++) + *dst_ptr++ = *src_ptr++; + } + else + { + row_skip = src_width * bytes_per_pixel; + + /* scale image up by scaling factor 'zoom_factor' */ + for (y = 0; y < src_height; y++) + { + for (yy = 0; yy < zoom_factor; yy++) + { + if (yy > 0) + src_ptr -= row_skip; + + for (x = 0; x < src_width; x++) + { + for (xx = 0; xx < zoom_factor; xx++) + for (i = 0; i < bytes_per_pixel; i++) + *dst_ptr++ = *(src_ptr + i); + + src_ptr += bytes_per_pixel; + } + } + } + } + + /* copy scaled image to destination pixmap */ + XPutImage(display, dst_pixmap, gc, dst_ximage, 0, 0, 0, 0, + dst_width, dst_height); - return(ximageinfo); + /* free temporary images */ + X11DestroyImage(src_ximage); + X11DestroyImage(dst_ximage); } void freeXImage(Image *image, XImageInfo *ximageinfo) @@ -528,7 +776,11 @@ int Read_PCX_to_Pixmap(Display *display, Window window, GC gc, char *filename, /* convert image structure to X11 Pixmap */ if (!(ximageinfo = Image_to_Pixmap(display, screen, visual, window, gc, depth, image))) - Error(ERR_EXIT, "cannot convert Image to Pixmap"); + { + freeImage(image); + + return PCX_OtherError; + } /* if a private colormap has been created, install it */ if (ximageinfo->cmap != DefaultColormap(display, screen)) @@ -548,8 +800,292 @@ int Read_PCX_to_Pixmap(Display *display, Window window, GC gc, char *filename, *pixmap = ximageinfo->pixmap; *pixmap_mask = ximageinfo->pixmap_mask; + /* free generic image and ximageinfo after native Pixmap has been created */ + free(ximageinfo); + freeImage(image); + return PCX_Success; } #endif /* PLATFORM_UNIX */ #endif /* TARGET_X11 */ + + +/* ========================================================================= */ +/* PLATFORM INDEPENDENT IMAGE FUNCTIONS */ +/* ========================================================================= */ + +struct ImageInfo +{ + char *source_filename; + int num_references; + + Bitmap *bitmap; + + int original_width; /* original image file width */ + int original_height; /* original image file height */ + + boolean contains_small_images; /* set after adding small images */ + boolean scaled_up; /* set after scaling up */ +}; +typedef struct ImageInfo ImageInfo; + +static struct ArtworkListInfo *image_info = NULL; + +#if 1 +static void *Load_Image(char *filename) +#else +static void *Load_PCX(char *filename) +#endif +{ + ImageInfo *img_info; + +#if 0 + printf("::: loading PCX file '%s'\n", filename); +#endif + + img_info = checked_calloc(sizeof(ImageInfo)); + + if ((img_info->bitmap = LoadImage(filename)) == NULL) + { + Error(ERR_WARN, "cannot load image file '%s': LoadImage() failed: %s", + filename, GetError()); + free(img_info); + return NULL; + } + + img_info->source_filename = getStringCopy(filename); + + img_info->original_width = img_info->bitmap->width; + img_info->original_height = img_info->bitmap->height; + + img_info->contains_small_images = FALSE; + img_info->scaled_up = FALSE; + + return img_info; +} + +static void FreeImage(void *ptr) +{ + ImageInfo *image = (ImageInfo *)ptr; + + if (image == NULL) + return; + + if (image->bitmap) + FreeBitmap(image->bitmap); + + if (image->source_filename) + free(image->source_filename); + + free(image); +} + +int getImageListSize() +{ + return (image_info->num_file_list_entries + + image_info->num_dynamic_file_list_entries); +} + +struct FileInfo *getImageListEntryFromImageID(int pos) +{ + int num_list_entries = image_info->num_file_list_entries; + int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries); + + return (pos < num_list_entries ? &image_info->file_list[list_pos] : + &image_info->dynamic_file_list[list_pos]); +} + +static ImageInfo *getImageInfoEntryFromImageID(int pos) +{ + int num_list_entries = image_info->num_file_list_entries; + int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries); + ImageInfo **img_info = + (ImageInfo **)(pos < num_list_entries ? image_info->artwork_list : + image_info->dynamic_artwork_list); + + return img_info[list_pos]; +} + +Bitmap *getBitmapFromImageID(int pos) +{ + ImageInfo *img_info = getImageInfoEntryFromImageID(pos); + + return (img_info != NULL ? img_info->bitmap : NULL); +} + +int getOriginalImageWidthFromImageID(int pos) +{ + ImageInfo *img_info = getImageInfoEntryFromImageID(pos); + + return (img_info != NULL ? img_info->original_width : 0); +} + +int getOriginalImageHeightFromImageID(int pos) +{ + ImageInfo *img_info = getImageInfoEntryFromImageID(pos); + + return (img_info != NULL ? img_info->original_height : 0); +} + +char *getTokenFromImageID(int graphic) +{ + struct FileInfo *file_list = getImageListEntryFromImageID(graphic); + + return (file_list != NULL ? file_list->token : NULL); +} + +int getImageIDFromToken(char *token) +{ + struct FileInfo *file_list = image_info->file_list; + int num_list_entries = image_info->num_file_list_entries; + int i; + + for (i = 0; i < num_list_entries; i++) + if (strEqual(file_list[i].token, token)) + return i; + + return -1; +} + +char *getImageConfigFilename() +{ + return getCustomArtworkConfigFilename(image_info->type); +} + +int getImageListPropertyMappingSize() +{ + return image_info->num_property_mapping_entries; +} + +struct PropertyMapping *getImageListPropertyMapping() +{ + return image_info->property_mapping; +} + +void InitImageList(struct ConfigInfo *config_list, int num_file_list_entries, + struct ConfigTypeInfo *config_suffix_list, + char **base_prefixes, char **ext1_suffixes, + char **ext2_suffixes, char **ext3_suffixes, + char **ignore_tokens) +{ + int i; + + image_info = checked_calloc(sizeof(struct ArtworkListInfo)); + image_info->type = ARTWORK_TYPE_GRAPHICS; + + /* ---------- initialize file list and suffix lists ---------- */ + + image_info->num_file_list_entries = num_file_list_entries; + image_info->num_dynamic_file_list_entries = 0; + + image_info->file_list = + getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens, + num_file_list_entries); + image_info->dynamic_file_list = NULL; + + image_info->num_suffix_list_entries = 0; + for (i = 0; config_suffix_list[i].token != NULL; i++) + image_info->num_suffix_list_entries++; + + image_info->suffix_list = config_suffix_list; + + /* ---------- initialize base prefix and suffixes lists ---------- */ + + image_info->num_base_prefixes = 0; + for (i = 0; base_prefixes[i] != NULL; i++) + image_info->num_base_prefixes++; + + image_info->num_ext1_suffixes = 0; + for (i = 0; ext1_suffixes[i] != NULL; i++) + image_info->num_ext1_suffixes++; + + image_info->num_ext2_suffixes = 0; + for (i = 0; ext2_suffixes[i] != NULL; i++) + image_info->num_ext2_suffixes++; + + image_info->num_ext3_suffixes = 0; + for (i = 0; ext3_suffixes[i] != NULL; i++) + image_info->num_ext3_suffixes++; + + image_info->num_ignore_tokens = 0; + for (i = 0; ignore_tokens[i] != NULL; i++) + image_info->num_ignore_tokens++; + + image_info->base_prefixes = base_prefixes; + image_info->ext1_suffixes = ext1_suffixes; + image_info->ext2_suffixes = ext2_suffixes; + image_info->ext3_suffixes = ext3_suffixes; + image_info->ignore_tokens = ignore_tokens; + + image_info->num_property_mapping_entries = 0; + + image_info->property_mapping = NULL; + + /* ---------- initialize artwork reference and content lists ---------- */ + + image_info->sizeof_artwork_list_entry = sizeof(ImageInfo *); + + image_info->artwork_list = + checked_calloc(num_file_list_entries * sizeof(ImageInfo *)); + image_info->dynamic_artwork_list = NULL; + + image_info->content_list = NULL; + + /* ---------- initialize artwork loading/freeing functions ---------- */ + +#if 1 + image_info->load_artwork = Load_Image; +#else + image_info->load_artwork = Load_PCX; +#endif + image_info->free_artwork = FreeImage; +} + +void ReloadCustomImages() +{ +#if 0 + printf("::: reloading images '%s' ...\n", artwork.gfx_current_identifier); +#endif + + print_timestamp_init("ReloadCustomImages"); + + LoadArtworkConfig(image_info); + print_timestamp_time("LoadArtworkConfig"); + + ReloadCustomArtworkList(image_info); + print_timestamp_time("ReloadCustomArtworkList"); + + print_timestamp_done("ReloadCustomImages"); +} + +void CreateImageWithSmallImages(int pos, int zoom_factor) +{ + ImageInfo *img_info = getImageInfoEntryFromImageID(pos); + + if (img_info == NULL || img_info->contains_small_images) + return; + + CreateBitmapWithSmallBitmaps(img_info->bitmap, zoom_factor); + + img_info->contains_small_images = TRUE; + img_info->scaled_up = TRUE; +} + +void ScaleImage(int pos, int zoom_factor) +{ + ImageInfo *img_info = getImageInfoEntryFromImageID(pos); + + if (img_info == NULL || img_info->scaled_up) + return; + + if (zoom_factor != 1) + ScaleBitmap(img_info->bitmap, zoom_factor); + + img_info->scaled_up = TRUE; +} + +void FreeAllImages() +{ + FreeCustomArtworkLists(image_info); +}