14

Assuming I want to have an org buffer in which I can preview images from url which I don't want to store on my hard drive - is there a possibility to use a solution similar to org links and display images functions?

I know I can use e.g.

(eww-browse-url "url.jpg")

but it opens an image in another buffer, which I want to avoid.

As a temporary solution I'm using a shell command (which I can put into an "clickable" elisp link in an org buffer):

(async-shell-command "wget -O /tmp/image.jpg https://url/some-name.jpg")

but to make it work I have to put another org link which will use downloaded image path (and then call org-redisplay-inline-images function):

[[file:/tmp/image.jpg]]

I am looking for a oneliner solution in which I just paste the link to the image and then toggle org display images. Is there a generic Emacs way to do that?

2 Answers 2

12

And again we have a use-case for image data not stored on harddisk. (The other two use-cases are base64 encoded images in org buffers and displaying previews of youtube videos.)

Get org-yt and paste the following elisp code into your init-file.

After evaluating your init-file you can use links analog to the example:

[[imghttp://tn-home.de/Pic/tn-home.png]]

(require 'org-yt)

(defun org-image-link (protocol link _description)
  "Interpret LINK as base64-encoded image data."
  (cl-assert (string-match "\\`img" protocol) nil
             "Expected protocol type starting with img")
  (let ((buf (url-retrieve-synchronously (concat (substring protocol 3) ":" link))))
    (cl-assert buf nil
               "Download of image \"%s\" failed." link)
    (with-current-buffer buf
      (goto-char (point-min))
      (re-search-forward "\r?\n\r?\n")
      (buffer-substring-no-properties (point) (point-max)))))

(org-link-set-parameters
 "imghttp"
 :image-data-fun #'org-image-link)

(org-link-set-parameters
 "imghttps"
 :image-data-fun #'org-image-link)
7
  • Thank you, @Tobias, for the link to your package. It seems to work as intended.
    – caseneuve
    Commented Jun 27, 2018 at 21:00
  • 1
    Sorry to be a critic, but I don't think assertions should be included in SE answers. Readers may not understand the meaning and proper use of assertions, and even if they do, the assertions still tend to complicate and obfuscate the answer, IMO. Rather give the straight-ahead, just-what's-needed code. As a matter of fact, I believe that the second assertion in the code above is not proper usage. Assertions are meant to be capable of being "turned off" without affecting the proper running of the code, are they not? This case requires permanent runtime error handling, I believe. Commented Jul 4, 2018 at 16:11
  • 1
    This solution seems only work with online *.png files. Is there a way to modify it to work also with jpg and jpeg files?
    – George
    Commented Jun 19, 2019 at 16:57
  • 2
    This should be included in org-mode main. Any plans? Commented Jan 24, 2020 at 13:00
  • 2
    @George [[imghttps://64.media.tumblr.com/tumblr_m6d80q6QJK1qcgf56o1_1280.jpg]] works for me.
    – HappyFace
    Commented Oct 7, 2020 at 9:17
0

The above solution is great and I use it. I also added an additional function for when I don't want to display the images inline in the text, which creates scrolling issues.

(use-package url)
(defun display-online-image-in-new-buffer (&optional url)
  (interactive)
  (unless url (setq url (url-get-url-at-point)))
  (unless url
    (error "Couldn't find URL."))
  (let ((buffer (url-retrieve-synchronously url))
        (image-buffer (generate-new-buffer "*Image*")))
    (unwind-protect
        (with-current-buffer buffer
          (goto-char (point-min))
          (search-forward "\n\n")
          (let ((data (buffer-substring (point) (point-max))))
            (with-current-buffer image-buffer
              (insert-image (create-image data nil t))
              ;; Check if the current frame is already split
              (if (> (length (window-list)) 1)
                  (set-window-buffer (next-window) image-buffer)  ; Use existing window
                ;; Else, split the window and switch to the image buffer
                (split-window-right)
                (other-window 1)
                (switch-to-buffer image-buffer)
                (other-window -1))))
      (kill-buffer buffer))))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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