All credit goes to Joe Walton for his rather handy Tools for iTunes Libraries (titl) Project – http://code.google.com/p/titl/
In the last post I looked at how you can find iTunes artwork for a track from the library persistent ID and the track’s persistent ID. But that isn’t much use unless you can actually get the artwork from the *.itc or *.itc2 file. Below is a java method that I wrote, using code from the above project, which takes an artwork file and returns a BufferedImage which can then be saved to the hard drive, or stored into the ID3 tag of a track however you like.
You will need the rest of the itil library to use this code.
import org.kafsemo.titl.Input; import org.kafsemo.titl.InputImpl; import org.kafsemo.titl.Util; /** * A class to extract image data from an .itc2 file. Minimal implementation * using notes from <a href="http://www.falsecognate.org/2007/01/deciphering_the_itunes_itc_fil/">this article</a>. * * @author Joseph Modified by Alun King to simply return the first image. * Original code can be found at http://code.google.com/p/titl/ */ public class ExtractArt { public static BufferedImage extractArt(File f) { Collection<byte[]> streams = extract(f); /* * This method actually can return more than one image if there are * multiple images stored in the itc file. So this code will only return * the first, but you can loop through and get them all. */ byte[] image = streams.iterator().next(); BufferedImage trackArtwork = null; try { ImageIO.read(new ByteArrayInputStream(image)); } catch (IOException e) { System.err.println("Image not read correctly."); } return trackArtwork; } private static Collection<byte[]> extract(File f) { Collection<byte[]> streams = new ArrayList<byte[]>(); int remaining = (int) f.length(); System.out.println(remaining); try { InputStream in = new FileInputStream(f); Input di = new InputImpl(in); while (remaining > 0) { int bl = di.readInt(); String type = Util.toString(di.readInt()); if (type.equals("item")) { int ltd = di.readInt(); di.skipBytes(ltd - 12); byte[] ba = new byte[bl - ltd]; di.readFully(ba); streams.add(ba); } else { di.skipBytes(bl - 8); } remaining -= bl; } in.close(); } catch (Exception e) { e.printStackTrace(); } return streams; } }
I hope that is useful! I’ll try and get the whole XML parser working soon and then I will be able to automate the artwork being embedded into the music file.