Does anyone know how I would do this, using AppleScript? I’ve been racking my brain for ideas, but have come up with nothing.
Thanks,
Spidy
Does anyone know how I would do this, using AppleScript? I’ve been racking my brain for ideas, but have come up with nothing.
Thanks,
Spidy
going down the iTunes route, you can look how its done here:
http://sourceforge.net/cvs/?group_id=109614
just do a cvs checkout, and then open the .scpt files with Script Editor. It does seem… limited to 1 picture though. It might be that no one has just stumbled upon how to do muliple pix… I don’t go down that route.
You can do everything outside of iTunes as well - or nearly everything. For m4a files, its still a bit of a harangue. Its a lot easier for mp3 files.
To get at mp3 artwork, there are a number of tools (perl, python, php, c++). The first I figured out was PyID3 in python. You can also use eyeD3 but you’ll have to overcome its overly zealous adherence to strictness. With id3lib, you’re left pretty much on your own as there is no stock solution (but it is by far the fastest).
You can also have a look at the source on this page:
http://members.verizon.net/pucklock/id3Infiltr8/IDInfiltr8.htm
But keep in mind its in a state of flux (and some… bits of errata I have already fixed). It contains a crude pic extraction script for PyID3 called “getapic2.py”. Crude in that it extracts all pix as “.png” files - but I haven’t revisited it yet.
Hi,
Here’s an example of writing the picture data to file. I chose the first track in iTunes library play list because that one is purchased from Apple and has artwork.
tell application “iTunes”
set lib_pl to first library playlist
set the_track to first track of lib_pl
set the_art to first artwork of the_track
set the_data to data of the_art
end tell
set desk_path to (path to desktop) as string
set file_spec to (desk_path & “Artwork.pict”) as file specification
set ref_num to (open for access file_spec with write permission)
try
set eof ref_num to 512
write the_data to ref_num starting at 513
close access ref_num
on error err_mess
close access ref_num
display dialog err_mess
end try
You can try this. Create a blank plain text file in something like TextEdit and save it. Change the extension to .pict and write to that file instead of a file specification as in the script above. When you write to a file specification using the read/write standard additions commands, it adds a file type “TEXT”. By using TextEdit there is no file type. You might try adding the blank TextEdit file to your app’s AS Studio resources. You can then write to that file and load image into the image view.
gl,
with kel’s script I got:
iTunes got an error: Out of memory.
but I guess if it works, it works.
Hi anaxamander,
Does your first track of your library playlist have artwork?
Later,
Ah, yes that does give me a clue (I have so few of these clues). I should actually read the script on occasion as well - I’m told its illuminating. Still, its a retarded error for not having artwork.
In any event, I just used instead:
set the_track to the current track
and sure enough I was able to get pic1 & pic2 (only 2 pics in my test mp3). Not as slow as I imagined - but then every picture came in a pict wrapper too. Faster than the python solutions as well (though these don’t require fseeking out of the pict wrapper).
Thanks for that.
Hi anaxamander,
What do you mean by fseeking out of the pict wrapper? Maybe there’s a better way to do this. Are you saying that you can strip the pict wrapper and write the data to a file as maybe its original type (maybe jpeg or tiff). I don’t know much about how pictures are stored and maybe you can strip the wrapper with AppleScript’s read/write commands and write just the necessary data to a file. That’s why I took so long replying to this post. I’m thinking that there might be a better way.
Later,
Yeah, pretty much.
I took the output from your applescript (the Artwork.pict file) and looked at in a hex editor. I know what the original unaltered jpeg looks like (in hex) because I can extract it as a jpeg with any number of tools - I can even see the original jpeg hex data as the embedded APIC id3 tag in the source mp3.
jpegs start with “\x89\x50\x4E\x47\x0D\x0A\x1A\x0A” - where \x just represents hex data
pngs start with “\xFF\xD8\xFF\xE0”
gifs start with “GIF87a” or “GIF89a” - iTunes refuses to even see gifs in APICs
I only gave a cursory look, but it seems that the ‘extract as .pict method’ prepends… ah, it was like 732bytes or something like that, and appends 260 or however many bytes at the end. The original unaltered jpeg is embedded within that pict wrapper - at least for the 1 (and only) pict/jpeg I evaluated.
What I mean by fseeking out (->man fseek) is to write a small c program that would fseek to byte offset 732 or whatever, and fread/getc or whatever to the ending offset (the ~260 bytes), and write that out as… oh, store that file in a buffer, test its header and append the appropriate suffix to the basefilename.
Essentially, your way is the same in applescript that this fseek c/c++ way is. Not that I know for certain, but I imagine any other way would somehow convert the image if even slightly (say using image events or some 3rd party cli program).
Hi anaxamander,
When you wrote that the data was in a wrapper, I thought that there was a certain byte where you could read from that would eliminate the pict part of the data.
kel,
Yes, offset from the start of 734 bytes ending at (eof-132) - that is the payload data. I just checked those numbers.
See… I blame you - it’s all your fault. I said to myself, “Self, don’t write it, you aren’t even going down this path.” Self, being wholly retarded, wrote the c++ program to do it:
[code]// $Id: dPict.cpp,v 0.5 2005/09/03 10:01:05 anaxamander Exp $
//Not fit for any specific purpose.
//Licensed to you under a Creative Commons Non-Commercial ShareAlike license
//
//http://creativecommons.org/licenses/by-nc-sa/2.5/
//
//Grub for money from yo mommy!
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
int main( int argc, char *argv[])
{
char *progName = argv[0];
char *qtPict = argv[1];
char *basename = argv[2];
char *outgoingArtworkPath = (char *)malloc(sizeof(char)*240);
char *suffix = (char *)malloc(sizeof(char)*5);
u_int8_t *artData = NULL;
u_int64_t artSize = 0;
assert(qtPict!=NULL);
FILE *artFile = fopen(qtPict, "rb");
if(artFile) {
u_int64_t r;
fseek(artFile, 0, SEEK_END);
artSize = (ftell(artFile) - (734 + 133));
artData = (uint8_t *)malloc(artSize);
fseek(artFile, 734, SEEK_SET);
clearerr(artFile);
r = fread(artData, artSize, 1, artFile);
if (r != 1) {
free(artData);
artData = NULL;
}
}
fclose(artFile);
if (artData != NULL) {
//Tests the header (of artData, the indeterminate picture) to get a file extension
if (strncmp((char *)artData, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8) == 0)
suffix = ".png";
else if (strncmp((char *)artData, "\xFF\xD8\xFF\xE0", 4) == 0)
suffix = ".jpg";
else if (strncmp((char *)artData, "GIF87a", 6) || strncmp((char *)artData, "GIF89a", 6) == 0)
suffix = ".gif";
//copy the 2nd argument, basename into a more... flexible variable, and then append the file extension
strcpy(outgoingArtworkPath,basename);
strcat(outgoingArtworkPath, suffix);
FILE *outfile = fopen(outgoingArtworkPath, "wb");
if (outfile != NULL) {
fwrite(artData, artSize, 1, outfile);
fclose(outfile);
}
printf("Wrote out %s\n", outgoingArtworkPath);
}
return 0;
}[/code]
The make script is:
[code]#!/bin/sh
g++ -g -O2 -Wall -Wno-unused -Wno-inline -Wno-non-virtual-dtor -MT id3Gateway.o -MD -MP -MF “./dPict.Tpo” -c -o dPict.o dPict.cpp
g++ -g -O2 -Wall -Wno-unused -Wno-inline -Wno-non-virtual-dtor -Woverloaded-virtual -Wmissing-declarations -o dPict dPict.o
strip -x dPict[/code]
and you “dPict /Users/aUser/Desktop/Artwork\ copy.pict /Users/aUser/Desktop/out” to get a picture.ext
I go now to teach Self a lesson.
Edited for extraneous crud in the makefile (THAT was Self’s fault, I’m onto blaming him now).
Hi,
My computer finally went down and I had to reinstall. Lost all my files including purchased music because the disc burner is broken and couldn’t backup.
Anyway, I downloaded hexedit, because I can’t read from what backup I had. I compared a jpeg and a Preview exported pict and the data doesn’t look the same from the 734th byte. Maybe I’m not getting what your saying, but if you want to read from the pict, you could do this in AppleScript:
set f to choose file
set d to (read f from 734 to -132)
gl,
I hope you manage to retrieve the important stuff.
You can add artwork to file by doing get info on it in iTunes and in the artwork tab just drag-n-drop a jpeg/png there. In iTunes you can also choose “Show Artwork” (Command - g) from the Edit menu. An artwork area will appear below your playlist section.
What do you mean “from a Preview exported pict”? I’m working off the Artwork.pict file left behind from the iTunes applescript you posted originally. If you used Preview to “Save As” the jpeg to pict your file size would balloon - and didn’t have a pict wrapper around a jpeg picture. In fact, in my single test, file size ballooned by 800% using Preview.
I already had all of that code in my project so I just copied and changed variable names, I relented to the ancient inexorable human force: laziness. So when I posted “I wrote” I really mean to say “I copied and pasted”. Personally, I’m moving away from Applescript more and more.
I tested on:
15 mp3s with APIC jpegs (varying from artwork 1 to artwork 5), including progressive jpegs
2 mp3 with APIC pngs (these work, but with data loss, solution below)
2 m4a (1 jpeg covr atom, 1 png covr atom) - png had same problem
All pictures (png & jpeg) I have embedded emerge with the 734-byte offset in the .pict file. png files (which I didn’t originally test on) had some data loss at the end. This is due to the pict wrapper footer, which is shorter than a jpeg footer (125 bytes in a png), so I was actually removing pertinent png data.
To amend the behavior, fseek to SEEK_END and then based on the picture header subtract the footer size from artSize. In pseudo applescript:
¢ read in some file.
¢ strip off xxx-bytes (possibly 734) from the .pict leaving “The Payload”
¢ test the first few bytes of “The Payload”
¢ based on the type of art, write out the length of “The Payload” minus payload-specific footer value to strip off the original pict wrapper footer. I think its jpeg=133, png around 125 (I didn’t test - just noted there was a missing amount of data).
¢ write out data to some file.
BTW, what start offset of picture data do you get? The “FF D8 FF E0 00 10 4A 46 49 46” jpeg picture header will be there somewhere - its part of the jpeg spec. The pict wrapper header seems to end with “18 FF FF”. If the jpeg header isn’t there, then Preview converted the starting jpeg into a full blown pict (no wrapper).