FileDocCategorySizeDatePackage
AsfTagCoverField.javaAPI DocJaudiotagger 2.0.47514Wed Mar 30 16:12:10 BST 2011org.jaudiotagger.tag.asf

AsfTagCoverField.java

package org.jaudiotagger.tag.asf;

import org.jaudiotagger.audio.asf.data.AsfHeader;
import org.jaudiotagger.audio.asf.data.MetadataDescriptor;
import org.jaudiotagger.logging.ErrorMessage;
import org.jaudiotagger.tag.id3.valuepair.ImageFormats;
import org.jaudiotagger.tag.asf.AbstractAsfTagImageField;
import org.jaudiotagger.tag.asf.AsfFieldKey;

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.util.logging.Logger;

/**
 * Encapsulates the WM/Pictures provides some convenience methods for decoding
 * the binary data it contains
 * <p/>
 * The value of a WM/Pictures metadata descriptor is as follows:
 * <p/>
 * byte0 Picture Type byte1-4 Length of the image data mime type encoded as
 * UTF-16LE null byte null byte description encoded as UTF-16LE (optional) null
 * byte null byte image data
 */
public class AsfTagCoverField extends AbstractAsfTagImageField
{
    /**
     * Logger Object
     */
    public final static Logger LOGGER = Logger
            .getLogger("org.jaudiotagger.audio.asf.tag");

    /**
     * Description
     */
    private String description;

    /**
     * We need this to retrieve the buffered image, if required
     */
    private int endOfName = 0;

    /**
     * Image Data Size as read
     */
    private int imageDataSize;

    /**
     * Mimetype of binary
     */
    private String mimeType;

    /**
     * Picture Type
     */
    private int pictureType;

    /**
     * Create New Image Field
     * 
     * @param imageData
     * @param pictureType
     * @param description
     * @param mimeType
     */
    public AsfTagCoverField(final byte[] imageData, final int pictureType,
            final String description, final String mimeType) {
        super(new MetadataDescriptor(AsfFieldKey.COVER_ART.getFieldName(),
                MetadataDescriptor.TYPE_BINARY));
        this.getDescriptor()
                .setBinaryValue(
                        createRawContent(imageData, pictureType, description,
                                mimeType));
    }

    /**
     * Creates an instance from a metadata descriptor
     * 
     * @param source
     *            The metadata descriptor, whose content is published.<br>
     */
    public AsfTagCoverField(final MetadataDescriptor source) {
        super(source);

        if (!source.getName().equals(AsfFieldKey.COVER_ART.getFieldName())) {
            throw new IllegalArgumentException(
                    "Descriptor description must be WM/Picture");
        }
        if (source.getType() != MetadataDescriptor.TYPE_BINARY) {
            throw new IllegalArgumentException("Descriptor type must be binary");
        }

        try {
            processRawContent();
        } catch (final UnsupportedEncodingException uee) {
            // Should never happen
            throw new RuntimeException(uee); // NOPMD by Christian Laireiter on 5/9/09 5:45 PM
        }
    }

    private byte[] createRawContent(final byte[] data, final int pictureType,
            final String description, String mimeType) { // NOPMD by Christian Laireiter on 5/9/09 5:46 PM
        this.description = description;

        // Get Mimetype from data if not already setField
        if (mimeType == null) {
            mimeType = ImageFormats.getMimeTypeForBinarySignature(data);
            // Couldnt identify lets default to png because probably error in
            // code because not 100% sure how to identify
            // formats
            if (mimeType == null) {
                LOGGER.warning(ErrorMessage.GENERAL_UNIDENITIFED_IMAGE_FORMAT
                        .getMsg());
                mimeType = ImageFormats.MIME_TYPE_PNG;
            }
        }

        final ByteArrayOutputStream baos = new ByteArrayOutputStream();

        // PictureType
        baos.write(pictureType);

        // ImageDataSize
        baos.write(org.jaudiotagger.audio.generic.Utils
                .getSizeLEInt32(data.length), 0, 4);

        // mimetype
        byte[] mimeTypeData;
        try {
            mimeTypeData = mimeType.getBytes(AsfHeader.ASF_CHARSET.name());
        } catch (final UnsupportedEncodingException uee) {
            // Should never happen
            throw new RuntimeException("Unable to find encoding:" // NOPMD by Christian Laireiter on 5/9/09 5:45 PM
                    + AsfHeader.ASF_CHARSET.name());
        }
        baos.write(mimeTypeData, 0, mimeTypeData.length);

        // Seperator
        baos.write(0x00);
        baos.write(0x00);

        // description
        if (description != null && description.length() > 0) {
            byte[] descriptionData;
            try {
                descriptionData = description.getBytes(AsfHeader.ASF_CHARSET
                        .name());
            } catch (final UnsupportedEncodingException uee) {
                // Should never happen
                throw new RuntimeException("Unable to find encoding:" // NOPMD by Christian Laireiter on 5/9/09 5:45 PM
                        + AsfHeader.ASF_CHARSET.name());
            }
            baos.write(descriptionData, 0, descriptionData.length);
        }

        // Seperator (always write whther or not we have descriptor field)
        baos.write(0x00);
        baos.write(0x00);

        // Image data
        baos.write(data, 0, data.length);

        return baos.toByteArray();
    }

    public String getDescription() {
        return this.description;
    }

    @Override
    public int getImageDataSize() {
        return this.imageDataSize;
    }

    public String getMimeType() {
        return this.mimeType;
    }

    public int getPictureType() {
        return this.pictureType;
    }

    /**
     * @return the raw image data only
     */
    @Override
    public byte[] getRawImageData() {
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        baos.write(getRawContent(), this.endOfName, this.toWrap
                .getRawDataSize()
                - this.endOfName);
        return baos.toByteArray();
    }

    private void processRawContent() throws UnsupportedEncodingException {
        // PictureType
        this.pictureType = this.getRawContent()[0];

        // ImageDataSize
        this.imageDataSize = org.jaudiotagger.audio.generic.Utils.getIntLE(this
                .getRawContent(), 1, 2);

        // Set Count to after picture type,datasize and two byte nulls
        int count = 5;
        this.mimeType = null;
        this.description = null; // Optional
        int endOfMimeType = 0;

        while (count < this.getRawContent().length - 1) {
            if (getRawContent()[count] == 0 && getRawContent()[count + 1] == 0) {
                if (this.mimeType == null) {
                    this.mimeType = new String(getRawContent(), 5, (count) - 5,
                            "UTF-16LE");
                    endOfMimeType = count + 2;
                } else if (this.description == null) {
                    this.description = new String(getRawContent(),
                            endOfMimeType, count - endOfMimeType, "UTF-16LE");
                    this.endOfName = count + 2;
                    break;
                }
            }
            count += 2; // keep on two byte word boundary
        }
    }

}