001/*
002 * $RCSfile: PCXMetadata.java,v $
003 *
004 * 
005 * Copyright (c) 2007 Sun Microsystems, Inc. All  Rights Reserved.
006 * 
007 * Redistribution and use in source and binary forms, with or without
008 * modification, are permitted provided that the following conditions
009 * are met: 
010 * 
011 * - Redistribution of source code must retain the above copyright 
012 *   notice, this  list of conditions and the following disclaimer.
013 * 
014 * - Redistribution in binary form must reproduce the above copyright
015 *   notice, this list of conditions and the following disclaimer in 
016 *   the documentation and/or other materials provided with the
017 *   distribution.
018 * 
019 * Neither the name of Sun Microsystems, Inc. or the names of 
020 * contributors may be used to endorse or promote products derived 
021 * from this software without specific prior written permission.
022 * 
023 * This software is provided "AS IS," without a warranty of any 
024 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
025 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
026 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
027 * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
028 * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
029 * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
030 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
031 * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
032 * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
033 * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
034 * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
035 * POSSIBILITY OF SUCH DAMAGES. 
036 * 
037 * You acknowledge that this software is not designed or intended for 
038 * use in the design, construction, operation or maintenance of any 
039 * nuclear facility. 
040 *
041 * $Revision: 1.2 $
042 * $Date: 2007/09/07 19:12:25 $
043 * $State: Exp $
044 */
045package com.github.jaiimageio.impl.plugins.pcx;
046
047import javax.imageio.metadata.IIOInvalidTreeException;
048import javax.imageio.metadata.IIOMetadata;
049import javax.imageio.metadata.IIOMetadataFormatImpl;
050import javax.imageio.metadata.IIOMetadataNode;
051
052import org.w3c.dom.NamedNodeMap;
053import org.w3c.dom.Node;
054
055public class PCXMetadata extends IIOMetadata implements Cloneable, PCXConstants {
056
057    short version;
058    byte bitsPerPixel;
059    boolean gotxmin, gotymin;
060    short xmin, ymin;
061    int vdpi, hdpi;
062    int hsize,vsize;
063
064    PCXMetadata() {
065        super(true, null, null, null, null);
066        reset();
067    }
068
069    public Node getAsTree(String formatName) {
070        if (formatName.equals(IIOMetadataFormatImpl.standardMetadataFormatName)) {
071            return getStandardTree();
072        } else {
073            throw new IllegalArgumentException("Not a recognized format!");
074        }
075    }
076
077    public boolean isReadOnly() {
078        return false;
079    }
080
081    public void mergeTree(String formatName, Node root) throws IIOInvalidTreeException {
082        if (formatName.equals(IIOMetadataFormatImpl.standardMetadataFormatName)) {
083            if (root == null) {
084                throw new IllegalArgumentException("root == null!");
085            }
086            mergeStandardTree(root);
087        } else {
088            throw new IllegalArgumentException("Not a recognized format!");
089        }   
090    }
091
092    public void reset() {
093        version = VERSION_3_0;
094        bitsPerPixel = 0;
095        gotxmin = false;
096        gotymin = false;
097        xmin = 0;
098        ymin = 0;
099        vdpi = 72;
100        hdpi = 72;
101        hsize = 0;
102        vsize = 0;
103    }
104
105    public IIOMetadataNode getStandardDocumentNode() {
106        String versionString;
107        switch(version) {
108        case VERSION_2_5:
109            versionString = "2.5";
110            break;
111        case VERSION_2_8_W_PALETTE:
112            versionString = "2.8 with palette";
113            break;
114        case VERSION_2_8_WO_PALETTE:
115            versionString = "2.8 without palette";
116            break;
117        case VERSION_PC_WINDOWS:
118            versionString = "PC Paintbrush for Windows";
119            break;
120        case VERSION_3_0:
121            versionString = "3.0";
122            break;
123        default:
124            // unknown
125            versionString = null;
126        }
127
128        IIOMetadataNode documentNode = null;
129        if(versionString != null) {
130            documentNode = new IIOMetadataNode("Document");
131            IIOMetadataNode node = new IIOMetadataNode("FormatVersion");
132            node.setAttribute("value", versionString);
133            documentNode.appendChild(node);
134        }
135
136        return documentNode;
137    }
138
139    public IIOMetadataNode getStandardDimensionNode() {
140        IIOMetadataNode dimensionNode = new IIOMetadataNode("Dimension");
141        IIOMetadataNode node = null; // scratch node
142
143        node = new IIOMetadataNode("HorizontalPixelOffset");
144        node.setAttribute("value", String.valueOf(xmin));
145        dimensionNode.appendChild(node);
146
147        node = new IIOMetadataNode("VerticalPixelOffset");
148        node.setAttribute("value", String.valueOf(ymin));
149        dimensionNode.appendChild(node);
150
151        node = new IIOMetadataNode("HorizontalPixelSize");
152        node.setAttribute("value", String.valueOf(254.0/hdpi));
153        dimensionNode.appendChild(node);
154
155        node = new IIOMetadataNode("VerticalPixelSize");
156        node.setAttribute("value", String.valueOf(254.0/vdpi));
157        dimensionNode.appendChild(node);
158
159        if(hsize != 0) {
160            node = new IIOMetadataNode("HorizontalScreenSize");
161            node.setAttribute("value", String.valueOf(hsize));
162            dimensionNode.appendChild(node);
163        }
164
165        if(vsize != 0) {
166            node = new IIOMetadataNode("VerticalScreenSize");
167            node.setAttribute("value", String.valueOf(vsize));
168            dimensionNode.appendChild(node);
169        }
170
171        return dimensionNode;
172    }
173
174    private void mergeStandardTree(Node root) throws IIOInvalidTreeException {
175        Node node = root;
176        if (!node.getNodeName().equals(IIOMetadataFormatImpl.standardMetadataFormatName))
177            throw new IIOInvalidTreeException("Root must be " +
178                                              IIOMetadataFormatImpl.standardMetadataFormatName,
179                                              node);
180
181        node = node.getFirstChild();
182        while (node != null) {
183            String name = node.getNodeName();
184
185            if (name.equals("Dimension")) {
186                Node child = node.getFirstChild();
187
188                while (child != null) {
189                    String childName = child.getNodeName();
190                    if (childName.equals("HorizontalPixelOffset")) {
191                        String hpo = getAttribute(child, "value");
192                        xmin = Short.valueOf(hpo).shortValue();
193                        gotxmin = true;
194                    } else if (childName.equals("VerticalPixelOffset")) {
195                        String vpo = getAttribute(child, "value");
196                        ymin = Short.valueOf(vpo).shortValue();
197                        gotymin = true;
198                    } else if (childName.equals("HorizontalPixelSize")) {
199                        String hps = getAttribute(child, "value");
200                        hdpi = (int)(254.0F/Float.parseFloat(hps) + 0.5F);
201                    } else if (childName.equals("VerticalPixelSize")) {
202                        String vps = getAttribute(child, "value");
203                        vdpi = (int)(254.0F/Float.parseFloat(vps) + 0.5F);
204                    } else if (childName.equals("HorizontalScreenSize")) {
205                        String hss = getAttribute(child, "value");
206                        hsize = Integer.valueOf(hss).intValue();
207                    } else if (childName.equals("VerticalScreenSize")) {
208                        String vss = getAttribute(child, "value");
209                        vsize = Integer.valueOf(vss).intValue();
210                    }
211
212                    child = child.getNextSibling();
213                }
214            }
215
216            node = node.getNextSibling();
217        }
218    }
219
220    private static String getAttribute(Node node, String attrName) {
221        NamedNodeMap attrs = node.getAttributes();
222        Node attr = attrs.getNamedItem(attrName);
223        return attr != null ? attr.getNodeValue() : null;
224    }
225}