FileDocCategorySizeDatePackage
ImageFormats.javaAPI DocJaudiotagger 2.0.48639Wed Mar 30 16:12:04 BST 2011org.jaudiotagger.tag.id3.valuepair

ImageFormats.java

/**
 *  @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.
 *
 *
 * 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
     *
     * 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
     *
     * 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
     *
     * 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;
        }
    }
}