| /* |
| * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package com.sun.imageio.plugins.bmp; |
| |
| import java.io.UnsupportedEncodingException; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| import javax.imageio.ImageTypeSpecifier; |
| import javax.imageio.metadata.IIOMetadata; |
| import javax.imageio.metadata.IIOMetadataNode; |
| import javax.imageio.metadata.IIOMetadataFormat; |
| import javax.imageio.metadata.IIOMetadataFormatImpl; |
| import org.w3c.dom.Node; |
| import com.sun.imageio.plugins.common.I18N; |
| |
| import com.sun.imageio.plugins.common.ImageUtil; |
| |
| public class BMPMetadata extends IIOMetadata implements BMPConstants { |
| public static final String nativeMetadataFormatName = |
| "javax_imageio_bmp_1.0"; |
| |
| // Fields for Image Descriptor |
| public String bmpVersion; |
| public int width ; |
| public int height; |
| public short bitsPerPixel; |
| public int compression; |
| public int imageSize; |
| |
| // Fields for PixelsPerMeter |
| public int xPixelsPerMeter; |
| public int yPixelsPerMeter; |
| |
| public int colorsUsed; |
| public int colorsImportant; |
| |
| // Fields for BI_BITFIELDS compression(Mask) |
| public int redMask; |
| public int greenMask; |
| public int blueMask; |
| public int alphaMask; |
| |
| public int colorSpace; |
| |
| // Fields for CIE XYZ for the LCS_CALIBRATED_RGB color space |
| public double redX; |
| public double redY; |
| public double redZ; |
| public double greenX; |
| public double greenY; |
| public double greenZ; |
| public double blueX; |
| public double blueY; |
| public double blueZ; |
| |
| // Fields for Gamma values for the LCS_CALIBRATED_RGB color space |
| public int gammaRed; |
| public int gammaGreen; |
| public int gammaBlue; |
| |
| public int intent; |
| |
| // Fields for the Palette and Entries |
| public byte[] palette = null; |
| public int paletteSize; |
| public int red; |
| public int green; |
| public int blue; |
| |
| // Fields from CommentExtension |
| // List of byte[] |
| public List comments = null; // new ArrayList(); |
| |
| public BMPMetadata() { |
| super(true, |
| nativeMetadataFormatName, |
| "com.sun.imageio.plugins.bmp.BMPMetadataFormat", |
| null, null); |
| } |
| |
| public boolean isReadOnly() { |
| return true; |
| } |
| |
| public Node getAsTree(String formatName) { |
| if (formatName.equals(nativeMetadataFormatName)) { |
| return getNativeTree(); |
| } else if (formatName.equals |
| (IIOMetadataFormatImpl.standardMetadataFormatName)) { |
| return getStandardTree(); |
| } else { |
| throw new IllegalArgumentException(I18N.getString("BMPMetadata0")); |
| } |
| } |
| |
| private String toISO8859(byte[] data) { |
| try { |
| return new String(data, "ISO-8859-1"); |
| } catch (UnsupportedEncodingException e) { |
| return ""; |
| } |
| } |
| |
| private Node getNativeTree() { |
| IIOMetadataNode root = |
| new IIOMetadataNode(nativeMetadataFormatName); |
| |
| addChildNode(root, "BMPVersion", bmpVersion); |
| addChildNode(root, "Width", new Integer(width)); |
| addChildNode(root, "Height", new Integer(height)); |
| addChildNode(root, "BitsPerPixel", new Short(bitsPerPixel)); |
| addChildNode(root, "Compression", new Integer(compression)); |
| addChildNode(root, "ImageSize", new Integer(imageSize)); |
| |
| IIOMetadataNode node = addChildNode(root, "PixelsPerMeter", null); |
| addChildNode(node, "X", new Integer(xPixelsPerMeter)); |
| addChildNode(node, "Y", new Integer(yPixelsPerMeter)); |
| |
| addChildNode(root, "ColorsUsed", new Integer(colorsUsed)); |
| addChildNode(root, "ColorsImportant", new Integer(colorsImportant)); |
| |
| int version = 0; |
| for (int i = 0; i < bmpVersion.length(); i++) |
| if (Character.isDigit(bmpVersion.charAt(i))) |
| version = bmpVersion.charAt(i) -'0'; |
| |
| if (version >= 4) { |
| node = addChildNode(root, "Mask", null); |
| addChildNode(node, "Red", new Integer(redMask)); |
| addChildNode(node, "Green", new Integer(greenMask)); |
| addChildNode(node, "Blue", new Integer(blueMask)); |
| addChildNode(node, "Alpha", new Integer(alphaMask)); |
| |
| addChildNode(root, "ColorSpaceType", new Integer(colorSpace)); |
| |
| node = addChildNode(root, "CIEXYZEndPoints", null); |
| addXYZPoints(node, "Red", redX, redY, redZ); |
| addXYZPoints(node, "Green", greenX, greenY, greenZ); |
| addXYZPoints(node, "Blue", blueX, blueY, blueZ); |
| |
| node = addChildNode(root, "Intent", new Integer(intent)); |
| } |
| |
| // Palette |
| if ((palette != null) && (paletteSize > 0)) { |
| node = addChildNode(root, "Palette", null); |
| int numComps = palette.length / paletteSize; |
| |
| for (int i = 0, j = 0; i < paletteSize; i++) { |
| IIOMetadataNode entry = |
| addChildNode(node, "PaletteEntry", null); |
| red = palette[j++] & 0xff; |
| green = palette[j++] & 0xff; |
| blue = palette[j++] & 0xff; |
| addChildNode(entry, "Red", new Byte((byte)red)); |
| addChildNode(entry, "Green", new Byte((byte)green)); |
| addChildNode(entry, "Blue", new Byte((byte)blue)); |
| if (numComps == 4) |
| addChildNode(entry, "Alpha", |
| new Byte((byte)(palette[j++] & 0xff))); |
| } |
| } |
| |
| return root; |
| } |
| |
| // Standard tree node methods |
| protected IIOMetadataNode getStandardChromaNode() { |
| |
| if ((palette != null) && (paletteSize > 0)) { |
| IIOMetadataNode node = new IIOMetadataNode("Chroma"); |
| IIOMetadataNode subNode = new IIOMetadataNode("Palette"); |
| int numComps = palette.length / paletteSize; |
| subNode.setAttribute("value", "" + numComps); |
| |
| for (int i = 0, j = 0; i < paletteSize; i++) { |
| IIOMetadataNode subNode1 = new IIOMetadataNode("PaletteEntry"); |
| subNode1.setAttribute("index", ""+i); |
| subNode1.setAttribute("red", "" + palette[j++]); |
| subNode1.setAttribute("green", "" + palette[j++]); |
| subNode1.setAttribute("blue", "" + palette[j++]); |
| if (numComps == 4 && palette[j] != 0) |
| subNode1.setAttribute("alpha", "" + palette[j++]); |
| subNode.appendChild(subNode1); |
| } |
| node.appendChild(subNode); |
| return node; |
| } |
| |
| return null; |
| } |
| |
| protected IIOMetadataNode getStandardCompressionNode() { |
| IIOMetadataNode node = new IIOMetadataNode("Compression"); |
| |
| // CompressionTypeName |
| IIOMetadataNode subNode = new IIOMetadataNode("CompressionTypeName"); |
| subNode.setAttribute("value", BMPCompressionTypes.getName(compression)); |
| node.appendChild(subNode); |
| return node; |
| } |
| |
| protected IIOMetadataNode getStandardDataNode() { |
| IIOMetadataNode node = new IIOMetadataNode("Data"); |
| |
| String bits = ""; |
| if (bitsPerPixel == 24) |
| bits = "8 8 8 "; |
| else if (bitsPerPixel == 16 || bitsPerPixel == 32) { |
| bits = "" + countBits(redMask) + " " + countBits(greenMask) + |
| countBits(blueMask) + "" + countBits(alphaMask); |
| } |
| |
| IIOMetadataNode subNode = new IIOMetadataNode("BitsPerSample"); |
| subNode.setAttribute("value", bits); |
| node.appendChild(subNode); |
| |
| return node; |
| } |
| |
| protected IIOMetadataNode getStandardDimensionNode() { |
| if (yPixelsPerMeter > 0.0F && xPixelsPerMeter > 0.0F) { |
| IIOMetadataNode node = new IIOMetadataNode("Dimension"); |
| float ratio = yPixelsPerMeter / xPixelsPerMeter; |
| IIOMetadataNode subNode = new IIOMetadataNode("PixelAspectRatio"); |
| subNode.setAttribute("value", "" + ratio); |
| node.appendChild(subNode); |
| |
| subNode = new IIOMetadataNode("HorizontalPhysicalPixelSpacing"); |
| subNode.setAttribute("value", "" + (1 / xPixelsPerMeter * 1000)); |
| node.appendChild(subNode); |
| |
| subNode = new IIOMetadataNode("VerticalPhysicalPixelSpacing"); |
| subNode.setAttribute("value", "" + (1 / yPixelsPerMeter * 1000)); |
| node.appendChild(subNode); |
| |
| return node; |
| } |
| return null; |
| } |
| |
| public void setFromTree(String formatName, Node root) { |
| throw new IllegalStateException(I18N.getString("BMPMetadata1")); |
| } |
| |
| public void mergeTree(String formatName, Node root) { |
| throw new IllegalStateException(I18N.getString("BMPMetadata1")); |
| } |
| |
| public void reset() { |
| throw new IllegalStateException(I18N.getString("BMPMetadata1")); |
| } |
| |
| private String countBits(int num) { |
| int count = 0; |
| while(num > 0) { |
| if ((num & 1) == 1) |
| count++; |
| num >>>= 1; |
| } |
| |
| return count == 0 ? "" : "" + count; |
| } |
| |
| private void addXYZPoints(IIOMetadataNode root, String name, double x, double y, double z) { |
| IIOMetadataNode node = addChildNode(root, name, null); |
| addChildNode(node, "X", new Double(x)); |
| addChildNode(node, "Y", new Double(y)); |
| addChildNode(node, "Z", new Double(z)); |
| } |
| |
| private IIOMetadataNode addChildNode(IIOMetadataNode root, |
| String name, |
| Object object) { |
| IIOMetadataNode child = new IIOMetadataNode(name); |
| if (object != null) { |
| child.setUserObject(object); |
| child.setNodeValue(ImageUtil.convertObjectToString(object)); |
| } |
| root.appendChild(child); |
| return child; |
| } |
| } |