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;
823 boolean contains_small_images;
825 typedef struct ImageInfo ImageInfo;
827 static struct ArtworkListInfo *image_info = NULL;
829 static void *Load_PCX(char *filename)
834 printf("loading PCX file '%s'\n", filename);
837 img_info = checked_calloc(sizeof(ImageInfo));
839 if ((img_info->bitmap = LoadImage(filename)) == NULL)
841 Error(ERR_WARN, "cannot load image file '%s': LoadImage() failed: %s",
842 filename, GetError());
847 img_info->source_filename = getStringCopy(filename);
849 img_info->contains_small_images = FALSE;
854 static void FreeImage(void *ptr)
856 ImageInfo *image = (ImageInfo *)ptr;
862 FreeBitmap(image->bitmap);
864 if (image->source_filename)
865 free(image->source_filename);
870 int getImageListSize()
872 return (image_info->num_file_list_entries +
873 image_info->num_dynamic_file_list_entries);
876 struct FileInfo *getImageListEntry(int pos)
878 int num_list_entries = image_info->num_file_list_entries;
879 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
881 return (pos < num_list_entries ? &image_info->file_list[list_pos] :
882 &image_info->dynamic_file_list[list_pos]);
885 static ImageInfo *getImageInfoEntryFromImageID(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);
889 ImageInfo **img_info =
890 (ImageInfo **)(pos < num_list_entries ? image_info->artwork_list :
891 image_info->dynamic_artwork_list);
893 return img_info[list_pos];
896 Bitmap *getBitmapFromImageID(int pos)
899 int num_list_entries = image_info->num_file_list_entries;
900 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
901 ImageInfo **img_info =
902 (ImageInfo **)(pos < num_list_entries ? image_info->artwork_list :
903 image_info->dynamic_artwork_list);
905 return (img_info[list_pos] != NULL ? img_info[list_pos]->bitmap : NULL);
907 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
909 return (img_info != NULL ? img_info->bitmap : NULL);
913 char *getTokenFromImageID(int graphic)
916 /* !!! this does not work for dynamic artwork (crash!) !!! */
917 struct FileInfo *file_list = (struct FileInfo *)image_info->file_list;
919 return file_list[graphic].token;
921 struct FileInfo *file_list = getImageListEntry(graphic);
923 return (file_list != NULL ? file_list->token : NULL);
927 int getImageIDFromToken(char *token)
929 struct FileInfo *file_list = image_info->file_list;
930 int num_list_entries = image_info->num_file_list_entries;
933 for (i = 0; i < num_list_entries; i++)
934 if (strcmp(file_list[i].token, token) == 0)
940 char *getImageConfigFilename()
942 return getCustomArtworkConfigFilename(image_info->type);
945 int getImageListPropertyMappingSize()
947 return image_info->num_property_mapping_entries;
950 struct PropertyMapping *getImageListPropertyMapping()
952 return image_info->property_mapping;
955 void InitImageList(struct ConfigInfo *config_list, int num_file_list_entries,
956 struct ConfigTypeInfo *config_suffix_list,
957 char **base_prefixes, char **ext1_suffixes,
958 char **ext2_suffixes, char **ext3_suffixes,
959 char **ignore_tokens)
963 image_info = checked_calloc(sizeof(struct ArtworkListInfo));
964 image_info->type = ARTWORK_TYPE_GRAPHICS;
966 /* ---------- initialize file list and suffix lists ---------- */
968 image_info->num_file_list_entries = num_file_list_entries;
969 image_info->num_dynamic_file_list_entries = 0;
971 image_info->file_list =
972 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
973 num_file_list_entries);
974 image_info->dynamic_file_list = NULL;
976 image_info->num_suffix_list_entries = 0;
977 for (i = 0; config_suffix_list[i].token != NULL; i++)
978 image_info->num_suffix_list_entries++;
980 image_info->suffix_list = config_suffix_list;
982 /* ---------- initialize base prefix and suffixes lists ---------- */
984 image_info->num_base_prefixes = 0;
985 for (i = 0; base_prefixes[i] != NULL; i++)
986 image_info->num_base_prefixes++;
988 image_info->num_ext1_suffixes = 0;
989 for (i = 0; ext1_suffixes[i] != NULL; i++)
990 image_info->num_ext1_suffixes++;
992 image_info->num_ext2_suffixes = 0;
993 for (i = 0; ext2_suffixes[i] != NULL; i++)
994 image_info->num_ext2_suffixes++;
996 image_info->num_ext3_suffixes = 0;
997 for (i = 0; ext3_suffixes[i] != NULL; i++)
998 image_info->num_ext3_suffixes++;
1000 image_info->num_ignore_tokens = 0;
1001 for (i = 0; ignore_tokens[i] != NULL; i++)
1002 image_info->num_ignore_tokens++;
1004 image_info->base_prefixes = base_prefixes;
1005 image_info->ext1_suffixes = ext1_suffixes;
1006 image_info->ext2_suffixes = ext2_suffixes;
1007 image_info->ext3_suffixes = ext3_suffixes;
1008 image_info->ignore_tokens = ignore_tokens;
1010 image_info->num_property_mapping_entries = 0;
1012 image_info->property_mapping = NULL;
1014 /* ---------- initialize artwork reference and content lists ---------- */
1016 image_info->sizeof_artwork_list_entry = sizeof(ImageInfo *);
1018 image_info->artwork_list =
1019 checked_calloc(num_file_list_entries * sizeof(ImageInfo *));
1020 image_info->dynamic_artwork_list = NULL;
1022 image_info->content_list = NULL;
1024 /* ---------- initialize artwork loading/freeing functions ---------- */
1026 image_info->load_artwork = Load_PCX;
1027 image_info->free_artwork = FreeImage;
1030 void ReloadCustomImages()
1033 printf("DEBUG: reloading images '%s' ...\n", artwork.gfx_current_identifier);
1036 LoadArtworkConfig(image_info);
1037 ReloadCustomArtworkList(image_info);
1040 void CreateImageWithSmallImages(int pos, int zoom_factor)
1042 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
1044 if (img_info == NULL || img_info->contains_small_images)
1047 CreateBitmapWithSmallBitmaps(img_info->bitmap, zoom_factor);
1049 img_info->contains_small_images = TRUE;
1053 printf("CreateImageWithSmallImages: '%s' zoomed by factor %d\n",
1054 img_info->source_filename, zoom_factor);
1058 printf("CreateImageWithSmallImages: '%s' done\n", img_info->source_filename);
1062 void FreeAllImages()
1064 FreeCustomArtworkLists(image_info);