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 forxclipcannot 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.xclipcannot currently copy to multiple targets/atoms (github issue), so programs that can't deal with theimage/pngtarget 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/pngirrespective of whether the image is actually apngor not. However, it seems that the programs that can deal with an "image" target atom (such asgimporinkscape) 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