PlutoUI.jl icon indicating copy to clipboard operation
PlutoUI.jl copied to clipboard

Paste screenshot from clipboard

Open KronosTheLate opened this issue 3 years ago • 13 comments

A feature that I love in Jupyter is the ability to take a screenshot of the task at hand (especially in a school setting, as is the case for me), and paste it directly into the notebook, so that you have it right there as you solve the task. This is a fast and easy fix to the problem of having to tab back and forth from the problem to the notebook.

When I tried to paste a picture from my clipboard into a pluto notebook, nothing happened. I don't know if I am doing it wrong, but I am unable to find a way to paste a picture, so I guess it is not a feature yet. Would it be possible to make this a thing in Pluto?

I am imagining that the data for the screenshot could be put into an array of the type that holds RGB data and printed directly, as demonstrated by Grant Sanderson in some detail in the "Computational thinking" series. This would also maintain the ideal of reproducibility, and "everything needed is right there in the notebook".

Are there others that would like this feature? Would something like this be hard to implement?

KronosTheLate avatar Oct 13 '20 10:10 KronosTheLate

Do you want the screenshot stored in the notebook as well?

The problem is that this could be doable, but will have to put the image content, encoded in the notebook.

We could also make a PlutoUI.paste_image() that allows you to paste an image, but it won't stay when you restart the notebook.

dralletje avatar Oct 13 '20 10:10 dralletje

Pasting a picture that is gone after restart is perfectly fine for what I have in mind.

KronosTheLate avatar Oct 13 '20 10:10 KronosTheLate

I have realized that one can also paste screenshots easily in GitHub comments, like the one seen below: image

It seems like it uploads the image to some GitHub file hosting service, so I don't think that this solution is directly applicable to pluto, but I wanted to promote it here as another example of exactly the feature I am looking for, from the users perspective.

KronosTheLate avatar Nov 18 '20 08:11 KronosTheLate

I actually also wanted to achieve something similar, but my use case would be sharing stand-alone static pluto notebooks instead of power-point presentation for example. I love the way a pluto notebook can be used to generate results and accompanying documentation/text and I would love to then be able to create notebooks to be then able to share with colleagues. For this thing, being able to add images is of great use, and I often find myself getting such images from the clipboard. Due to proprietary information often included in such images, it would be impossible for me to simply put them hosted on some public domain. At the same time, to avoid the problems of reproducibility of a static notebook when passed around, I would like to avoid the need of using local images that are pointing to a path on the filesystem.

Looking around a bit I found that is quite easy to get base64 encoding from an image on the clipboard.

I can easily define a short function as below:

paste_image() =  html"""
	<div contentEditable = true>
	<img src=""/>
	<script>
	const div = currentScript.parentElement
	const img = div.querySelector("img")
	
	div.onpaste = function(e) {
    var data = e.clipboardData.items[0].getAsFile();

    var fr = new FileReader;

    fr.onloadend = function() {
        img.src = fr.result; // fr.result is all data
    };

    fr.readAsDataURL(data);
};
	</script>

and then call it in a cell to create an empty div placeholder that I can paste any image from the clipboard on.

My current issue with this implementation is that when saving the file to a static HTML the image is not retained, but for the use case of @KronosTheLate where having the picture gone after restart is fine, I suppose this solution would quite handy.

Edit: Added a video to show the functionality

https://user-images.githubusercontent.com/12846528/120822312-930e9d80-c556-11eb-8b77-9efb45f5caf4.mp4

disberd avatar Jun 04 '21 14:06 disberd

Oh that's nice! I'll get inspiration from your code to see if we can do something more plutonian! Thanks!!

pankgeorg avatar Jun 04 '21 15:06 pankgeorg

Happy to help! Would you have any suggestion on how I could achieve what I want? Meaning having a way to paste embed the image such that it is also maintained when performing the static export? I tried putting directly the base64 encoded string in the input cell but I suspect that way you have twice the overhead as somehow the input cell states get saved, so I end up with each image occupying a lot of space.

disberd avatar Jun 04 '21 18:06 disberd

Happy to help! Would you have any suggestion on how I could achieve what I want? Meaning having a way to paste embed the image such that it is also maintained when performing the static export? I tried putting directly the base64 encoded string in the input cell but I suspect that way you have twice the overhead as somehow the input cell states get saved, so I end up with each image occupying a lot of space.

We would need to save the base64 somewhere - either within the notebook or in a folder or online. Saving within the notebook is most likely the best idea but there are some real issues like the fact that we wall of text (the Base64) is both ugly and bulky.

pankgeorg avatar Jun 07 '21 10:06 pankgeorg

Indeed due to the point I raised above for my use case I was also considering putting the base64 in the html directly, and I would be willing to live with the wall of text in the resulting HTML file.

My only problem now is that the only way I found of having the image persist the static export, is putting directly the base64 string inside some html code in the input cell. I have been looking around at the Pluto.jl source and it seems that this would indeed result in the same base64 string be saved twice in the notebook state (once in the input cell and once in the output cell), effecitvely wasting two times the size and wall of text.

Ideally I would want to have the base64 encoded string just in the output of the cell but still have no clue on how to do that

disberd avatar Jun 07 '21 20:06 disberd

I just realized that what I want can somehow be achieved by using the PlutoUI.LocalResource widget. I only needed to slightly modify the code inside CellInput.js to automatically save the file on my disk when detecting a paste event of an image and point to it with LocalResource to have my desired behavior :)

disberd avatar Jun 09 '21 10:06 disberd

Hi! I made a package ImageClipboard.jl for images in the clipboard, so this may help this issue. pluto_with_imageclipboard

https://discourse.julialang.org/t/ann-announcing-imageclipboard-jl/63169/3

hyrodium avatar Jun 22 '21 16:06 hyrodium

@hyrodium Thanks for the package which seems quite nice!

Regarding the usage in Pluto, I can't seem to have the cell output be displayed as an image though:

0c97a0f3-aa90-4b7a-886c-6fc69458600b

I suppose it's a matter of the not having the right show method, but it seems strange that it doesn't work natively

disberd avatar Jun 22 '21 17:06 disberd

@disberd Hmm, maybe it depends on the version of Pluto? In my environment, it is v0.14.7.

Or, adding using Images will change the show method. image

hyrodium avatar Jun 23 '21 00:06 hyrodium

Ah, ImageShow.jl was good enough.

hyrodium avatar Jun 23 '21 15:06 hyrodium