]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Fix JPEG with many long APPS markers.
authorJeremias Maerki <jeremias@apache.org>
Mon, 16 Aug 2004 19:33:19 +0000 (19:33 +0000)
committerJeremias Maerki <jeremias@apache.org>
Mon, 16 Aug 2004 19:33:19 +0000 (19:33 +0000)
Also defers the creation of the original node until it absolutely has to thus avoiding decoding the JPEG file and creating the raster unless needed.
Submitted by: Thomas DeWeese <Thomas.DeWeese.at.Kodak.com>

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@197881 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/image/analyser/JPEGReader.java
src/java/org/apache/fop/svg/PDFImageElementBridge.java

index 21adf0c60e04f1eaa3b0df1309f08744747f378a..3aafbb8bc282812ede5ad04370a91f35effefed8 100644 (file)
@@ -98,17 +98,35 @@ public class JPEGReader implements ImageReader {
     private FopImage.ImageInfo getDimension(InputStream imageStream) throws IOException {
         FopImage.ImageInfo info = new FopImage.ImageInfo();
         try {
-            imageStream.mark(imageStream.available());
+            int pos=0, avail = imageStream.available();
+            imageStream.mark(avail);
             int marker = NULL;
             long length, skipped;
 outer:
-            while (imageStream.available() > 0) {
-                while ((marker = imageStream.read()) != MARK) {
-                    //nop, simply skip
+            while (true) {
+                do {
+                    if (avail == 0) {
+                        imageStream.reset();
+                        avail = 2*pos;
+                        imageStream.mark(avail);
+                        pos = (int)this.skip(imageStream, pos);
+                        avail -= pos;
                 }
 
+                    marker = imageStream.read();
+                    pos++; avail--;
+                } while (marker != MARK);
+
                 do {
+                    if (avail == 0) {
+                        imageStream.reset();
+                        avail = 2*pos;
+                        imageStream.mark(avail);
+                        pos = (int)this.skip(imageStream, pos);
+                        avail -= pos;
+                    }
                     marker = imageStream.read();
+                    pos++; avail--;
                 } while (marker == MARK);
 
                 switch (marker) {
@@ -120,13 +138,42 @@ outer:
                     case SOF2:
                     case SOF3: // SOF3 and SOFA are only supported by PDF 1.3
                     case SOFA:
+                        while (avail < 7) {
+                            imageStream.reset();
+                            avail = 2*pos;
+                            imageStream.mark(avail);
+                            pos = (int)this.skip(imageStream, pos);
+                            avail -= pos;
+                        }
                         this.skip(imageStream, 3);
+                        pos+=3; avail-=3;
                         info.height = this.read2bytes(imageStream);
+                        pos+=2; avail-=2;
                         info.width = this.read2bytes(imageStream);
+                        pos+=2; avail-=2;
                         break outer;
                     default:
+                        while (avail < 2) {
+                            imageStream.reset();
+                            avail = 2*pos;
+                            imageStream.mark(avail);
+                            pos = (int)this.skip(imageStream, pos);
+                            avail -= pos;
+                        }
                         length = this.read2bytes(imageStream);
+                        pos+=2; avail-=2;
+                        if (avail < length) {
+                            imageStream.reset();
+                            avail = 2*pos;
+                            if (avail < pos+length+10) {
+                                avail = (int)(pos+length+10);
+                            }
+                            imageStream.mark(avail);
+                            pos = (int)this.skip(imageStream, pos);
+                            avail -= pos;
+                        }
                         skipped = this.skip(imageStream, length - 2);
+                        pos += skipped; avail -= skipped;
                         if (skipped != length - 2) {
                             throw new IOException("Skipping Error");
                         }
index 567e0c46d2d00a833c672217da06d44f434ec455..a77855ed04fae61a4f07ffa8967cc6e31f24c9e6 100644 (file)
@@ -27,6 +27,8 @@ import org.apache.fop.image.analyser.ImageReaderFactory;
 import java.awt.Shape;
 import java.awt.Graphics2D;
 import java.awt.geom.Rectangle2D;
+import java.io.BufferedInputStream;
+import java.io.InputStream;
 
 import org.w3c.dom.Element;
 
@@ -59,17 +61,25 @@ public class PDFImageElementBridge extends SVGImageElementBridge {
      */
     protected GraphicsNode createImageGraphicsNode
         (BridgeContext ctx, Element e, ParsedURL purl) {
-        GraphicsNode origGN = super.createImageGraphicsNode
-            (ctx, e, purl);
         try {
+            InputStream is = purl.openStream();
+            if (!is.markSupported()) {
+                is = new BufferedInputStream(is, 1024);
+            }
+            
+            is.mark(3);
+            byte [] data = new byte[3];
+            is.read(data);
+            is.reset();
+            if ((data[0] == (byte)0xFF) && (data[1] == (byte)0xD8) && 
+                (data[2] == (byte)0xFF)) {
             FopImage.ImageInfo ii = ImageReaderFactory.make
-                (purl.toString(), purl.openStream(), null);
-            if (ii.mimeType.toLowerCase() == "image/jpeg") {
+                    (purl.toString(), is, null);
                 JpegImage jpeg = new JpegImage(ii);
                 SimpleLog logger = new SimpleLog("FOP/SVG");
                 logger.setLevel(SimpleLog.LOG_LEVEL_INFO);
                 jpeg.load(FopImage.ORIGINAL_DATA);
-                PDFJpegNode node = new PDFJpegNode(jpeg, origGN);
+                PDFJpegNode node = new PDFJpegNode(jpeg, ctx, e, purl);
 
                 Rectangle2D imgBounds = getImageBounds(ctx, e);
             Rectangle2D bounds = node.getPrimitiveBounds();
@@ -87,26 +97,37 @@ public class PDFImageElementBridge extends SVGImageElementBridge {
         } catch (Exception ex) {
         }
 
-        return origGN;
+        return superCreateGraphicsNode(ctx, e, purl);
+    }
+
+    protected GraphicsNode superCreateGraphicsNode
+        (BridgeContext ctx, Element e, ParsedURL purl) {
+        return super.createImageGraphicsNode(ctx, e, purl);
     }
 
+
     /**
      * A PDF jpeg node.
      * This holds a jpeg image so that it can be drawn into
      * the PDFGraphics2D.
      */
-    public static class PDFJpegNode extends AbstractGraphicsNode {
+    public class PDFJpegNode extends AbstractGraphicsNode {
         private JpegImage jpeg;
-        private GraphicsNode origGraphicsNode ;
+        private BridgeContext ctx;
+        private Element e;
+        private ParsedURL purl;
+        private GraphicsNode origGraphicsNode=null;
         /**
          * Create a new pdf jpeg node for drawing jpeg images
          * into pdf graphics.
          * @param j the jpeg image
          */
-        public PDFJpegNode(JpegImage j,
-                           GraphicsNode origGraphicsNode) {
-            jpeg = j;
-            this.origGraphicsNode = origGraphicsNode;
+        public PDFJpegNode(JpegImage j, BridgeContext ctx, 
+                           Element e, ParsedURL purl) {
+            this.jpeg = j;
+            this.ctx  = ctx;
+            this.e    = e;
+            this.purl = purl;
         }
 
         /**
@@ -137,7 +158,14 @@ public class PDFImageElementBridge extends SVGImageElementBridge {
                 }
             } else {
                 // Not going directly into PDF so use
-                // original implemtation so filters etc work.
+                // original implementation so filters etc work.
+                if (origGraphicsNode == null) {
+                    // Haven't constructed baseclass Graphics Node,
+                    // so do so now.
+                    origGraphicsNode = 
+                        PDFImageElementBridge.this.superCreateGraphicsNode
+                        (ctx,  e, purl);
+                }
                 origGraphicsNode.primitivePaint(g2d);
             }
         }