]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
AFP Renderer: Bugfix for 1 bit images where the width is not a multiple of 8.
authorJeremias Maerki <jeremias@apache.org>
Tue, 31 Jul 2007 09:28:47 +0000 (09:28 +0000)
committerJeremias Maerki <jeremias@apache.org>
Tue, 31 Jul 2007 09:28:47 +0000 (09:28 +0000)
Essentially, I rewrote convertToGrayScaleImage() to properly padding at the end of each scanline if necessary.

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

src/java/org/apache/fop/render/afp/AFPRenderer.java
status.xml

index 1960b1110d93f958a21d6745b22a46e8e963887d..423f48d7369d8dc1cfc814a7fefa85882e2f2571 100644 (file)
@@ -45,8 +45,8 @@ import org.apache.fop.area.PageViewport;
 import org.apache.fop.area.RegionReference;
 import org.apache.fop.area.RegionViewport;
 import org.apache.fop.area.Trait;
-import org.apache.fop.area.inline.Leader;
 import org.apache.fop.area.inline.Image;
+import org.apache.fop.area.inline.Leader;
 import org.apache.fop.area.inline.SpaceArea;
 import org.apache.fop.area.inline.TextArea;
 import org.apache.fop.area.inline.WordArea;
@@ -67,8 +67,8 @@ import org.apache.fop.render.Graphics2DAdapter;
 import org.apache.fop.render.RendererContext;
 import org.apache.fop.render.afp.extensions.AFPElementMapping;
 import org.apache.fop.render.afp.extensions.AFPPageSetup;
-import org.apache.fop.render.afp.fonts.AFPFontInfo;
 import org.apache.fop.render.afp.fonts.AFPFont;
+import org.apache.fop.render.afp.fonts.AFPFontInfo;
 import org.apache.fop.render.afp.fonts.CharacterSet;
 import org.apache.fop.render.afp.fonts.FopCharacterSet;
 import org.apache.fop.render.afp.fonts.OutlineFont;
@@ -954,13 +954,15 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
                         if (!fopimage.load(FopImage.BITMAP)) {
                             return;
                         }
-                        convertToGrayScaleImage(io, fopimage.getBitmaps());
+                        convertToGrayScaleImage(io, fopimage.getBitmaps(), 
+                                fopimage.getWidth(), fopimage.getHeight());
                     }
                 } else {
                     if (!fopimage.load(FopImage.BITMAP)) {
                         return;
                     }
-                    convertToGrayScaleImage(io, fopimage.getBitmaps());
+                    convertToGrayScaleImage(io, fopimage.getBitmaps(),
+                            fopimage.getWidth(), fopimage.getHeight());
                 }
             } else {
                 if (!fopimage.load(FopImage.BITMAP)) {
@@ -983,7 +985,8 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
                     io.setImageIDESize((byte)24);
                     io.setImageData(fopimage.getBitmaps());
                 } else {
-                    convertToGrayScaleImage(io, fopimage.getBitmaps());
+                    convertToGrayScaleImage(io, fopimage.getBitmaps(),
+                            fopimage.getWidth(), fopimage.getHeight());
                 }
             }
         }
@@ -1045,7 +1048,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
             } else {
                 //TODO Teach it how to handle grayscale BufferedImages directly
                 //because this is pretty inefficient
-                convertToGrayScaleImage(io, buf);
+                convertToGrayScaleImage(io, buf, bi.getWidth(), bi.getHeight());
             }
         } catch (IOException ioe) {
             log.error("Error while serializing bitmap: " + ioe.getMessage(), ioe);
@@ -1433,35 +1436,53 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
         return (int)Math.round(mpt / DPI_CONVERSION_FACTOR_240);
     }
 
-    private void convertToGrayScaleImage(ImageObject io, byte[] raw) {
+    /**
+     * Converts a byte array containing 24 bit RGB image data to a grayscale image.
+     * @param io the target image object
+     * @param raw the buffer containing the RGB image data
+     * @param width the width of the image in pixels
+     * @param height the height of the image in pixels
+     */
+    private void convertToGrayScaleImage(ImageObject io, byte[] raw, int width, int height) {
         int pixelsPerByte = 8 / bitsPerPixel;
-        byte[] bw = new byte[raw.length / (3 * pixelsPerByte)];
-        int k = 0;
-        for (int i = 0, j = 0; i < raw.length; i += 3, j++) {
-            if (j == pixelsPerByte) {
-                j = 0;
-                k++;
-                if (k == bw.length) {
-                    break;
-                }
-            }
-            // see http://www.jguru.com/faq/view.jsp?EID=221919
-            double greyVal = 0.212671d * ((int) raw[i] & 0xff)
-                + 0.715160d * ((int) raw[i + 1] & 0xff)
-                + 0.072169d * ((int) raw[i + 2] & 0xff);
-            switch (bitsPerPixel) {
+        int bytewidth = (width / pixelsPerByte);
+        if ((width % pixelsPerByte) != 0) {
+            bytewidth++;
+        }
+        byte[] bw = new byte[height * bytewidth];
+        byte ib;
+        for (int y = 0; y < height; y++) {
+            ib = 0;
+            int i = 3 * y * width;
+            for (int x = 0; x < width; x++, i += 3) {
+                
+                // see http://www.jguru.com/faq/view.jsp?EID=221919
+                double greyVal = 0.212671d * ((int) raw[i] & 0xff)
+                    + 0.715160d * ((int) raw[i + 1] & 0xff)
+                    + 0.072169d * ((int) raw[i + 2] & 0xff);
+
+                switch (bitsPerPixel) {
                 case 1:
-                    if (greyVal > 128) {
-                        bw[k] |= (byte)(1 << j);
+                    if (greyVal < 128) {
+                        ib |= (byte)(1 << (7 - (x % 8)));
                     }
                     break;
                 case 4:
                     greyVal /= 16;
-                    bw[k] |= (byte)((byte)greyVal << (j * 4));
+                    ib |= (byte)((byte)greyVal << ((1 - (x % 2)) * 4));
                     break;
                 case 8:
-                    bw[k] = (byte)greyVal;
+                    ib = (byte)greyVal;
                     break;
+                default:
+                    throw new UnsupportedOperationException(
+                            "Unsupported bits per pixel: " + bitsPerPixel);
+                }
+                
+                if ((x % pixelsPerByte) == (pixelsPerByte - 1) || ((x + 1) == width)) {
+                    bw[(y * bytewidth) + (x / pixelsPerByte)] = ib;
+                    ib = 0;
+                }
             }
         }
         io.setImageIDESize((byte)bitsPerPixel);
index f9fcd31a46956782d52291dd32af6a9f9ee2b6b8..58e76f3a500948131daa5b769149413e237d05d8 100644 (file)
 
   <changes>
     <release version="FOP Trunk">
-      <action context="code" dev="MM" type="add">
+      <action context="Code" dev="JM" type="fix">
+        AFP Renderer: Bugfix for 1 bit images where the width is not a multiple of 8.
+      </action>
+      <action context="Code" dev="MM" type="add">
         Support for keep-together.within-line="always".
       </action>
       <action context="Code" dev="MM" type="fix">
         Fixed incomplete support for Unicode Word Joiner characters (U+2060 and U+FEFF).
       </action>
-      <action context="code" dev="AD" type="add" fixes-bug="42785" due-to="Max Berger">
+      <action context="Code" dev="AD" type="add" fixes-bug="42785" due-to="Max Berger">
         Support alignment-adjust for images.
       </action>
-      <action context="code" dev="AD" type="add" fixes-bug="41044" due-to="Richard Wheeldon">
+      <action context="Code" dev="AD" type="add" fixes-bug="41044" due-to="Richard Wheeldon">
         Partial application of the patch in Bugzilla 41044:
           * addition of a generic PropertyCache to be used by all Property
             types that can be safely canonicalized
           * modified EnumProperty, StringProperty, NumberProperty, EnumNumber
             and FixedLength to make use of the cache infrastructure
       </action>
-      <action context="code" dev="AD" type="update" fixes-bug="41656">
+      <action context="Code" dev="AD" type="update" fixes-bug="41656">
         Refactoring in the fo package:
         -> removal of the childNodes instance member in fop.fo.FObj
         -> addition of a firstChild instance member in fop.fo.FObj
@@ -52,7 +55,7 @@
         -> addition of a FONodeIterator interface in FONode + corresponding implementation in FObj
         -> changed implementations of FObj.addChildNode(), .removeChild() and .getChildNodes()
       </action>
-      <action context="code" dev="AD" type="update" fixes-bug="42089" due-to="Adrian Cumiskey">
+      <action context="Code" dev="AD" type="update" fixes-bug="42089" due-to="Adrian Cumiskey">
         Code cleanup and restructuring: 
         Refactoring of PageSequenceLayoutManager and provide common FObj id property use
       </action>