X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Flibgame%2Fimage.c;h=31975e04b29850fa988377c88f6ccfcec57e2cef;hb=8458af9ed76d6194de77b184e4e1ba2041e6aa17;hp=ae53b44a3b8b2d909b610adf2ef0176655d4db5d;hpb=322297d68005c08b35e7c309a841553b73259a9c;p=rocksndiamonds.git diff --git a/src/libgame/image.c b/src/libgame/image.c index ae53b44a..31975e04 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-2002 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,30 +28,31 @@ 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 0 if (depth > 8) Error(ERR_EXIT, "images with more than 256 colors are not supported"); depth = 8; +#endif - 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->rgb.used = 0; + 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); - image->bytes_per_row = (depth + 7) / 8; - image->bytes_per_row *= width; - return image; } @@ -93,7 +99,7 @@ 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; @@ -116,8 +122,9 @@ static Pixmap Image_to_Mask(Image *image, Display *display, Window window) for (x=0; xwidth; x++) { - if (*src_ptr++) /* source pixel solid? (pixel index != 0) */ - *dst_ptr2 |= bitmask; /* then write a bit into the image mask */ + for (i=0; ibytes_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? */ { @@ -167,11 +174,19 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, static int num_cmap_entries, free_cmap_entries; static boolean private_cmap = FALSE; Pixel *redvalue, *greenvalue, *bluevalue; - unsigned int a, c = 0, x, y, bytes_per_pixel, bits_per_pixel; + unsigned int display_bytes_per_pixel, display_bits_per_pixel; + unsigned int a, c = 0, x, y; XColor xcolor; XImage *ximage; XImageInfo *ximageinfo; byte *src_ptr, *dst_ptr; + char *error = "Image_to_Pixmap(): %s"; + + if (image->type == IMAGETYPE_TRUECOLOR && depth == 8) + { + SetError(error, "cannot handle true-color images on 8-bit display"); + return NULL; + } if (!global_cmap) { @@ -235,6 +250,7 @@ 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++) { if (redbottom < 256) @@ -265,10 +281,12 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, /* something completely unexpected happened */ fprintf(stderr, "Image_to_Pixmap: XAllocColor failed on a TrueColor/Directcolor visual\n"); + free(redvalue); free(greenvalue); free(bluevalue); free(ximageinfo); + return NULL; } @@ -281,6 +299,7 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, while ((bluebottom < 256) && (bluebottom < bluetop)) bluevalue[bluebottom++] = xcolor.pixel & visual->blue_mask; } + break; } @@ -386,7 +405,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; @@ -406,9 +428,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_RETURN,"DirectColor, TrueColor or PseudoColor display needed"); + SetError(error, "display class not supported"); + + return NULL; } #if DEBUG_TIMING @@ -417,14 +440,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); + 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; @@ -450,10 +473,11 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, 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; + value_to_memory(pixval, dst_ptr, display_bytes_per_pixel); + dst_ptr += display_bytes_per_pixel; } } + break; } @@ -463,30 +487,33 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, { for (x=0; xwidth; x++) { - pixval = memory_to_value(src_ptr, image->depth); + 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, bytes_per_pixel); - src_ptr += image->depth; - dst_ptr += bytes_per_pixel; + 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_RETURN, "image type not supported"); - Error(ERR_EXIT, "RGB or TrueColor image needed"); - break; + Error(ERR_RETURN, "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++) @@ -499,18 +526,20 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, for (x=0; xwidth; 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_RETURN,"DirectColor, TrueColor or PseudoColor display needed"); + SetError(error, "display class not supported"); + + return NULL; } if (redvalue) @@ -531,11 +560,9 @@ 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); - return(ximageinfo); + return ximageinfo; } void freeXImage(Image *image, XImageInfo *ximageinfo) @@ -580,7 +607,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)) @@ -600,8 +631,195 @@ 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 INDEPENDANT IMAGE FUNCTIONS */ +/* ========================================================================= */ + +struct ImageInfo +{ + char *source_filename; + int num_references; + + Bitmap *bitmap; +}; +typedef struct ImageInfo ImageInfo; + +static struct ArtworkListInfo *image_info = NULL; + +static void *Load_PCX(char *filename) +{ + 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 read image file '%s': LoadImage() failed: %s", + filename, GetError()); + free(img_info); + return NULL; + } + + img_info->source_filename = getStringCopy(filename); + + 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 *getImageListEntry(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]); +} + +Bitmap *getBitmapFromImageID(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] != NULL ? img_info[list_pos]->bitmap : NULL); +} + +char *getTokenFromImageID(int graphic) +{ + struct FileInfo *file_list = (struct FileInfo *)image_info->file_list; + + return file_list[graphic].token; +} + +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 ConfigInfo *config_suffix_list, + char **base_prefixes, + char **ext1_suffixes, + char **ext2_suffixes) +{ + 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, + 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->base_prefixes = base_prefixes; + image_info->ext1_suffixes = ext1_suffixes; + image_info->ext2_suffixes = ext2_suffixes; + + 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 ---------- */ + + image_info->load_artwork = Load_PCX; + image_info->free_artwork = FreeImage; +} + +void ReloadCustomImages() +{ +#if 0 + printf("DEBUG: reloading images '%s' ...\n", artwork.gfx_current_identifier); +#endif + + LoadArtworkConfig(image_info); + ReloadCustomArtworkList(image_info); +} + +void FreeAllImages() +{ + FreeCustomArtworkLists(image_info); +}