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:
Timo Taipalus 2022-06-24 14:44:02 +02:00 committed by Lars Ingebrigtsen
parent cd479aa8bd
commit 6fbea946bf
4 changed files with 55 additions and 4 deletions

View file

@ -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

View file

@ -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
+++

View file

@ -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

View file

@ -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");