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;
image->bytes_per_row = width * bytes_per_pixel;
image->rgb.used = 0;
- for (i=0; i<MAX_COLORS; i++)
+ for (i = 0; i < MAX_COLORS; i++)
image->rgb.color_used[i] = FALSE;
image->type = (depth < 8 ? IMAGETYPE_BITMAP :
* the corresponding image pixmap
*/
- for (y=0; y<image->height; 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; x < image->width; x++)
+ {
+ 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 */
+
+ 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, (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<image->width; x++)
+ for (x = 0; x < src_width; x++)
{
- for (i=0; i<image->bytes_per_pixel; i++)
+ 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 */
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->drawable,
+ (char *)mask_data,
+ src_width, src_height)) == None)
+ Error(ERR_EXIT, "Pixmap_to_Mask(): XCreateBitmapFromData() failed");
+
free(mask_data);
return mask_pixmap;
pixmap_format = XListPixmapFormats(display, &num_pixmap_formats);
/* find format that matches the given depth */
- for (i=0; i<num_pixmap_formats; i++)
+ for (i = 0; i < num_pixmap_formats; i++)
if (pixmap_format[i].depth == depth)
bits_per_pixel = pixmap_format[i].bits_per_pixel;
/* calculate number of distinct colors in each band */
redcolors = greencolors = bluecolors = 1;
- for (pixval=1; pixval; pixval <<= 1)
+ for (pixval = 1; pixval; pixval <<= 1)
{
if (pixval & visual->red_mask)
redcolors <<= 1;
redbottom = greenbottom = bluebottom = 0;
redtop = greentop = bluetop = 0;
- for (a=0; a<visual->map_entries; a++)
+ for (a = 0; a < visual->map_entries; a++)
{
if (redbottom < 256)
redtop = redbottom + redstep;
ximageinfo->cmap = global_cmap;
- for (a=0; a<MAX_COLORS; a++)
+ for (a = 0; a < MAX_COLORS; a++)
{
XColor xcolor2;
unsigned short mask;
/* allocate the rest of the color cells read/write */
global_cmap_index =
(Pixel *)checked_malloc(sizeof(Pixel) * NOFLASH_COLORS);
- for (i=0; i<NOFLASH_COLORS; i++)
+ for (i = 0; i < NOFLASH_COLORS; i++)
if (!XAllocColorCells(display, global_cmap, FALSE, NULL, 0,
global_cmap_index + i, 1))
break;
/* to minimize colormap flashing, copy default colors and try
to keep them as near as possible to the old values */
- for(i=0; i<num_cmap_entries; i++)
+ for (i = 0; i < num_cmap_entries; i++)
{
xcolor2.pixel = *(global_cmap_index + i);
XQueryColor(display, DefaultColormap(display, screen), &xcolor2);
while (!color_found)
{
- for (i=num_cmap_entries-1; i>=0; i--)
+ for (i = num_cmap_entries - 1; i >= 0; i--)
{
xcolor2.pixel = *(global_cmap_index + i);
xcolor2 = xcolor_private[xcolor2.pixel];
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);
{
case IMAGETYPE_RGB:
{
- for (y=0; y<image->height; y++) /* general case */
+ for (y = 0; y < image->height; y++) /* general case */
{
- for (x=0; x<image->width; x++)
+ for (x = 0; x < image->width; x++)
{
pixval = *src_ptr++;
pixval =
case IMAGETYPE_TRUECOLOR:
{
- for (y=0; y<image->height; y++) /* general case */
+ for (y = 0; y < image->height; y++) /* general case */
{
- for (x=0; x<image->width; x++)
+ for (x = 0; x < image->width; x++)
{
pixval = memory_to_value(src_ptr, image->bytes_per_pixel);
pixval =
{
if (display_bytes_per_pixel == 1) /* special case */
{
- for (y=0; y<image->height; y++)
- for (x=0; x<image->width; 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; y<image->height; y++)
+ for (y = 0; y < image->height; y++)
{
- for (x=0; x<image->width; x++)
+ for (x = 0; x < image->width; x++)
{
value_to_memory(ximageinfo->index[c + *src_ptr++],
dst_ptr, display_bytes_per_pixel);
XPutImage(ximageinfo->display, ximageinfo->pixmap, gc,
ximage, 0, 0, 0, 0, ximage->width, ximage->height);
- XDestroyImage(ximage);
+ X11DestroyImage(ximage);
return ximageinfo;
}
+/*
+ -----------------------------------------------------------------------------
+ ZoomPixmap
+
+ 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.
+ -----------------------------------------------------------------------------
+*/
+
+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, 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 */
+ 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;
+
+ 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;
+
+ src_ptr = (byte *)src_ximage->data;
+ dst_ptr = (byte *)dst_ximage->data;
+
+ 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 up by scaling factor 'zoom_factor' */
+ for (y = 0; y < src_height; y++)
+ {
+ for (yy = 0; yy < zoom_factor; yy++)
+ {
+ if (yy > 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 += bytes_per_pixel;
+ }
+ }
+ }
+ }
+
+ /* copy scaled image to destination pixmap */
+ XPutImage(display, dst_pixmap, gc, dst_ximage, 0, 0, 0, 0,
+ dst_width, dst_height);
+
+ /* free temporary images */
+ X11DestroyImage(src_ximage);
+ X11DestroyImage(dst_ximage);
+}
+
void freeXImage(Image *image, XImageInfo *ximageinfo)
{
if (ximageinfo->index != NULL && ximageinfo->no > 0)
/* ========================================================================= */
-/* PLATFORM INDEPENDANT IMAGE FUNCTIONS */
+/* PLATFORM INDEPENDENT IMAGE FUNCTIONS */
/* ========================================================================= */
struct ImageInfo
int num_references;
Bitmap *bitmap;
+
+ 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));
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;
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);
&image_info->dynamic_file_list[list_pos]);
}
-Bitmap *getBitmapFromImageID(int 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 **)(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);
+ return img_info[list_pos];
+}
+
+Bitmap *getBitmapFromImageID(int pos)
+{
+ ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
+
+ return (img_info != NULL ? img_info->bitmap : NULL);
+}
+
+int getOriginalImageWidthFromImageID(int pos)
+{
+ ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
+
+ 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 = (struct FileInfo *)image_info->file_list;
+ struct FileInfo *file_list = getImageListEntryFromImageID(graphic);
- return file_list[graphic].token;
+ return (file_list != NULL ? file_list->token : NULL);
+}
+
+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 (strEqual(file_list[i].token, token))
+ 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)
+ struct ConfigTypeInfo *config_suffix_list,
+ char **base_prefixes, char **ext1_suffixes,
+ char **ext2_suffixes, char **ext3_suffixes,
+ char **ignore_tokens)
{
int i;
image_info->num_file_list_entries = num_file_list_entries;
image_info->num_dynamic_file_list_entries = 0;
- 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->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++)
+ 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++)
+ 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;
+
+ image_info->property_mapping = NULL;
/* ---------- initialize artwork reference and content lists ---------- */
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, int zoom_factor)
+{
+ ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
+
+ if (img_info == NULL || img_info->contains_small_images)
+ return;
+
+ CreateBitmapWithSmallBitmaps(img_info->bitmap, zoom_factor);
+
+ img_info->contains_small_images = TRUE;
+ img_info->scaled_up = TRUE;
+}
+
+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()
{
FreeCustomArtworkLists(image_info);