001: /*
002: * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.imageio.plugins.bmp;
027:
028: import java.io.UnsupportedEncodingException;
029: import java.util.ArrayList;
030: import java.util.Iterator;
031: import java.util.List;
032: import javax.imageio.ImageTypeSpecifier;
033: import javax.imageio.metadata.IIOMetadata;
034: import javax.imageio.metadata.IIOMetadataNode;
035: import javax.imageio.metadata.IIOMetadataFormat;
036: import javax.imageio.metadata.IIOMetadataFormatImpl;
037: import org.w3c.dom.Node;
038: import com.sun.imageio.plugins.common.I18N;
039:
040: import com.sun.imageio.plugins.common.ImageUtil;
041:
042: public class BMPMetadata extends IIOMetadata implements BMPConstants {
043: public static final String nativeMetadataFormatName = "javax_imageio_bmp_1.0";
044:
045: // Fields for Image Descriptor
046: public String bmpVersion;
047: public int width;
048: public int height;
049: public short bitsPerPixel;
050: public int compression;
051: public int imageSize;
052:
053: // Fields for PixelsPerMeter
054: public int xPixelsPerMeter;
055: public int yPixelsPerMeter;
056:
057: public int colorsUsed;
058: public int colorsImportant;
059:
060: // Fields for BI_BITFIELDS compression(Mask)
061: public int redMask;
062: public int greenMask;
063: public int blueMask;
064: public int alphaMask;
065:
066: public int colorSpace;
067:
068: // Fields for CIE XYZ for the LCS_CALIBRATED_RGB color space
069: public double redX;
070: public double redY;
071: public double redZ;
072: public double greenX;
073: public double greenY;
074: public double greenZ;
075: public double blueX;
076: public double blueY;
077: public double blueZ;
078:
079: // Fields for Gamma values for the LCS_CALIBRATED_RGB color space
080: public int gammaRed;
081: public int gammaGreen;
082: public int gammaBlue;
083:
084: public int intent;
085:
086: // Fields for the Palette and Entries
087: public byte[] palette = null;
088: public int paletteSize;
089: public int red;
090: public int green;
091: public int blue;
092:
093: // Fields from CommentExtension
094: // List of byte[]
095: public List comments = null; // new ArrayList();
096:
097: public BMPMetadata() {
098: super (true, nativeMetadataFormatName,
099: "com.sun.imageio.plugins.bmp.BMPMetadataFormat", null,
100: null);
101: }
102:
103: public boolean isReadOnly() {
104: return true;
105: }
106:
107: public Node getAsTree(String formatName) {
108: if (formatName.equals(nativeMetadataFormatName)) {
109: return getNativeTree();
110: } else if (formatName
111: .equals(IIOMetadataFormatImpl.standardMetadataFormatName)) {
112: return getStandardTree();
113: } else {
114: throw new IllegalArgumentException(I18N
115: .getString("BMPMetadata0"));
116: }
117: }
118:
119: private String toISO8859(byte[] data) {
120: try {
121: return new String(data, "ISO-8859-1");
122: } catch (UnsupportedEncodingException e) {
123: return "";
124: }
125: }
126:
127: private Node getNativeTree() {
128: IIOMetadataNode root = new IIOMetadataNode(
129: nativeMetadataFormatName);
130:
131: addChildNode(root, "BMPVersion", bmpVersion);
132: addChildNode(root, "Width", new Integer(width));
133: addChildNode(root, "Height", new Integer(height));
134: addChildNode(root, "BitsPerPixel", new Short(bitsPerPixel));
135: addChildNode(root, "Compression", new Integer(compression));
136: addChildNode(root, "ImageSize", new Integer(imageSize));
137:
138: IIOMetadataNode node = addChildNode(root, "PixelsPerMeter",
139: null);
140: addChildNode(node, "X", new Integer(xPixelsPerMeter));
141: addChildNode(node, "Y", new Integer(yPixelsPerMeter));
142:
143: addChildNode(root, "ColorsUsed", new Integer(colorsUsed));
144: addChildNode(root, "ColorsImportant", new Integer(
145: colorsImportant));
146:
147: int version = 0;
148: for (int i = 0; i < bmpVersion.length(); i++)
149: if (Character.isDigit(bmpVersion.charAt(i)))
150: version = bmpVersion.charAt(i) - '0';
151:
152: if (version >= 4) {
153: node = addChildNode(root, "Mask", null);
154: addChildNode(node, "Red", new Integer(redMask));
155: addChildNode(node, "Green", new Integer(greenMask));
156: addChildNode(node, "Blue", new Integer(blueMask));
157: addChildNode(node, "Alpha", new Integer(alphaMask));
158:
159: addChildNode(root, "ColorSpaceType",
160: new Integer(colorSpace));
161:
162: node = addChildNode(root, "CIEXYZEndPoints", null);
163: addXYZPoints(node, "Red", redX, redY, redZ);
164: addXYZPoints(node, "Green", greenX, greenY, greenZ);
165: addXYZPoints(node, "Blue", blueX, blueY, blueZ);
166:
167: node = addChildNode(root, "Intent", new Integer(intent));
168: }
169:
170: // Palette
171: if ((palette != null) && (paletteSize > 0)) {
172: node = addChildNode(root, "Palette", null);
173: int numComps = palette.length / paletteSize;
174:
175: for (int i = 0, j = 0; i < paletteSize; i++) {
176: IIOMetadataNode entry = addChildNode(node,
177: "PaletteEntry", null);
178: red = palette[j++] & 0xff;
179: green = palette[j++] & 0xff;
180: blue = palette[j++] & 0xff;
181: addChildNode(entry, "Red", new Byte((byte) red));
182: addChildNode(entry, "Green", new Byte((byte) green));
183: addChildNode(entry, "Blue", new Byte((byte) blue));
184: if (numComps == 4)
185: addChildNode(entry, "Alpha", new Byte(
186: (byte) (palette[j++] & 0xff)));
187: }
188: }
189:
190: return root;
191: }
192:
193: // Standard tree node methods
194: protected IIOMetadataNode getStandardChromaNode() {
195:
196: if ((palette != null) && (paletteSize > 0)) {
197: IIOMetadataNode node = new IIOMetadataNode("Chroma");
198: IIOMetadataNode subNode = new IIOMetadataNode("Palette");
199: int numComps = palette.length / paletteSize;
200: subNode.setAttribute("value", "" + numComps);
201:
202: for (int i = 0, j = 0; i < paletteSize; i++) {
203: IIOMetadataNode subNode1 = new IIOMetadataNode(
204: "PaletteEntry");
205: subNode1.setAttribute("index", "" + i);
206: subNode1.setAttribute("red", "" + palette[j++]);
207: subNode1.setAttribute("green", "" + palette[j++]);
208: subNode1.setAttribute("blue", "" + palette[j++]);
209: if (numComps == 4 && palette[j] != 0)
210: subNode1.setAttribute("alpha", "" + palette[j++]);
211: subNode.appendChild(subNode1);
212: }
213: node.appendChild(subNode);
214: return node;
215: }
216:
217: return null;
218: }
219:
220: protected IIOMetadataNode getStandardCompressionNode() {
221: IIOMetadataNode node = new IIOMetadataNode("Compression");
222:
223: // CompressionTypeName
224: IIOMetadataNode subNode = new IIOMetadataNode(
225: "CompressionTypeName");
226: subNode
227: .setAttribute("value",
228: compressionTypeNames[compression]);
229: node.appendChild(subNode);
230: return node;
231: }
232:
233: protected IIOMetadataNode getStandardDataNode() {
234: IIOMetadataNode node = new IIOMetadataNode("Data");
235:
236: String bits = "";
237: if (bitsPerPixel == 24)
238: bits = "8 8 8 ";
239: else if (bitsPerPixel == 16 || bitsPerPixel == 32) {
240: bits = "" + countBits(redMask) + " " + countBits(greenMask)
241: + countBits(blueMask) + "" + countBits(alphaMask);
242: }
243:
244: IIOMetadataNode subNode = new IIOMetadataNode("BitsPerSample");
245: subNode.setAttribute("value", bits);
246: node.appendChild(subNode);
247:
248: return node;
249: }
250:
251: protected IIOMetadataNode getStandardDimensionNode() {
252: if (yPixelsPerMeter > 0.0F && xPixelsPerMeter > 0.0F) {
253: IIOMetadataNode node = new IIOMetadataNode("Dimension");
254: float ratio = yPixelsPerMeter / xPixelsPerMeter;
255: IIOMetadataNode subNode = new IIOMetadataNode(
256: "PixelAspectRatio");
257: subNode.setAttribute("value", "" + ratio);
258: node.appendChild(subNode);
259:
260: subNode = new IIOMetadataNode(
261: "HorizontalPhysicalPixelSpacing");
262: subNode.setAttribute("value", ""
263: + (1 / xPixelsPerMeter * 1000));
264: node.appendChild(subNode);
265:
266: subNode = new IIOMetadataNode(
267: "VerticalPhysicalPixelSpacing");
268: subNode.setAttribute("value", ""
269: + (1 / yPixelsPerMeter * 1000));
270: node.appendChild(subNode);
271:
272: return node;
273: }
274: return null;
275: }
276:
277: public void setFromTree(String formatName, Node root) {
278: throw new IllegalStateException(I18N.getString("BMPMetadata1"));
279: }
280:
281: public void mergeTree(String formatName, Node root) {
282: throw new IllegalStateException(I18N.getString("BMPMetadata1"));
283: }
284:
285: public void reset() {
286: throw new IllegalStateException(I18N.getString("BMPMetadata1"));
287: }
288:
289: private String countBits(int num) {
290: int count = 0;
291: while (num > 0) {
292: if ((num & 1) == 1)
293: count++;
294: num >>>= 1;
295: }
296:
297: return count == 0 ? "" : "" + count;
298: }
299:
300: private void addXYZPoints(IIOMetadataNode root, String name,
301: double x, double y, double z) {
302: IIOMetadataNode node = addChildNode(root, name, null);
303: addChildNode(node, "X", new Double(x));
304: addChildNode(node, "Y", new Double(y));
305: addChildNode(node, "Z", new Double(z));
306: }
307:
308: private IIOMetadataNode addChildNode(IIOMetadataNode root,
309: String name, Object object) {
310: IIOMetadataNode child = new IIOMetadataNode(name);
311: if (object != null) {
312: child.setUserObject(object);
313: child.setNodeValue(ImageUtil.convertObjectToString(object));
314: }
315: root.appendChild(child);
316: return child;
317: }
318: }
|