Implement :max-width/:max-height for (ImageMagic) images

* doc/lispref/display.texi (ImageMagick Images): Mention :max-width and
:max-height.

* lisp/net/shr.el (shr-rescale-image): Use the new
:max-width/:max-height functionality.

* src/image.c (compute_image_size): New function to implement
:max-width and :max-height.
(imagemagick_load_image): Use it.
This commit is contained in:
Lars Magne Ingebrigtsen 2013-06-23 21:24:27 +02:00
parent e854cfc719
commit f3f9606c7a
7 changed files with 121 additions and 45 deletions

View file

@ -1,3 +1,8 @@
2013-06-23 Lars Magne Ingebrigtsen <larsi@gnus.org>
* display.texi (ImageMagick Images): Mention :max-width and
:max-height.
2013-06-20 Paul Eggert <eggert@cs.ucla.edu>
* numbers.texi (Math Functions): Remove obsolete function log10.

View file

@ -4653,6 +4653,15 @@ image. If only one of them is specified, the other one will be
calculated so as to preserve the aspect ratio. If both are specified,
aspect ratio may not be preserved.
@item :max-width, :max-height
The @code{:max-width} and @code{:max-height} keywords are used for
scaling if the size of the image of the image exceeds these values.
If @code{:width} is set it will have presedence over @code{max-width},
and if @code{:height} is set it will have presedence over
@code{max-height}, but you can otherwise mix these keywords as you
wish. @code{:max-width} and @code{:max-height} will always preserve
the aspec ratio.
@item :rotation
Specifies a rotation angle in degrees.

View file

@ -695,6 +695,9 @@ ImageMagick types are treated as images. The function
`imagemagick-filter-types' returns the list of types that will be
treated as images.
*** ImageMagick images now support the :max-width and :max-height
keywords.
** Minibuffer
*** In minibuffer filename prompts, `C-M-f' and `C-M-b' now move to the

View file

@ -1,3 +1,8 @@
2013-06-23 Lars Magne Ingebrigtsen <larsi@gnus.org>
* net/shr.el (shr-rescale-image): Use the new
:max-width/:max-height functionality.
2013-06-23 Ivan Kanis <ivan@kanis.fr>
* net/eww.el (eww-search-prefix): New variable.

View file

@ -741,34 +741,18 @@ size, and full-buffer size."
(defun shr-rescale-image (data &optional force)
"Rescale DATA, if too big, to fit the current buffer.
If FORCE, rescale the image anyway."
(let ((image (create-image data nil t :ascent 100)))
(if (or (not (fboundp 'imagemagick-types))
(not (get-buffer-window (current-buffer))))
image
(let* ((size (image-size image t))
(width (car size))
(height (cdr size))
(edges (window-inside-pixel-edges
(get-buffer-window (current-buffer))))
(window-width (truncate (* shr-max-image-proportion
(- (nth 2 edges) (nth 0 edges)))))
(window-height (truncate (* shr-max-image-proportion
(- (nth 3 edges) (nth 1 edges)))))
scaled-image)
(when (or force
(> height window-height))
(setq image (or (create-image data 'imagemagick t
:height window-height
:ascent 100)
image))
(setq size (image-size image t)))
(when (> (car size) window-width)
(setq image (or
(create-image data 'imagemagick t
:width window-width
:ascent 100)
image)))
image))))
(if (or (not (fboundp 'imagemagick-types))
(not (get-buffer-window (current-buffer))))
(create-image data nil t :ascent 100)
(let ((edges (window-inside-pixel-edges
(get-buffer-window (current-buffer)))))
(create-image
data 'imagemagick t
:ascent 100
:max-width (truncate (* shr-max-image-proportion
(- (nth 2 edges) (nth 0 edges))))
:max-height (truncate (* shr-max-image-proportion
(- (nth 3 edges) (nth 1 edges))))))))
;; url-cache-extract autoloads url-cache.
(declare-function url-cache-create-filename "url-cache" (url))

View file

@ -1,3 +1,9 @@
2013-06-23 Lars Magne Ingebrigtsen <larsi@gnus.org>
* image.c (compute_image_size): New function to implement
:max-width and :max-height.
(imagemagick_load_image): Use it.
2013-06-23 Paul Eggert <eggert@cs.ucla.edu>
Try to avoid malloc SEGVs on Cygwin (Bug#14569).

View file

@ -132,6 +132,8 @@ static void free_color_table (void);
static unsigned long *colors_in_color_table (int *n);
#endif
Lisp_Object QCmax_width, QCmax_height;
/* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
id, which is just an int that this section returns. Bitmaps are
reference counted so they can be shared among frames.
@ -7489,6 +7491,76 @@ gif_load (struct frame *f, struct image *img)
#endif /* HAVE_GIF */
static void
compute_image_size (size_t width, size_t height,
Lisp_Object spec,
int *d_width, int *d_height)
{
Lisp_Object value;
int desired_width, desired_height;
/* If width and/or height is set in the display spec assume we want
to scale to those values. If either h or w is unspecified, the
unspecified should be calculated from the specified to preserve
aspect ratio. */
value = image_spec_value (spec, QCwidth, NULL);
desired_width = (INTEGERP (value) ? XFASTINT (value) : -1);
value = image_spec_value (spec, QCheight, NULL);
desired_height = (INTEGERP (value) ? XFASTINT (value) : -1);
if (desired_width == -1)
{
value = image_spec_value (spec, QCmax_width, NULL);
if (INTEGERP (value) &&
width > XFASTINT (value))
{
/* The image is wider than :max-width. */
desired_width = XFASTINT (value);
if (desired_height == -1)
{
value = image_spec_value (spec, QCmax_height, NULL);
if (INTEGERP (value))
{
/* We have no specified height, but we have a
:max-height value, so check that we satisfy both
conditions. */
desired_height = (double) desired_width / width * height;
if (desired_height > XFASTINT (value))
{
desired_height = XFASTINT (value);
desired_width = (double) desired_height / height * width;
}
}
else
{
/* We have no specified height and no specified
max-height, so just compute the height. */
desired_height = (double) desired_width / width * height;
}
}
}
}
if (desired_height == -1)
{
value = image_spec_value (spec, QCmax_height, NULL);
if (INTEGERP (value) &&
height > XFASTINT (value))
desired_height = XFASTINT (value);
}
if (desired_width != -1 && desired_height == -1)
/* w known, calculate h. */
desired_height = (double) desired_width / width * height;
if (desired_width == -1 && desired_height != -1)
/* h known, calculate w. */
desired_width = (double) desired_height / height * width;
*d_width = desired_width;
*d_height = desired_height;
}
/***********************************************************************
ImageMagick
***********************************************************************/
@ -7516,6 +7588,8 @@ enum imagemagick_keyword_index
IMAGEMAGICK_BACKGROUND,
IMAGEMAGICK_HEIGHT,
IMAGEMAGICK_WIDTH,
IMAGEMAGICK_MAX_HEIGHT,
IMAGEMAGICK_MAX_WIDTH,
IMAGEMAGICK_ROTATION,
IMAGEMAGICK_CROP,
IMAGEMAGICK_LAST
@ -7538,6 +7612,8 @@ static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] =
{":background", IMAGE_STRING_OR_NIL_VALUE, 0},
{":height", IMAGE_INTEGER_VALUE, 0},
{":width", IMAGE_INTEGER_VALUE, 0},
{":max-height", IMAGE_INTEGER_VALUE, 0},
{":max-width", IMAGE_INTEGER_VALUE, 0},
{":rotation", IMAGE_NUMBER_VALUE, 0},
{":crop", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
};
@ -7726,24 +7802,10 @@ imagemagick_load_image (struct frame *f, struct image *img,
PixelSetBlue (bg_wand, (double) bgcolor.blue / 65535);
}
/* If width and/or height is set in the display spec assume we want
to scale to those values. If either h or w is unspecified, the
unspecified should be calculated from the specified to preserve
aspect ratio. */
value = image_spec_value (img->spec, QCwidth, NULL);
desired_width = (INTEGERP (value) ? XFASTINT (value) : -1);
value = image_spec_value (img->spec, QCheight, NULL);
desired_height = (INTEGERP (value) ? XFASTINT (value) : -1);
compute_image_size (MagickGetImageWidth (image_wand),
MagickGetImageHeight (image_wand),
img->spec, &desired_width, &desired_height);
height = MagickGetImageHeight (image_wand);
width = MagickGetImageWidth (image_wand);
if (desired_width != -1 && desired_height == -1)
/* w known, calculate h. */
desired_height = (double) desired_width / width * height;
if (desired_width == -1 && desired_height != -1)
/* h known, calculate w. */
desired_width = (double) desired_height / height * width;
if (desired_width != -1 && desired_height != -1)
{
status = MagickScaleImage (image_wand, desired_width, desired_height);
@ -8895,6 +8957,8 @@ non-numeric, there is no explicit limit on the size of images. */);
DEFSYM (Qheuristic, "heuristic");
DEFSYM (Qpostscript, "postscript");
DEFSYM (QCmax_width, ":max-width");
DEFSYM (QCmax_height, ":max-height");
#ifdef HAVE_GHOSTSCRIPT
ADD_IMAGE_TYPE (Qpostscript);
DEFSYM (QCloader, ":loader");