/***********************************************************
* Artsoft Retro-Game Library *
*----------------------------------------------------------*
-* (c) 1994-2002 Artsoft Entertainment *
+* (c) 1994-2006 Artsoft Entertainment *
* Holger Schemel *
* Detmolder Strasse 189 *
* 33604 Bielefeld *
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_calloc(sizeof(Image));
image->data = checked_calloc(width * height * bytes_per_pixel);
image->width = width;
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;
if (!private_cmap)
{
if (options.verbose)
- Error(ERR_RETURN, "switching to private colormap");
+ Error(ERR_INFO, "switching to private colormap");
/* we just filled up the default colormap -- get a private one
which contains all already allocated colors */
break;
default:
- Error(ERR_RETURN,"DirectColor, TrueColor or PseudoColor display needed");
+ Error(ERR_INFO,"DirectColor, TrueColor or PseudoColor display needed");
SetError(error, "display class not supported");
return NULL;
}
default:
- Error(ERR_RETURN, "RGB or TrueColor image needed");
+ Error(ERR_INFO, "RGB or TrueColor image needed");
SetError(error, "image type not supported");
return NULL;
}
default:
- Error(ERR_RETURN,"DirectColor, TrueColor or PseudoColor display needed");
+ Error(ERR_INFO,"DirectColor, TrueColor or PseudoColor display needed");
SetError(error, "display class not supported");
return NULL;
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.
-----------------------------------------------------------------------------
*/
int bits_per_pixel;
int bytes_per_pixel;
int x, y, xx, yy, i;
-#if 1
- boolean scale_down = (src_width > dst_width);
- int zoom_factor;
-#else
- int zoom_factor = src_width / dst_width; /* currently very limited! */
-#endif
int row_skip, col_skip;
+ int zoom_factor;
+ boolean scale_down = (src_width > dst_width);
if (scale_down)
{
+#if 1
+ zoom_factor = MIN(src_width / dst_width, src_height / dst_height);
+#else
zoom_factor = src_width / dst_width;
+#endif
/* adjust source image size to integer multiple of destination size */
src_width = dst_width * zoom_factor;
}
else
{
+#if 1
+ zoom_factor = MIN(dst_width / src_width, dst_height / src_height);
+#else
zoom_factor = dst_width / src_width;
+#endif
/* 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;
for (i = 0; i < bytes_per_pixel; i++)
*dst_ptr++ = *(src_ptr + i);
- src_ptr += i;
+ src_ptr += bytes_per_pixel;
}
}
}
int num_references;
Bitmap *bitmap;
- boolean contains_small_images;
+
+ int original_width; /* original image file width */
+ int original_height; /* original image file height */
+
+ boolean contains_small_images; /* set after adding small images */
+ boolean scaled_up; /* set after scaling up */
};
typedef struct ImageInfo ImageInfo;
ImageInfo *img_info;
#if 0
- printf("loading PCX file '%s'\n", filename);
+ printf("::: loading PCX file '%s'\n", filename);
#endif
img_info = checked_calloc(sizeof(ImageInfo));
img_info->source_filename = getStringCopy(filename);
+ img_info->original_width = img_info->bitmap->width;
+ img_info->original_height = img_info->bitmap->height;
+
img_info->contains_small_images = FALSE;
+ img_info->scaled_up = FALSE;
return img_info;
}
image_info->num_dynamic_file_list_entries);
}
-struct FileInfo *getImageListEntry(int pos)
+struct FileInfo *getImageListEntryFromImageID(int pos)
{
int num_list_entries = image_info->num_file_list_entries;
int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
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)
+int getOriginalImageWidthFromImageID(int pos)
{
-#if 0
- /* !!! this does not work for dynamic artwork (crash!) !!! */
- struct FileInfo *file_list = (struct FileInfo *)image_info->file_list;
+ ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
- return file_list[graphic].token;
-#else
- struct FileInfo *file_list = getImageListEntry(graphic);
+ return (img_info != NULL ? img_info->original_width : 0);
+}
+
+int getOriginalImageHeightFromImageID(int pos)
+{
+ ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
+
+ return (img_info != NULL ? img_info->original_height : 0);
+}
+
+char *getTokenFromImageID(int graphic)
+{
+ struct FileInfo *file_list = getImageListEntryFromImageID(graphic);
return (file_list != NULL ? file_list->token : NULL);
-#endif
}
int getImageIDFromToken(char *token)
int i;
for (i = 0; i < num_list_entries; i++)
- if (strcmp(file_list[i].token, token) == 0)
+ if (strEqual(file_list[i].token, token))
return i;
return -1;
void ReloadCustomImages()
{
#if 0
- printf("DEBUG: reloading images '%s' ...\n", artwork.gfx_current_identifier);
+ printf("::: reloading images '%s' ...\n", artwork.gfx_current_identifier);
#endif
LoadArtworkConfig(image_info);
ReloadCustomArtworkList(image_info);
}
-void CreateImageWithSmallImages(int pos)
+void CreateImageWithSmallImages(int pos, int zoom_factor)
{
ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
if (img_info == NULL || img_info->contains_small_images)
return;
- CreateBitmapWithSmallBitmaps(img_info->bitmap);
+ CreateBitmapWithSmallBitmaps(img_info->bitmap, zoom_factor);
img_info->contains_small_images = TRUE;
+ img_info->scaled_up = TRUE;
+}
-#if 0
- printf("CreateImageWithSmallImages: '%s' done\n", img_info->source_filename);
-#endif
+void ScaleImage(int pos, int zoom_factor)
+{
+ ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
+
+ if (img_info == NULL || img_info->scaled_up)
+ return;
+
+ if (zoom_factor != 1)
+ ScaleBitmap(img_info->bitmap, zoom_factor);
+
+ img_info->scaled_up = TRUE;
}
void FreeAllImages()