Extracting Images from iTunes .itc or .itc2 files

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&lt;byte[]&gt; 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&lt;byte[]&gt; extract(File f) {
		Collection&lt;byte[]&gt; streams = new ArrayList&lt;byte[]&gt;();

		int remaining = (int) f.length();
		System.out.println(remaining);
		try {
			InputStream in = new FileInputStream(f);

			Input di = new InputImpl(in);
			while (remaining &gt; 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.