X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Flibgame%2Fimage.c;h=e267fd8099604e7005ea4144be13746c60d66f86;hb=74c0f7de91268e40d15948f473eac51a9760b9c0;hp=13cfce001e50e03caf5a01eee2241bbfccc4b9b5;hpb=28f0f8708f4b4f8c4f39f1b23bc5fc7e0fed7579;p=rocksndiamonds.git diff --git a/src/libgame/image.c b/src/libgame/image.c index 13cfce00..e267fd80 100644 --- a/src/libgame/image.c +++ b/src/libgame/image.c @@ -14,6 +14,7 @@ #include "image.h" #include "pcx.h" #include "misc.h" +#include "setup.h" /* ========================================================================= */ @@ -37,8 +38,8 @@ Image *newImage(unsigned int width, unsigned int height, unsigned int depth) 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; @@ -46,7 +47,7 @@ Image *newImage(unsigned int width, unsigned int height, unsigned int depth) 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 : @@ -114,14 +115,14 @@ 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; xwidth; x++) + for (x = 0; x < image->width; x++) { - for (i=0; ibytes_per_pixel; i++) + 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 */ @@ -151,7 +152,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; ired_mask) redcolors <<= 1; @@ -250,7 +251,7 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, 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; @@ -306,7 +307,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]; @@ -442,8 +443,8 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, 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, + 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 * display_bytes_per_pixel); @@ -463,9 +464,9 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, { case IMAGETYPE_RGB: { - for (y=0; yheight; y++) /* general case */ + for (y = 0; y < image->height; y++) /* general case */ { - for (x=0; xwidth; x++) + for (x = 0; x < image->width; x++) { pixval = *src_ptr++; pixval = @@ -482,9 +483,9 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, case IMAGETYPE_TRUECOLOR: { - for (y=0; yheight; y++) /* general case */ + for (y = 0; y < image->height; y++) /* general case */ { - for (x=0; xwidth; x++) + for (x = 0; x < image->width; x++) { pixval = memory_to_value(src_ptr, image->bytes_per_pixel); pixval = @@ -514,15 +515,15 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, { 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, display_bytes_per_pixel); @@ -564,6 +565,66 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, return ximageinfo; } +/* + ----------------------------------------------------------------------------- + ZoomPixmap + + Important note: The scaling code currently only supports scaling down the + image by a power of 2 -- scaling up is currently not supported at all! + ----------------------------------------------------------------------------- +*/ + +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, i; + int zoom_factor = src_width / dst_width; /* currently very limited! */ + int row_skip, col_skip; + + /* adjust source image size to integer multiple of destination image size */ + src_width = dst_width * zoom_factor; + src_height = dst_height * zoom_factor; + + /* copy source pixmap to temporary image */ + src_ximage = XGetImage(display, src_pixmap, 0, 0, src_width, src_height, + AllPlanes, ZPixmap); + + bits_per_pixel = src_ximage->bits_per_pixel; + bytes_per_pixel = (bits_per_pixel + 7) / 8; + + dst_ximage = XCreateImage(display, visual, src_ximage->depth, ZPixmap, + 0, NULL, dst_width, dst_height, + 8, dst_width * bytes_per_pixel); + 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; + + 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++; + + /* copy scaled image to destination pixmap */ + XPutImage(display, dst_pixmap, gc, dst_ximage, 0, 0, 0, 0, + dst_width, dst_height); + + /* free temporary images */ + XDestroyImage(src_ximage); + XDestroyImage(dst_ximage); +} + void freeXImage(Image *image, XImageInfo *ximageinfo) { if (ximageinfo->index != NULL && ximageinfo->no > 0) @@ -642,25 +703,249 @@ int Read_PCX_to_Pixmap(Display *display, Window window, GC gc, char *filename, /* ========================================================================= */ -/* PLATFORM INDEPENDANT IMAGE FUNCTIONS */ +/* PLATFORM INDEPENDENT IMAGE FUNCTIONS */ /* ========================================================================= */ struct ImageInfo { char *source_filename; int num_references; + + Bitmap *bitmap; + boolean contains_small_images; }; typedef struct ImageInfo ImageInfo; -static ImageInfo **ImageList = NULL; -static struct ArtworkConfigInfo *image_config = NULL; -static int num_images = 0; +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); + + img_info->contains_small_images = 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 *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]); +} + +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) +{ +#if 0 + 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); +#else + ImageInfo *img_info = getImageInfoEntryFromImageID(pos); + + return (img_info != NULL ? img_info->bitmap : NULL); +#endif +} + +char *getTokenFromImageID(int graphic) +{ +#if 0 + /* !!! this does not work for dynamic artwork (crash!) !!! */ + struct FileInfo *file_list = (struct FileInfo *)image_info->file_list; + + return file_list[graphic].token; +#else + struct FileInfo *file_list = getImageListEntry(graphic); + + return (file_list != NULL ? file_list->token : NULL); +#endif +} + +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 (strcmp(file_list[i].token, token) == 0) + 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 ConfigInfo *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++; -void InitImageList(struct ArtworkConfigInfo *config_list, int num_list_entries) + 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 ---------- */ + + image_info->load_artwork = Load_PCX; + image_info->free_artwork = FreeImage; +} + +void ReloadCustomImages() { - if (ImageList == NULL) - ImageList = checked_calloc(num_list_entries * sizeof(ImageInfo *)); +#if 0 + printf("DEBUG: reloading images '%s' ...\n", artwork.gfx_current_identifier); +#endif + + LoadArtworkConfig(image_info); + ReloadCustomArtworkList(image_info); +} + +void CreateImageWithSmallImages(int pos) +{ + ImageInfo *img_info = getImageInfoEntryFromImageID(pos); + + if (img_info == NULL || img_info->contains_small_images) + return; + + CreateBitmapWithSmallBitmaps(img_info->bitmap); - image_config = config_list; - num_images = num_list_entries; + img_info->contains_small_images = TRUE; + +#if 0 + printf("CreateImageWithSmallImages: '%s' done\n", img_info->source_filename); +#endif +} + +void FreeAllImages() +{ + FreeCustomArtworkLists(image_info); }