]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Following the model of Graphics2DAdapter, added a new interface ImageAdapter which...
authorJeremias Maerki <jeremias@apache.org>
Tue, 24 Jan 2006 20:02:30 +0000 (20:02 +0000)
committerJeremias Maerki <jeremias@apache.org>
Tue, 24 Jan 2006 20:02:30 +0000 (20:02 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@372004 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/render/AbstractRenderer.java
src/java/org/apache/fop/render/ImageAdapter.java [new file with mode: 0644]
src/java/org/apache/fop/render/Renderer.java
src/java/org/apache/fop/render/ps/PSImageUtils.java
src/java/org/apache/fop/render/ps/PSRenderer.java

index 850190aab8dbb047fedff2a3baa686847fb2d447..8dbaeaa20dd0cf1385b838e95dd754ba97ac219b 100644 (file)
@@ -164,6 +164,11 @@ public abstract class AbstractRenderer
         return null;
     }
     
+    /** @see org.apache.fop.render.Renderer#getImageAdapter() */
+    public ImageAdapter getImageAdapter() {
+        return null;
+    }
+    
     /** @return the current PageViewport or null, if none is active */
     protected PageViewport getCurrentPageViewport() {
         return this.currentPageViewport;
diff --git a/src/java/org/apache/fop/render/ImageAdapter.java b/src/java/org/apache/fop/render/ImageAdapter.java
new file mode 100644 (file)
index 0000000..e49741d
--- /dev/null
@@ -0,0 +1,46 @@
+/*\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
index da347e0e637bf1a1900bad3c6c399245dd41c418..e71f3300122291505b0ef2e912e3e31f5caf34ec 100644 (file)
@@ -121,6 +121,11 @@ public interface Renderer {
      */
     Graphics2DAdapter getGraphics2DAdapter();
     
+    /**
+     * @return the adapter for painting RenderedImages (or null if not supported)
+     */
+    ImageAdapter getImageAdapter();
+    
     /**
      * This is called if the renderer supports out of order rendering. The
      * renderer should prepare the page so that a page further on in the set of
index 991ea73965b3dec69bc620739c3b782d9a91aa8c..bd3736eb5e211dd3cee993d44ef15350372ecf4b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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;
 
@@ -64,23 +70,38 @@ public class PSImageUtils {
                 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");
@@ -90,7 +111,7 @@ public class PSImageUtils {
         // 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 {
@@ -104,10 +125,10 @@ public class PSImageUtils {
         }
         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 {
@@ -119,8 +140,8 @@ public class PSImageUtils {
             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(">>");
@@ -135,7 +156,7 @@ public class PSImageUtils {
 
         OutputStream out = gen.getOutputStream();
         out = new ASCII85OutputStream(out);
-        if (img instanceof JpegImage) {
+        if (isJPEG) {
             //nop
         } else {
             if (gen.getPSLevel() >= 3) {
@@ -144,7 +165,7 @@ public class PSImageUtils {
                 out = new RunLengthEncodeOutputStream(out);
             }
         }
-        out.write(imgmap);
+        out.write(img);
         if (out instanceof Finalizable) {
             ((Finalizable)out).finalizeStream();
         } else {
@@ -156,6 +177,95 @@ public class PSImageUtils {
         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) {
index 5d32423461c719e43521b1694aed1c33e4afa973..b786a49627c33348b11a6b5da63b6704973ebe53 100644 (file)
@@ -21,6 +21,7 @@ package org.apache.fop.render.ps;
 // 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;
@@ -63,6 +64,7 @@ import org.apache.fop.image.ImageFactory;
 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;
@@ -88,7 +90,7 @@ import org.w3c.dom.Document;
  * @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";
@@ -154,6 +156,11 @@ public class PSRenderer extends AbstractPathOrientedRenderer {
         return new PSGraphics2DAdapter(this);
     }
 
+    /** @see org.apache.fop.render.Renderer#getImageAdapter() */
+    public ImageAdapter getImageAdapter() {
+        return this;
+    }
+
     /**
      * Write out a command
      * @param cmd PostScript command
@@ -303,6 +310,16 @@ public class PSRenderer extends AbstractPathOrientedRenderer {
         }
     }
 
+    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.
      *
@@ -740,7 +757,8 @@ public class PSRenderer extends AbstractPathOrientedRenderer {
         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();
@@ -1104,4 +1122,5 @@ public class PSRenderer extends AbstractPathOrientedRenderer {
         return MIME_TYPE;
     }
 
+
 }