aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache/fop/image/XmlGraphicsCommonsImage.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/java/org/apache/fop/image/XmlGraphicsCommonsImage.java')
-rw-r--r--src/java/org/apache/fop/image/XmlGraphicsCommonsImage.java237
1 files changed, 237 insertions, 0 deletions
diff --git a/src/java/org/apache/fop/image/XmlGraphicsCommonsImage.java b/src/java/org/apache/fop/image/XmlGraphicsCommonsImage.java
new file mode 100644
index 000000000..ee079aad5
--- /dev/null
+++ b/src/java/org/apache/fop/image/XmlGraphicsCommonsImage.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2004-2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.image;
+
+import java.awt.Color;
+import java.awt.Transparency;
+import java.awt.image.ColorModel;
+import java.awt.image.IndexColorModel;
+import java.awt.image.RenderedImage;
+import java.awt.image.WritableRaster;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+
+import org.apache.xmlgraphics.image.GraphicsUtil;
+import org.apache.xmlgraphics.image.codec.util.SeekableStream;
+import org.apache.xmlgraphics.image.codec.util.MemoryCacheSeekableStream;
+import org.apache.xmlgraphics.image.codec.util.FileCacheSeekableStream;
+import org.apache.xmlgraphics.image.rendered.CachableRed;
+
+import org.apache.commons.io.IOUtils;
+
+/**
+ * Abstract FopImage implementation which uses the internal codecs from XML Graphics Commons.
+ * @see AbstractFopImage
+ * @see FopImage
+ */
+public abstract class XmlGraphicsCommonsImage extends AbstractFopImage {
+
+ private byte[] softMask = null;
+
+ /**
+ * The InputStream wrapped into a SeekableStream for decoding.
+ */
+ protected SeekableStream seekableInput = null;
+
+ /**
+ * The Batik representation of the image
+ */
+ protected CachableRed cr = null;
+
+ /**
+ * Constructs a new BatikImage instance.
+ * @param imgReader basic metadata for the image
+ */
+ public XmlGraphicsCommonsImage(FopImage.ImageInfo imgReader) {
+ super(imgReader);
+ }
+
+ /**
+ * @see org.apache.fop.image.AbstractFopImage#loadDimensions()
+ */
+ protected boolean loadDimensions() {
+ if (seekableInput == null && inputStream != null) {
+ try {
+ seekableInput = new FileCacheSeekableStream(inputStream);
+ } catch (IOException ioe) {
+ seekableInput = new MemoryCacheSeekableStream(inputStream);
+ }
+ try {
+ this.bitsPerPixel = 8;
+ cr = decodeImage(seekableInput);
+ this.height = cr.getHeight();
+ this.width = cr.getWidth();
+ this.isTransparent = false;
+ this.softMask = null;
+ ColorModel cm = cr.getColorModel();
+
+ this.height = cr.getHeight();
+ this.width = cr.getWidth();
+ this.isTransparent = false;
+ this.softMask = null;
+
+ int transparencyType = cm.getTransparency();
+ if (cm instanceof IndexColorModel) {
+ if (transparencyType == Transparency.BITMASK) {
+ // Use 'transparent color'.
+ IndexColorModel icm = (IndexColorModel)cm;
+ int numColor = icm.getMapSize();
+ byte [] alpha = new byte[numColor];
+ icm.getAlphas(alpha);
+ for (int i = 0; i < numColor; i++) {
+ if ((alpha[i] & 0xFF) == 0) {
+ this.isTransparent = true;
+ int red = (icm.getRed (i)) & 0xFF;
+ int grn = (icm.getGreen(i)) & 0xFF;
+ int blu = (icm.getBlue (i)) & 0xFF;
+ this.transparentColor = new Color(red, grn, blu);
+ break;
+ }
+ }
+ }
+ } else {
+ cr = GraphicsUtil.convertTosRGB(cr);
+ }
+
+ // Get our current ColorModel
+ cm = cr.getColorModel();
+ if (this.colorSpace == null) {
+ this.colorSpace = cm.getColorSpace();
+ }
+ } catch (IOException ioe) {
+ log.error("Error while loading image (Batik): " + ioe.getMessage(), ioe);
+ IOUtils.closeQuietly(seekableInput);
+ IOUtils.closeQuietly(inputStream);
+ seekableInput = null;
+ inputStream = null;
+ return false;
+ }
+ }
+ return this.height != -1;
+ }
+
+ /**
+ * @see org.apache.fop.image.AbstractFopImage#loadBitmap()
+ */
+ protected boolean loadBitmap() {
+ if (this.bitmaps == null) {
+ loadImage();
+ }
+
+ return this.bitmaps != null;
+ }
+
+ /**
+ * @see org.apache.fop.image.FopImage#hasSoftMask()
+ */
+ public boolean hasSoftMask() {
+ if (this.bitmaps == null && this.raw == null) {
+ loadImage();
+ }
+
+ return (this.softMask != null);
+ }
+
+ /**
+ * @see org.apache.fop.image.FopImage#getSoftMask()
+ */
+ public byte[] getSoftMask() {
+ if (this.bitmaps == null) {
+ loadImage();
+ }
+
+ return this.softMask;
+ }
+
+ /**
+ * Decodes the image from the stream.
+ * @param stream the stream to read the image from
+ * @return the decoded image
+ * @throws IOException in case an I/O problem occurs
+ */
+ protected abstract CachableRed decodeImage(SeekableStream stream) throws IOException;
+
+ /**
+ * Loads the image from the InputStream.
+ */
+ protected void loadImage() {
+ if (loadDimensions()) {
+ try {
+ if (cr == null) {
+ throw new IllegalStateException(
+ "Can't load the bitmaps data without the CachableRed instance");
+ }
+
+ // Get our current ColorModel
+ ColorModel cm = cr.getColorModel();
+
+ // It has an alpha channel so generate a soft mask.
+ if (!this.isTransparent && cm.hasAlpha()) {
+ this.softMask = new byte[this.width * this.height];
+ }
+
+ this.bitmaps = new byte[this.width * this.height * 3];
+
+ constructBitmaps(cr, this.bitmaps, this.softMask);
+ } catch (Exception ex) {
+ log.error("Error while loading image (Batik): " + ex.getMessage(), ex);
+ } finally {
+ // Make sure we clean up
+ IOUtils.closeQuietly(seekableInput);
+ IOUtils.closeQuietly(inputStream);
+ seekableInput = null;
+ inputStream = null;
+ cr = null;
+ }
+ }
+ }
+
+ private static void constructBitmaps(RenderedImage red, byte[] bitmaps, byte[] softMask) {
+ WritableRaster wr = (WritableRaster)red.getData();
+ ColorModel cm = red.getColorModel();
+ BufferedImage bi = new BufferedImage
+ (cm, wr.createWritableTranslatedChild(0, 0),
+ cm.isAlphaPremultiplied(), null);
+ int width = red.getWidth();
+ int height = red.getHeight();
+ int [] tmpMap = new int[width];
+ int idx = 0;
+ int sfIdx = 0;
+ for (int y = 0; y < height; y++) {
+ tmpMap = bi.getRGB(0, y, width, 1, tmpMap, 0, width);
+ if (softMask != null) {
+ for (int x = 0; x < width; x++) {
+ int pix = tmpMap[x];
+ softMask[sfIdx++] = (byte)(pix >>> 24);
+ bitmaps[idx++] = (byte)((pix >>> 16) & 0xFF);
+ bitmaps[idx++] = (byte)((pix >>> 8) & 0xFF);
+ bitmaps[idx++] = (byte)((pix) & 0xFF);
+ }
+ } else {
+ for (int x = 0; x < width; x++) {
+ int pix = tmpMap[x];
+ bitmaps[idx++] = (byte)((pix >> 16) & 0xFF);
+ bitmaps[idx++] = (byte)((pix >> 8) & 0xFF);
+ bitmaps[idx++] = (byte)((pix) & 0xFF);
+ }
+ }
+ }
+ }
+
+} \ No newline at end of file