--- /dev/null
+/*\r
+ * Copyright 2006 The Apache Software Foundation.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/* $Id$ */\r
+ \r
+package org.apache.fop.render;\r
+\r
+import java.awt.image.RenderedImage;\r
+import java.io.IOException;\r
+\r
+/**\r
+ * This interface represents an optional feature that can be provided by\r
+ * a renderer. It is exposed by calling the getImageAdapter() method\r
+ * on the renderer. Renderers that support this feature allow painting\r
+ * of images (RendererImage instances).\r
+ */\r
+public interface ImageAdapter {\r
+\r
+ /**\r
+ * Paints an image at the given position.\r
+ * @param image the image which will be painted\r
+ * @param context the renderer context for the current renderer\r
+ * @param x X position of the image\r
+ * @param y Y position of the image\r
+ * @param width width of the image\r
+ * @param height height of the image\r
+ * @throws IOException In case of an I/O error while writing the output format\r
+ */\r
+ void paintImage(RenderedImage image, \r
+ RendererContext context,\r
+ int x, int y, int width, int height) throws IOException;\r
+ \r
+}\r
/*
- * Copyright 2004-2005 The Apache Software Foundation.
+ * 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.
package org.apache.fop.render.ps;
+import java.awt.Dimension;
import java.awt.color.ColorSpace;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.ColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.Raster;
+import java.awt.image.RenderedImage;
import java.io.IOException;
import java.io.OutputStream;
return;
}
}
- boolean iscolor = img.getColorSpace().getType()
- != ColorSpace.CS_GRAY;
byte[] imgmap;
if (img.getBitmapsSize() > 0) {
imgmap = img.getBitmaps();
} else {
imgmap = img.getRessourceBytes();
}
+
+ String imgName = img.getMimeType() + " " + img.getOriginalURI();
+ Dimension imgDim = new Dimension(img.getWidth(), img.getHeight());
+ Rectangle2D targetRect = new Rectangle2D.Double(x, y, w, h);
+ boolean isJPEG = (img instanceof JpegImage);
+ writeImage(imgmap, imgDim, imgName, targetRect, isJPEG,
+ img.getColorSpace(), gen);
+ }
+
+ private static void writeImage(byte[] img,
+ Dimension imgDim, String imgName,
+ Rectangle2D targetRect,
+ boolean isJPEG, ColorSpace colorSpace,
+ PSGenerator gen) throws IOException {
+ boolean iscolor = colorSpace.getType() != ColorSpace.CS_GRAY;
gen.saveGraphicsState();
- gen.writeln(x + " " + y + " translate");
- gen.writeln(w + " " + h + " scale");
+ gen.writeln(gen.formatDouble(targetRect.getX()) + " "
+ + gen.formatDouble(targetRect.getY()) + " translate");
+ gen.writeln(gen.formatDouble(targetRect.getWidth()) + " "
+ + gen.formatDouble(targetRect.getHeight()) + " scale");
- gen.commentln("%FOPBeginBitmap: " + img.getMimeType() + " " + img.getOriginalURI());
- if (img.getColorSpace().getType() == ColorSpace.TYPE_CMYK) {
+ gen.commentln("%FOPBeginBitmap: " + imgName);
+ if (colorSpace.getType() == ColorSpace.TYPE_CMYK) {
gen.writeln("/DeviceCMYK setcolorspace");
- } else if (img.getColorSpace().getType() == ColorSpace.CS_GRAY) {
+ } else if (colorSpace.getType() == ColorSpace.CS_GRAY) {
gen.writeln("/DeviceGray setcolorspace");
} else {
gen.writeln("/DeviceRGB setcolorspace");
// Template: (RawData is used for the EOF signal only)
// gen.write("/RawData currentfile <first filter> filter def");
// gen.write("/Data RawData <second filter> <third filter> [...] def");
- if (img instanceof JpegImage) {
+ if (isJPEG) {
gen.writeln("/RawData currentfile /ASCII85Decode filter def");
gen.writeln("/Data RawData << >> /DCTDecode filter def");
} else {
}
gen.writeln("<<");
gen.writeln(" /ImageType 1");
- gen.writeln(" /Width " + img.getWidth());
- gen.writeln(" /Height " + img.getHeight());
+ gen.writeln(" /Width " + imgDim.width);
+ gen.writeln(" /Height " + imgDim.height);
gen.writeln(" /BitsPerComponent 8");
- if (img.getColorSpace().getType() == ColorSpace.TYPE_CMYK) {
+ if (colorSpace.getType() == ColorSpace.TYPE_CMYK) {
if (false /*TODO img.invertImage()*/) {
gen.writeln(" /Decode [1 0 1 0 1 0 1 0]");
} else {
gen.writeln(" /Decode [0 1]");
}
// Setup scanning for left-to-right and top-to-bottom
- gen.writeln(" /ImageMatrix [" + img.getWidth() + " 0 0 "
- + img.getHeight() + " 0 0]");
+ gen.writeln(" /ImageMatrix [" + imgDim.width + " 0 0 "
+ + imgDim.height + " 0 0]");
gen.writeln(" /DataSource Data");
gen.writeln(">>");
OutputStream out = gen.getOutputStream();
out = new ASCII85OutputStream(out);
- if (img instanceof JpegImage) {
+ if (isJPEG) {
//nop
} else {
if (gen.getPSLevel() >= 3) {
out = new RunLengthEncodeOutputStream(out);
}
}
- out.write(imgmap);
+ out.write(img);
if (out instanceof Finalizable) {
((Finalizable)out).finalizeStream();
} else {
gen.restoreGraphicsState();
}
+ /**
+ * Renders a bitmap image to PostScript.
+ * @param img image to render
+ * @param x x position
+ * @param y y position
+ * @param w width
+ * @param h height
+ * @param gen PS generator
+ * @throws IOException In case of an I/O problem while rendering the image
+ */
+ public static void renderBitmapImage(RenderedImage img,
+ float x, float y, float w, float h, PSGenerator gen)
+ throws IOException {
+ byte[] imgmap = getBitmapBytes(img);
+
+ String imgName = img.getClass().getName();
+ Dimension imgDim = new Dimension(img.getWidth(), img.getHeight());
+ Rectangle2D targetRect = new Rectangle2D.Double(x, y, w, h);
+ boolean isJPEG = false;
+ writeImage(imgmap, imgDim, imgName, targetRect, isJPEG,
+ img.getColorModel().getColorSpace(), gen);
+ }
+
+ private static byte[] getBitmapBytes(RenderedImage img) {
+ int[] tmpMap = getRGB(img, 0, 0, img.getWidth(), img.getHeight(), null, 0, img.getWidth());
+ // Should take care of the ColorSpace and bitsPerPixel
+ byte[] bitmaps = new byte[img.getWidth() * img.getHeight() * 3];
+ for (int y = 0, my = img.getHeight(); y < my; y++) {
+ for (int x = 0, mx = img.getWidth(); x < mx; x++) {
+ int p = tmpMap[y * mx + x];
+ int r = (p >> 16) & 0xFF;
+ int g = (p >> 8) & 0xFF;
+ int b = (p) & 0xFF;
+ bitmaps[3 * (y * mx + x)] = (byte)(r & 0xFF);
+ bitmaps[3 * (y * mx + x) + 1] = (byte)(g & 0xFF);
+ bitmaps[3 * (y * mx + x) + 2] = (byte)(b & 0xFF);
+ }
+ }
+ return bitmaps;
+ }
+
+ public static int[] getRGB(RenderedImage img,
+ int startX, int startY, int w, int h,
+ int[] rgbArray, int offset, int scansize) {
+ Raster raster = img.getData();
+ int yoff = offset;
+ int off;
+ Object data;
+ int nbands = raster.getNumBands();
+ int dataType = raster.getDataBuffer().getDataType();
+ switch (dataType) {
+ case DataBuffer.TYPE_BYTE:
+ data = new byte[nbands];
+ break;
+ case DataBuffer.TYPE_USHORT:
+ data = new short[nbands];
+ break;
+ case DataBuffer.TYPE_INT:
+ data = new int[nbands];
+ break;
+ case DataBuffer.TYPE_FLOAT:
+ data = new float[nbands];
+ break;
+ case DataBuffer.TYPE_DOUBLE:
+ data = new double[nbands];
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown data buffer type: "+
+ dataType);
+ }
+
+ if (rgbArray == null) {
+ rgbArray = new int[offset+h*scansize];
+ }
+
+ ColorModel colorModel = img.getColorModel();
+ for (int y = startY; y < startY+h; y++, yoff+=scansize) {
+ off = yoff;
+ for (int x = startX; x < startX+w; x++) {
+ rgbArray[off++] = colorModel.getRGB(raster.getDataElements(x,
+ y,
+ data));
+ }
+ }
+
+ return rgbArray;
+
+ }
+
public static void renderEPS(EPSImage img,
float x, float y, float w, float h,
PSGenerator gen) {
// Java
import java.awt.Color;
import java.awt.geom.Rectangle2D;
+import java.awt.image.RenderedImage;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.OutputStream;
import org.apache.fop.image.XMLImage;
import org.apache.fop.render.Graphics2DAdapter;
import org.apache.fop.render.AbstractPathOrientedRenderer;
+import org.apache.fop.render.ImageAdapter;
import org.apache.fop.render.RendererContext;
import org.apache.fop.render.ps.extensions.PSSetupCode;
import org.apache.fop.util.CharUtilities;
* @author <a href="mailto:fop-dev@xmlgraphics.apache.org">Apache FOP Development Team</a>
* @version $Id$
*/
-public class PSRenderer extends AbstractPathOrientedRenderer {
+public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAdapter {
/** The MIME type for PostScript */
public static final String MIME_TYPE = "application/postscript";
return new PSGraphics2DAdapter(this);
}
+ /** @see org.apache.fop.render.Renderer#getImageAdapter() */
+ public ImageAdapter getImageAdapter() {
+ return this;
+ }
+
/**
* Write out a command
* @param cmd PostScript command
}
}
+ public void paintImage(RenderedImage image, RendererContext context, int x, int y, int width, int height) throws IOException {
+ float fx = (float)x / 1000f;
+ x += currentIPPosition / 1000f;
+ float fy = (float)y / 1000f;
+ y += currentBPPosition / 1000f;
+ float fw = (float)width / 1000f;
+ float fh = (float)height / 1000f;
+ PSImageUtils.renderBitmapImage(image, fx, fy, fw, fh, gen);
+ }
+
/**
* Draw a line.
*
gen.writeDSCComment(DSCConstants.BEGIN_PAGE_SETUP);
//Handle PSSetupCode instances on simple-page-master
- if (page.getExtensionAttachments().size() > 0) {
+ if (page.getExtensionAttachments() != null
+ && page.getExtensionAttachments().size() > 0) {
List list = new java.util.ArrayList();
//Extract all PSSetupCode instances from the attachment list on the s-p-m
Iterator i = page.getExtensionAttachments().iterator();
return MIME_TYPE;
}
+
}