aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/lispref/display.texi20
-rw-r--r--etc/NEWS17
-rw-r--r--lisp/image.el63
3 files changed, 89 insertions, 11 deletions
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index c8e7e4fa5c1..26f3de40e91 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -5508,6 +5508,26 @@ cache, it can always be displayed, even if the value of
5508@code{max-image-size} is subsequently changed (@pxref{Image Cache}). 5508@code{max-image-size} is subsequently changed (@pxref{Image Cache}).
5509@end defvar 5509@end defvar
5510 5510
5511Images inserted with the insertion functions above also get a local
5512keymap installed in the text properties (or overlays) that span the
5513displayed image. This keymap defines the following commands:
5514
5515@table @kbd
5516@item +
5517Increase the image size (@code{image-increase-size}). A prefix value
5518of @samp{4} means to increase the size by 40%. The default is 20%.
5519
5520@item -
5521Decrease the image size (@code{image-increase-size}). A prefix value
5522of @samp{4} means to decrease the size by 40%. The default is 20%.
5523
5524@item r
5525Rotate the image by 90 degrees (@code{image-rotate}).
5526
5527@item o
5528Save the image to a file (@code{image-save}).
5529@end table
5530
5511@node Multi-Frame Images 5531@node Multi-Frame Images
5512@subsection Multi-Frame Images 5532@subsection Multi-Frame Images
5513@cindex multi-frame images 5533@cindex multi-frame images
diff --git a/etc/NEWS b/etc/NEWS
index 750d671cc63..957b0c24791 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -824,11 +824,6 @@ while in non-`visual-line-mode' it will move the point to the indented
824header’s value. 824header’s value.
825 825
826+++ 826+++
827** Images are automatically scaled before displaying based on the
828`image-scaling-factor' variable (if Emacs supports scaling the images
829in question).
830
831+++
832** In Show Paren Mode, a parenthesis can be highlighted when point 827** In Show Paren Mode, a parenthesis can be highlighted when point
833stands inside it, and certain parens can be highlighted when point is 828stands inside it, and certain parens can be highlighted when point is
834at BOL or EOL, or in whitespace there. To enable these, customize, 829at BOL or EOL, or in whitespace there. To enable these, customize,
@@ -839,6 +834,18 @@ respectively, `show-paren-when-point-inside-paren' or
839** If gpg2 exists on the system, it is now used as the default value 834** If gpg2 exists on the system, it is now used as the default value
840of `epg-gpg-program' (instead of gpg). 835of `epg-gpg-program' (instead of gpg).
841 836
837** Images
838
839+++
840*** Images are automatically scaled before displaying based on the
841`image-scaling-factor' variable (if Emacs supports scaling the images
842in question).
843
844*** Images inserted with `insert-image' and related functions get a
845keymap put into the text properties (or overlays) that span the
846image. This keymap binds keystrokes for manipulating size and
847rotation, as well as saving the image to a file.
848
842** Lisp mode 849** Lisp mode
843 850
844--- 851---
diff --git a/lisp/image.el b/lisp/image.el
index b69d3b15a43..4f2733adb7e 100644
--- a/lisp/image.el
+++ b/lisp/image.el
@@ -139,6 +139,15 @@ based on the font pixel size."
139 :group 'image 139 :group 'image
140 :version "25.2") 140 :version "25.2")
141 141
142;; Map put into text properties on images.
143(defvar image-map
144 (let ((map (make-keymap)))
145 (define-key map "-" 'image-decrease-size)
146 (define-key map "+" 'image-increase-size)
147 (define-key map "r" 'image-rotate)
148 (define-key map "o" 'image-save)
149 map))
150
142(defun image-load-path-for-library (library image &optional path no-error) 151(defun image-load-path-for-library (library image &optional path no-error)
143 "Return a suitable search path for images used by LIBRARY. 152 "Return a suitable search path for images used by LIBRARY.
144 153
@@ -466,6 +475,7 @@ means display it in the right marginal area."
466 (put-text-property 0 (length string) 'display prop string) 475 (put-text-property 0 (length string) 'display prop string)
467 (overlay-put overlay 'put-image t) 476 (overlay-put overlay 'put-image t)
468 (overlay-put overlay 'before-string string) 477 (overlay-put overlay 'before-string string)
478 (overlay-put overlay 'map image-map)
469 overlay))) 479 overlay)))
470 480
471 481
@@ -505,7 +515,9 @@ height of the image; integer values are taken as pixel values."
505 (add-text-properties start (point) 515 (add-text-properties start (point)
506 `(display ,(if slice 516 `(display ,(if slice
507 (list (cons 'slice slice) image) 517 (list (cons 'slice slice) image)
508 image) rear-nonsticky (display))))) 518 image)
519 rear-nonsticky (display)
520 keymap ,image-map))))
509 521
510 522
511;;;###autoload 523;;;###autoload
@@ -541,7 +553,8 @@ The image is automatically split into ROWS x COLS slices."
541 (insert string) 553 (insert string)
542 (add-text-properties start (point) 554 (add-text-properties start (point)
543 `(display ,(list (list 'slice x y dx dy) image) 555 `(display ,(list (list 'slice x y dx dy) image)
544 rear-nonsticky (display))) 556 rear-nonsticky (display)
557 keymap ,image-map))
545 (setq x (+ x dx)))) 558 (setq x (+ x dx))))
546 (setq x 0.0 559 (setq x 0.0
547 y (+ y dy)) 560 y (+ y dy))
@@ -931,17 +944,55 @@ default is 20%."
931 (- 1 (/ n 10)) 944 (- 1 (/ n 10))
932 0.8))) 945 0.8)))
933 946
934(defun image-change-size (factor) 947(defun image--get-image ()
935 (unless (fboundp 'imagemagick-types) 948 (let ((image (or (get-text-property (point) 'display)
936 (error "Can't rescale images without ImageMagick support")) 949 ;; `put-image' uses overlays, so find an image in
937 (let ((image (get-text-property (point) 'display))) 950 ;; the overlays.
951 (seq-find (lambda (overlay)
952 (overlay-get overlay 'display))
953 (overlays-at (point))))))
938 (when (or (not (consp image)) 954 (when (or (not (consp image))
939 (not (eq (car image) 'image))) 955 (not (eq (car image) 'image)))
940 (error "No image under point")) 956 (error "No image under point"))
957 image))
958
959(defun image--get-imagemagick-and-warn ()
960 (unless (fboundp 'imagemagick-types)
961 (error "Can't rescale images without ImageMagick support"))
962 (let ((image (image--get-image)))
963 (image-flush image)
941 (plist-put (cdr image) :type 'imagemagick) 964 (plist-put (cdr image) :type 'imagemagick)
965 image))
966
967(defun image-change-size (factor)
968 (let ((image (image--get-imagemagick-and-warn)))
942 (plist-put (cdr image) :scale 969 (plist-put (cdr image) :scale
943 (* (or (plist-get (cdr image) :scale) 1) factor)))) 970 (* (or (plist-get (cdr image) :scale) 1) factor))))
944 971
972(defun image-rotate ()
973 "Rotate the image under point by 90 degrees clockwise."
974 (interactive)
975 (let ((image (image--get-imagemagick-and-warn)))
976 (plist-put (cdr image) :rotation
977 (float (+ (or (plist-get (cdr image) :rotation) 0) 90)))))
978
979(defun image-save ()
980 "Save the image under point."
981 (interactive)
982 (let ((image (get-text-property (point) 'display)))
983 (when (or (not (consp image))
984 (not (eq (car image) 'image)))
985 (error "No image under point"))
986 (with-temp-buffer
987 (let ((file (plist-get (cdr image) :file)))
988 (if file
989 (if (not (file-exists-p file))
990 (error "File %s no longer exists" file)
991 (insert-file-contents-literally file))
992 (insert (plist-get (cdr image) :data))))
993 (write-region (point-min) (point-max)
994 (read-file-name "Write image to file: ")))))
995
945(provide 'image) 996(provide 'image)
946 997
947;;; image.el ends here 998;;; image.el ends here