/* * Copyright 2004 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.WritableRaster; import java.awt.image.BufferedImage; import java.io.IOException; import org.apache.batik.ext.awt.image.codec.SeekableStream; import org.apache.batik.ext.awt.image.codec.MemoryCacheSeekableStream; import org.apache.batik.ext.awt.image.codec.FileCacheSeekableStream; import org.apache.batik.ext.awt.image.rendered.Any2sRGBRed; import org.apache.batik.ext.awt.image.rendered.CachableRed; /** * FopImage object using TIFF * @author Eric SCHAEFFER * @see AbstractFopImage * @see FopImage */ public abstract class BatikImage extends AbstractFopImage { private byte[] softMask = null; /** * Constructs a new BatikImage instance. * @param imgReader basic metadata for the image */ public BatikImage(FopImage.ImageInfo imgReader) { super(imgReader); } /** * @see org.apache.fop.image.AbstractFopImage#loadDimensions() */ protected boolean loadDimensions() { if (this.bitmaps == null) { loadImage(); } return this.bitmaps != null; } /** * @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) { 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() { try { SeekableStream seekableInput; try { seekableInput = new FileCacheSeekableStream(inputStream); } catch (IOException ioe) { seekableInput = new MemoryCacheSeekableStream(inputStream); } CachableRed cr = decodeImage(seekableInput); ColorModel cm = cr.getColorModel(); this.height = cr.getHeight(); this.width = cr.getWidth(); this.isTransparent = false; this.softMask = null; this.bitmapsSize = this.width * this.height * 3; this.bitmaps = new byte[this.bitmapsSize]; this.bitsPerPixel = 8; 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 = new Any2sRGBRed(cr); } // Get our current 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.colorSpace = cm.getColorSpace(); WritableRaster wr = (WritableRaster)cr.getData(); BufferedImage bi = new BufferedImage (cm, wr.createWritableTranslatedChild(0, 0), cm.isAlphaPremultiplied(), null); int [] tmpMap = new int[this.width]; int idx = 0; int sfIdx = 0; for (int y = 0; y < this.height; y++) { tmpMap = bi.getRGB(0, y, this.width, 1, tmpMap, 0, this.width); if (softMask != null) { for (int x = 0; x < this.width; x++) { int pix = tmpMap[x]; this.softMask[sfIdx++] = (byte)(pix >>> 24); this.bitmaps[idx++] = (byte)((pix >>> 16) & 0xFF); this.bitmaps[idx++] = (byte)((pix >>> 8) & 0xFF); this.bitmaps[idx++] = (byte)((pix) & 0xFF); } } else { for (int x = 0; x < this.width; x++) { int pix = tmpMap[x]; this.bitmaps[idx++] = (byte)((pix >> 16) & 0xFF); this.bitmaps[idx++] = (byte)((pix >> 8) & 0xFF); this.bitmaps[idx++] = (byte)((pix) & 0xFF); } } } } catch (Exception ex) { log.error("Error loading an image" , ex); /*throw new FopImageException("Error while loading image " + "" + " : " + ex.getClass() + " - " + ex.getMessage()); */ } } };