Add support for image flipping
* lisp/image.el (image-map): Keybindings for flipping functions. (image-flip-horizontally): New function that toggles image flipping property. (image-flip-vertically): New function that toggles image flipping property and rotates image 180 degrees. * src/image.c (syms_of_image): Add property. (image_set_transform): Modify image rotation code to also horizontally flip the image when the property is set. * etc/NEWS: Add description. * doc/lispref/display.texi (Image Descriptors): Document :flip (bug#47095).
This commit is contained in:
parent
cd479aa8bd
commit
6fbea946bf
4 changed files with 55 additions and 4 deletions
|
@ -5717,6 +5717,12 @@ are supported, unless the image type is @code{imagemagick}. Positive
|
|||
values rotate clockwise, negative values counter-clockwise. Rotation
|
||||
is performed after scaling and cropping.
|
||||
|
||||
@item :flip @var{flip}
|
||||
If this is @code{t}, the image will be horizontally flipped.
|
||||
Currently it has no effect if the image type is @code{imagemagick}.
|
||||
Vertical flipping can be achieved by rotating the image 180 degrees
|
||||
and toggling this value.
|
||||
|
||||
@item :transform-smoothing @var{smooth}
|
||||
If this is @code{t}, any image transform will have smoothing applied;
|
||||
if @code{nil}, no smoothing will be applied. The exact algorithm used
|
||||
|
|
4
etc/NEWS
4
etc/NEWS
|
@ -1545,6 +1545,10 @@ This controls whether or not to show a message when opening certain
|
|||
image formats saying how to edit it as text. The default is to show
|
||||
this message for SVG and XPM.
|
||||
|
||||
+++
|
||||
*** New commands: 'image-flip-horizontally' and 'image-flip-vertically'.
|
||||
These commands horizontally and vertically flip the image under point.
|
||||
|
||||
** Image-Dired
|
||||
|
||||
+++
|
||||
|
|
|
@ -177,6 +177,8 @@ or \"ffmpeg\") is installed."
|
|||
"+" #'image-increase-size
|
||||
"r" #'image-rotate
|
||||
"o" #'image-save
|
||||
"h" #'image-flip-horizontally
|
||||
"v" #'image-flip-vertically
|
||||
"C-<wheel-down>" #'image-mouse-decrease-size
|
||||
"C-<mouse-5>" #'image-mouse-decrease-size
|
||||
"C-<wheel-up>" #'image-mouse-increase-size
|
||||
|
@ -1288,6 +1290,22 @@ changing the displayed image size does not affect the saved image."
|
|||
(write-region (point-min) (point-max)
|
||||
(read-file-name "Write image to file: ")))))
|
||||
|
||||
(defun image-flip-horizontally ()
|
||||
"Horizontally flip the image under point."
|
||||
(interactive)
|
||||
(let ((image (image--get-image)))
|
||||
(image-flush image)
|
||||
(setf (image-property image :flip)
|
||||
(not (image-property image :flip)))))
|
||||
|
||||
(defun image-flip-vertically ()
|
||||
"Vertically flip the image under point."
|
||||
(interactive)
|
||||
(let ((image (image--get-image)))
|
||||
(image-rotate 180)
|
||||
(setf (image-property image :flip)
|
||||
(not (image-property image :flip)))))
|
||||
|
||||
(provide 'image)
|
||||
|
||||
;;; image.el ends here
|
||||
|
|
31
src/image.c
31
src/image.c
|
@ -2587,6 +2587,11 @@ image_set_transform (struct frame *f, struct image *img)
|
|||
double rotation = 0.0;
|
||||
compute_image_rotation (img, &rotation);
|
||||
|
||||
/* Determine flipping. */
|
||||
bool flip;
|
||||
Lisp_Object m = image_spec_value (img->spec, QCflip, NULL);
|
||||
flip = !NILP (m);
|
||||
|
||||
#ifndef HAVE_HAIKU
|
||||
# if defined USE_CAIRO || defined HAVE_XRENDER || defined HAVE_NS
|
||||
/* We want scale up operations to use a nearest neighbor filter to
|
||||
|
@ -2626,14 +2631,25 @@ image_set_transform (struct frame *f, struct image *img)
|
|||
/* Perform rotation transformation. */
|
||||
|
||||
int rotate_flag = -1;
|
||||
if (rotation == 0)
|
||||
if (rotation == 0 && !flip)
|
||||
rotate_flag = 0;
|
||||
else
|
||||
{
|
||||
# if (defined USE_CAIRO || defined HAVE_XRENDER \
|
||||
|| defined HAVE_NTGUI || defined HAVE_NS)
|
||||
int cos_r, sin_r;
|
||||
if (rotation == 90)
|
||||
if (rotation == 0)
|
||||
{
|
||||
/* FLIP is always true here. As this will rotate by 0
|
||||
degrees, it has no visible effect. Applying only
|
||||
translation matrix to the image would be sufficient for
|
||||
horizontal flipping, but writing special handling for
|
||||
this case would increase code complexity somewhat. */
|
||||
cos_r = 1;
|
||||
sin_r = 0;
|
||||
rotate_flag = 1;
|
||||
}
|
||||
else if (rotation == 90)
|
||||
{
|
||||
width = img->height;
|
||||
height = img->width;
|
||||
|
@ -2674,9 +2690,14 @@ image_set_transform (struct frame *f, struct image *img)
|
|||
matrix3x3 v;
|
||||
matrix3x3_mult (rot, u, v);
|
||||
|
||||
/* 3. Translate back. */
|
||||
/* 3. Translate back. Flip horizontally if requested. */
|
||||
t[2][0] = width * -.5;
|
||||
t[2][1] = height * -.5;
|
||||
if (flip)
|
||||
{
|
||||
t[0][0] = -t[0][0];
|
||||
t[2][0] = -t[2][0];
|
||||
}
|
||||
matrix3x3_mult (t, v, matrix);
|
||||
# else
|
||||
/* 1. Translate so (0, 0) is in the center of the image. */
|
||||
|
@ -2694,9 +2715,10 @@ image_set_transform (struct frame *f, struct image *img)
|
|||
matrix3x3 v;
|
||||
matrix3x3_mult (u, rot, v);
|
||||
|
||||
/* 3. Translate back. */
|
||||
/* 3. Translate back. Flip horizontally if requested. */
|
||||
t[2][0] = width * .5;
|
||||
t[2][1] = height * .5;
|
||||
if (flip) t[0][0] = -t[0][0];
|
||||
matrix3x3_mult (v, t, matrix);
|
||||
# endif
|
||||
img->width = width;
|
||||
|
@ -11940,6 +11962,7 @@ non-numeric, there is no explicit limit on the size of images. */);
|
|||
DEFSYM (QCtransform_smoothing, ":transform-smoothing");
|
||||
DEFSYM (QCcolor_adjustment, ":color-adjustment");
|
||||
DEFSYM (QCmask, ":mask");
|
||||
DEFSYM (QCflip, ":flip");
|
||||
|
||||
/* Other symbols. */
|
||||
DEFSYM (Qlaplace, "laplace");
|
||||
|
|
Loading…
Add table
Reference in a new issue