62

I have a graphic on the clipboard on OS X.

What's the quickest way to get it onto disk as a png or jpg?

83

Maybe the File | New From Clipboard menu of /Application/Preview.app.

enter image description here

2
  • 8
    Pressing ⌘N is faster. :)
    – rightfold
    Jul 11 '11 at 21:43
  • 4
    @WTP It does show that in the image. :P I included it for that purpose.
    – nix
    Dec 19 '11 at 20:03
47

Here is a utility to do just that.

pngpaste

Paste PNG into files, much like pbpaste does for text.

However instead of pngpaste > thefile.png, it's pngpaste thefile.png, so one does not accidentally barf binary into the console.

5
  • 1
    That rocks. You cranked that out pretty quick.
    – sholsinger
    Mar 30 '11 at 20:54
  • You are my hero
    – psp
    Jun 3 '15 at 7:51
  • I custom a shell function to save and then select it in finder: function pngp { local path=~/Downloads/${1-000}.png pngpaste $path | open -R $path }
    – lingceng
    Dec 30 '15 at 4:12
  • Install with: brew install pngpaste
    – stevec
    Mar 7 at 15:09
  • This is buggy, see github.com/jcsalterego/pngpaste/issues/16
    – HappyFace
    Apr 3 at 9:27
29

If you have Preview.app open you can simply 'create new' cmd+n and that will generate the proper canvas and paste the clipboard image. Only thing left to do is save that file. Presto!

9

Not nearly as slick, but without using Preview.

Finder -> Edit -> Show Clipboard

Cmd+Shift+4 to get the screen shot marquee tool, and copy the part of the clipboard you want. It's now a PNG on your desktop. But probably not precisely the same image file.

But at that rate, you probably could have screen-captured the original source using the same method and went right to the PNG without using the clipboard.

2
  • Thanks for the edit Jeff... was trying to do that myself when you changed it. Never noticed that you could format the keys like that!
    – bpanulla
    Mar 30 '11 at 17:27
  • 3
    Additionally, if you add Control to the screenshot command above, it will screenshot to clipboard and not a file. I realize that's the opposite of the OPs question, but it never hurts to close the circle.
    – atroon
    Mar 30 '11 at 19:55
5

From terminal, you can get an image from the clipboard with osascript.

Define the following functions. The first function gets the clipboard contents as a string of hex digits. The second function decodes the hex digits into binary.

# get clipboard as <class>
getclip() {
  local class=$1; shift; : ${class:?}
  osascript -e "get the clipboard as «class ${class}»"
}

# get clipboard as <class> (decoding hex string)
getclipb() {
  local class=$1; shift; : ${class:?}
  getclip "$class" | sed "s/«data ${class}//; s/»//" | xxd -r -p
}
$ getclipb PNGf >x.png

You can print the clipboard information (current set of data formats & sizes) with this function:

# print clipboard info
cbi() {
  osascript -e "clipboard info" |
  sed -E 's/, /,/g; s/,([0-9]+)/:\1/g' | tr ':,' '\t\n'
}
$ cbi | expand -t 16
«class PNGf»    3970
«class 8BPS»    4610
GIF picture     60
«class jp2 »    4367
JPEG picture    4877
TIFF picture    4810
«class BMP »    534
«class TPIC»    68
1
  • Excellent! For PNG, just osascript -e "get the clipboard as «class PNGf»" | sed "s/«data PNGf//; s/»//" | xxd -r -p > x.png works. Thanks!
    – chan1142
    Mar 6 '20 at 13:31
2

Using Preview.app is a way, but a little cumbersome. It can also be done on the command line.

Because pbpaste can only pbpaste > filename text snippets, you want to use pngpaste instead.

Install it with Brew:

brew install pngpaste

and use it:

pngpaste <filename>
1
function pngpaste() {
    local name="${1}"
    ensure-args name @MRET
    ensure isDarwin @MRET

    [[ "$name" =~ '\.png$' ]] || name+=.png

    osascript -e "tell application \"System Events\" to ¬
                  write (the clipboard as «class PNGf») to ¬
                          (make new file at folder \"$(pwd)\" with properties ¬
                                  {name:\"${name}\"})"
}
function jpgpaste() {
    local name="${1}"
    ensure-args name @MRET
    ensure isDarwin @MRET


    [[ "$name" =~ '\.jpg$' ]] || name+=.jpg

    osascript -e "tell application \"System Events\" to ¬
                  write (the clipboard as JPEG picture) to ¬
                          (make new file at folder \"$(pwd)\" with properties ¬
                                  {name:\"${name}\"})"
}

Usage:

pngpaste a1.png
#or
jpgpaste a1.jpg
1

I realise the original question calls for saving as a PNG or JPEG, but...

I use a script that saves any graphic on the clipboard to a new page in a PDF document, thus sort-of replicating the old 'Scrapbook' app on Classic MacOS.

The 'quickest way' bit is that I save the script to /Library/Scripts, so I can execute it from the Scripts menulet in the menubar. (which you can enable in the AppleScript Script Editor.app's Preferences dialog).

The images can be copy-and-pasted for other purposes or exported as images.

#!/usr/bin/python   
# getPDFclip v.1.3 : Get PDF from Clipboard image data.
# This script saves a PDF with a copy of any image data found on the Mac Clipboard.   
# If Clipboard.pdf exists, the image is added as an extra page.

from AppKit import NSPasteboard, NSPasteboardTypePDF, NSPasteboardTypeTIFF, NSPasteboardTypePNG, NSTIFFPboardType, NSPICTPboardType, NSImage
from Foundation import NSURL
import Quartz as Quartz
import os, syslog

# Change this to whatever filepath you want:
outfile=os.path.expanduser("~/Desktop/Clipboard.pdf")


myFavoriteTypes = [NSPasteboardTypePDF, NSPasteboardTypeTIFF, NSPasteboardTypePNG, NSTIFFPboardType, NSPICTPboardType, 'com.adobe.encapsulated-postscript']
pb = NSPasteboard.generalPasteboard()
best_type = pb.availableTypeFromArray_(myFavoriteTypes)
if best_type:
    clipData = pb.dataForType_(best_type)
    if clipData:
        image = NSImage.alloc().initWithPasteboard_(pb)
        if image:
            page = Quartz.PDFPage.alloc().initWithImage_(image)
        if os.path.exists(outfile):
            pdfURL = NSURL.fileURLWithPath_(outfile)
            myFile = Quartz.PDFDocument.alloc().initWithURL_(pdfURL)
            if myFile:
                pagenum = myFile.pageCount()
                myFile.insertPage_atIndex_(page, pagenum)
                print ("Image added to Clipboard file.")
        
        else:
            pageData = page.dataRepresentation()
            myFile = Quartz.PDFDocument.alloc().initWithData_(pageData)
        myFile.writeToFile_(outfile)
        print ("Clipboard file created.")

else:
    print ("No clipboard image data was retrieved.")
    print ("These types were available:")
    print (pb.types())
-2

I like to use the command line:

pbpaste > myfile.png

The pbcopy command is useful as well. See this post for details.

6
  • 2
    I just tested it, and pbpaste only works with plain text, rich text, etc. No binary data. See this SO post
    – Alex Vidal
    Mar 30 '11 at 17:25
  • 1
    -1 as it doesn't actually work for the question he asked.
    – cabbey
    Mar 30 '11 at 17:58
  • 3
    Bummer, thought for sure it would work with binary but didn't test (mac is at home, not here at work). Got the StackOverflow urge to post something as fast as I could. Tried to downvote my own answer but I couldn't. :) Mar 30 '11 at 18:04
  • Oh hells yeah. This is rad -- despite the obvious failure suggested by others.
    – sholsinger
    Mar 30 '11 at 20:49
  • 5
    There's always the "delete" link!
    – Arjan
    Apr 5 '11 at 11:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .