22

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?

Drew
  • 75,699
  • 9
  • 109
  • 225
Lee H
  • 2,697
  • 1
  • 16
  • 31

4 Answers4

18

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.
itsjeyd
  • 14,586
  • 3
  • 58
  • 87
kmicu
  • 2,395
  • 1
  • 15
  • 15
9

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 JPEG 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, JPEG, 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 JPEG 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

bignose
  • 627
  • 3
  • 15
Kaushal Modi
  • 25,203
  • 3
  • 74
  • 179
2

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."

dgtized
  • 4,169
  • 20
  • 41
  • 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
1

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)
killdash9
  • 179
  • 8