Kludgy success in setting iTunes artwork from file

First post jitters :wink: Sorry if this has already been solved; I’ve been digging through here for a couple of days and found no solutions…

Like so many others, I want to select a few tracks in iTunes, choose an image file, and have Applescript “paste” the image into each track’s artwork space. Typically the art sources are jpeg files that have been downloaded from web sites like Amazon; i.e. the jpeg files are just raw jpegs (JPEGFFD8FFE0…) with no PICT wrapper, which means that iTunes will reject them. (Reading the files in "as picture"s doesn’t seem to generate a “proper” header…you can get something to stick, but it’s transparent.)

So I went looking for a way to get a proper header (I’m guessing it’s the type of header generated by CGImageCreateWithJPEGDataProvider?), and it seems that QTPlayer provideth – yay!

But now I’d like to know if there’s a simpler/better way to get this done; preferably something that works in RAM without having to generate a file (or even open QTPlayer for that matter).

Here’s the doofus code. Yes, it should be much better, but this is what worked in my testing, so it’s what you get to see :wink:

-- to use, select an artless track in iTunes; when prompted, choose a JPEG file.
-- A new file will be created by QTPlayer "Export...", which will be read into the first artwork of the track

-- clumsy name-maker for the exported file
on prependToLastPathItem(in_path, str_to_prepend)
	set {TID, text item delimiters} to {text item delimiters, ":"}
	set path_list to text items of in_path
	set str to str_to_prepend & last item of path_list
	set str to trimFileName(str, 20)
	set last item of path_list to str
	set out_path to path_list as string
	set text item delimiters to TID
	return out_path
end prependToLastPathItem
on trimFileName(file_name, num_chars_to_keep)
	set {TID, text item delimiters} to {text item delimiters, "."}
	set file_name_list to text items of file_name
	set str to text 1 through num_chars_to_keep of item -2 of file_name_list
	set item -2 of file_name_list to str
	set txt to file_name_list as string
	set text item delimiters to TID
	return txt
end trimFileName

-- get an alias to art source:
set the_file to choose file with prompt "Select a JPEG file:" of type {"public.jpeg"}
-- make a new name for the exported file:
copy the_file as string to the_mod_file
set the_mod_file to prependToLastPathItem(the_mod_file, "MOD")

-- use QTPlayer to give the image an acceptable PICT wrapper:
-- (QTPro not required)
tell application "QuickTime Player"
	open the_file
	export document 1 as picture to the_mod_file
	close document 1 saving no
end tell

-- the exported file has a "canonical" PICT wrapper? i.e. ignore first 512 bytes
set filePtr to open for access the_mod_file
set the_image to read filePtr from 513 as JPEG picture
close access filePtr

tell application "iTunes"
	set the_track to item 1 of selection
	if not (exists artworks of the_track) then
		set data of artwork 1 of the_track to the_image
	end if
end tell

Model: intel iMac
AppleScript: 1.10.7
Browser: Safari 4525.18
Operating System: Mac OS X (10.4)

Hi S2,

If you do not want to open the QuickTime Player every time you run your script, then you can also use Image Events in the background to silently convert JPEG into PICT images:


set imgpath to "/Users/martin/Desktop/old.jpg"
set pictpath to "/Users/martin/Desktop/new.pict"

tell application "Image Events"
	launch
	set img to open imgpath
	save img in pictpath as PICT
	close img
end tell

Martin –

A thousand apologies for not responding to your prompt reply – the real world got ugly, and I completely forgot about making my post. Sorry! And thanks!

Yes, I tried Image Events after realizing that conversion was handled through Save (silly me, I thought it would be called something like Convert ;-). However, the files produced are huge – 10 times larger than QuickTime Player. Same results with sips – original file size X 10.

So I’m sticking with QT Player and just blinking in rhythm with the flashing window :wink:

  • S2

Hi,

try this version with sips, it avoids opening QT Player, but has to create a temporary file (in the temporary items folder).
Considering a good memory management the temp file will be deleted after use


set tempFolder to (path to temporary items as text)

set the_file to choose file with prompt "Select a JPEG file:" of type {"public.jpeg"}
set theName to name of (info for the_file)
set tempFile to (tempFolder & theName & ".pict")
do shell script "/usr/bin/sips -s format pict " & quoted form of POSIX path of the_file & " --out " & quoted form of POSIX path of tempFile
set filePtr to open for access file tempFile
set the_image to read filePtr from 513 as picture
close access filePtr
do shell script "/bin/rm " & quoted form of POSIX path of tempFile

tell application "iTunes"
	set the_track to item 1 of selection
	if not (exists artworks of the_track) then
		set data of artwork 1 of the_track to the_image
	end if
end tell

Thanks for the reply, Stefan. The issue here is not that the generated file hangs around, but that the image produced by sips (or image events, for that matter) is so huge. Ultimately, the script I’m working on will be a helper for folks migrating a Windows-type music collection into iTunes – where “Windows-type” means a collection of folders containing mp3 files and a “FolderImage.jpg” (or whatever it’s called) image file. Windows automatically associates the “FolderImage.jpg” with the mp3 files inside the folder; nice enough until the file gets moved, at which point it has no more art. My goal is to embed that one image into each of the folder’s files, allowing the mp3 files to be moved around without losing their art. (And actually, I want to hang onto the converted file, since it can easily be re-used for adding art to other tracks down the road.)

P’bly just because I’m old (reared in the days of loading programs from cassette tapes ;-), I want the converted images to be as small as possible. Say the user drops 100 tracks onto the droplet – using QT Player and 25K original images, the script is only adding 2.5MB to the user’s drive. Using sips, that same scenario plays out to adding 25MB to the user’s drive – 10X more space consumed for no benefit.

So, I’m happy to use QT Player and hope the flashes don’t induce seizures :wink: Sadly, what’s holding this up is my inability to get iTunes to idenitfy a track by its path. No matter what variations and coercions I try, I can’t get iTunes to

set target_track to some track of playlist "Music" whose location is target_track_path

despite casting target_track_path as an alias, a file, a posix path, etc. Frustrating! Works for every other prop of a track object – as in, ‘set target_track to some track of playlist “Music” whose name is “Yesterday”’ or ‘set target_track to some track of playlist “Music” whose genre is “Reaggae”’ – but I can’t find a way to make iTunes get a track object based on its path…

(And yes, I could use perl to parse the iTunes .xml file and create a hash of track paths and IDs, and then direct iTunes to use the IDs, but it’s really under my skin to find a way to get iTunes to recognize a track by its location property :wink:

Thanks again!

But you could easily parse the iTunes XML file and quickly create a list/dictionary containing key-value pairs of track paths and IDs. This way you could query this list for matching track paths and get the corresponding IDs in return to identify the searched tracks in iTunes.

Just an idea :slight_smile: