Attaching the patch this time.
On Wed, 2006-09-13 at 16:59 -0400, Francis Kung wrote:
> Hi,
>
> This patch, committed, optimizes filtering in
> java.awt.image.BandCombineOp.
>
> With this patch, running on cacao, our filtering is faster (!) than
> Sun's for small images (under ~ 150x150 pixels), but doesn't scale as
> well to larger images.
>
> One catch is that the Op now does int arithmetic, instead of using
> floats (floats will be rounded and cast). Using floats as image sample
> datatypes is pretty rare though (I think), and I've added a note in our
> API documentation about this (Sun's API states, "... built-in image
> processing operators may not operate on all possible sample types, but
> generally will work for unsigned integral samples of 16 bits or less.").
> I think the speed tradeoff is worth it.
>
> Regards,
> Francis
>
>
> 2006-09-13 Francis Kung <[EMAIL PROTECTED]>
>
> * java/awt/image/BandCombineOp.java: Updated documentation.
> (filter(Raster, WritableRaster)): Use int arrays, and added simple
> cache.
>
Index: java/awt/image/BandCombineOp.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/image/BandCombineOp.java,v
retrieving revision 1.5
diff -u -r1.5 BandCombineOp.java
--- java/awt/image/BandCombineOp.java 14 Aug 2006 16:12:38 -0000 1.5
+++ java/awt/image/BandCombineOp.java 13 Sep 2006 21:01:12 -0000
@@ -40,6 +40,7 @@
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
+import java.util.Arrays;
/**
* Filter Raster pixels by applying a matrix.
@@ -53,6 +54,9 @@
* for the destination. Therefore the destination Raster must contain the
* same number of bands as the number of rows in the filter matrix.
*
+ * This Op assumes that samples are integers; floating point sample types will
+ * be rounded to their nearest integer value during filtering.
+ *
* @author Jerry Quinn ([EMAIL PROTECTED])
*/
public class BandCombineOp implements RasterOp
@@ -109,19 +113,27 @@
throw new IllegalArgumentException("Destination raster is incompatible with source raster");
// Filter the pixels
- float[] spix = new float[matrix[0].length - 1];
- float[] dpix = new float[matrix.length];
+ int[] spix = new int[matrix[0].length - 1];
+ int[] spix2 = new int[matrix[0].length - 1];
+ int[] dpix = new int[matrix.length];
for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
{
// In case matrix rows have implicit translation
- spix[spix.length - 1] = 1.0f;
+ spix[spix.length - 1] = 1;
src.getPixel(x, y, spix);
- for (int i = 0; i < matrix.length; i++)
+
+ // Do not re-calculate if pixel is identical to the last one
+ // (ie, blocks of the same colour)
+ if (!Arrays.equals(spix, spix2))
{
- dpix[i] = 0;
- for (int j = 0; j < matrix[0].length - 1; j++)
- dpix[i] += spix[j] * matrix[i][j];
+ System.arraycopy(spix, 0, spix2, 0, spix.length);
+ for (int i = 0; i < matrix.length; i++)
+ {
+ dpix[i] = 0;
+ for (int j = 0; j < matrix[0].length - 1; j++)
+ dpix[i] += spix[j] * (int)matrix[i][j];
+ }
}
dest.setPixel(x, y, dpix);
}
Index: ChangeLog
===================================================================
RCS file: /cvsroot/classpath/classpath/ChangeLog,v
retrieving revision 1.8536
diff -u -r1.8536 ChangeLog
--- ChangeLog 13 Sep 2006 17:18:01 -0000 1.8536
+++ ChangeLog 13 Sep 2006 21:01:12 -0000
@@ -1,5 +1,10 @@
2006-09-13 Francis Kung <[EMAIL PROTECTED]>
+ * java/awt/image/BandCombineOp.java: Updated documentation.
+ (filter(Raster, WritableRaster)): Use int arrays, and added simple cache.
+
+2006-09-13 Francis Kung <[EMAIL PROTECTED]>
+
* java/awt/image/ConvolveOp.java (filter(Raster, WritableRaster)):
Removed hard-coded max sample value.
* java/awt/image/RescaleOp.java (filter(Raster, WritableRaster)):