Change Format of Clipboard Image

I keep my screenshot file format as PNG, because I usually need something lossless.

However, I also commonly paste screenshots into emails, and if those emails go to PC users, a lot of them will show any inline PNG as an attachment instead of an inline graphic. To actually display the graphic inline on their email clients, it must be a jpg.

I was wondering if I could applescript changing the format of the clipboard just for the specific graphic that’s currently there. Not by changing the defaults before and after taking each screenshot, just converting an already captured screen grab on the clipboard.

The only way that came to mind is to script having preview make a new document, save it out to a temp folder as a jpg, then use

set the clipboard to (read “[whatever]” as JPEG picture)

then delete the temp file.

This certainly seems feasible, I just thought I’d ask if there’s anything less clunky first.

Should have done more looking before I posted.

Sometimes, Applescript is just so easy I miss the obvious.

set the clipboard to (the clipboard as JPEG picture)

Well, fantastic. Any image pasted from the clipboard into Apple Mail seems to get turned into a TIFF in Apple Mail, regardless of the image’s default format on the clipboard.

Anybody have a solution for that?

I think you’re misunderstanding how the clipboard works. Suppose you copy an image as jpeg or png. The clipboard will then offer that image when pasting in several formats. So typically a receiving app will either ask what types are available, and pick what it regards as the “richest”, or it will pass a list of preferred types in preference order. In other words, you don’t have any real control over what Mail prefers.

If you run this:

set the clipboard to (the clipboard as JPEG picture)
clipboard info

you will see (partly) what I mean.

I did know how the clipboard worked, I was already running “clipboard info” in between to see that my script had worked.

While applications can choose what they want from the multiple formats on the clipboard, many applications can accept more than one of those formats. For example, Mail can take an inline image as a JPG, PNG, or TIFF. If you drag an image file from the desktop into Mail it doesn’t convert it to TIFF - you get whatever format the file was in your email. So Mail supports all of them.

On the clipboard, the formats are ordered. So ideally, and I’m pretty sure I’ve seen programs behaving this way, the program may take that order preference into account. So if JPEG is the first format, the original was probably a JPG. The program originating the “copy” action might write out a TIFF and a PNG to the clipboard also, in support of applications that can only make use of one of those formats. But JPG being the first format on the clipboard is indicative that JPG was the original. So programs that support multiple formats can take the first one by order, so they don’t take an already small, compressed image file with compression artifacts and make a TIFF out of it, making it huge while keeping the artifacts.

On the other hand, if the first format is TIFF, there may be a JPG on the clipboard also to support software that can’t accept the TIFF, but presumably using the JPG might be introducing compression artifacts that aren’t in the TIFF.

I took a screenshot, pasted it into Photoshop, ran my script:
set the clipboard to (the clipboard as JPEG picture)
and pasted into Photoshop again. I confirmed that the second paste has compression artifacts while the first does not. So the script really is changing the image data on the clipboard to a JPG and you get different image data on paste. It’s just that Mail, which can use JPG’s, ignores the clipboard order and always grabs a TIFF copy if present.

The script line:
set the clipboard to (the clipboard as JPEG picture)
while it does convert the actual image data on the clipboard to a JPG and change the order so JPG is the first copy on the clipboard, it still writes out other formats to the clipboard, and Mail always grabs the TIFF. Now with compression artifacts.

So now I’m wondering if there’s a way to force the clipboard to not have the other copies… even saving the image as a JPG and using:
set the clipboard to (read “[whatever]” as JPEG picture)
it still helpful puts copies of the image on the clipboard as TIFF, GIF, Bitmap, etc.

I’m guessing the only way I can get this to work is to forget about pasting it into Mail… script saving the clipboard as a JPG and then adding that JPG file to the mail message.

Sure.

That’s a different operation, though. When you drag-and-drop, what gets passed is an NSURL of the file, which Mail then reads; no image goes on to the clipboard.

Right, they may. But it’s not anything you have control over.

Applications haven’t been putting jpegs on the clipboard for a long time. Don’t take too much notice of clipboard info – it’s using very old Carbon APIs, where the old clipboard would synthesize those formats. No modern app works that way. The image formats supported today are tif, png, and pdf (and rtfd, which can contain jpegs).

Copy an image and run this:

use framework "Foundation"
use framework "AppKit"
use scripting additions

set thePasteboard to current application's NSPasteboard's generalPasteboard()
set theTypes to thePasteboard's |types|() as list

In fact the types are doubled up here, once using the newer UTI format, and a second time using older string types. (Depending where you copy from, you may also see proprietary formats which apps use for their own needs.)

It’s really just indicative of AppleScript using ancient APIs.

What you’re seeing is artefacts of the old Carbon APIs. It doesn’t happen with real apps.

Today’s apps either get a list of types and pick the best, or pass a list of types they want in preference order (calling availableTypeFromArray:), and the clipboard returns the first it finds. Whichever Mail does, you can’t change it.

Sort of. You can make a file, then put the URL for it on the clipboard, ready for pasting:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

set thePasteboard to current application's NSPasteboard's generalPasteboard()
-- make bitmap rep of existing clipboard image
set imageRep to current application's NSBitmapImageRep's imageRepWithPasteboard:thePasteboard
-- extract jpeg data
set theData to imageRep's representationUsingType:(current application's NSJPEGFileType) |properties|:{NSImageCompressionFactor:0.7}
-- write to temp file
set thePath to POSIX path of (path to temporary items) & "Temp.jpg"
theData's writeToFile:thePath atomically:true
-- put the URL on the clipboard, ready for pasting into Mail
set theURL to current application's NSURL's fileURLWithPath:thePath
thePasteboard's clearContents()
thePasteboard's writeObjects:{theURL}

Of course, you can achieve that the cow flew. Enough to put it in the basket of the balloon. But why? Make a temporary copy of the PNG image as a JPG image and insert it into the message in the usual way:


set theBody to "We are having a birthday party for everyone on January 1, 2013 at The Factory!
 Hope you can come" & return & return

tell application "Mail"
	set new_message to make new outgoing message with properties {subject:"Flying cow", content:theBody, visible:true}
	tell new_message to make new to recipient at end with properties {address:"kniazidis.rompert@gmail.com"}
	tell content of new_message
		make new attachment with properties {file name:"/Users/123/Desktop/Screenshots/AQDS0_Fotor.jpg"} at after last paragraph
	end tell
end tell

Note: “Mail” perfectly sends PNG files too, in the same way. So you can send without converting to another format.

Shane,

Thanks a million, your last script does exactly what I want to do. I take a screenshot, run your script, and when I hit paste in Mail, the image shows up inline as a JPG. I don’t understand all the ASObjC wizardry you’re using to accomplish it, but it functions perfectly to override Mail’s default craving for TIFF’s.

KniazidisR,

Thanks for the help. I’m often going back and forth screenshotting things and pasting them interspersed with email text in the same message, so I don’t want a script to make a new message every time. I think I could script it to add the image to the current front message, then drag it where I want in the text, but Shane’s script is working perfectly for me.

Also, I know Mail deals perfectly well with inserting PNG’s into the text. The issue is that, with some Windows email clients, any PNG, even inserted inline with the text of the email, shows on their end as a file attached with the message. This is super annoying for inline images. JPG’s don’t do this, they still show inline.

  • Tom.

Most of it is just creating a jpeg file from the image on the clipboard; you might want to change the compression value.

FWIW, understanding the details of how the pasteboard works took me a long time, for various reasons, but largely because I had spent a lot of time playing with it in AppleScript. It only became clearer when the penny dropped, and I realized that AS looks at it through a pre-OS X time-warp, and is thus quite misleading.

Is the choice to use NSPNGFileType intentional or a mistake ? If it’s intentional, what’s the reason for choosing it over NSJPEGFileType ?

Whoops – yes it’s a mistake. Thanks! I’ll go fix it…

I noticed that, but what I ended up with in Mail was still a JPG, so I assumed it was intentional. I’ll update my saved copy. Thanks.