/** * @author : Paul Taylor * * Version @version:$Id: ImageFormats.java 924 2010-10-18 09:52:40Z paultaylor $ * * MusicTag Copyright (C)2003,2004 * * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along with this library; if not, * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Description: * This class maps from v2.2 Image formats (PIC) to v2.3/v2.4 Mimetypes (APIC) and * vice versa. */ package org.jaudiotagger.tag.id3.valuepair; import java.util.HashMap; import java.util.Map; /** * Represents common image formats support by ID3 and provides a mapping between the format field supported in ID3v22 and the * mimetype field supported by ID3v23/ID3v24. * <p/> * <p/> * Note only JPG and PNG are mentioned specifically in the ID3 v22 Spec but it only says 'Image Format is preferably * PNG or JPG' , not mandatory. In the jaudiotagger library we also consider GIF as a portable format, and we recognise * BMP,PDF and TIFF but do not consider these formats as portable. */ //TODO identifying PICT, bit more difficult because in certain formats has an empty 512byte header public class ImageFormats { public static final String V22_JPG_FORMAT = "JPG"; public static final String V22_PNG_FORMAT = "PNG"; public static final String V22_GIF_FORMAT = "GIF"; public static final String V22_BMP_FORMAT = "BMP"; public static final String V22_TIF_FORMAT = "TIF"; public static final String V22_PDF_FORMAT = "PDF"; public static final String V22_PIC_FORMAT = "PIC"; public static final String MIME_TYPE_JPEG = "image/jpeg"; public static final String MIME_TYPE_PNG = "image/png"; public static final String MIME_TYPE_GIF = "image/gif"; public static final String MIME_TYPE_BMP = "image/bmp"; public static final String MIME_TYPE_TIFF = "image/tiff"; public static final String MIME_TYPE_PDF = "image/pdf"; public static final String MIME_TYPE_PICT = "image/x-pict"; /** * Sometimes this is used for jpg instead :or have I made this up */ public static final String MIME_TYPE_JPG = "image/jpg"; private static Map<String, String> imageFormatsToMimeType = new HashMap<String, String>(); private static Map<String, String> imageMimeTypeToFormat = new HashMap<String, String>(); static { imageFormatsToMimeType.put(V22_JPG_FORMAT, MIME_TYPE_JPEG); imageFormatsToMimeType.put(V22_PNG_FORMAT, MIME_TYPE_PNG); imageFormatsToMimeType.put(V22_GIF_FORMAT, MIME_TYPE_GIF); imageFormatsToMimeType.put(V22_BMP_FORMAT, MIME_TYPE_BMP); imageFormatsToMimeType.put(V22_TIF_FORMAT, MIME_TYPE_TIFF); imageFormatsToMimeType.put(V22_PDF_FORMAT, MIME_TYPE_PDF); imageFormatsToMimeType.put(V22_PIC_FORMAT, MIME_TYPE_PICT); String value; for (String key : imageFormatsToMimeType.keySet()) { value = imageFormatsToMimeType.get(key); imageMimeTypeToFormat.put(value, key); } //The mapping isn't one-one lets add other mimetypes imageMimeTypeToFormat.put(MIME_TYPE_JPG, V22_JPG_FORMAT); } /** * Get v2.3 mimetype from v2.2 format * * @param format * @return */ public static String getMimeTypeForFormat(String format) { return imageFormatsToMimeType.get(format); } /** * Get v2.2 format from v2.3 mimetype * * @param mimeType * @return */ public static String getFormatForMimeType(String mimeType) { return imageMimeTypeToFormat.get(mimeType); } /** * Is this binary data a png image * * @param data * @return true if binary data matches expected header for a png */ public static boolean binaryDataIsPngFormat(byte[] data) { //Read signature if (data.length < 4) { return false; } return (0x89 == (data[0] & 0xff)) && (0x50 == (data[1] & 0xff)) && (0x4E == (data[2] & 0xff)) && (0x47 == (data[3] & 0xff)); } /** * Is this binary data a jpg image * * @param data * @return true if binary data matches expected header for a jpg * <p/> * Some details http://www.obrador.com/essentialjpeg/headerinfo.htm */ public static boolean binaryDataIsJpgFormat(byte[] data) { if (data.length < 4) { return false; } //Read signature //Can be FF D8 FF E0 or FF D8 FF E1 //FF D8 is SOI Marker, FFE0 or FFE1 is JFIF Marker return (0xff == (data[0] & 0xff)) && (0xd8 == (data[1] & 0xff)) && (0xff == (data[2] & 0xff)) && (0xe0 <= (data[3] & 0xff)); } /** * Is this binary data a gif image * * @param data * @return true if binary data matches expected header for a gif */ public static boolean binaryDataIsGifFormat(byte[] data) { if (data.length < 3) { return false; } //Read signature return (0x47 == (data[0] & 0xff)) && (0x49 == (data[1] & 0xff)) && (0x46 == (data[2] & 0xff)); } /** * Is this binary data a bmp image * * @param data * @return true if binary data matches expected header for a bmp */ public static boolean binaryDataIsBmpFormat(byte[] data) { //Read signature return (0x42 == (data[0] & 0xff)) && (0x4d == (data[1] & 0xff)); } /** * Is this binary data a pdf image * <p/> * Details at http://en.wikipedia.org/wiki/Magic_number_%28programming%29 * * @param data * @return true if binary data matches expected header for a pdf */ public static boolean binaryDataIsPdfFormat(byte[] data) { //Read signature return (0x25 == (data[0] & 0xff)) && (0x50 == (data[1] & 0xff)) && (0x44 == (data[2] & 0xff)) && (0x46 == (data[3] & 0xff)); } /** * is this binary data a tiff image * <p/> * Details at http://en.wikipedia.org/wiki/Magic_number_%28programming%29 * * @param data * @return true if binary data matches expected header for a tiff */ public static boolean binaryDataIsTiffFormat(byte[] data) { //Read signature Intel return ( ((0x49 == (data[0] & 0xff)) && (0x49 == (data[1] & 0xff)) && (0x2a == (data[2] & 0xff)) && (0x00 == (data[3] & 0xff))) || ((0x4d == (data[0] & 0xff)) && (0x4d == (data[1] & 0xff)) && (0x00 == (data[2] & 0xff)) && (0x2a == (data[3] & 0xff))) ); } /** * @param data * @return true if the image format is a portable format recognised across operating systems */ public static boolean isPortableFormat(byte[] data) { return binaryDataIsPngFormat(data) || binaryDataIsJpgFormat(data) || binaryDataIsGifFormat(data); } /** * @param data * @return correct mimetype for the image data represented by this byte data */ public static String getMimeTypeForBinarySignature(byte[] data) { if (binaryDataIsPngFormat(data)) { return MIME_TYPE_PNG; } else if (binaryDataIsJpgFormat(data)) { return MIME_TYPE_JPEG; } else if (binaryDataIsGifFormat(data)) { return MIME_TYPE_GIF; } else if (binaryDataIsBmpFormat(data)) { return MIME_TYPE_BMP; } else if (binaryDataIsPdfFormat(data)) { return MIME_TYPE_PDF; } else if (binaryDataIsTiffFormat(data)) { return MIME_TYPE_TIFF; } else { return null; } } }