X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Flibgame%2Fimage.c;h=8ddcc6879fea3fff5a9a2688218579e5e93ee2b7;hb=2b65ec99f743dde3ee41083cf89623d4d9b8740e;hp=8cdf83245a88ec88c6e5ed5cb746d7842869b785;hpb=56c6c0e7a97a0831480dd9fdac411923b046ba38;p=rocksndiamonds.git diff --git a/src/libgame/image.c b/src/libgame/image.c index 8cdf8324..8ddcc687 100644 --- a/src/libgame/image.c +++ b/src/libgame/image.c @@ -47,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 : @@ -115,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 */ @@ -136,8 +136,73 @@ 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, (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; x < src_width; x++) + { + 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? */ + { + 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->drawable, + (char *)mask_data, + src_width, src_height)) == None) + Error(ERR_EXIT, "Pixmap_to_Mask(): XCreateBitmapFromData() failed"); + free(mask_data); return mask_pixmap; @@ -152,7 +217,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; @@ -251,7 +316,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; @@ -307,7 +372,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]; @@ -464,9 +529,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 = @@ -483,9 +548,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 = @@ -515,15 +580,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); @@ -560,7 +625,7 @@ 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); - XDestroyImage(ximage); + X11DestroyImage(ximage); return ximageinfo; } @@ -569,8 +634,10 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, ----------------------------------------------------------------------------- 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! + 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. ----------------------------------------------------------------------------- */ @@ -582,20 +649,39 @@ void ZoomPixmap(Display *display, GC gc, Pixmap src_pixmap, Pixmap dst_pixmap, 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 x, y, xx, yy, i; int row_skip, col_skip; + int zoom_factor; + boolean scale_down = (src_width > dst_width); + + if (scale_down) + { + zoom_factor = src_width / dst_width; + + /* adjust source image size to integer multiple of destination size */ + src_width = dst_width * zoom_factor; + src_height = dst_height * zoom_factor; + } + else + { + zoom_factor = dst_width / src_width; + + /* no adjustment needed when scaling up (some pixels may be left blank) */ + } /* copy source pixmap to temporary image */ - src_ximage = XGetImage(display, src_pixmap, 0, 0, - src_width, src_height, AllPlanes, ZPixmap); + 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; - dst_ximage = XCreateImage(display, visual, src_ximage->depth, ZPixmap, - 0, NULL, dst_width, dst_height, - 8, dst_width * bytes_per_pixel); + 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; @@ -603,22 +689,48 @@ void ZoomPixmap(Display *display, GC gc, Pixmap src_pixmap, Pixmap dst_pixmap, 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; + 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 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 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 += i; + } + } + } + } /* copy scaled image to destination pixmap */ XPutImage(display, dst_pixmap, gc, dst_ximage, 0, 0, 0, 0, - MIN(src_width, dst_width), MIN(src_height, dst_height)); + dst_width, dst_height); /* free temporary images */ - XDestroyImage(src_ximage); - XDestroyImage(dst_ximage); + X11DestroyImage(src_ximage); + X11DestroyImage(dst_ximage); } void freeXImage(Image *image, XImageInfo *ximageinfo) @@ -699,7 +811,7 @@ int Read_PCX_to_Pixmap(Display *display, Window window, GC gc, char *filename, /* ========================================================================= */ -/* PLATFORM INDEPENDANT IMAGE FUNCTIONS */ +/* PLATFORM INDEPENDENT IMAGE FUNCTIONS */ /* ========================================================================= */ struct ImageInfo @@ -726,7 +838,7 @@ static void *Load_PCX(char *filename) if ((img_info->bitmap = LoadImage(filename)) == NULL) { - Error(ERR_WARN, "cannot read image file '%s': LoadImage() failed: %s", + Error(ERR_WARN, "cannot load image file '%s': LoadImage() failed: %s", filename, GetError()); free(img_info); return NULL; @@ -800,9 +912,29 @@ Bitmap *getBitmapFromImageID(int pos) 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() @@ -821,10 +953,10 @@ struct PropertyMapping *getImageListPropertyMapping() } 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) + struct ConfigTypeInfo *config_suffix_list, + char **base_prefixes, char **ext1_suffixes, + char **ext2_suffixes, char **ext3_suffixes, + char **ignore_tokens) { int i; @@ -837,12 +969,12 @@ void InitImageList(struct ConfigInfo *config_list, int num_file_list_entries, image_info->num_dynamic_file_list_entries = 0; image_info->file_list = - getFileListFromConfigList(config_list, config_suffix_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++) + for (i = 0; config_suffix_list[i].token != NULL; i++) image_info->num_suffix_list_entries++; image_info->suffix_list = config_suffix_list; @@ -850,20 +982,30 @@ void InitImageList(struct ConfigInfo *config_list, int num_file_list_entries, /* ---------- initialize base prefix and suffixes lists ---------- */ image_info->num_base_prefixes = 0; - for (i=0; base_prefixes[i] != NULL; i++) + 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++) + 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++) + 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; @@ -902,11 +1044,13 @@ void CreateImageWithSmallImages(int pos) if (img_info == NULL || img_info->contains_small_images) return; - printf(" creating small image for '%s'\n", img_info->source_filename); - CreateBitmapWithSmallBitmaps(img_info->bitmap); img_info->contains_small_images = TRUE; + +#if 0 + printf("CreateImageWithSmallImages: '%s' done\n", img_info->source_filename); +#endif } void FreeAllImages()