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.

iTunes Artwork Folder Structure

With the weather and dark nights forcing me out of the garden, I have recently turned my attention to sorting out my media library, working towards a music streaming solution throughout the house. This starts with getting my iTunes library in order.

One of the problems for me with iTunes is the way it stores artwork. All the tracks are stored in their folders, but iTunes will use a sneaky way of hiding the artwork into an *.itc file which is then hidden away in a confusing folder structure, thus stopping other programs from accessing it.

After finding this post decyphering the location of the artwork file, I wrote a Java function to take a track’s persistent ID and return the location of the artwork, if it existed. Here is the code.

public static File getArtwork(String libId, String trackId) {
		File artwork = null;

		// Get the last three characters from the tracks ID and turn them into
		// decimals, with a leading zero if needed.
		String folderOne = hexToDec(trackId.charAt(trackId.length() - 1));
		String folderTwo = hexToDec(trackId.charAt(trackId.length() - 2));
		String folderThree = hexToDec(trackId.charAt(trackId.length() - 3));

		// artwork can be stored in itc or itc2 files, so we should check if the
		// itc exists, and if not, try the itc2.
		artwork = new File("Album Artwork/Download/" + libId + "/" + folderOne
				+ "/" + folderTwo + "/" + folderThree + "/" + libId + "-"
				+ trackId + ".itc");
		/*
		 * Note: the Downloads folder is the best place to look. If the artwork
		 * is in the Cache folder, then I think that means the track already had
		 * artwork embedded in the MP3 so it wasn't downloaded, just cached for
		 * faster access by iTunes.
		 */
		return artwork;
	}

	private static String hexToDec(char hexValue) {
		switch (hexValue) {
		case '0':
			return "00";
		case '1':
			return "01";
		case '2':
			return "02";
		case '3':
			return "03";
		case '4':
			return "04";
		case '5':
			return "05";
		case '6':
			return "06";
		case '7':
			return "07";
		case '8':
			return "08";
		case '9':
			return "09";
		case 'A':
			return "10";
		case 'B':
			return "11";
		case 'C':
			return "12";
		case 'D':
			return "13";
		case 'E':
			return "14";
		case 'F':
			return "15";
		default:
			return "";
		}
	}

I am basically using this to parse an XML file, find any artwork which isn’t embedded into the MP3 file and then save it inside, so that all my other media players have access to the image. It will increase the file size a little, but for me that’s negligible. I suppose someone could also use it to store the artwork in an understandable structure (ArtistName/AlbumName) so that it could be retrieved that way, but that can be looked at later.

Merry Christmas

I’ve been quiet for a few months on here, as the nights have closed in and not a lot is going on in the garden. I’ve put a few paving stones down to make the path up to the shed a lot nicer, and laid some decking, so I do need to post but I’ll have to wait for a nice day to get some good photos!

Until then, I hope if you are reading this, you have the heating on, or even better a fire is lit and you are enjoying the warm feeling that being with your friends and family brings around Christmas time. Stay safe and don’t drink too much 😉

I’ll be updating with more posts as Easter approaches!