All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.jaiimageio.impl.plugins.pnm.PNMMetadata Maven / Gradle / Ivy

Go to download

Java Advanced Imaging Image I/O Tools API core, but without the classes involved with javax.media.jai dependencies, JPEG2000 or codecLibJIIO, meaning that this library can be distributed under the modified BSD license and should be GPL compatible.

The newest version!
/*
 * $RCSfile: PNMMetadata.java,v $
 *
 * 
 * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met: 
 * 
 * - Redistribution of source code must retain the above copyright 
 *   notice, this  list of conditions and the following disclaimer.
 * 
 * - Redistribution in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in 
 *   the documentation and/or other materials provided with the
 *   distribution.
 * 
 * Neither the name of Sun Microsystems, Inc. or the names of 
 * contributors may be used to endorse or promote products derived 
 * from this software without specific prior written permission.
 * 
 * This software is provided "AS IS," without a warranty of any 
 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
 * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
 * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
 * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
 * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
 * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
 * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
 * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES. 
 * 
 * You acknowledge that this software is not designed or intended for 
 * use in the design, construction, operation or maintenance of any 
 * nuclear facility. 
 *
 * $Revision: 1.1 $
 * $Date: 2005/02/11 05:01:41 $
 * $State: Exp $
 */
package com.github.jaiimageio.impl.plugins.pnm;

import java.awt.image.SampleModel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriteParam;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import javax.imageio.metadata.IIOMetadataNode;

import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.github.jaiimageio.impl.common.ImageUtil;
import com.github.jaiimageio.plugins.pnm.PNMImageWriteParam;
/**
 * Metadata for the PNM plug-in.
 */
public class PNMMetadata extends IIOMetadata implements Cloneable {
    static final String nativeMetadataFormatName =
        "com_sun_media_imageio_plugins_pnm_image_1.0";

    /** The max value for the encoded/decoded image. */
    private int maxSample;

    /** The image width. */
    private int width;

    /** The image height. */
    private int height;

    /** The image variants. */
    private int variant;

    /** The comments. */
    private ArrayList comments;

    /** Maximum number of bits per sample (not in metadata). */
    private int maxSampleSize;

    /**
     * Constructor containing code shared by other constructors.
     */
    PNMMetadata() {
        super(true,  // Supports standard format
              nativeMetadataFormatName,  // and a native format
              "com.github.jaiimageio.impl.plugins.pnm.PNMMetadataFormat",
              null, null);  // No other formats
    }

    public PNMMetadata(IIOMetadata metadata) throws IIOInvalidTreeException {

        this();

        if(metadata != null) {
            List formats = Arrays.asList(metadata.getMetadataFormatNames());

            if(formats.contains(nativeMetadataFormatName)) {
                // Initialize from native image metadata format.
                setFromTree(nativeMetadataFormatName,
                            metadata.getAsTree(nativeMetadataFormatName));
            } else if(metadata.isStandardMetadataFormatSupported()) {
                // Initialize from standard metadata form of the input tree.
                String format =
                    IIOMetadataFormatImpl.standardMetadataFormatName;
                setFromTree(format, metadata.getAsTree(format));
            }
        }
    }

    /**
     * Constructs a default image PNMMetadata object appropriate
     * for the given image type and write parameters.
     */
    PNMMetadata(ImageTypeSpecifier imageType,
                ImageWriteParam param) {
        this();
        initialize(imageType, param);
    }

    void initialize(ImageTypeSpecifier imageType,
                    ImageWriteParam param) {
        ImageTypeSpecifier destType = null;

        if (param != null) {
            destType = param.getDestinationType();
            if (destType == null) {
                destType = imageType;
            }
        } else {
            destType = imageType;
        }

        if (destType != null) {
            SampleModel sm = destType.getSampleModel();
            int[] sampleSize = sm.getSampleSize();

            this.width = sm.getWidth();
            this.height = sm.getHeight();

            for (int i = 0; i < sampleSize.length; i++) {
                if (sampleSize[i] > maxSampleSize) {
                    maxSampleSize = sampleSize[i];
                }
            }
            this.maxSample = (1 << maxSampleSize) - 1;

            boolean isRaw = true; // default value
            if(param instanceof PNMImageWriteParam) {
                isRaw = ((PNMImageWriteParam)param).getRaw();
            }

            if (maxSampleSize == 1)
                variant = '1';
            else if (sm.getNumBands() == 1) {
                variant = '2';
            } else if (sm.getNumBands() == 3) {
                variant = '3';
            }

            // Force to Raw if the sample size is small enough.
            if (variant <= '3' && isRaw && maxSampleSize <= 8) {
                variant += 0x3;
            }
        }
    }

    protected Object clone() {
        PNMMetadata theClone = null;

        try {
            theClone = (PNMMetadata) super.clone();
        } catch (CloneNotSupportedException e) {} // won't happen

        if (comments != null) {
            int numComments = comments.size();
            for(int i = 0; i < numComments; i++) {
                theClone.addComment((String)comments.get(i));
            }
        }
        return theClone;
    }

    public Node getAsTree(String formatName) {
        if (formatName == null) {
            throw new IllegalArgumentException(I18N.getString("PNMMetadata0"));
        }

        if (formatName.equals(nativeMetadataFormatName)) {
            return getNativeTree();
        }

        if (formatName.equals
            (IIOMetadataFormatImpl.standardMetadataFormatName)) {
            return getStandardTree();
        }

        throw  new IllegalArgumentException(I18N.getString("PNMMetadata1") + " " +
                                                formatName);
    }

    IIOMetadataNode getNativeTree() {
        IIOMetadataNode root =
            new IIOMetadataNode(nativeMetadataFormatName);

        IIOMetadataNode child = new IIOMetadataNode("FormatName");
        child.setUserObject(getFormatName());
	child.setNodeValue(getFormatName());
        root.appendChild(child);

        child = new IIOMetadataNode("Variant");
        child.setUserObject(getVariant());
        child.setNodeValue(getVariant());
        root.appendChild(child);

        child = new IIOMetadataNode("Width");
	Object tmp = new Integer(width);
        child.setUserObject(tmp);
	child.setNodeValue(ImageUtil.convertObjectToString(tmp));
        root.appendChild(child);

        child = new IIOMetadataNode("Height");
	tmp = new Integer(height);
        child.setUserObject(tmp);
	child.setNodeValue(ImageUtil.convertObjectToString(tmp));
        root.appendChild(child);

        child = new IIOMetadataNode("MaximumSample");
	tmp = new Byte((byte)maxSample);
        child.setUserObject(tmp);
	child.setNodeValue(ImageUtil.convertObjectToString(new Integer(maxSample)));
        root.appendChild(child);

        if(comments != null) {
            for (int i = 0; i < comments.size(); i++) {
                child = new IIOMetadataNode("Comment");
                tmp = comments.get(i);
                child.setUserObject(tmp);
                child.setNodeValue(ImageUtil.convertObjectToString(tmp));
                root.appendChild(child);
            }
        }

        return root;
    }

    // Standard tree node methods
    protected IIOMetadataNode getStandardChromaNode() {
        IIOMetadataNode node = new IIOMetadataNode("Chroma");

        int temp = (variant - '1') % 3 + 1;

        IIOMetadataNode subNode = new IIOMetadataNode("ColorSpaceType");
        if (temp == 3) {
            subNode.setAttribute("name", "RGB");
        } else {
            subNode.setAttribute("name", "GRAY");
        }
        node.appendChild(subNode);

        subNode = new IIOMetadataNode("NumChannels");
        subNode.setAttribute("value", "" + (temp == 3 ? 3 : 1));
        node.appendChild(subNode);

        if(temp != 3) {
            subNode = new IIOMetadataNode("BlackIsZero");
            subNode.setAttribute("value", "TRUE");
            node.appendChild(subNode);
        }

        return node;
    }

    protected IIOMetadataNode getStandardDataNode() {
        IIOMetadataNode node = new IIOMetadataNode("Data");

        IIOMetadataNode subNode = new IIOMetadataNode("SampleFormat");
        subNode.setAttribute("value", "UnsignedIntegral");
        node.appendChild(subNode);

        int temp = (variant - '1') % 3 + 1;
        subNode = new IIOMetadataNode("BitsPerSample");
        if(temp == 1) {
            subNode.setAttribute("value", "1");
        } else if(temp == 2) {
            subNode.setAttribute("value", "8");
        } else {
            subNode.setAttribute("value", "8 8 8");
        }
        node.appendChild(subNode);

        subNode = new IIOMetadataNode("SignificantBitsPerSample");
        if(temp == 1 || temp == 2) {
            subNode.setAttribute("value", "" + maxSampleSize);
        } else {
            subNode.setAttribute("value",
                                 maxSampleSize + " " +
                                 maxSampleSize + " " +
                                 maxSampleSize);
        }
        node.appendChild(subNode);

        return node;
    }

    protected IIOMetadataNode getStandardDimensionNode() {
        IIOMetadataNode node = new IIOMetadataNode("Dimension");

        IIOMetadataNode subNode = new IIOMetadataNode("ImageOrientation");
        subNode.setAttribute("value", "Normal");
        node.appendChild(subNode);

        return node;
    }

    protected IIOMetadataNode getStandardTextNode() {
        if(comments != null) {
	    IIOMetadataNode node = new IIOMetadataNode("Text");
            Iterator iter = comments.iterator();
            while(iter.hasNext()) {
                String comment = (String)iter.next();
                IIOMetadataNode subNode = new IIOMetadataNode("TextEntry");
                subNode.setAttribute("keyword", "comment");
                subNode.setAttribute("value", comment);
                node.appendChild(subNode);
            }
            return node;
        }
	return null;
    }

    public boolean isReadOnly() {
        return false;
    }

    public void mergeTree(String formatName, Node root)
        throws IIOInvalidTreeException {
        if (formatName == null) {
            throw new IllegalArgumentException(I18N.getString("PNMMetadata0"));
        }

        if (root == null) {
            throw new IllegalArgumentException(I18N.getString("PNMMetadata2"));
        }

        if (formatName.equals(nativeMetadataFormatName) &&
            root.getNodeName().equals(nativeMetadataFormatName)) {
            mergeNativeTree(root);
        } else if (formatName.equals
                    (IIOMetadataFormatImpl.standardMetadataFormatName)) {
            mergeStandardTree(root);
        } else {
            throw  new IllegalArgumentException(I18N.getString("PNMMetadata1") + " " +
                                                formatName);
        }
    }

    public void setFromTree(String formatName, Node root)
        throws IIOInvalidTreeException {
        if (formatName == null) {
            throw new IllegalArgumentException(I18N.getString("PNMMetadata0"));
        }

        if (root == null) {
            throw new IllegalArgumentException(I18N.getString("PNMMetadata2"));
        }

        if (formatName.equals(nativeMetadataFormatName) &&
            root.getNodeName().equals(nativeMetadataFormatName)) {
            mergeNativeTree(root);
        } else if (formatName.equals
                    (IIOMetadataFormatImpl.standardMetadataFormatName)) {
            mergeStandardTree(root);
        } else {
            throw  new IllegalArgumentException(I18N.getString("PNMMetadata2") + " " +
                                                formatName);
        }
    }

    public void reset() {
        maxSample = width = height = variant = maxSampleSize = 0;
        comments = null;
    }

    public String getFormatName() {
        int v = (variant - '1') % 3 + 1;
        if (v == 1)
            return "PBM";
        if (v == 2)
            return "PGM";
        if (v == 3)
            return "PPM";
        return null;
    }

    public String getVariant() {
        if (variant > '3')
            return "RAWBITS";
        return "ASCII";
    }

    boolean isRaw() {
        return getVariant().equals("RAWBITS");
    }

    /** Sets the variant: '1' - '6'. */
    public void setVariant(int v) {
        this.variant = v;
    }

    public void setWidth(int w) {
        this.width = w;
    }

    public void setHeight(int h) {
        this.height = h;
    }

    int getMaxBitDepth() {
        return maxSampleSize;
    }

    int getMaxValue() {
        return maxSample;
    }

    /** Set the maximum sample size and maximum sample value.
     *  @param maxValue The maximum sample value.  This method computes the
     *                  maximum sample size.
     */
    public void setMaxBitDepth(int maxValue) {
        this.maxSample = maxValue;

        this.maxSampleSize = 0;
        while(maxValue > 0) {
            maxValue >>>= 1;
            maxSampleSize++;
        }
    }

    public synchronized void addComment(String comment) {
        if (comments == null) {
            comments = new ArrayList();
        }
        comment = comment.replaceAll("[\n\r\f]", " ");
        comments.add(comment);
    }

    Iterator getComments() {
        return comments == null ? null : comments.iterator();
    }

    private void mergeNativeTree(Node root) throws IIOInvalidTreeException {
        NodeList list = root.getChildNodes();
        String format = null;
        String var = null;

        for (int i = list.getLength() - 1; i >= 0; i--) {
            IIOMetadataNode node = (IIOMetadataNode)list.item(i);
            String name = node.getNodeName();

            if (name.equals("Comment")) {
                addComment((String)node.getUserObject());
            } else if (name.equals("Width")) {
                this.width = ((Integer)node.getUserObject()).intValue();
            } else if (name.equals("Height")) {
                this.width = ((Integer)node.getUserObject()).intValue();
            } else if (name.equals("MaximumSample")) {
                int maxValue = ((Integer)node.getUserObject()).intValue();
                setMaxBitDepth(maxValue);
            } else if (name.equals("FormatName")) {
                format = (String)node.getUserObject();
            } else if (name.equals("Variant")) {
                var = (String)node.getUserObject();
            }
        }

        if (format.equals("PBM"))
            variant = '1';
        else if (format.equals("PGM"))
            variant = '2';
        else if (format.equals("PPM"))
            variant = '3';

        if (var.equals("RAWBITS"))
            variant += 3;
    }

    private void mergeStandardTree(Node root) throws IIOInvalidTreeException {
        NodeList children = root.getChildNodes();

        String colorSpace = null;
        int numComps = 0;
        int[] bitsPerSample = null;

        for (int i = 0; i < children.getLength(); i++) {
            Node node = children.item(i);
            String name = node.getNodeName();
            if (name.equals("Chroma")) {
                NodeList children1 = node.getChildNodes();
                for (int j = 0; j < children1.getLength(); j++) {
                    Node child = children1.item(j);
                    String name1 = child.getNodeName();

                    if (name1.equals("NumChannels")) {
                        String s = (String)getAttribute(child, "value");
                        numComps = new Integer(s).intValue();
                    } else if (name1.equals("ColorSpaceType")) {
                        colorSpace = (String)getAttribute(child, "name");
                    }
                }
            } else if (name.equals("Compression")) {
                // Do nothing.
            } else if (name.equals("Data")) {
                NodeList children1 = node.getChildNodes();
                int maxBitDepth = -1;
                for (int j = 0; j < children1.getLength(); j++) {
                    Node child = children1.item(j);
                    String name1 = child.getNodeName();

                    if (name1.equals("BitsPerSample")) {
                        List bps = new ArrayList(3);
                        String s = (String)getAttribute(child, "value");
                        StringTokenizer t = new StringTokenizer(s);
                        while(t.hasMoreTokens()) {
                            bps.add(Integer.valueOf(t.nextToken()));
                        }
                        bitsPerSample = new int[bps.size()];
                        for(int k = 0; k < bitsPerSample.length; k++) {
                            bitsPerSample[k] =
                                ((Integer)bps.get(k)).intValue();
                        }
                    } else if (name1.equals("SignificantBitsPerSample")) {
                        String s = (String)getAttribute(child, "value");
                        StringTokenizer t = new StringTokenizer(s);
                        while(t.hasMoreTokens()) {
                            int sbps =
                                Integer.valueOf(t.nextToken()).intValue();
                            maxBitDepth = Math.max(sbps, maxBitDepth);
                        }
                    }
                }

                // Set maximum bit depth and value.
                if(maxBitDepth > 0) {
                    setMaxBitDepth((1 << maxBitDepth) - 1);
                } else if(bitsPerSample != null) {
                    for(int k = 0; k < bitsPerSample.length; k++) {
                        if(bitsPerSample[k] > maxBitDepth) {
                            maxBitDepth = bitsPerSample[k];
                        }
                    }
                    setMaxBitDepth((1 << maxBitDepth) - 1);
                }
            } else if (name.equals("Dimension")) {
                // Do nothing.
            } else if (name.equals("Document")) {
                // Do nothing.
            } else if (name.equals("Text")) {
                NodeList children1 = node.getChildNodes();
                for (int j = 0; j < children1.getLength(); j++) {
                    Node child = children1.item(j);
                    String name1 = child.getNodeName();

                    if (name1.equals("TextEntry")) {
                        addComment((String)getAttribute(child, "value"));
                    }
                }
            } else if (name.equals("Transparency")) {
                // Do nothing.
            } else {
                throw new IIOInvalidTreeException(I18N.getString("PNMMetadata3") + " " +
						name, node);
            }
        }

        // Go from higher to lower: PPM > PGM > PBM.
        if((colorSpace != null && colorSpace.equals("RGB")) ||
           numComps > 1 ||
           bitsPerSample.length > 1) {
            variant = '3';
        } else if(maxSampleSize > 1) {
            variant = '2';
        } else {
            variant = '1';
        }
    }

    public Object getAttribute(Node node, String name) {
        NamedNodeMap map = node.getAttributes();
        node = map.getNamedItem(name);
        return (node != null) ? node.getNodeValue() : null;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy