I want to copy images from Emacs to macOS clipboard. I have tried selecting them and yanking, which hasn't worked. Google also didn't have a solution.
-
Not exactly a duplicate, but a similar question: https://emacs.stackexchange.com/questions/26418/emacs-mark-contents-as-type-image-in-copy-to-clipboard – aplaice Apr 14 '18 at 16:32
-
@Dan I want to copy the image files to macOS clipboard. I have tried selecting the image and pressing 'y'. – HappyFace Apr 15 '18 at 15:24
2 Answers
A very rudimentary function that will yank the displayed image at point to the X11 clipboard:
(defun x11-yank-image-at-point-as-image ()
"Yank the image at point to the X11 clipboard as image/png."
(interactive)
(let ((image (get-text-property (point) 'display)))
(if (eq (car image) 'image)
(let ((data (plist-get (cdr image) ':data))
(file (plist-get (cdr image) ':file)))
(cond (data
(with-temp-buffer
(insert data)
(call-shell-region
(point-min) (point-max)
"xclip -i -selection clipboard -t image/png")))
(file
(if (file-exists-p file)
(start-process
"xclip-proc" nil "xclip"
"-i" "-selection" "clipboard" "-t" "image/png"
"-quiet" (file-truename file))))
(t
(message "The image seems to be malformed."))))
(message "Point is not at an image."))))
Requirements
You need to have xclip
installed.
Limitations
Only works on a system with X11 (i.e. won't easily work on MacOS, Windows etc.). Unfortunately, it seems that
pbpaste
, which is usually a drop-in replacement forxclip
cannot copy an image to the clipboard. For possible workarounds, see here. I don't have access to a MacOS system, so I can't apply these myself.xclip
cannot currently copy to multiple targets/atoms (github issue), so programs that can't deal with theimage/png
target atom, will either ignore the paste from the clipboard or insert the image as binary "text".(Relatively easily circumventable.) Currently, the atom used is
image/png
irrespective of whether the image is actually apng
or not. However, it seems that the programs that can deal with an "image" target atom (such asgimp
orinkscape
) seem to (somehow) correctly deal with the paste, even if the image was not apng
. If needed, this could be circumvented by first inspecting the image type and selecting the target atom based on that.
Miscellaneous
Region
For a region, (get-text-property (text-property-not-all (point-min) (point-max) 'display nil) 'display)
would get you the first image (or other "special" display
property) in the region. The other property search functions might also be helpful.
Debugging :data
Try:
(let ((data (plist-get
(cdr (get-text-property (point) 'display))
':data))
(coding-system-for-write 'no-conversion))
(with-temp-buffer
(insert data)
(save-buffer)))
(you will be prompted about the location where to save).

- 2,126
- 17
- 23
-
1
-
This only works when the point is exactly before the image. How can I make it work for regions? Or when the point is after the image? – HappyFace Apr 15 '18 at 16:06
-
-
I have done some testing for the data case, using pbcopy instead of impbcopy. Running 'pbpaste > t.jpg' results in a corrupt file. Here is the data variable: https://gist.github.com/NightMachinary/2c67957b1aa8261679d9d973a5f6366a – HappyFace Apr 15 '18 at 16:48
-
I've edited the answer with some suggestions. I've also made it into a "community wiki" so you can change it, if you want. Looking at the data in the gist, it does indeed seem to be corrupt, but I'm not sure why. – aplaice Apr 15 '18 at 18:28
From @aplaice's answer, adapted to macOS:
(defun ns-yank-image-at-point-as-image ()
"Yank the image at point to the X11 clipboard as image/png."
(interactive)
(let ((image (get-text-property (point) 'display)))
(if (eq (car image) 'image)
(let ((data (plist-get (cdr image) ':data))
(file (plist-get (cdr image) ':file)))
(cond (data
(with-temp-buffer
(insert data)
(call-shell-region
(point-min) (point-max)
"impbcopy"))) ;; http://www.alecjacobson.com/weblog/?p=3816 Linux x11: https://emacs.stackexchange.com/questions/41016/how-can-i-yank-images-from-emacs?noredirect=1#comment64407_41016
(file
(if (file-exists-p file)
(start-process
"_" nil "impbcopy" (file-truename file))))
(t
(message "The image seems to be malformed."))))
(message "Point is not at an image."))))

- 751
- 4
- 16