20

With Emacs' doc-view-mode I can easily shrink/zoom/etc PDFs, however, I would like to be able to do the same thing with images. Currently when I open an image I cannot adjust the zoom level to fit it to the frame. I know there is image-mode-fit-frame, however, it does not help when the image is larger than my screen.

Is there a package or mode that will allow me zoom in and out on an image?

15

Such functionality is provied by packages:

  • image-dired-thumbnail-mode

    With point in the thumbnail buffer, you can type RET (image-dired-display-thumbnail-original-image) to display a sized version of it in another window. This sizes the image to fit the window.

    It uses ImageMagick's convert command.

    You can also use image-dired-external-viewer to avoid the problem and display your images in an external image viewer such as feh.

  • eimp

    (add-hook 'image-mode-hook 'eimp-mode)
    

    It uses the mogrify utility from ImageMagick to do the actual transformations.

    (kbd "+") 'eimp-increase-image-size
    (kbd "-") 'eimp-decrease-image-size
    (kbd "<") 'eimp-rotate-image-anticlockwise
    (kbd ">") 'eimp-rotate-image-clockwise
    (kbd "B +") 'eimp-blur-image
    (kbd "B -") 'eimp-sharpen-image
    (kbd "B E") 'eimp-emboss-image
    (kbd "B G") 'eimp-gaussian-blur-image
    (kbd "B R") 'eimp-radial-blur-image
    (kbd "C B +") 'eimp-increase-image-brightness
    (kbd "C B -") 'eimp-decrease-image-brightness
    (kbd "C C +") 'eimp-increase-image-contrast
    (kbd "C C -") 'eimp-decrease-image-contrast
    (kbd "F ^") 'eimp-flip-image
    (kbd "F >") 'eimp-flop-image
    (kbd "F <") 'eimp-flop-image
    (kbd "N") 'eimp-negate-image
    
    ; Commands most relevant to you:
    (kbd "S f") 'eimp-fit-image-to-window
    (kbd "S h") 'eimp-fit-image-height-to-window
    (kbd "S w") 'eimp-fit-image-width-to-window
    
    (kbd "<right>") 'eimp-roll-image-right
    (kbd "<left>") 'eimp-roll-image-left
    (kbd "<up>") 'eimp-roll-image-up
    (kbd "<down>") 'eimp-roll-image-down
    (kbd "<down-mouse-1>") 'eimp-mouse-resize-image
    (kbd "<S-down-mouse-1>") 'eimp-mouse-resize-image-preserve-aspect
    (kbd "C-c C-k") 'eimp-stop-all
    
  • eiv - It also uses the ImageMagick package which should provide mogrify.

    Complete command list:

    • eiv-fit-image-to-window - Resize image to current window size.
    • eiv-rotate-current-image - Rotate current image at 90 degrees.
    • eiv-dec-or-inc-image - Resize image to current window size.
    • eiv-diaporama - Start a diaporama on tree.
    • eiv-viewer - The emacs-image-viewer. Allows to navigate in a tree of dir and subdir.
  • 5
    One should note that eimp modifies the file. It doesn't work on read-only images. – Kaushal Modi Oct 22 '14 at 17:52
6

Solution

I used the source code in lisp/image-mode.el to write this up. Calling this function in any image buffer will resize it to fit to width or height depending on the image and window height/width ratios.

You do need these 2 things for this function to work:

  • Your emacs needs to have been compiled with Imagemagick.
  • By default libjpeg loader is used to handle jpg images. The hack shown in next part of this answer is used to force emacs to use imagemagick loader.
(defun modi/image-transform-fit-to-window()
  "Resize the image to fit the width or height based on the image and window ratios.
Imagemagick is required to run this function."
  (interactive)
  (let* ( (img-size (image-display-size (image-get-display-property) t))
          (img-width (car img-size))
          (img-height (cdr img-size))
          (img-h/w-ratio (/ (float img-height) (float img-width)))
          (win-width (- (nth 2 (window-inside-pixel-edges))
                        (nth 0 (window-inside-pixel-edges))))
          (win-height (- (nth 3 (window-inside-pixel-edges))
                         (nth 1 (window-inside-pixel-edges))))
          (win-h/w-ratio (/ (float win-height) (float win-width))))
    ;; Fit image by width if the h/w ratio of window is > h/w ratio of the image
    (if (> win-h/w-ratio img-h/w-ratio)
        (image-transform-fit-to-width)
      ;; Else fit by height
      (image-transform-fit-to-height))))

Hack to force emacs to use imagemagick for loading images

After following through the emacs bug reports #18797, #10746 and #10112, the following solution worked for forcing Imagemagick to load images; put it somewhere in your init.el:

I have forced emacs to use imagemagick only for the image files familiar to me: png, tiff, jpg/jpeg and svg; the rest are kept as default. I have chosen to allow gif files to be opened by the default loader as emacs 24.4 has improved support for viewing multi-frame images. The whole regexp is taken from lisp/image.el.

 (setq image-type-header-regexps
       `(
         ("\\`/[\t\n\r ]*\\*.*XPM.\\*/" . xpm)
         ("\\`P[1-6]\\\(?:\
              \\(?:\\(?:#[^\r\n]*[\r\n]\\)?[[:space:]]\\)+\
              \\(?:\\(?:#[^\r\n]*[\r\n]\\)?[0-9]\\)+\
              \\)\\{2\\}" . pbm)
         ("\\`GIF8[79]a" . gif)
         ;; ("\\`\x89PNG\r\n\x1a\n" . png) ;; Uncomment this (and comment the below line) to enable inline png images in org-mode
         ("\\`\x89PNG\r\n\x1a\n" . imagemagick) ; png
         ("\\`[\t\n\r ]*#define \\([a-z0-9_]+\\)_width [0-9]+\n\
              #define \\1_height [0-9]+\n\\(\
              #define \\1_x_hot [0-9]+\n\
              #define \\1_y_hot [0-9]+\n\\)?\
              static \\(unsigned \\)?char \\1_bits" . xbm)
         ;; ("\\`\\(?:MM\0\\*\\|II\\*\0\\)" . tiff)
         ("\\`\\(?:MM\0\\*\\|II\\*\0\\)" . imagemagick) ; tiff
         ("\\`[\t\n\r ]*%!PS" . postscript)
         ;; ("\\`\xff\xd8" . jpeg) ;; Uncomment this (and comment the below line) to enable inline jpg images in org-mode
         ("\\`\xff\xd8" . imagemagick)    ; jpeg
         ("\\`\377\330" . imagemagick)    ; jpeg
         (,(let* ((incomment-re "\\(?:[^-]\\|-[^-]\\)")
                  (comment-re (concat "\\(?:!--" incomment-re "*-->[ \t\r\n]*<\\)")))
             (concat "\\(?:<\\?xml[ \t\r\n]+[^>]*>\\)?[ \t\r\n]*<"
                     comment-re "*"
                     "\\(?:!DOCTYPE[ \t\r\n]+[^>]*>[ \t\r\n]*<[ \t\r\n]*" comment-re "*\\)?"
                     "[Ss][Vv][Gg]"))
          ;; . svg)  ;; Uncomment this (and comment the below line) to enable inline svg images in org-mode
          . imagemagick) ; svg
         ))

Drawback

  • Image types chosen to be loaded by imagemagick will not show up as inline images in org-mode.

References

1

image-transform-set-scale may be what you are looking for. However it requires Emacs to be compiled with Imagemagick support.

There is also a commented out image-transform-mode in image-mode.el labeled "Not yet implemented."

  • I see Does Emacs use imagemagick? yes when running ./configure. So it did compile with imagemagick. Still image transform doesn't work for me. (On emacs 24.4 x86_64-unknown-linux-gnu) I also have the following in config.log: | #define HAVE_IMAGEMAGICK 1 | #define HAVE_MAGICKEXPORTIMAGEPIXELS 1 | #define HAVE_MAGICKMERGEIMAGELAYERS 1. – Kaushal Modi Oct 22 '14 at 16:17
0

Here's a solution that lets you scale up and down using the same keys as are used for text scaling, C-x C-= and C-x C--

(defun scale-image ()
  "Scale the image by the same factor specified by the text scaling."
  (image-transform-set-scale
   (expt text-scale-mode-step
         text-scale-mode-amount)))

(defun scale-image-register-hook ()
  "Register the image scaling hook."
  (add-hook 'text-scale-mode-hook 'scale-image))

(add-hook 'image-mode-hook 'scale-image-register-hook)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.