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
055import com.github.jaiimageio.impl.common.ImageUtil;
056
057public class PCXMetadata extends IIOMetadata implements Cloneable, PCXConstants {
058
059    short version;
060    byte bitsPerPixel;
061    boolean gotxmin, gotymin;
062    short xmin, ymin;
063    int vdpi, hdpi;
064    int hsize,vsize;
065
066    PCXMetadata() {
067        super(true, null, null, null, null);
068        reset();
069    }
070
071    public Node getAsTree(String formatName) {
072        if (formatName.equals(IIOMetadataFormatImpl.standardMetadataFormatName)) {
073            return getStandardTree();
074        } else {
075            throw new IllegalArgumentException("Not a recognized format!");
076        }
077    }
078
079    public boolean isReadOnly() {
080        return false;
081    }
082
083    public void mergeTree(String formatName, Node root) throws IIOInvalidTreeException {
084        if (formatName.equals(IIOMetadataFormatImpl.standardMetadataFormatName)) {
085            if (root == null) {
086                throw new IllegalArgumentException("root == null!");
087            }
088            mergeStandardTree(root);
089        } else {
090            throw new IllegalArgumentException("Not a recognized format!");
091        }   
092    }
093
094    public void reset() {
095        version = VERSION_3_0;
096        bitsPerPixel = 0;
097        gotxmin = false;
098        gotymin = false;
099        xmin = 0;
100        ymin = 0;
101        vdpi = 72;
102        hdpi = 72;
103        hsize = 0;
104        vsize = 0;
105    }
106
107    public IIOMetadataNode getStandardDocumentNode() {
108        String versionString;
109        switch(version) {
110        case VERSION_2_5:
111            versionString = "2.5";
112            break;
113        case VERSION_2_8_W_PALETTE:
114            versionString = "2.8 with palette";
115            break;
116        case VERSION_2_8_WO_PALETTE:
117            versionString = "2.8 without palette";
118            break;
119        case VERSION_PC_WINDOWS:
120            versionString = "PC Paintbrush for Windows";
121            break;
122        case VERSION_3_0:
123            versionString = "3.0";
124            break;
125        default:
126            // unknown
127            versionString = null;
128        }
129
130        IIOMetadataNode documentNode = null;
131        if(versionString != null) {
132            documentNode = new IIOMetadataNode("Document");
133            IIOMetadataNode node = new IIOMetadataNode("FormatVersion");
134            node.setAttribute("value", versionString);
135            documentNode.appendChild(node);
136        }
137
138        return documentNode;
139    }
140
141    public IIOMetadataNode getStandardDimensionNode() {
142        IIOMetadataNode dimensionNode = new IIOMetadataNode("Dimension");
143        IIOMetadataNode node = null; // scratch node
144
145        node = new IIOMetadataNode("HorizontalPixelOffset");
146        node.setAttribute("value", String.valueOf(xmin));
147        dimensionNode.appendChild(node);
148
149        node = new IIOMetadataNode("VerticalPixelOffset");
150        node.setAttribute("value", String.valueOf(ymin));
151        dimensionNode.appendChild(node);
152
153        node = new IIOMetadataNode("HorizontalPixelSize");
154        node.setAttribute("value", String.valueOf(254.0/hdpi));
155        dimensionNode.appendChild(node);
156
157        node = new IIOMetadataNode("VerticalPixelSize");
158        node.setAttribute("value", String.valueOf(254.0/vdpi));
159        dimensionNode.appendChild(node);
160
161        if(hsize != 0) {
162            node = new IIOMetadataNode("HorizontalScreenSize");
163            node.setAttribute("value", String.valueOf(hsize));
164            dimensionNode.appendChild(node);
165        }
166
167        if(vsize != 0) {
168            node = new IIOMetadataNode("VerticalScreenSize");
169            node.setAttribute("value", String.valueOf(vsize));
170            dimensionNode.appendChild(node);
171        }
172
173        return dimensionNode;
174    }
175
176    private void mergeStandardTree(Node root) throws IIOInvalidTreeException {
177        Node node = root;
178        if (!node.getNodeName().equals(IIOMetadataFormatImpl.standardMetadataFormatName))
179            throw new IIOInvalidTreeException("Root must be " +
180                                              IIOMetadataFormatImpl.standardMetadataFormatName,
181                                              node);
182
183        node = node.getFirstChild();
184        while (node != null) {
185            String name = node.getNodeName();
186
187            if (name.equals("Dimension")) {
188                Node child = node.getFirstChild();
189
190                while (child != null) {
191                    String childName = child.getNodeName();
192                    if (childName.equals("HorizontalPixelOffset")) {
193                        String hpo = getAttribute(child, "value");
194                        xmin = Short.valueOf(hpo).shortValue();
195                        gotxmin = true;
196                    } else if (childName.equals("VerticalPixelOffset")) {
197                        String vpo = getAttribute(child, "value");
198                        ymin = Short.valueOf(vpo).shortValue();
199                        gotymin = true;
200                    } else if (childName.equals("HorizontalPixelSize")) {
201                        String hps = getAttribute(child, "value");
202                        hdpi = (int)(254.0F/Float.parseFloat(hps) + 0.5F);
203                    } else if (childName.equals("VerticalPixelSize")) {
204                        String vps = getAttribute(child, "value");
205                        vdpi = (int)(254.0F/Float.parseFloat(vps) + 0.5F);
206                    } else if (childName.equals("HorizontalScreenSize")) {
207                        String hss = getAttribute(child, "value");
208                        hsize = Integer.valueOf(hss).intValue();
209                    } else if (childName.equals("VerticalScreenSize")) {
210                        String vss = getAttribute(child, "value");
211                        vsize = Integer.valueOf(vss).intValue();
212                    }
213
214                    child = child.getNextSibling();
215                }
216            }
217
218            node = node.getNextSibling();
219        }
220    }
221
222    private static String getAttribute(Node node, String attrName) {
223        NamedNodeMap attrs = node.getAttributes();
224        Node attr = attrs.getNamedItem(attrName);
225        return attr != null ? attr.getNodeValue() : null;
226    }
227}