You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-dev@xmlgraphics.apache.org by vh...@apache.org on 2001/01/25 01:15:23 UTC
cvs commit: xml-batik/sources/org/apache/batik/ext/awt/image/renderable BumpMap.java DiffuseLightingRable8Bit.java SpecularLightingRable8Bit.java DefaultBumpMap.java FlatBumpMap.java
vhardy 01/01/24 16:15:23
Modified: sources/org/apache/batik/ext/awt/image/renderable
BumpMap.java DiffuseLightingRable8Bit.java
SpecularLightingRable8Bit.java
Removed: sources/org/apache/batik/ext/awt/image/renderable
DefaultBumpMap.java FlatBumpMap.java
Log:
Added optimization to normal computation.
Revision Changes Path
1.2 +321 -11 xml-batik/sources/org/apache/batik/ext/awt/image/renderable/BumpMap.java
Index: BumpMap.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/ext/awt/image/renderable/BumpMap.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- BumpMap.java 2001/01/24 05:39:30 1.1
+++ BumpMap.java 2001/01/25 00:15:22 1.2
@@ -9,29 +9,339 @@
package org.apache.batik.ext.awt.image.renderable;
import java.awt.Rectangle;
+import java.awt.image.ColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferInt;
+import java.awt.image.DirectColorModel;
+import java.awt.image.Raster;
+import java.awt.image.RenderedImage;
+import java.awt.image.SampleModel;
+import java.awt.image.SinglePixelPackedSampleModel;
+import java.awt.image.WritableRaster;
/**
- * Models a map of elevations, used by various lighting filters.
+ * Default BumpMap implementation.
*
* @author <a href="mailto:vincent.hardy@eng.sun.com>Vincent Hardy</a>
- * @version $Id: BumpMap.java,v 1.1 2001/01/24 05:39:30 vhardy Exp $
+ * @version $Id: BumpMap.java,v 1.2 2001/01/25 00:15:22 vhardy Exp $
*/
-public interface BumpMap {
+public final class BumpMap {
/**
+ * Image whose alpha channel is used for the
+ * normal calculation
+ */
+ private RenderedImage texture;
+
+ /**
+ * Surface scale used in the normal computation
+ */
+ private double surfaceScale, surfaceScaleX, surfaceScaleY;
+
+ /**
+ * User space to device space scale factors
+ */
+ private double scaleX, scaleY;
+
+ /**
+ * Stores the normals for this bumpMap.
+ * scaleX and scaleY are the user space to device
+ * space scales.
+ */
+ public BumpMap(RenderedImage texture,
+ double surfaceScale,
+ double scaleX, double scaleY){
+ this.texture = texture;
+ this.surfaceScaleX = surfaceScale*scaleX;
+ this.surfaceScaleY = surfaceScale*scaleY;
+ this.surfaceScale = surfaceScale;
+ this.scaleX = scaleX;
+ this.scaleY = scaleY;
+ }
+
+ /**
* @return surface scale used by this bump map.
*/
- public double getSurfaceScale();
+ public final double getSurfaceScale(){
+ return surfaceScale;
+ }
/**
* @param x x-axis coordinate for which the normal is computed
* @param y y-axis coordinate for which the normal is computed
*/
- public double[][][] getNormalArray(int x, int y,
- int width, int height);
-
- /*
- * @return true if the normal is constant over the surface
- */
- public boolean isConstant(Rectangle area);
+ public final double[][][] getNormalArray
+ (final int x, final int y,
+ final int w, final int h)
+ {
+ final Raster r = texture.getData(new Rectangle(x, y, w, h));
+
+ final double[][][] N = new double[h][w][4];
+ double[] n;
+
+ final DataBufferInt db = (DataBufferInt)r.getDataBuffer();
+
+
+ final int[] pixels = db.getBankData()[0];
+
+ final SinglePixelPackedSampleModel sppsm;
+ sppsm = (SinglePixelPackedSampleModel)r.getSampleModel();
+
+ final int offset =
+ (db.getOffset() +
+ sppsm.getOffset(r.getMinX() -r.getSampleModelTranslateX(),
+ r.getMinY() -r.getSampleModelTranslateY()));
+
+ final int scanStride = sppsm.getScanlineStride();
+ final int scanStridePP = scanStride + 1;
+ final int scanStrideMM = scanStride - 1;
+ final int adjust = scanStride - w;
+ int p = offset + scanStride;
+ int a = 0;
+ int i=0, j=0;
+ double prpc=0, prcc=0, prnc=0;
+ double crpc=0, crcc=0, crnc=0;
+ double nrpc=0, nrcc=0, nrnc=0;
+ double norm;
+
+ final double quarterSurfaceScaleX = surfaceScaleX / 4f;
+ final double quarterSurfaceScaleY = surfaceScaleY / 4f;
+ final double halfSurfaceScaleX = surfaceScaleX / 2f;
+ final double halfSurfaceScaleY = surfaceScaleY /2;
+ final double thirdSurfaceScaleX = surfaceScaleX / 3f;
+ final double thirdSurfaceScaleY = surfaceScaleY / 3f;
+ final double twoThirdSurfaceScaleX = surfaceScaleX * 2 / 3f;
+ final double twoThirdSurfaceScaleY = surfaceScaleY * 2 / 3f;
+
+ if(w > 1){
+ for(i=1; i<h-1; i++){
+
+ crcc = (pixels[p] >>> 24)/255.;
+ crnc = (pixels[p+1] >>> 24)/255.;
+ prcc = (pixels[p - scanStride] >>> 24)/255.;
+ prnc = (pixels[p - scanStrideMM] >>> 24)/255.;
+ nrcc = (pixels[p + scanStride] >>> 24)/255.;
+ nrnc = (pixels[p + scanStridePP] >>> 24)/255.;
+
+ p++; // start in 1, not 0.
+ for(j=1; j<w-1; j++){
+ prpc = prcc;
+ crpc = crcc;
+ nrpc = nrcc;
+ prcc = prnc;
+ crcc = crnc;
+ nrcc = nrnc;
+
+ crnc = (pixels[p+1] >>> 24)/255.;
+ prnc = (pixels[p - scanStrideMM] >>> 24)/255.;
+ nrnc = (pixels[p + scanStridePP] >>> 24)/255.;
+
+ n = N[i][j];
+ n[0] = - quarterSurfaceScaleX *(( prnc + 2*crnc + nrnc)
+ - (prpc + 2*crpc + nrpc));
+ n[1] = - quarterSurfaceScaleY *(( nrpc + 2*nrcc + nrnc)
+ - (prpc + 2*prcc + prnc));
+
+ norm = Math.sqrt(n[0]*n[0] + n[1]*n[1] + 1);
+ n[0] /= norm;
+ n[1] /= norm;
+ n[2] = 1/norm;
+ n[3] = crcc*surfaceScale;
+ p++;
+ }
+ p += adjust + 1;
+ }
+
+ // Process pixels on the border
+ if(h>1){
+ p = offset;
+
+ // Top left pixel, in (0, 0);
+ n = N[0][0];
+
+ crcc = (pixels[p] >>> 24)/255.;
+ crnc = (pixels[p+1] >>> 24)/255.;
+ nrcc = (pixels[p + scanStride] >>> 24)/255.;
+ nrnc = (pixels[p + scanStridePP] >>> 24)/255.;
+
+ n[0] = - twoThirdSurfaceScaleX *((2*crnc + nrnc - 2*crcc - nrcc));
+ n[1] = - twoThirdSurfaceScaleY *((2*nrcc + nrnc - 2*crcc - crnc));
+ norm = Math.sqrt(n[0]*n[0] + n[1]*n[1] + 1);
+ n[0] /= norm;
+ n[1] /= norm;
+ n[2] = 1/norm;
+ n[3] = crcc*surfaceScale;
+
+ // Top row...
+ p++;
+ for(j=1; j<w-1; j++){
+ crpc = crcc;
+ nrpc = nrcc;
+ crcc = crnc;
+ nrcc = nrnc;
+
+ crnc = (pixels[p+1] >>> 24)/255.;
+ nrnc = (pixels[p + scanStridePP] >>> 24)/255.;
+
+ n = N[0][j];
+ n[0] = - thirdSurfaceScaleX * (( 2*crnc + nrnc)
+ - (2*crpc + nrpc));
+ n[1] = - halfSurfaceScaleY *(( nrpc + 2*nrcc + nrnc)
+ - (crpc + 2*crcc + crnc));
+
+ norm = Math.sqrt(n[0]*n[0] + n[1]*n[1] + 1);
+ n[0] /= norm;
+ n[1] /= norm;
+ n[2] = 1/norm;
+ n[3] = crcc*surfaceScale;
+ p++;
+
+ }
+
+ // Last pixel of top row
+ if(w > 1){
+ n = N[0][j];
+ crpc = crcc;
+ nrpc = nrcc;
+ crcc = crnc;
+ nrcc = nrnc;
+ n[0] = - twoThirdSurfaceScaleX *(( 2*crcc + nrcc)
+ - (2*crpc + nrpc));
+ n[1] = - twoThirdSurfaceScaleY *(( 2*nrcc + nrpc)
+ - (2*crcc + crpc));
+
+ norm = Math.sqrt(n[0]*n[0] + n[1]*n[1] + 1);
+ n[0] /= norm;
+ n[1] /= norm;
+ n[2] = 1/norm;
+ n[3] = crcc*surfaceScale;
+ }
+
+ // Now, process left column, from (0, 1) to (0, h-1)
+ p = offset;
+ crcc = (pixels[p] >>> 24)/255.;
+ crnc = (pixels[p+1] >>> 24)/255.;
+ nrcc = (pixels[p + scanStride] >>> 24)/255.;
+ nrnc = (pixels[p + scanStridePP] >>> 24)/255.;
+ p += scanStride;
+
+ for(i=1; i<h-1; i++){
+ prcc = crcc;
+ crcc = nrcc;
+ prnc = crnc;
+ crnc = nrnc;
+
+ nrcc = (pixels[p + scanStride] >>> 24)/255.;
+ nrnc = (pixels[p + scanStridePP] >>> 24)/255.;
+
+ n = N[i][0];
+ n[0] = - halfSurfaceScaleX *(( prnc + 2*crnc + nrnc)
+ - (prcc + 2*crcc + nrcc));
+ n[1] = - thirdSurfaceScaleY *(( 2*prcc + prnc)
+ - ( 2*crcc + crnc));
+
+ norm = Math.sqrt(n[0]*n[0] + n[1]*n[1] + 1);
+ n[0] /= norm;
+ n[1] /= norm;
+ n[2] = 1/norm;
+ n[3] = crcc*surfaceScale;
+ p += scanStride;
+
+ }
+
+ // Now, proces right column, from (w-1, 1) to (w-1, h-1)
+ p = offset + scanStride -1;
+ crcc = (pixels[p] >>> 24)/255.;
+ crpc = (pixels[p-1] >>> 24)/255.;
+ nrcc = (pixels[p + scanStride] >>> 24)/255.;
+ nrpc = (pixels[p + scanStrideMM] >>> 24)/255.;
+ p += scanStride;
+
+ for(i=1; i<h-1; i++){
+ prcc = crcc;
+ prpc = crpc;
+ crcc = nrcc;
+ crpc = nrpc;
+
+ nrcc = (pixels[p + scanStride] >>> 24)/255.;
+ nrpc = (pixels[p + scanStrideMM] >>> 24)/255.;
+
+ n = N[i][w-1];
+ n[0] = - halfSurfaceScaleX *(( prcc + 2*crcc + nrcc)
+ - (prpc + 2*crpc + nrpc));
+ n[1] = - thirdSurfaceScaleY *(( nrpc + 2*nrcc)
+ - ( prpc + 2*prcc));
+
+ norm = Math.sqrt(n[0]*n[0] + n[1]*n[1] + 1);
+ n[0] /= norm;
+ n[1] /= norm;
+ n[2] = 1/norm;
+ n[3] = crcc*surfaceScale;
+ p += scanStride;
+ }
+
+ // Process first pixel of last row
+ p = offset + (h-1)*scanStride;
+ crcc = (pixels[p] >>> 24)/255.;
+ crnc = (pixels[p+1] >>> 24)/255.;
+ prcc = (pixels[p - scanStride] >>> 24)/255.;
+ prnc = (pixels[p - scanStrideMM] >>> 24)/255.;
+
+ n = N[h-1][0];
+
+ n[0] = - twoThirdSurfaceScaleX * ((2*crnc + prnc - 2*crcc - prcc));
+ n[1] = - twoThirdSurfaceScaleY * ((2*crcc + crnc - 2*prcc - prnc));
+ norm = Math.sqrt(n[0]*n[0] + n[1]*n[1] + 1);
+ n[0] /= norm;
+ n[1] /= norm;
+ n[2] = 1/norm;
+ n[3] = crcc*surfaceScale;
+
+ // Bottom row...
+ p++;
+ for(j=1; j<w-1; j++){
+ crpc = crcc;
+ prpc = prcc;
+ crcc = crnc;
+ prcc = prnc;
+
+ crnc = (pixels[p+1] >>> 24)/255.;
+ prnc = (pixels[p - scanStrideMM] >>> 24)/255.;
+
+ n = N[h-1][j];
+ n[0] = - thirdSurfaceScaleX *(( 2*crnc + prnc)
+ - (2*crpc + prpc));
+ n[1] = - halfSurfaceScaleY *(( crpc + 2*crcc + crnc)
+ - (prpc + 2*prcc + prnc));
+
+ norm = Math.sqrt(n[0]*n[0] + n[1]*n[1] + 1);
+ n[0] /= norm;
+ n[1] /= norm;
+ n[2] = 1/norm;
+ n[3] = crcc*surfaceScale;
+ p++;
+ }
+
+ // Bottom right corner
+ crpc = crcc;
+ prpc = prcc;
+ crcc = crnc;
+ prcc = prnc;
+
+ n = N[h-1][w-1];
+ n[0] = - twoThirdSurfaceScaleX *(( 2*crcc + prcc)
+ - (2*crpc + prpc));
+ n[1] = - twoThirdSurfaceScaleY *(( 2*crcc + crpc)
+ - (2*prcc + prpc));
+
+ norm = Math.sqrt(n[0]*n[0] + n[1]*n[1] + 1);
+ n[0] /= norm;
+ n[1] /= norm;
+ n[2] = 1/norm;
+ n[3] = crcc*surfaceScale;
+ }
+ }
+
+ return N;
+ }
}
1.2 +2 -2 xml-batik/sources/org/apache/batik/ext/awt/image/renderable/DiffuseLightingRable8Bit.java
Index: DiffuseLightingRable8Bit.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/ext/awt/image/renderable/DiffuseLightingRable8Bit.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- DiffuseLightingRable8Bit.java 2001/01/24 05:39:31 1.1
+++ DiffuseLightingRable8Bit.java 2001/01/25 00:15:22 1.2
@@ -28,7 +28,7 @@
* Implementation of the DiffuseLightRable interface.
*
* @author <a href="mailto:vincent.hardy@eng.sun.com>Vincent Hardy</a>
- * @version $Id: DiffuseLightingRable8Bit.java,v 1.1 2001/01/24 05:39:31 vhardy Exp $
+ * @version $Id: DiffuseLightingRable8Bit.java,v 1.2 2001/01/25 00:15:22 vhardy Exp $
*/
public class DiffuseLightingRable8Bit
extends AbstractRable
@@ -203,7 +203,7 @@
PadMode.ZERO_PAD,
rh);
- BumpMap bumpMap = new DefaultBumpMap(texture, surfaceScale, scaleX, scaleY);
+ BumpMap bumpMap = new BumpMap(texture, surfaceScale, scaleX, scaleY);
DiffuseLightingRed diffuseRed =
new DiffuseLightingRed(kd,
1.2 +2 -2 xml-batik/sources/org/apache/batik/ext/awt/image/renderable/SpecularLightingRable8Bit.java
Index: SpecularLightingRable8Bit.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/ext/awt/image/renderable/SpecularLightingRable8Bit.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- SpecularLightingRable8Bit.java 2001/01/24 05:39:34 1.1
+++ SpecularLightingRable8Bit.java 2001/01/25 00:15:23 1.2
@@ -28,7 +28,7 @@
* Implementation of the SpecularLightRable interface.
*
* @author <a href="mailto:vincent.hardy@eng.sun.com>Vincent Hardy</a>
- * @version $Id: SpecularLightingRable8Bit.java,v 1.1 2001/01/24 05:39:34 vhardy Exp $
+ * @version $Id: SpecularLightingRable8Bit.java,v 1.2 2001/01/25 00:15:23 vhardy Exp $
*/
public class SpecularLightingRable8Bit
extends AbstractRable
@@ -224,7 +224,7 @@
PadMode.ZERO_PAD,
rh);
- BumpMap bumpMap = new DefaultBumpMap(texture, surfaceScale, scaleX, scaleY);
+ BumpMap bumpMap = new BumpMap(texture, surfaceScale, scaleX, scaleY);
SpecularLightingRed specularRed =
new SpecularLightingRed(ks,