1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2002 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
20 /* ========================================================================= */
21 /* PLATFORM SPECIFIC IMAGE FUNCTIONS */
22 /* ========================================================================= */
24 #if defined(TARGET_X11)
26 /* for MS-DOS/Allegro, exclude all except newImage() and freeImage() */
28 Image *newImage(unsigned int width, unsigned int height, unsigned int depth)
31 unsigned int bytes_per_pixel = (depth + 7) / 8;
36 Error(ERR_EXIT, "images with more than 256 colors are not supported");
41 image = checked_calloc(sizeof(Image));
42 image->data = checked_calloc(width * height * bytes_per_pixel);
44 image->height = height;
46 image->bytes_per_pixel = bytes_per_pixel;
47 image->bytes_per_row = width * bytes_per_pixel;
50 for (i = 0; i < MAX_COLORS; i++)
51 image->rgb.color_used[i] = FALSE;
53 image->type = (depth < 8 ? IMAGETYPE_BITMAP :
54 depth > 8 ? IMAGETYPE_TRUECOLOR : IMAGETYPE_RGB);
59 void freeImage(Image *image)
65 #if defined(PLATFORM_UNIX)
67 /* extra colors to try allocating in private color maps to minimize flashing */
68 #define NOFLASH_COLORS 256
70 /* architecture independent value <-> memory conversions;
71 note: the internal format is big endian */
73 #define memory_to_value(ptr, len) ( \
74 (len) == 1 ? (unsigned long)( *( (byte *)(ptr)) ) : \
75 (len) == 2 ? (unsigned long)(((unsigned long)(*( (byte *)(ptr)) ))<< 8) \
76 + ( *(((byte *)(ptr))+1) ) : \
77 (len) == 3 ? (unsigned long)(((unsigned long)(*( (byte *)(ptr)) ))<<16) \
78 + (((unsigned long)(*(((byte *)(ptr))+1)))<< 8) \
79 + ( *(((byte *)(ptr))+2) ) : \
80 (unsigned long)(((unsigned long)(*( (byte *)(ptr)) ))<<24) \
81 + (((unsigned long)(*(((byte *)(ptr))+1)))<<16) \
82 + (((unsigned long)(*(((byte *)(ptr))+2)))<< 8) \
83 + ( *(((byte *)(ptr))+3) ) )
86 #define value_to_memory(value, ptr, len) ( \
87 (len) == 1 ? (*( (byte *)(ptr) ) = ( value ) ) : \
88 (len) == 2 ? (*( (byte *)(ptr) ) = (((unsigned long)(value))>> 8), \
89 *(((byte *)(ptr))+1) = ( value ) ) : \
90 (len) == 3 ? (*( (byte *)(ptr) ) = (((unsigned long)(value))>>16), \
91 *(((byte *)(ptr))+1) = (((unsigned long)(value))>> 8), \
92 *(((byte *)(ptr))+2) = ( value ) ) : \
93 (*( (byte *)(ptr) ) = (((unsigned long)(value))>>24), \
94 *(((byte *)(ptr))+1) = (((unsigned long)(value))>>16), \
95 *(((byte *)(ptr))+2) = (((unsigned long)(value))>> 8), \
96 *(((byte *)(ptr))+3) = ( value ) ))
98 static Pixmap Image_to_Mask(Image *image, Display *display, Window window)
100 byte *src_ptr, *dst_ptr, *dst_ptr2;
101 unsigned int bytes_per_row;
102 unsigned int x, y, i;
107 bytes_per_row = (image->width + 7) / 8;
108 mask_data = checked_calloc(bytes_per_row * image->height);
110 src_ptr = image->data;
113 /* create bitmap data which can be used by 'XCreateBitmapFromData()'
114 * directly to create a pixmap of depth 1 for use as a clip mask for
115 * the corresponding image pixmap
118 for (y = 0; y < image->height; y++)
120 bitmask = 0x01; /* start with leftmost bit in the byte */
121 dst_ptr2 = dst_ptr; /* start with leftmost byte in the row */
123 for (x = 0; x < image->width; x++)
125 for (i = 0; i < image->bytes_per_pixel; i++)
126 if (*src_ptr++) /* source pixel solid? (pixel index != 0) */
127 *dst_ptr2 |= bitmask; /* then write a bit into the image mask */
129 if ((bitmask <<= 1) == 0) /* bit at rightmost byte position reached? */
131 bitmask = 0x01; /* start again with leftmost bit position */
132 dst_ptr2++; /* continue with next byte in image mask */
136 dst_ptr += bytes_per_row; /* continue with leftmost byte of next row */
139 if ((mask_pixmap = XCreateBitmapFromData(display, window, (char *)mask_data,
140 image->width, image->height))
142 Error(ERR_EXIT, "Image_to_Mask(): XCreateBitmapFromData() failed");
149 Pixmap Pixmap_to_Mask(Pixmap src_pixmap, int src_width, int src_height)
152 byte *src_ptr, *dst_ptr, *dst_ptr2;
155 unsigned int bytes_per_row;
156 unsigned int x, y, i;
161 /* copy source pixmap to temporary image */
162 if ((src_ximage = XGetImage(display, src_pixmap, 0, 0, src_width, src_height,
163 AllPlanes, ZPixmap)) == NULL)
164 Error(ERR_EXIT, "Pixmap_to_Mask(): XGetImage() failed");
166 bits_per_pixel = src_ximage->bits_per_pixel;
167 bytes_per_pixel = (bits_per_pixel + 7) / 8;
169 bytes_per_row = (src_width + 7) / 8;
170 mask_data = checked_calloc(bytes_per_row * src_height);
172 src_ptr = (byte *)src_ximage->data;
175 /* create bitmap data which can be used by 'XCreateBitmapFromData()'
176 * directly to create a pixmap of depth 1 for use as a clip mask for
177 * the corresponding image pixmap
180 for (y = 0; y < src_height; y++)
182 bitmask = 0x01; /* start with leftmost bit in the byte */
183 dst_ptr2 = dst_ptr; /* start with leftmost byte in the row */
185 for (x = 0; x < src_width; x++)
187 for (i = 0; i < bytes_per_pixel; i++)
188 if (*src_ptr++) /* source pixel solid? (pixel index != 0) */
189 *dst_ptr2 |= bitmask; /* then write a bit into the image mask */
191 if ((bitmask <<= 1) == 0) /* bit at rightmost byte position reached? */
193 bitmask = 0x01; /* start again with leftmost bit position */
194 dst_ptr2++; /* continue with next byte in image mask */
198 dst_ptr += bytes_per_row; /* continue with leftmost byte of next row */
201 if ((mask_pixmap = XCreateBitmapFromData(display, window->drawable,
203 src_width, src_height)) == None)
204 Error(ERR_EXIT, "Pixmap_to_Mask(): XCreateBitmapFromData() failed");
211 static int bitsPerPixelAtDepth(Display *display, int screen, int depth)
213 XPixmapFormatValues *pixmap_format;
214 int i, num_pixmap_formats, bits_per_pixel = -1;
216 /* get Pixmap formats supported by the X server */
217 pixmap_format = XListPixmapFormats(display, &num_pixmap_formats);
219 /* find format that matches the given depth */
220 for (i = 0; i < num_pixmap_formats; i++)
221 if (pixmap_format[i].depth == depth)
222 bits_per_pixel = pixmap_format[i].bits_per_pixel;
224 XFree(pixmap_format);
226 if (bits_per_pixel == -1)
227 Error(ERR_EXIT, "cannot find pixmap format for depth %d", depth);
229 return bits_per_pixel;
232 XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual,
233 Window window, GC gc, int depth, Image *image)
235 static XColor xcolor_private[NOFLASH_COLORS];
236 static int colorcell_used[NOFLASH_COLORS];
237 static Colormap global_cmap = 0;
238 static Pixel *global_cmap_index;
239 static int num_cmap_entries, free_cmap_entries;
240 static boolean private_cmap = FALSE;
241 Pixel *redvalue, *greenvalue, *bluevalue;
242 unsigned int display_bytes_per_pixel, display_bits_per_pixel;
243 unsigned int a, c = 0, x, y;
246 XImageInfo *ximageinfo;
247 byte *src_ptr, *dst_ptr;
248 char *error = "Image_to_Pixmap(): %s";
250 if (image->type == IMAGETYPE_TRUECOLOR && depth == 8)
252 SetError(error, "cannot handle true-color images on 8-bit display");
258 if (visual == DefaultVisual(display, screen))
259 global_cmap = DefaultColormap(display, screen);
262 global_cmap = XCreateColormap(display, RootWindow(display, screen),
268 xcolor.flags = DoRed | DoGreen | DoBlue;
269 redvalue = greenvalue = bluevalue = NULL;
270 ximageinfo = checked_malloc(sizeof(XImageInfo));
271 ximageinfo->display = display;
272 ximageinfo->depth = depth;
274 switch (visual->class)
280 unsigned int redcolors, greencolors, bluecolors;
281 unsigned int redstep, greenstep, bluestep;
282 unsigned int redbottom, greenbottom, bluebottom;
283 unsigned int redtop, greentop, bluetop;
285 redvalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256);
286 greenvalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256);
287 bluevalue = (Pixel *)checked_malloc(sizeof(Pixel) * 256);
289 ximageinfo->cmap = global_cmap;
291 retry_direct: /* tag we hit if a DirectColor allocation fails on
292 * default colormap */
294 /* calculate number of distinct colors in each band */
296 redcolors = greencolors = bluecolors = 1;
297 for (pixval = 1; pixval; pixval <<= 1)
299 if (pixval & visual->red_mask)
301 if (pixval & visual->green_mask)
303 if (pixval & visual->blue_mask)
307 /* consistency check */
308 if (redcolors > visual->map_entries ||
309 greencolors > visual->map_entries ||
310 bluecolors > visual->map_entries)
311 Error(ERR_WARN, "inconsistency in color information");
313 redstep = 256 / redcolors;
314 greenstep = 256 / greencolors;
315 bluestep = 256 / bluecolors;
316 redbottom = greenbottom = bluebottom = 0;
317 redtop = greentop = bluetop = 0;
319 for (a = 0; a < visual->map_entries; a++)
322 redtop = redbottom + redstep;
323 if (greenbottom < 256)
324 greentop = greenbottom + greenstep;
325 if (bluebottom < 256)
326 bluetop = bluebottom + bluestep;
328 xcolor.red = (redtop - 1) << 8;
329 xcolor.green = (greentop - 1) << 8;
330 xcolor.blue = (bluetop - 1) << 8;
331 if (!XAllocColor(display, ximageinfo->cmap, &xcolor))
333 /* if an allocation fails for a DirectColor default visual then
334 we should create a private colormap and try again. */
336 if ((visual->class == DirectColor) &&
337 (visual == DefaultVisual(display, screen)))
339 global_cmap = XCopyColormapAndFree(display, global_cmap);
340 ximageinfo->cmap = global_cmap;
346 /* something completely unexpected happened */
348 fprintf(stderr, "Image_to_Pixmap: XAllocColor failed on a TrueColor/Directcolor visual\n");
358 /* fill in pixel values for each band at this intensity */
360 while ((redbottom < 256) && (redbottom < redtop))
361 redvalue[redbottom++] = xcolor.pixel & visual->red_mask;
362 while ((greenbottom < 256) && (greenbottom < greentop))
363 greenvalue[greenbottom++] = xcolor.pixel & visual->green_mask;
364 while ((bluebottom < 256) && (bluebottom < bluetop))
365 bluevalue[bluebottom++] = xcolor.pixel & visual->blue_mask;
373 ximageinfo->cmap = global_cmap;
375 for (a = 0; a < MAX_COLORS; a++)
382 if (!image->rgb.color_used[a])
385 xcolor.red = *(image->rgb.red + a);
386 xcolor.green = *(image->rgb.green + a);
387 xcolor.blue = *(image->rgb.blue + a);
389 /* look if this color already exists in our colormap */
390 if (!XAllocColor(display, ximageinfo->cmap, &xcolor))
395 Error(ERR_RETURN, "switching to private colormap");
397 /* we just filled up the default colormap -- get a private one
398 which contains all already allocated colors */
400 global_cmap = XCopyColormapAndFree(display, global_cmap);
401 ximageinfo->cmap = global_cmap;
404 /* allocate the rest of the color cells read/write */
406 (Pixel *)checked_malloc(sizeof(Pixel) * NOFLASH_COLORS);
407 for (i = 0; i < NOFLASH_COLORS; i++)
408 if (!XAllocColorCells(display, global_cmap, FALSE, NULL, 0,
409 global_cmap_index + i, 1))
411 num_cmap_entries = free_cmap_entries = i;
414 printf("We've got %d free colormap entries.\n", free_cmap_entries);
417 /* to minimize colormap flashing, copy default colors and try
418 to keep them as near as possible to the old values */
420 for (i = 0; i < num_cmap_entries; i++)
422 xcolor2.pixel = *(global_cmap_index + i);
423 XQueryColor(display, DefaultColormap(display, screen), &xcolor2);
424 XStoreColor(display, global_cmap, &xcolor2);
425 xcolor_private[xcolor2.pixel] = xcolor2;
426 colorcell_used[xcolor2.pixel] = FALSE;
429 /* now we have the default colormap private: all colors we
430 successfully allocated so far are read-only, which is okay,
431 because we don't want to change them anymore -- if we need
432 an existing color again, we get it by XAllocColor; all other
433 colors are read/write and we can set them by XStoreColor,
434 but we will try to overwrite those color cells with our new
435 color which are as close as possible to our new color */
438 /* look for an existing default color close the one we want */
445 for (i = num_cmap_entries - 1; i >= 0; i--)
447 xcolor2.pixel = *(global_cmap_index + i);
448 xcolor2 = xcolor_private[xcolor2.pixel];
450 if (colorcell_used[xcolor2.pixel])
453 if ((xcolor.red & mask) == (xcolor2.red & mask) &&
454 (xcolor.green & mask) == (xcolor2.green & mask) &&
455 (xcolor.blue & mask) == (xcolor2.blue & mask))
458 printf("replacing color cell %ld with a close color\n",
469 mask = (mask << 1) & 0xffff;
472 if (!color_found) /* no more free color cells */
474 SetError(error, "cannot allocate enough color cells");
478 xcolor.pixel = xcolor2.pixel;
479 xcolor_private[xcolor.pixel] = xcolor;
480 colorcell_used[xcolor.pixel] = TRUE;
481 XStoreColor(display, ximageinfo->cmap, &xcolor);
485 *(ximageinfo->index + a) = xcolor.pixel;
489 printf("still %d free colormap entries\n", free_cmap_entries);
492 ximageinfo->no = a; /* number of pixels allocated for this image */
496 Error(ERR_RETURN,"DirectColor, TrueColor or PseudoColor display needed");
497 SetError(error, "display class not supported");
503 debug_print_timestamp(2, " ALLOCATING IMAGE COLORS: ");
506 /* create XImage from internal image structure and convert it to Pixmap */
508 display_bits_per_pixel = bitsPerPixelAtDepth(display, screen, depth);
509 display_bytes_per_pixel = (display_bits_per_pixel + 7) / 8;
511 ximage = XCreateImage(display, visual, depth, ZPixmap,
512 0, NULL, image->width, image->height,
513 8, image->width * display_bytes_per_pixel);
515 checked_malloc(image->width * image->height * display_bytes_per_pixel);
516 ximage->byte_order = MSBFirst;
518 src_ptr = image->data;
519 dst_ptr = (byte *)ximage->data;
521 switch (visual->class)
532 for (y = 0; y < image->height; y++) /* general case */
534 for (x = 0; x < image->width; x++)
538 redvalue[image->rgb.red[pixval] >> 8] |
539 greenvalue[image->rgb.green[pixval] >> 8] |
540 bluevalue[image->rgb.blue[pixval] >> 8];
541 value_to_memory(pixval, dst_ptr, display_bytes_per_pixel);
542 dst_ptr += display_bytes_per_pixel;
549 case IMAGETYPE_TRUECOLOR:
551 for (y = 0; y < image->height; y++) /* general case */
553 for (x = 0; x < image->width; x++)
555 pixval = memory_to_value(src_ptr, image->bytes_per_pixel);
557 redvalue[TRUECOLOR_RED(pixval)] |
558 greenvalue[TRUECOLOR_GREEN(pixval)] |
559 bluevalue[TRUECOLOR_BLUE(pixval)];
560 value_to_memory(pixval, dst_ptr, display_bytes_per_pixel);
561 src_ptr += image->bytes_per_pixel;
562 dst_ptr += display_bytes_per_pixel;
570 Error(ERR_RETURN, "RGB or TrueColor image needed");
571 SetError(error, "image type not supported");
581 if (display_bytes_per_pixel == 1) /* special case */
583 for (y = 0; y < image->height; y++)
584 for (x = 0; x < image->width; x++)
585 *dst_ptr++ = ximageinfo->index[c + *src_ptr++];
587 else /* general case */
589 for (y = 0; y < image->height; y++)
591 for (x = 0; x < image->width; x++)
593 value_to_memory(ximageinfo->index[c + *src_ptr++],
594 dst_ptr, display_bytes_per_pixel);
595 dst_ptr += display_bytes_per_pixel;
604 Error(ERR_RETURN,"DirectColor, TrueColor or PseudoColor display needed");
605 SetError(error, "display class not supported");
612 free((byte *)redvalue);
613 free((byte *)greenvalue);
614 free((byte *)bluevalue);
618 debug_print_timestamp(2, " CONVERTING IMAGE TO XIMAGE:");
621 ximageinfo->pixmap = XCreatePixmap(display, window,
622 ximage->width, ximage->height,
625 XPutImage(ximageinfo->display, ximageinfo->pixmap, gc,
626 ximage, 0, 0, 0, 0, ximage->width, ximage->height);
628 X11DestroyImage(ximage);
634 -----------------------------------------------------------------------------
637 Important note: The scaling code currently only supports scaling of the image
638 up or down by a power of 2 -- other scaling factors currently not supported!
639 Also not supported is scaling of pixmap masks (with depth 1); to scale them,
640 better use Pixmap_to_Mask() for now.
641 -----------------------------------------------------------------------------
644 void ZoomPixmap(Display *display, GC gc, Pixmap src_pixmap, Pixmap dst_pixmap,
645 int src_width, int src_height,
646 int dst_width, int dst_height)
648 XImage *src_ximage, *dst_ximage;
649 byte *src_ptr, *dst_ptr;
653 int row_skip, col_skip;
655 boolean scale_down = (src_width > dst_width);
659 zoom_factor = src_width / dst_width;
661 /* adjust source image size to integer multiple of destination size */
662 src_width = dst_width * zoom_factor;
663 src_height = dst_height * zoom_factor;
667 zoom_factor = dst_width / src_width;
669 /* no adjustment needed when scaling up (some pixels may be left blank) */
672 /* copy source pixmap to temporary image */
673 if ((src_ximage = XGetImage(display, src_pixmap, 0, 0, src_width, src_height,
674 AllPlanes, ZPixmap)) == NULL)
675 Error(ERR_EXIT, "ZoomPixmap(): XGetImage() failed");
677 bits_per_pixel = src_ximage->bits_per_pixel;
678 bytes_per_pixel = (bits_per_pixel + 7) / 8;
680 if ((dst_ximage = XCreateImage(display, visual, src_ximage->depth, ZPixmap,
681 0, NULL, dst_width, dst_height,
682 8, dst_width * bytes_per_pixel)) == NULL)
683 Error(ERR_EXIT, "ZoomPixmap(): XCreateImage() failed");
686 checked_malloc(dst_width * dst_height * bytes_per_pixel);
687 dst_ximage->byte_order = src_ximage->byte_order;
689 src_ptr = (byte *)src_ximage->data;
690 dst_ptr = (byte *)dst_ximage->data;
694 col_skip = (zoom_factor - 1) * bytes_per_pixel;
695 row_skip = col_skip * src_width;
697 /* scale image down by scaling factor 'zoom_factor' */
698 for (y = 0; y < src_height; y += zoom_factor, src_ptr += row_skip)
699 for (x = 0; x < src_width; x += zoom_factor, src_ptr += col_skip)
700 for (i = 0; i < bytes_per_pixel; i++)
701 *dst_ptr++ = *src_ptr++;
705 row_skip = src_width * bytes_per_pixel;
707 /* scale image up by scaling factor 'zoom_factor' */
708 for (y = 0; y < src_height; y++)
710 for (yy = 0; yy < zoom_factor; yy++)
715 for (x = 0; x < src_width; x++)
717 for (xx = 0; xx < zoom_factor; xx++)
718 for (i = 0; i < bytes_per_pixel; i++)
719 *dst_ptr++ = *(src_ptr + i);
727 /* copy scaled image to destination pixmap */
728 XPutImage(display, dst_pixmap, gc, dst_ximage, 0, 0, 0, 0,
729 dst_width, dst_height);
731 /* free temporary images */
732 X11DestroyImage(src_ximage);
733 X11DestroyImage(dst_ximage);
736 void freeXImage(Image *image, XImageInfo *ximageinfo)
738 if (ximageinfo->index != NULL && ximageinfo->no > 0)
739 XFreeColors(ximageinfo->display, ximageinfo->cmap, ximageinfo->index,
741 /* this ^^^^^^^^^^^^^^ is wrong, because the used color cells
742 * are somewhere between 0 and MAX_COLORS; there are indeed 'ximageinfo->no'
743 * used color cells, but they are not at array position 0 - 'ximageinfo->no'
749 int Read_PCX_to_Pixmap(Display *display, Window window, GC gc, char *filename,
750 Pixmap *pixmap, Pixmap *pixmap_mask)
753 XImageInfo *ximageinfo;
759 debug_print_timestamp(2, NULL); /* initialize timestamp function */
762 /* read the graphic file in PCX format to image structure */
763 if ((image = Read_PCX_to_Image(filename)) == NULL)
767 printf("%s:\n", filename);
768 debug_print_timestamp(2, " READING PCX FILE TO IMAGE: ");
771 screen = DefaultScreen(display);
772 visual = DefaultVisual(display, screen);
773 depth = DefaultDepth(display, screen);
775 /* convert image structure to X11 Pixmap */
776 if (!(ximageinfo = Image_to_Pixmap(display, screen, visual,
777 window, gc, depth, image)))
781 return PCX_OtherError;
784 /* if a private colormap has been created, install it */
785 if (ximageinfo->cmap != DefaultColormap(display, screen))
786 XSetWindowColormap(display, window, ximageinfo->cmap);
789 debug_print_timestamp(2, " CONVERTING IMAGE TO PIXMAP:");
792 /* create clip mask for the image */
793 ximageinfo->pixmap_mask = Image_to_Mask(image, display, window);
796 debug_print_timestamp(2, " CONVERTING IMAGE TO MASK: ");
799 *pixmap = ximageinfo->pixmap;
800 *pixmap_mask = ximageinfo->pixmap_mask;
802 /* free generic image and ximageinfo after native Pixmap has been created */
809 #endif /* PLATFORM_UNIX */
810 #endif /* TARGET_X11 */
813 /* ========================================================================= */
814 /* PLATFORM INDEPENDENT IMAGE FUNCTIONS */
815 /* ========================================================================= */
819 char *source_filename;
824 int original_width; /* original image file width */
825 int original_height; /* original image file height */
827 boolean contains_small_images; /* set after adding small images */
828 boolean scaled_up; /* set after scaling up */
830 typedef struct ImageInfo ImageInfo;
832 static struct ArtworkListInfo *image_info = NULL;
834 static void *Load_PCX(char *filename)
839 printf("loading PCX file '%s'\n", filename);
842 img_info = checked_calloc(sizeof(ImageInfo));
844 if ((img_info->bitmap = LoadImage(filename)) == NULL)
846 Error(ERR_WARN, "cannot load image file '%s': LoadImage() failed: %s",
847 filename, GetError());
852 img_info->source_filename = getStringCopy(filename);
854 img_info->original_width = img_info->bitmap->width;
855 img_info->original_height = img_info->bitmap->height;
857 img_info->contains_small_images = FALSE;
858 img_info->scaled_up = FALSE;
863 static void FreeImage(void *ptr)
865 ImageInfo *image = (ImageInfo *)ptr;
871 FreeBitmap(image->bitmap);
873 if (image->source_filename)
874 free(image->source_filename);
879 int getImageListSize()
881 return (image_info->num_file_list_entries +
882 image_info->num_dynamic_file_list_entries);
885 struct FileInfo *getImageListEntryFromImageID(int pos)
887 int num_list_entries = image_info->num_file_list_entries;
888 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
890 return (pos < num_list_entries ? &image_info->file_list[list_pos] :
891 &image_info->dynamic_file_list[list_pos]);
894 static ImageInfo *getImageInfoEntryFromImageID(int pos)
896 int num_list_entries = image_info->num_file_list_entries;
897 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
898 ImageInfo **img_info =
899 (ImageInfo **)(pos < num_list_entries ? image_info->artwork_list :
900 image_info->dynamic_artwork_list);
902 return img_info[list_pos];
905 Bitmap *getBitmapFromImageID(int pos)
907 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
909 return (img_info != NULL ? img_info->bitmap : NULL);
912 int getOriginalImageWidthFromImageID(int pos)
914 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
916 return (img_info != NULL ? img_info->original_width : 0);
919 int getOriginalImageHeightFromImageID(int pos)
921 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
923 return (img_info != NULL ? img_info->original_height : 0);
926 char *getTokenFromImageID(int graphic)
928 struct FileInfo *file_list = getImageListEntryFromImageID(graphic);
930 return (file_list != NULL ? file_list->token : NULL);
933 int getImageIDFromToken(char *token)
935 struct FileInfo *file_list = image_info->file_list;
936 int num_list_entries = image_info->num_file_list_entries;
939 for (i = 0; i < num_list_entries; i++)
940 if (strcmp(file_list[i].token, token) == 0)
946 char *getImageConfigFilename()
948 return getCustomArtworkConfigFilename(image_info->type);
951 int getImageListPropertyMappingSize()
953 return image_info->num_property_mapping_entries;
956 struct PropertyMapping *getImageListPropertyMapping()
958 return image_info->property_mapping;
961 void InitImageList(struct ConfigInfo *config_list, int num_file_list_entries,
962 struct ConfigTypeInfo *config_suffix_list,
963 char **base_prefixes, char **ext1_suffixes,
964 char **ext2_suffixes, char **ext3_suffixes,
965 char **ignore_tokens)
969 image_info = checked_calloc(sizeof(struct ArtworkListInfo));
970 image_info->type = ARTWORK_TYPE_GRAPHICS;
972 /* ---------- initialize file list and suffix lists ---------- */
974 image_info->num_file_list_entries = num_file_list_entries;
975 image_info->num_dynamic_file_list_entries = 0;
977 image_info->file_list =
978 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
979 num_file_list_entries);
980 image_info->dynamic_file_list = NULL;
982 image_info->num_suffix_list_entries = 0;
983 for (i = 0; config_suffix_list[i].token != NULL; i++)
984 image_info->num_suffix_list_entries++;
986 image_info->suffix_list = config_suffix_list;
988 /* ---------- initialize base prefix and suffixes lists ---------- */
990 image_info->num_base_prefixes = 0;
991 for (i = 0; base_prefixes[i] != NULL; i++)
992 image_info->num_base_prefixes++;
994 image_info->num_ext1_suffixes = 0;
995 for (i = 0; ext1_suffixes[i] != NULL; i++)
996 image_info->num_ext1_suffixes++;
998 image_info->num_ext2_suffixes = 0;
999 for (i = 0; ext2_suffixes[i] != NULL; i++)
1000 image_info->num_ext2_suffixes++;
1002 image_info->num_ext3_suffixes = 0;
1003 for (i = 0; ext3_suffixes[i] != NULL; i++)
1004 image_info->num_ext3_suffixes++;
1006 image_info->num_ignore_tokens = 0;
1007 for (i = 0; ignore_tokens[i] != NULL; i++)
1008 image_info->num_ignore_tokens++;
1010 image_info->base_prefixes = base_prefixes;
1011 image_info->ext1_suffixes = ext1_suffixes;
1012 image_info->ext2_suffixes = ext2_suffixes;
1013 image_info->ext3_suffixes = ext3_suffixes;
1014 image_info->ignore_tokens = ignore_tokens;
1016 image_info->num_property_mapping_entries = 0;
1018 image_info->property_mapping = NULL;
1020 /* ---------- initialize artwork reference and content lists ---------- */
1022 image_info->sizeof_artwork_list_entry = sizeof(ImageInfo *);
1024 image_info->artwork_list =
1025 checked_calloc(num_file_list_entries * sizeof(ImageInfo *));
1026 image_info->dynamic_artwork_list = NULL;
1028 image_info->content_list = NULL;
1030 /* ---------- initialize artwork loading/freeing functions ---------- */
1032 image_info->load_artwork = Load_PCX;
1033 image_info->free_artwork = FreeImage;
1036 void ReloadCustomImages()
1039 printf("DEBUG: reloading images '%s' ...\n", artwork.gfx_current_identifier);
1042 LoadArtworkConfig(image_info);
1043 ReloadCustomArtworkList(image_info);
1046 void CreateImageWithSmallImages(int pos, int zoom_factor)
1048 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
1050 if (img_info == NULL || img_info->contains_small_images)
1053 CreateBitmapWithSmallBitmaps(img_info->bitmap, zoom_factor);
1055 img_info->contains_small_images = TRUE;
1056 img_info->scaled_up = TRUE;
1060 printf("CreateImageWithSmallImages: '%s' zoomed by factor %d\n",
1061 img_info->source_filename, zoom_factor);
1065 printf("CreateImageWithSmallImages: '%s' done\n", img_info->source_filename);
1069 void FreeAllImages()
1071 FreeCustomArtworkLists(image_info);