summaryrefslogtreecommitdiff
path: root/src/image.c
diff options
context:
space:
mode:
authorKim F. Storm <storm@cua.dk>2006-04-21 14:07:05 +0000
committerKim F. Storm <storm@cua.dk>2006-04-21 14:07:05 +0000
commit6ac3c7bb025ec4b37ca61c632c05d479cbfb6eb2 (patch)
treefd108f706bda4ac088465a4de7f1b32da19a236b /src/image.c
parent7b48cc1354a2efff9fb528c1b3c78f47d001178e (diff)
downloademacs-6ac3c7bb025ec4b37ca61c632c05d479cbfb6eb2.tar.gz
(four_corners_best): New arg CORNERS specifies what pixels
to look at in case image has margin. (x_create_bitmap_mask): Pass NULL for CORNERS to four_corners_best. (image_background, image_background_transparent) (x_build_heuristic_mask): Pass img->corners to four_corners_best. (gif_load): Set img->corners according to image's margin spec. Use img->corners values directly where applicable. Save image extension data in img->data.lisp_val. (gif_clear_image): New function to free img->data.lisp_val. (gif_type): Use it instead of generic x_clear_image. (Fimage_extension_data): New defun. (syms_of_image): Defsubr it.
Diffstat (limited to 'src/image.c')
-rw-r--r--src/image.c132
1 files changed, 101 insertions, 31 deletions
diff --git a/src/image.c b/src/image.c
index e1962d87b0f..688ff200055 100644
--- a/src/image.c
+++ b/src/image.c
@@ -603,7 +603,9 @@ x_destroy_all_bitmaps (dpyinfo)
/* Useful functions defined in the section
`Image type independent image structures' below. */
-static unsigned long four_corners_best P_ ((XImagePtr ximg, unsigned long width,
+static unsigned long four_corners_best P_ ((XImagePtr ximg,
+ int *corners,
+ unsigned long width,
unsigned long height));
static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height,
@@ -657,7 +659,7 @@ x_create_bitmap_mask (f, id)
return -1;
}
- bg = four_corners_best (ximg, width, height);
+ bg = four_corners_best (ximg, NULL, width, height);
for (y = 0; y < ximg->height; ++y)
{
@@ -732,7 +734,7 @@ Lisp_Object Qxbm;
/* Keywords. */
extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
-extern Lisp_Object QCdata, QCtype;
+extern Lisp_Object QCdata, QCtype, Qcount;
extern Lisp_Object Qcenter;
Lisp_Object QCascent, QCmargin, QCrelief;
Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
@@ -1141,6 +1143,27 @@ or omitted means use the selected frame. */)
return mask;
}
+DEFUN ("image-extension-data", Fimage_extension_data, Simage_extension_data, 1, 2, 0,
+ doc: /* Return extension data for image SPEC.
+FRAME is the frame on which the image will be displayed. FRAME nil
+or omitted means use the selected frame. */)
+ (spec, frame)
+ Lisp_Object spec, frame;
+{
+ Lisp_Object ext;
+
+ ext = Qnil;
+ if (valid_image_p (spec))
+ {
+ struct frame *f = check_x_frame (frame);
+ int id = lookup_image (f, spec);
+ struct image *img = IMAGE_FROM_ID (f, id);
+ ext = img->data.lisp_val;
+ }
+
+ return ext;
+}
+
/***********************************************************************
Image type independent image structures
@@ -1171,6 +1194,7 @@ make_image (spec, hash)
img->data.lisp_val = Qnil;
img->ascent = DEFAULT_IMAGE_ASCENT;
img->hash = hash;
+ img->corners[BOT_CORNER] = -1; /* Full image */
return img;
}
@@ -1322,30 +1346,41 @@ image_ascent (img, face, slice)
On W32, XIMG is assumed to a device context with the bitmap selected. */
static RGB_PIXEL_COLOR
-four_corners_best (ximg, width, height)
+four_corners_best (ximg, corners, width, height)
XImagePtr_or_DC ximg;
+ int *corners;
unsigned long width, height;
{
- RGB_PIXEL_COLOR corners[4], best;
+ RGB_PIXEL_COLOR corner_pixels[4], best;
int i, best_count;
- /* Get the colors at the corners of ximg. */
- corners[0] = GET_PIXEL (ximg, 0, 0);
- corners[1] = GET_PIXEL (ximg, width - 1, 0);
- corners[2] = GET_PIXEL (ximg, width - 1, height - 1);
- corners[3] = GET_PIXEL (ximg, 0, height - 1);
-
+ if (corners && corners[BOT_CORNER] >= 0)
+ {
+ /* Get the colors at the corner_pixels of ximg. */
+ corner_pixels[0] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[TOP_CORNER]);
+ corner_pixels[1] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[TOP_CORNER]);
+ corner_pixels[2] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[BOT_CORNER] - 1);
+ corner_pixels[3] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[BOT_CORNER] - 1);
+ }
+ else
+ {
+ /* Get the colors at the corner_pixels of ximg. */
+ corner_pixels[0] = GET_PIXEL (ximg, 0, 0);
+ corner_pixels[1] = GET_PIXEL (ximg, width - 1, 0);
+ corner_pixels[2] = GET_PIXEL (ximg, width - 1, height - 1);
+ corner_pixels[3] = GET_PIXEL (ximg, 0, height - 1);
+ }
/* Choose the most frequently found color as background. */
for (i = best_count = 0; i < 4; ++i)
{
int j, n;
for (j = n = 0; j < 4; ++j)
- if (corners[i] == corners[j])
+ if (corner_pixels[i] == corner_pixels[j])
++n;
if (n > best_count)
- best = corners[i], best_count = n;
+ best = corner_pixels[i], best_count = n;
}
return best;
@@ -1404,7 +1439,7 @@ image_background (img, f, ximg)
#endif /* !HAVE_NTGUI */
}
- img->background = four_corners_best (ximg, img->width, img->height);
+ img->background = four_corners_best (ximg, img->corners, img->width, img->height);
if (free_ximg)
Destroy_Image (ximg, prev);
@@ -1449,7 +1484,7 @@ image_background_transparent (img, f, mask)
}
img->background_transparent
- = (four_corners_best (mask, img->width, img->height) == PIX_MASK_RETAIN);
+ = (four_corners_best (mask, img->corners, img->width, img->height) == PIX_MASK_RETAIN);
if (free_mask)
Destroy_Image (mask, prev);
@@ -5358,7 +5393,7 @@ x_build_heuristic_mask (f, img, how)
}
if (use_img_background)
- bg = four_corners_best (ximg, img->width, img->height);
+ bg = four_corners_best (ximg, img->corners, img->width, img->height);
/* Set all bits in mask_img to 1 whose color in ximg is different
from the background color bg. */
@@ -7451,6 +7486,7 @@ tiff_load (f, img)
static int gif_image_p P_ ((Lisp_Object object));
static int gif_load P_ ((struct frame *f, struct image *img));
+static void gif_clear_image P_ ((struct frame *f, struct image *img));
/* The symbol `gif' identifying images of this type. */
@@ -7499,10 +7535,22 @@ static struct image_type gif_type =
&Qgif,
gif_image_p,
gif_load,
- x_clear_image,
+ gif_clear_image,
NULL
};
+/* Free X resources of GIF image IMG which is used on frame F. */
+
+static void
+gif_clear_image (f, img)
+ struct frame *f;
+ struct image *img;
+{
+ /* IMG->data.ptr_val may contain extension data. */
+ img->data.lisp_val = Qnil;
+ x_clear_image (f, img);
+}
+
/* Return non-zero if OBJECT is a valid GIF image specification. */
static int
@@ -7623,7 +7671,7 @@ gif_load (f, img)
GifFileType *gif;
struct gcpro gcpro1;
Lisp_Object image;
- int ino, image_left, image_top, image_width, image_height;
+ int ino, image_height, image_width;
gif_memory_source memsrc;
unsigned char *raster;
@@ -7700,17 +7748,19 @@ gif_load (f, img)
return 0;
}
- image_top = gif->SavedImages[ino].ImageDesc.Top;
- image_left = gif->SavedImages[ino].ImageDesc.Left;
- image_width = gif->SavedImages[ino].ImageDesc.Width;
+ img->corners[TOP_CORNER] = gif->SavedImages[ino].ImageDesc.Top;
+ img->corners[LEFT_CORNER] = gif->SavedImages[ino].ImageDesc.Left;
image_height = gif->SavedImages[ino].ImageDesc.Height;
+ img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + image_height;
+ image_width = gif->SavedImages[ino].ImageDesc.Width;
+ img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width;
width = img->width = max (gif->SWidth,
max (gif->Image.Left + gif->Image.Width,
- image_left + image_width));
+ img->corners[RIGHT_CORNER]));
height = img->height = max (gif->SHeight,
max (gif->Image.Top + gif->Image.Height,
- image_top + image_height));
+ img->corners[BOT_CORNER]));
if (!check_image_size (f, width, height))
{
@@ -7753,19 +7803,19 @@ gif_load (f, img)
requires more than can be done here (see the gif89 spec,
disposal methods). Let's simply assume that the part
not covered by a sub-image is in the frame's background color. */
- for (y = 0; y < image_top; ++y)
+ for (y = 0; y < img->corners[TOP_CORNER]; ++y)
for (x = 0; x < width; ++x)
XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
- for (y = image_top + image_height; y < height; ++y)
+ for (y = img->corners[BOT_CORNER]; y < height; ++y)
for (x = 0; x < width; ++x)
XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
- for (y = image_top; y < image_top + image_height; ++y)
+ for (y = img->corners[TOP_CORNER]; y < img->corners[BOT_CORNER]; ++y)
{
- for (x = 0; x < image_left; ++x)
+ for (x = 0; x < img->corners[LEFT_CORNER]; ++x)
XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
- for (x = image_left + image_width; x < width; ++x)
+ for (x = img->corners[RIGHT_CORNER]; x < width; ++x)
XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
}
@@ -7795,8 +7845,8 @@ gif_load (f, img)
for (x = 0; x < image_width; x++)
{
int i = raster[(y * image_width) + x];
- XPutPixel (ximg, x + image_left, row + image_top,
- pixel_colors[i]);
+ XPutPixel (ximg, x + img->corners[LEFT_CORNER],
+ row + img->corners[TOP_CORNER], pixel_colors[i]);
}
row += interlace_increment[pass];
@@ -7808,10 +7858,29 @@ gif_load (f, img)
for (x = 0; x < image_width; ++x)
{
int i = raster[y * image_width + x];
- XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
+ XPutPixel (ximg, x + img->corners[LEFT_CORNER],
+ y + img->corners[TOP_CORNER], pixel_colors[i]);
}
}
+ /* Save GIF image extension data for `image-extension-data'.
+ Format is (count IMAGES FUNCTION "BYTES" ...). */
+ img->data.lisp_val = Qnil;
+ if (gif->SavedImages[ino].ExtensionBlockCount > 0)
+ {
+ ExtensionBlock *ext = gif->SavedImages[ino].ExtensionBlocks;
+ for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++, ext++)
+ /* Append (... FUNCTION "BYTES") */
+ img->data.lisp_val = Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount),
+ Fcons (make_number (ext->Function),
+ img->data.lisp_val));
+ img->data.lisp_val = Fnreverse (img->data.lisp_val);
+ }
+ if (gif->ImageCount > 1)
+ img->data.lisp_val = Fcons (Qcount,
+ Fcons (make_number (gif->ImageCount),
+ img->data.lisp_val));
+
fn_DGifCloseFile (gif);
/* Maybe fill in the background field while we have ximg handy. */
@@ -8557,6 +8626,7 @@ non-numeric, there is no explicit limit on the size of images. */);
defsubr (&Sclear_image_cache);
defsubr (&Simage_size);
defsubr (&Simage_mask_p);
+ defsubr (&Simage_extension_data);
#if GLYPH_DEBUG
defsubr (&Simagep);