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 de...@apache.org on 2001/08/01 21:46:20 UTC
cvs commit: xml-batik/sources/org/apache/batik/ext/awt/image/rendered TurbulencePatternRed8Bit.java TurbulencePatternGenerator.java
deweese 01/08/01 12:46:20
Modified: sources/org/apache/batik/ext/awt/image/renderable
TurbulenceRable8Bit.java
Added: sources/org/apache/batik/ext/awt/image/rendered
TurbulencePatternRed8Bit.java
Removed: sources/org/apache/batik/ext/awt/image/rendered
TurbulencePatternGenerator.java
Log:
1) Made Turbulence a Red instead of an 'Op'
2) Made Turbulence ~30% faster.
Revision Changes Path
1.6 +12 -59 xml-batik/sources/org/apache/batik/ext/awt/image/renderable/TurbulenceRable8Bit.java
Index: TurbulenceRable8Bit.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/ext/awt/image/renderable/TurbulenceRable8Bit.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- TurbulenceRable8Bit.java 2001/05/02 15:41:25 1.5
+++ TurbulenceRable8Bit.java 2001/08/01 19:46:20 1.6
@@ -36,24 +36,18 @@
import java.awt.image.WritableRaster;
import java.awt.image.renderable.RenderContext;
-import org.apache.batik.ext.awt.image.rendered.TurbulencePatternGenerator;
-import org.apache.batik.ext.awt.image.rendered.BufferedImageCachableRed;
+import org.apache.batik.ext.awt.image.rendered.TurbulencePatternRed8Bit;
/**
* Creates a sourceless image from a turbulence function.
*
* @author <a href="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
- * @version $Id: TurbulenceRable8Bit.java,v 1.5 2001/05/02 15:41:25 tkormann Exp $
+ * @version $Id: TurbulenceRable8Bit.java,v 1.6 2001/08/01 19:46:20 deweese Exp $
*/
public class TurbulenceRable8Bit
extends AbstractColorInterpolationRable
implements TurbulenceRable {
- /**
- * Paint used to clear the area outside the area of interest
- */
- private static final Paint CLEAR_PAINT = new Color(0, 0, 0, 0);
-
int seed = 0; // Seed value to pseudo rand num gen.
int numOctaves = 1; // number of octaves in turbulence function
double baseFreqX = 0; // Frequency in X/Y directions
@@ -232,68 +226,27 @@
// System.out.println("Turbulence aoi : " + aoi);
// System.out.println("Scale X : " + usr2dev.getScaleX() + " scaleY : " + usr2dev.getScaleY());
// System.out.println("Turbulence aoi dev : " + usr2dev.createTransformedShape(aoi).getBounds());
- final Rectangle rasterRect
+ final Rectangle devRect
= usr2dev.createTransformedShape(aoiRect).getBounds();
- if ((rasterRect.width <= 0) ||
- (rasterRect.height <= 0))
+ if ((devRect.width <= 0) ||
+ (devRect.height <= 0))
return null;
ColorSpace cs = getOperationColorSpace();
- ColorModel cm = new DirectColorModel
- (cs, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000,
- false, DataBuffer.TYPE_INT);
-
- // Create a raster for the turbulence pattern
- WritableRaster wr, twr;
- wr = cm.createCompatibleWritableRaster(rasterRect.width,
- rasterRect.height);
- twr = wr.createWritableTranslatedChild(rasterRect.x,
- rasterRect.y);
-
- // Create a TurbulencePatternGenerator that will do the job
- // <!> FIX ME. The tile is not propagated properly to the turbulence op
- // <!> FIX ME. SHOULD OPTIMIZE THE CHANNELS REQUIRED FROM THE
- // FILTER. THIS COULD BE ADDED TO THE RENDER CONTEXT.
- TurbulencePatternGenerator turbGenerator
- = new TurbulencePatternGenerator
- (baseFreqX, baseFreqY, numOctaves,
- seed, stitched, fractalNoise,
- (Rectangle2D)region.clone(),
- new boolean[]{true, true, true, true});
+
+ Rectangle2D tile = null;
+ if (stitched)
+ tile = (Rectangle2D)region.clone();
AffineTransform patternTxf = new AffineTransform();
try{
patternTxf = usr2dev.createInverse();
}catch(NoninvertibleTransformException e){
}
-
- turbGenerator.generatePattern(twr, patternTxf);
-
- // Wrap raster in buffered image
- BufferedImage bi = new BufferedImage(cm, wr,
- cm.isAlphaPremultiplied(),
- null);
-
- // Clear area outside area of interest
- /*if(usr2dev.getShearX() != 0 || usr2dev.getShearY() != 0){
- Graphics2D g = bi.createGraphics();
- RenderingHints hints = rc.getRenderingHints();
- if(hints == null){
- hints = new RenderingHints(null);
- }
- g.setRenderingHints(hints);
- g.setComposite(AlphaComposite.Src);
-
- Area nonAoi = new Area(rasterRect);
- nonAoi.subtract(new Area(usr2dev.createTransformedShape(aoi)));
- g.setPaint(CLEAR_PAINT);
- // g.setPaint(java.awt.Color.red);
- g.translate(-rasterRect.x, -rasterRect.y);
- g.fill(nonAoi);
- g.dispose();
- }*/
- return new BufferedImageCachableRed(bi, rasterRect.x, rasterRect.y);
+ return new TurbulencePatternRed8Bit
+ (baseFreqX, baseFreqY, numOctaves, seed, fractalNoise,
+ tile, patternTxf, devRect, cs, true);
}
}
1.1 xml-batik/sources/org/apache/batik/ext/awt/image/rendered/TurbulencePatternRed8Bit.java
Index: TurbulencePatternRed8Bit.java
===================================================================
/****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.batik.ext.awt.image.rendered;
import java.awt.Rectangle;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.WritableRaster;
import java.awt.image.SampleModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferInt;
import java.awt.image.SinglePixelPackedSampleModel;
import java.awt.image.DirectColorModel;
import java.awt.image.ColorModel;
/**
* This class creates a noise pattern conform to the one defined for
* the feTurbulence filter of the SVG specification. It can be used by
* classes implementing specific interfaces, such as the TurbulenceOp
* and TurbulencePaintContext classes.
*
* @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
* @version $Id: TurbulencePatternRed8Bit.java,v 1.1 2001/08/01 19:46:20 deweese Exp $
*/
public final class TurbulencePatternRed8Bit extends AbstractRed {
/**
* Inner class to store tile stitching info.
* #see
*/
static final class StitchInfo {
/**
* Width of the integer lattice tile
*/
int width;
/**
* Height of the integer lattice tile
*/
int height;
/**
* Value beyond which values are wrapped on
* the x-axis.
* @see #noise2Stitch
*/
int wrapX;
/**
* Value beyond which values are wrapped on
* the y-axis.
* @see #noise2Stitch
*/
int wrapY;
/**
* Default constructor
*/
StitchInfo(){
}
/**
* Copy constructor
*/
StitchInfo(StitchInfo stitchInfo){
this.width = stitchInfo.width;
this.height = stitchInfo.height;
this.wrapX = stitchInfo.wrapX;
this.wrapY = stitchInfo.wrapY;
}
final void assign(StitchInfo stitchInfo) {
this.width = stitchInfo.width;
this.height = stitchInfo.height;
this.wrapX = stitchInfo.wrapX;
this.wrapY = stitchInfo.wrapY;
}
/*
* Adjustst the StitchInfo for when the frequency has been
* doubled.
*
* width = tileWidth*baseFrequencyX
* height = tileHeight*baseFrequencyY
* minY = tileY*baseFrequencyY + PerlinN
* wrapX = tileX*baseFrequencyX + PerlinN + width
* wrapY = tileY*baseFrequencyY + PerlinN + height
*
*/
final void doubleFrequency(){
width *= 2;
height *= 2;
wrapX *= 2;
wrapY *= 2;
wrapX -= PerlinN;
wrapY -= PerlinN;
}
}
/**
* Used when stitching is on
*/
private StitchInfo stitchInfo = null;
/**
* Identity transform, default used when null input in generatePattern
* @see #generatePattern
*/
private static final AffineTransform IDENTITY = new AffineTransform();
/**
* x-axis base frequency for the noise function along the x-axis
*/
private double baseFrequencyX;
/**
* y-axis base frequency for the noise function along the y-axis
*/
private double baseFrequencyY;
/**
* Number of octaves in the noise function
*/
private int numOctaves;
/**
* Starting number for the pseudo random number generator
*/
private int seed;
/**
* Defines the tile for the turbulence function, if non-null turns
* on stitching, so frequencies are adjusted to avoid
* discontinuities in case frequencies do not match tile
* boundaries.
*/
private Rectangle2D tile;
/**
* Defines the tile for the turbulence function
*/
private AffineTransform txf;
/**
* Defines whether the filter performs a fractal noise or a turbulence function
*/
private boolean isFractalNoise;
/**
* List of channels that the generator produces.
*/
private int channels[];
// To avoid doing an inverse transform on each pixel, transform
// the image space unit vectors and process how much of a delta
// this is in filter space.
double tx[] = {1, 0};
double ty[] = {0, 1};
/**
* Produces results in the range [1, 2**31 - 2].
* Algorithm is: r = (a * r) mod m
* where a = 16807 and m = 2**31 - 1 = 2147483647
* See [Park & Miller], CACM vol. 31 no. 10 p. 1195, Oct. 1988
* To test: the algorithm should produce the result 1043618065
* as the 10,000th generated number if the original seed is 1.
*/
private static final int RAND_m = 2147483647; /* 2**31 - 1 */
private static final int RAND_a = 16807; /* 7**5; primitive root of m */
private static final int RAND_q = 127773; /* m / a */
private static final int RAND_r = 2836; /* m % a */
private static final int BSize = 0x100;
private static final int BM = 0xff;
private static final double PerlinN = 0x1000;
private static final int NP = 12 /* 2^PerlinN */;
private static final int NM = 0xfff;
private final int latticeSelector[] = new int[BSize + BSize + 2];
private final double gradient[] = new double[BSize*8];
public double getBaseFrequencyX(){
return baseFrequencyX;
}
public double getBaseFrequencyY(){
return baseFrequencyY;
}
public int getNumOctaves(){
return numOctaves;
}
public int getSeed(){
return seed;
}
public Rectangle2D getTile(){
return (Rectangle2D)tile.clone();
}
public boolean isFractalNoise(){
return isFractalNoise;
}
public boolean[] getChannels(){
boolean channels[] = new boolean[4];
for(int i=0; i<this.channels.length; i++)
channels[this.channels[i]] = true;
return channels;
}
public final int setupSeed(int seed) {
if (seed <= 0) seed = -(seed % (RAND_m - 1)) + 1;
if (seed > RAND_m - 1) seed = RAND_m - 1;
return seed;
}
public final int random(int seed) {
int result = RAND_a * (seed % RAND_q) - RAND_r * (seed / RAND_q);
if (result <= 0) result += RAND_m;
return result;
}
private void initLattice(int seed) {
double u, v, s;
int i, j, k;
seed = setupSeed(seed);
for(k = 0; k < 4; k++){
for(i = 0; i < BSize; i++){
u = (((seed = random(seed)) % (BSize + BSize)) - BSize);
v = (((seed = random(seed)) % (BSize + BSize)) - BSize);
s = 1/Math.sqrt(u*u + v*v);
gradient[i*8 + k*2 ] = u*s;
gradient[i*8 + k*2 + 1] = v*s;
}
}
for(i = 0; i < BSize; i++)
latticeSelector[i] = i;
while(--i > 0){
k = latticeSelector[i];
j = (seed = random(seed)) % BSize;
latticeSelector[i] = latticeSelector[j];
latticeSelector[j] = k;
}
for(i = 0; i < BSize + 2; i++)
latticeSelector[BSize + i] = latticeSelector[i];
}
private static final double s_curve(final double t) {
return (t * t * (3 - 2 * t) );
}
private static final double lerp(double t, double a, double b) {
return ( a + t * (b - a) );
}
private final void noise2_4(final double noise[],
double vec0,
double vec1){
int b0, b1;
final int i, j, b00, b10, b01, b11;
final double rx0, rx1, ry0, ry1, sx, sy;
vec0 += PerlinN;
b0 = (int)vec0;
i = latticeSelector[b0 & BM];
j = latticeSelector[(b0+1) & BM];
rx0 = vec0 - (int)vec0;
rx1 = rx0 - 1.0;
sx = s_curve(rx0);
vec1 += PerlinN;
b0 = ((int)vec1) & BM;
b1 = (b0+1) & BM;
b00 = latticeSelector[i + b0]<<3;
b10 = latticeSelector[j + b0]<<3;
b01 = latticeSelector[i + b1]<<3;
b11 = latticeSelector[j + b1]<<3;
ry0 = vec1 - (int)vec1;
ry1 = ry0 - 1.0;
sy = s_curve(ry0);
noise[0] =
lerp(sy,
lerp(sx,
rx0*gradient[b00+0] + ry0*gradient[b00+1],
rx1*gradient[b10+0] + ry0*gradient[b10+1]),
lerp(sx,
rx0*gradient[b01+0] + ry1*gradient[b01+1],
rx1*gradient[b11+0] + ry1*gradient[b11+1]));
noise[1] =
lerp(sy,
lerp(sx,
rx0*gradient[b00+2] + ry0*gradient[b00+3],
rx1*gradient[b10+2] + ry0*gradient[b10+3]),
lerp(sx,
rx0*gradient[b01+2] + ry1*gradient[b01+3],
rx1*gradient[b11+2] + ry1*gradient[b11+3]));
noise[2] =
lerp(sy,
lerp(sx,
rx0*gradient[b00+4] + ry0*gradient[b00+5],
rx1*gradient[b10+4] + ry0*gradient[b10+5]),
lerp(sx,
rx0*gradient[b01+4] + ry1*gradient[b01+5],
rx1*gradient[b11+4] + ry1*gradient[b11+5]));
noise[3] =
lerp(sy,
lerp(sx,
rx0*gradient[b00+6] + ry0*gradient[b00+7],
rx1*gradient[b10+6] + ry0*gradient[b10+7]),
lerp(sx,
rx0*gradient[b01+6] + ry1*gradient[b01+7],
rx1*gradient[b11+6] + ry1*gradient[b11+7]));
}
private final void noise2(final double noise[], double vec0, double vec1) {
int b0, b1;
final int i, j, b00, b10, b01, b11;
final double rx0, rx1, ry0, ry1, sx, sy;
vec0 += PerlinN;
b0 = (int)vec0;
i = latticeSelector[b0 & BM];
j = latticeSelector[(b0+1) & BM];
rx0 = vec0 - (int)vec0;
rx1 = rx0 - 1.0;
sx = s_curve(rx0);
vec1 += PerlinN;
b0 = ((int)vec1) & BM;
b1 = (b0+1) & BM;
b00 = latticeSelector[i + b0]<<3;
b10 = latticeSelector[j + b0]<<3;
b01 = latticeSelector[i + b1]<<3;
b11 = latticeSelector[j + b1]<<3;
ry0 = vec1 - (int)vec1;
ry1 = ry0 - 1.0;
sy = s_curve(ry0);
switch (channels.length) {
// Intentionally use 'fall through' in switch statement.
case 4:
noise[3] =
lerp(sy,
lerp(sx,
rx0*gradient[b00+6] + ry0*gradient[b00+7],
rx1*gradient[b10+6] + ry0*gradient[b10+7]),
lerp(sx,
rx0*gradient[b01+6] + ry1*gradient[b01+7],
rx1*gradient[b11+6] + ry1*gradient[b11+7]));
case 3:
noise[2] =
lerp(sy,
lerp(sx,
rx0*gradient[b00+4] + ry0*gradient[b00+5],
rx1*gradient[b10+4] + ry0*gradient[b10+5]),
lerp(sx,
rx0*gradient[b01+4] + ry1*gradient[b01+5],
rx1*gradient[b11+4] + ry1*gradient[b11+5]));
case 2:
noise[1] =
lerp(sy,
lerp(sx,
rx0*gradient[b00+2] + ry0*gradient[b00+3],
rx1*gradient[b10+2] + ry0*gradient[b10+3]),
lerp(sx,
rx0*gradient[b01+2] + ry1*gradient[b01+3],
rx1*gradient[b11+2] + ry1*gradient[b11+3]));
case 1:
noise[0] =
lerp(sy,
lerp(sx,
rx0*gradient[b00+0] + ry0*gradient[b00+1],
rx1*gradient[b10+0] + ry0*gradient[b10+1]),
lerp(sx,
rx0*gradient[b01+0] + ry1*gradient[b01+1],
rx1*gradient[b11+0] + ry1*gradient[b11+1]));
}
}
/**
* This version of the noise function implements stitching.
* If any of the lattice is on the right or bottom edge, the
* function uses the the latice on the other side of the
* tile, i.e., the left or right edge.
*/
private final void noise2Stitch(final double noise[],
final double vec0, final double vec1,
final StitchInfo stitchInfo){
int b0, b1;
final int i, j, b00, b10, b01, b11;
double t;
final double rx0, rx1, ry0, ry1, sx, sy;
t = vec0 + PerlinN;
b0 = ((int)t);
b1 = b0+1;
// Stitch lattice tile x coordinates
if (b1 >= stitchInfo.wrapX) {
if (b0 >= stitchInfo.wrapX) {
b0 -= stitchInfo.width;
b1 -= stitchInfo.width;
} else {
b1 -= stitchInfo.width;
}
}
i = latticeSelector[b0&BM];
j = latticeSelector[b1&BM];
rx0 = t - (int)t;
rx1 = rx0 - 1.0;
sx = s_curve(rx0);
t = vec1 + PerlinN;
b0 = ((int)t);
b1 = b0+1;
// Stitch lattice tile y coordinates
if (b1 >= stitchInfo.wrapY) {
if (b0 >= stitchInfo.wrapY) {
b0 -= stitchInfo.height;
b1 -= stitchInfo.height;
} else {
b1 -= stitchInfo.height;
}
}
b0 &= BM;
b1 &= BM;
b00 = latticeSelector[i + b0]<<3;
b10 = latticeSelector[j + b0]<<3;
b01 = latticeSelector[i + b1]<<3;
b11 = latticeSelector[j + b1]<<3;
ry0 = t - (int)t;
ry1 = ry0 - 1.0;
sy = s_curve(ry0);
switch (channels.length) {
// Intentionally use 'fall through' in switch statement.
case 4:
noise[3] =
lerp(sy,
lerp(sx,
rx0*gradient[b00+6] + ry0*gradient[b00+7],
rx1*gradient[b10+6] + ry0*gradient[b10+7]),
lerp(sx,
rx0*gradient[b01+6] + ry1*gradient[b01+7],
rx1*gradient[b11+6] + ry1*gradient[b11+7]));
case 3:
noise[2] =
lerp(sy,
lerp(sx,
rx0*gradient[b00+4] + ry0*gradient[b00+5],
rx1*gradient[b10+4] + ry0*gradient[b10+5]),
lerp(sx,
rx0*gradient[b01+4] + ry1*gradient[b01+5],
rx1*gradient[b11+4] + ry1*gradient[b11+5]));
case 2:
noise[1] =
lerp(sy,
lerp(sx,
rx0*gradient[b00+2] + ry0*gradient[b00+3],
rx1*gradient[b10+2] + ry0*gradient[b10+3]),
lerp(sx,
rx0*gradient[b01+2] + ry1*gradient[b01+3],
rx1*gradient[b11+2] + ry1*gradient[b11+3]));
case 1:
noise[0] =
lerp(sy,
lerp(sx,
rx0*gradient[b00+0] + ry0*gradient[b00+1],
rx1*gradient[b10+0] + ry0*gradient[b10+1]),
lerp(sx,
rx0*gradient[b01+0] + ry1*gradient[b01+1],
rx1*gradient[b11+0] + ry1*gradient[b11+1]));
}
}
/**
* This is the heart of the turbulence calculation. It returns
* 'turbFunctionResult', as defined in the spec.
* @param rgb array for the four color components
* @param point x and y coordinates of the point to process.
* @param fSum array used to avoid reallocating double array for each pixel
* @param noise array used to avoid reallocating double array for
* each pixel
*/
private final int turbulence_4(double pointX,
double pointY,
final double fSum[]) {
double n, ratio = 255;
int b0, b1, nOctave;
int i, j, b00, b10, b01, b11;
double px, py, rx0, rx1, ry0, ry1, sx, sy;
pointX *= baseFrequencyX;
pointY *= baseFrequencyY;
fSum[0] = fSum[1] = fSum[2] = fSum[3] = 0;
for (nOctave = numOctaves; nOctave > 0; nOctave--){
px = pointX+PerlinN;
b0 = (int)px;
i = latticeSelector[b0 & BM];
j = latticeSelector[(b0+1) & BM];
rx0 = px - (int)px;
rx1 = rx0 - 1.0;
sx = s_curve(rx0);
py = pointY+PerlinN;
b0 = ((int)py) & BM;
b1 = (b0+1) & BM;
b00 = (latticeSelector[i + b0]&BM)<<3;
b10 = (latticeSelector[j + b0]&BM)<<3;
b01 = (latticeSelector[i + b1]&BM)<<3;
b11 = (latticeSelector[j + b1]&BM)<<3;
ry0 = py - (int)py;
ry1 = ry0 - 1.0;
sy = s_curve(ry0);
n = lerp(sy,
lerp(sx,
rx0*gradient[b00+0] + ry0*gradient[b00+1],
rx1*gradient[b10+0] + ry0*gradient[b10+1]),
lerp(sx,
rx0*gradient[b01+0] + ry1*gradient[b01+1],
rx1*gradient[b11+0] + ry1*gradient[b11+1]));
if (n<0) fSum[0] -= (n * ratio);
else fSum[0] += (n * ratio);
n = lerp(sy,
lerp(sx,
rx0*gradient[b00+2] + ry0*gradient[b00+3],
rx1*gradient[b10+2] + ry0*gradient[b10+3]),
lerp(sx,
rx0*gradient[b01+2] + ry1*gradient[b01+3],
rx1*gradient[b11+2] + ry1*gradient[b11+3]));
if (n<0) fSum[1] -= (n * ratio);
else fSum[1] += (n * ratio);
n = lerp(sy,
lerp(sx,
rx0*gradient[b00+4] + ry0*gradient[b00+5],
rx1*gradient[b10+4] + ry0*gradient[b10+5]),
lerp(sx,
rx0*gradient[b01+4] + ry1*gradient[b01+5],
rx1*gradient[b11+4] + ry1*gradient[b11+5]));
if (n<0) fSum[2] -= (n * ratio);
else fSum[2] += (n * ratio);
n = lerp(sy,
lerp(sx,
rx0*gradient[b00+6] + ry0*gradient[b00+7],
rx1*gradient[b10+6] + ry0*gradient[b10+7]),
lerp(sx,
rx0*gradient[b01+6] + ry1*gradient[b01+7],
rx1*gradient[b11+6] + ry1*gradient[b11+7]));
if (n<0) fSum[3] -= (n * ratio);
else fSum[3] += (n * ratio);
ratio *= .5;
pointX *= 2;
pointY *= 2;
}
i = (int)fSum[0];
if ((i & 0xFFFFFF00) == 0) j = i<<16;
else j = ((i & 0x80000000) != 0)?0:0xFF0000;
i = (int)fSum[1];
if ((i & 0xFFFFFF00) == 0) j |= i<<8;
else j |= ((i & 0x80000000) != 0)?0:0xFF00;
i = (int)fSum[2];
if ((i & 0xFFFFFF00) == 0) j |= i;
else j |= ((i & 0x80000000) != 0)?0:0xFF;
i = (int)fSum[3];
if ((i & 0xFFFFFF00) == 0) j |= i<<24;
else j |= ((i & 0x80000000) != 0)?0:0xFF000000;
return j;
}
/**
* This is the heart of the turbulence calculation. It returns
* 'turbFunctionResult', as defined in the spec.
* @param rgb array for the four color components
* @param point x and y coordinates of the point to process.
* @param fSum array used to avoid reallocating double array for each pixel
* @param noise array used to avoid reallocating double array for
* each pixel
*/
private final void turbulence(final int rgb[],
double pointX,
double pointY,
final double fSum[],
final double noise[]) {
fSum[0] = fSum[1] = fSum[2] = fSum[3] = 0;
double ratio = 255;
pointX *= baseFrequencyX;
pointY *= baseFrequencyY;
switch (channels.length) {
case 4:
for(int nOctave = 0; nOctave < numOctaves; nOctave++){
noise2_4(noise, pointX, pointY);
if (noise[0]<0) fSum[0] -= (noise[0] * ratio);
else fSum[0] += (noise[0] * ratio);
if (noise[1]<0) fSum[1] -= (noise[1] * ratio);
else fSum[1] += (noise[1] * ratio);
if (noise[2]<0) fSum[2] -= (noise[2] * ratio);
else fSum[2] += (noise[2] * ratio);
if (noise[3]<0) fSum[3] -= (noise[3] * ratio);
else fSum[3] += (noise[3] * ratio);
ratio *= .5;
pointX *= 2;
pointY *= 2;
}
rgb[0] = (int)fSum[0];
if ((rgb[0] & 0xFFFFFF00) != 0)
rgb[0] = ((rgb[0] & 0x80000000) != 0)?0:255;
rgb[1] = (int)fSum[1];
if ((rgb[1] & 0xFFFFFF00) != 0)
rgb[1] = ((rgb[1] & 0x80000000) != 0)?0:255;
rgb[2] = (int)fSum[2];
if ((rgb[2] & 0xFFFFFF00) != 0)
rgb[2] = ((rgb[2] & 0x80000000) != 0)?0:255;
rgb[3] = (int)fSum[3];
if ((rgb[3] & 0xFFFFFF00) != 0)
rgb[3] = ((rgb[3] & 0x80000000) != 0)?0:255;
break;
case 3:
for(int nOctave = 0; nOctave < numOctaves; nOctave++){
noise2(noise, pointX, pointY);
if (noise[2]<0) fSum[2] -= (noise[2] * ratio);
else fSum[2] += (noise[2] * ratio);
if (noise[1]<0) fSum[1] -= (noise[1] * ratio);
else fSum[1] += (noise[1] * ratio);
if (noise[0]<0) fSum[0] -= (noise[0] * ratio);
else fSum[0] += (noise[0] * ratio);
ratio *= .5;
pointX *= 2;
pointY *= 2;
}
rgb[2] = (int)fSum[2];
if ((rgb[2] & 0xFFFFFF00) != 0)
rgb[2] = ((rgb[2] & 0x80000000) != 0)?0:255;
rgb[1] = (int)fSum[1];
if ((rgb[1] & 0xFFFFFF00) != 0)
rgb[1] = ((rgb[1] & 0x80000000) != 0)?0:255;
rgb[0] = (int)fSum[0];
if ((rgb[0] & 0xFFFFFF00) != 0)
rgb[0] = ((rgb[0] & 0x80000000) != 0)?0:255;
break;
case 2:
for(int nOctave = 0; nOctave < numOctaves; nOctave++){
noise2(noise, pointX, pointY);
if (noise[1]<0) fSum[1] -= (noise[1] * ratio);
else fSum[1] += (noise[1] * ratio);
if (noise[0]<0) fSum[0] -= (noise[0] * ratio);
else fSum[0] += (noise[0] * ratio);
ratio *= .5;
pointX *= 2;
pointY *= 2;
}
rgb[1] = (int)fSum[1];
if ((rgb[1] & 0xFFFFFF00) != 0)
rgb[1] = ((rgb[1] & 0x80000000) != 0)?0:255;
rgb[0] = (int)fSum[0];
if ((rgb[0] & 0xFFFFFF00) != 0)
rgb[0] = ((rgb[0] & 0x80000000) != 0)?0:255;
break;
case 1:
for(int nOctave = 0; nOctave < numOctaves; nOctave++){
noise2(noise, pointX, pointY);
if (noise[0]<0) fSum[0] -= (noise[0] * ratio);
else fSum[0] += (noise[0] * ratio);
ratio *= .5;
pointX *= 2;
pointY *= 2;
}
rgb[0] = (int)fSum[0];
if ((rgb[0] & 0xFFFFFF00) != 0)
rgb[0] = ((rgb[0] & 0x80000000) != 0)?0:255;
break;
}
}
/**
* This is the heart of the turbulence calculation. It returns 'turbFunctionResult', as
* defined in the spec.
* @param rgb array for the four color components
* @param point x and y coordinates of the point to process.
* @param fSum array used to avoid reallocating double array for each pixel
* @param noise array used to avoid reallocating double array for each pixel
* @param channels channels for which values should be computed
*/
private final void turbulenceStitch(final int rgb[],
double pointX, double pointY,
final double fSum[],
final double noise[],
StitchInfo stitchInfo){
double ratio = 1;
pointX *= baseFrequencyX;
pointY *= baseFrequencyY;
fSum[0] = fSum[1] = fSum[2] = fSum[3] = 0;
switch (channels.length) {
case 4:
for(int nOctave = 0; nOctave < numOctaves; nOctave++){
noise2Stitch(noise, pointX, pointY, stitchInfo);
if (noise[3]<0) fSum[3] -= (noise[3] * ratio);
else fSum[3] += (noise[3] * ratio);
if (noise[2]<0) fSum[2] -= (noise[2] * ratio);
else fSum[2] += (noise[2] * ratio);
if (noise[1]<0) fSum[1] -= (noise[1] * ratio);
else fSum[1] += (noise[1] * ratio);
if (noise[0]<0) fSum[0] -= (noise[0] * ratio);
else fSum[0] += (noise[0] * ratio);
ratio *= .5;
pointX *= 2;
pointY *= 2;
stitchInfo.doubleFrequency();
}
rgb[3] = (int)(fSum[3] * 255);
if ((rgb[3] & 0xFFFFFF00) != 0)
rgb[3] = ((rgb[3] & 0x80000000) != 0)?0:255;
rgb[2] = (int)(fSum[2] * 255);
if ((rgb[2] & 0xFFFFFF00) != 0)
rgb[2] = ((rgb[2] & 0x80000000) != 0)?0:255;
rgb[1] = (int)(fSum[1] * 255);
if ((rgb[1] & 0xFFFFFF00) != 0)
rgb[1] = ((rgb[1] & 0x80000000) != 0)?0:255;
rgb[0] = (int)(fSum[0] * 255);
if ((rgb[0] & 0xFFFFFF00) != 0)
rgb[0] = ((rgb[0] & 0x80000000) != 0)?0:255;
break;
case 3:
for(int nOctave = 0; nOctave < numOctaves; nOctave++){
noise2Stitch(noise, pointX, pointY, stitchInfo);
if (noise[2]<0) fSum[2] -= (noise[2] * ratio);
else fSum[2] += (noise[2] * ratio);
if (noise[1]<0) fSum[1] -= (noise[1] * ratio);
else fSum[1] += (noise[1] * ratio);
if (noise[0]<0) fSum[0] -= (noise[0] * ratio);
else fSum[0] += (noise[0] * ratio);
ratio *= .5;
pointX *= 2;
pointY *= 2;
stitchInfo.doubleFrequency();
}
rgb[2] = (int)(fSum[2] * 255);
if ((rgb[2] & 0xFFFFFF00) != 0)
rgb[2] = ((rgb[2] & 0x80000000) != 0)?0:255;
rgb[1] = (int)(fSum[1] * 255);
if ((rgb[1] & 0xFFFFFF00) != 0)
rgb[1] = ((rgb[1] & 0x80000000) != 0)?0:255;
rgb[0] = (int)(fSum[0] * 255);
if ((rgb[0] & 0xFFFFFF00) != 0)
rgb[0] = ((rgb[0] & 0x80000000) != 0)?0:255;
break;
case 2:
for(int nOctave = 0; nOctave < numOctaves; nOctave++){
noise2Stitch(noise, pointX, pointY, stitchInfo);
if (noise[1]<0) fSum[1] -= (noise[1] * ratio);
else fSum[1] += (noise[1] * ratio);
if (noise[0]<0) fSum[0] -= (noise[0] * ratio);
else fSum[0] += (noise[0] * ratio);
ratio *= .5;
pointX *= 2;
pointY *= 2;
stitchInfo.doubleFrequency();
}
rgb[1] = (int)(fSum[1] * 255);
if ((rgb[1] & 0xFFFFFF00) != 0)
rgb[1] = ((rgb[1] & 0x80000000) != 0)?0:255;
rgb[0] = (int)(fSum[0] * 255);
if ((rgb[0] & 0xFFFFFF00) != 0)
rgb[0] = ((rgb[0] & 0x80000000) != 0)?0:255;
break;
case 1:
for(int nOctave = 0; nOctave < numOctaves; nOctave++){
noise2Stitch(noise, pointX, pointY, stitchInfo);
if (noise[0]<0) fSum[0] -= (noise[0] * ratio);
else fSum[0] += (noise[0] * ratio);
ratio *= .5;
pointX *= 2;
pointY *= 2;
stitchInfo.doubleFrequency();
}
rgb[0] = (int)(fSum[0] * 255);
if ((rgb[0] & 0xFFFFFF00) != 0)
rgb[0] = ((rgb[0] & 0x80000000) != 0)?0:255;
break;
}
}
/**
* This is the heart of the turbulence calculation. It returns 'turbFunctionResult', as
* defined in the spec.
* @param rgb array for the four color components
* @param point x and y coordinates of the point to process.
* @param fSum array used to avoid reallocating double array for each pixel
* @param noise array used to avoid reallocating double array for each pixel
* @param numOctaves number of octaves (may be limited so that spatial frequency below
* half a pixel are not processed).
* @param channels channels for which values should be computed
*/
private final int turbulenceFractal_4( double pointX,
double pointY,
final double fSum[]) {
int b0, b1, nOctave, i, j, b00, b10, b01, b11;
double px, py, rx0, rx1, ry0, ry1, sx, sy, ratio = 127.5;
pointX *= baseFrequencyX;
pointY *= baseFrequencyY;
fSum[0] = fSum[1] = fSum[2] = fSum[3] = 127.5;
for (nOctave = numOctaves; nOctave > 0; nOctave--){
px = pointX+PerlinN;
b0 = (int)px;
i = latticeSelector[b0 & BM];
j = latticeSelector[(b0+1) & BM];
rx0 = px - (int)px;
rx1 = rx0 - 1.0;
sx = s_curve(rx0);
py = pointY+PerlinN;
b0 = ((int)py) & BM;
b1 = (b0+1) & BM;
b00 = (latticeSelector[i + b0]&BM)<<3;
b10 = (latticeSelector[j + b0]&BM)<<3;
b01 = (latticeSelector[i + b1]&BM)<<3;
b11 = (latticeSelector[j + b1]&BM)<<3;
ry0 = py - (int)py;
ry1 = ry0 - 1.0;
sy = s_curve(ry0);
fSum[0] += lerp(sy,
lerp(sx,
rx0*gradient[b00+0] + ry0*gradient[b00+1],
rx1*gradient[b10+0] + ry0*gradient[b10+1]),
lerp(sx,
rx0*gradient[b01+0] + ry1*gradient[b01+1],
rx1*gradient[b11+0] + ry1*gradient[b11+1]))*ratio;
fSum[1] += lerp(sy,
lerp(sx,
rx0*gradient[b00+2] + ry0*gradient[b00+3],
rx1*gradient[b10+2] + ry0*gradient[b10+3]),
lerp(sx,
rx0*gradient[b01+2] + ry1*gradient[b01+3],
rx1*gradient[b11+2] + ry1*gradient[b11+3]))*ratio;
fSum[2] += lerp(sy,
lerp(sx,
rx0*gradient[b00+4] + ry0*gradient[b00+5],
rx1*gradient[b10+4] + ry0*gradient[b10+5]),
lerp(sx,
rx0*gradient[b01+4] + ry1*gradient[b01+5],
rx1*gradient[b11+4] + ry1*gradient[b11+5]))*ratio;
fSum[3] += lerp(sy,
lerp(sx,
rx0*gradient[b00+6] + ry0*gradient[b00+7],
rx1*gradient[b10+6] + ry0*gradient[b10+7]),
lerp(sx,
rx0*gradient[b01+6] + ry1*gradient[b01+7],
rx1*gradient[b11+6] + ry1*gradient[b11+7]))*ratio;
ratio *= .5;
pointX *= 2;
pointY *= 2;
}
i = (int)fSum[0];
if ((i & 0xFFFFFF00) == 0) j = i<<16;
else j = ((i & 0x80000000) != 0)?0:0xFF0000;
i = (int)fSum[1];
if ((i & 0xFFFFFF00) == 0) j |= i<<8;
else j |= ((i & 0x80000000) != 0)?0:0xFF00;
i = (int)fSum[2];
if ((i & 0xFFFFFF00) == 0) j |= i;
else j |= ((i & 0x80000000) != 0)?0:0xFF;
i = (int)fSum[3];
if ((i & 0xFFFFFF00) == 0) j |= i<<24;
else j |= ((i & 0x80000000) != 0)?0:0xFF000000;
return j;
}
/**
* This is the heart of the turbulence calculation. It returns 'turbFunctionResult', as
* defined in the spec.
* @param rgb array for the four color components
* @param point x and y coordinates of the point to process.
* @param fSum array used to avoid reallocating double array for each pixel
* @param noise array used to avoid reallocating double array for each pixel
* @param numOctaves number of octaves (may be limited so that spatial frequency below
* half a pixel are not processed).
* @param channels channels for which values should be computed
*/
private final void turbulenceFractal(final int rgb[],
double pointX,
double pointY,
final double fSum[],
final double noise[]){
double ratio = 127.5;
int nOctave;
fSum[0] = fSum[1] = fSum[2] = fSum[3] = 127.5;
pointX *= baseFrequencyX;
pointY *= baseFrequencyY;
for(nOctave = numOctaves; nOctave > 0; nOctave--){
noise2(noise, pointX, pointY);
switch (channels.length) {
case 4:
fSum[3] += (noise[3] * ratio);
case 3:
fSum[2] += (noise[2] * ratio);
case 2:
fSum[1] += (noise[1] * ratio);
case 1:
fSum[0] += (noise[0] * ratio);
}
ratio *= .5;
pointX *= 2;
pointY *= 2;
}
switch (channels.length) {
case 4:
rgb[3] = (int)fSum[3];
if ((rgb[3] & 0xFFFFFF00) != 0)
rgb[3] = ((rgb[3] & 0x80000000) != 0)?0:255;
case 3:
rgb[2] = (int)fSum[2];
if ((rgb[2] & 0xFFFFFF00) != 0)
rgb[2] = ((rgb[2] & 0x80000000) != 0)?0:255;
case 2:
rgb[1] = (int)fSum[1];
if ((rgb[1] & 0xFFFFFF00) != 0)
rgb[1] = ((rgb[1] & 0x80000000) != 0)?0:255;
case 1:
rgb[0] = (int)fSum[0];
if ((rgb[0] & 0xFFFFFF00) != 0)
rgb[0] = ((rgb[0] & 0x80000000) != 0)?0:255;
}
}
/**
* This is the heart of the turbulence calculation. It returns 'turbFunctionResult', as
* defined in the spec.
* @param rgb array for the four color components
* @param point x and y coordinates of the point to process.
* @param fSum array used to avoid reallocating double array for each pixel
* @param noise array used to avoid reallocating double array for each pixel
* @param numOctaves number of octaves (may be limited so that spatial frequency below
* half a pixel are not processed).
* @param channels channels for which values should be computed
*/
private final void turbulenceFractalStitch(final int rgb[],
double pointX,
double pointY,
final double fSum[],
final double noise[],
StitchInfo stitchInfo){
double ratio = 127.5;
int nOctave;
fSum[0] = fSum[1] = fSum[2] = fSum[3] = 127.5;
pointX *= baseFrequencyX;
pointY *= baseFrequencyY;
for(nOctave = numOctaves; nOctave > 0; nOctave--){
noise2Stitch(noise, pointX, pointY, stitchInfo);
switch (channels.length) {
case 4:
fSum[3] += (noise[3] * ratio);
case 3:
fSum[2] += (noise[2] * ratio);
case 2:
fSum[1] += (noise[1] * ratio);
case 1:
fSum[0] += (noise[0] * ratio);
}
ratio *= .5;
pointX *= 2;
pointY *= 2;
stitchInfo.doubleFrequency();
}
switch (channels.length) {
case 4:
rgb[3] = (int)fSum[3];
if ((rgb[3] & 0xFFFFFF00) != 0)
rgb[3] = ((rgb[3] & 0x80000000) != 0)?0:255;
case 3:
rgb[2] = (int)fSum[2];
if ((rgb[2] & 0xFFFFFF00) != 0)
rgb[2] = ((rgb[2] & 0x80000000) != 0)?0:255;
case 2:
rgb[1] = (int)fSum[1];
if ((rgb[1] & 0xFFFFFF00) != 0)
rgb[1] = ((rgb[1] & 0x80000000) != 0)?0:255;
case 1:
rgb[0] = (int)fSum[0];
if ((rgb[0] & 0xFFFFFF00) != 0)
rgb[0] = ((rgb[0] & 0x80000000) != 0)?0:255;
}
}
/**
* Generates a Perlin noise pattern into dest Raster.
*
* @param txf image space to noise space transform. The 'noise space' is the
* space where the spatial characteristics of the noise are defined.
* @param des Raster where the pattern should be generated.
*/
public WritableRaster copyData(WritableRaster dest) {
//
// First, check input arguments
//
if(dest==null)
throw new IllegalArgumentException
("Cannot generate a noise pattern into a null raster");
//
// Now, limit the number of octaves so that we do not get frequencies
// below half a pixel.
//
// If d is the distance between to pixels in user space, then,
// numOctavesMax = -(log2(d) + log2(bf))
// along one axis.
//
// The maximum distance along each axis is processed by computing the
// inverse transform of 'maximum' vectors from device space to the filter space
// and determining the maximum component along each axis.
//
int w = dest.getWidth();
int h = dest.getHeight();
// Access the integer buffer for the destination Raster
DataBufferInt dstDB = (DataBufferInt)dest.getDataBuffer();
SinglePixelPackedSampleModel sppsm;
int minX = dest.getMinX();
int minY = dest.getMinY();
sppsm = (SinglePixelPackedSampleModel)dest.getSampleModel();
int dstOff = dstDB.getOffset() +
sppsm.getOffset(minX - dest.getSampleModelTranslateX(),
minY - dest.getSampleModelTranslateY());
final int destPixels[] = dstDB.getBankData()[0];
int dstAdjust = sppsm.getScanlineStride() - w;
// Generate pixel pattern now
int i, end, dp=dstOff;
final int rgb[] = new int[4];
final double fSum[] = {0, 0, 0, 0};
final double noise[] = {0, 0, 0, 0};
final double tx0, tx1, ty0, ty1;
tx0 = tx[0];
tx1 = tx[1];
// Update for y step, (note we substract all the stuff we
// added while going across the scan line).
ty0 = ty[0]-(w*tx0);
ty1 = ty[1]-(w*tx1);
double p[] = {minX, minY};
txf.transform(p, 0, p, 0, 1);
double point_0 = p[0];
double point_1 = p[1];
if(isFractalNoise){
if(stitchInfo == null){
if (channels.length == 4) {
for(i=0; i<h; i++){
for(end=dp+w; dp<end; dp++) {
destPixels[dp] = turbulenceFractal_4
(point_0, point_1, fSum);
point_0 += tx0;
point_1 += tx1;
}
point_0 += ty0;
point_1 += ty1;
dp += dstAdjust;
}
} else {
for(i=0; i<h; i++){
for(end=dp+w; dp<end; dp++){
turbulenceFractal(rgb, point_0, point_1, fSum, noise);
// Write RGB value.
destPixels[dp] = ((rgb[3]<<24) |
(rgb[0]<<16) |
(rgb[1]<<8) |
(rgb[2] ));
point_0 += tx0;
point_1 += tx1;
}
point_0 += ty0;
point_1 += ty1;
dp += dstAdjust;
}
}
}
else{
StitchInfo si = new StitchInfo();
for(i=0; i<h; i++){
for(end=dp+w; dp<end; dp++){
si.assign(this.stitchInfo);
turbulenceFractalStitch(rgb, point_0, point_1,
fSum, noise, si);
// Write RGB value.
destPixels[dp] = ((rgb[3]<<24) |
(rgb[0]<<16) |
(rgb[1]<<8) |
(rgb[2] ));
point_0 += tx0;
point_1 += tx1;
}
point_0 += ty0;
point_1 += ty1;
dp += dstAdjust;
}
}
}
else{ // Loop for turbulence noise
if(stitchInfo == null){
if (channels.length == 4) {
for(i=0; i<h; i++){
for(end=dp+w; dp<end; dp++){
destPixels[dp] = turbulence_4
(point_0, point_1, fSum);
point_0 += tx0;
point_1 += tx1;
}
point_0 += ty0;
point_1 += ty1;
dp += dstAdjust;
}
} else {
for(i=0; i<h; i++){
for(end=dp+w; dp<end; dp++){
turbulence(rgb, point_0, point_1, fSum, noise);
// Write RGB value.
destPixels[dp] = ((rgb[3]<<24) |
(rgb[0]<<16) |
(rgb[1]<<8) |
(rgb[2] ));
point_0 += tx0;
point_1 += tx1;
}
point_0 += ty0;
point_1 += ty1;
dp += dstAdjust;
}
}
}
else{
StitchInfo si = new StitchInfo();
for(i=0; i<h; i++){
for(end=dp+w; dp<end; dp++){
si.assign(this.stitchInfo);
turbulenceStitch(rgb, point_0, point_1,
fSum, noise, si);
// Write RGB value.
destPixels[dp] = ((rgb[3]<<24) |
(rgb[0]<<16) |
(rgb[1]<<8) |
(rgb[2] ));
point_0 += tx0;
point_1 += tx1;
}
point_0 += ty0;
point_1 += ty1;
dp += dstAdjust;
}
}
}
return dest;
}
/**
* @param baseFrequencyX x-axis base frequency for the noise
* function along the x-axis
* @param baseFrequencyY y-axis base frequency for the noise
* function along the x-axis
* @param numOctaves number of octaves in the noise
* function. Positive integral value.
* @param seed starting number for the pseudo random number generator
* @param isFractalNoise defines whether the filter performs a
* fractal noise or a turbulence function.
* @param tile defines the tile size. May be null if stitchTiles
* is false. Otherwise, should not be null.
* @param txf The affine transform from device to user space.
* @param cs The Colorspace to output.
* @param alpha True if the data should have an alpha channel.
*/
public TurbulencePatternRed8Bit(double baseFrequencyX,
double baseFrequencyY,
int numOctaves,
int seed,
boolean isFractalNoise,
Rectangle2D tile,
AffineTransform txf,
Rectangle devRect,
ColorSpace cs,
boolean alpha) {
this.baseFrequencyX = baseFrequencyX;
this.baseFrequencyY = baseFrequencyY;
this.seed = seed;
this.isFractalNoise = isFractalNoise;
this.tile = tile;
this.txf = txf;
if(this.txf == null)
this.txf = IDENTITY;
int nChannels = cs.getNumComponents();
if (alpha) nChannels++;
channels = new int[nChannels];
for(int i=0; i<channels.length; i++)
channels[i] = i;
txf.deltaTransform(tx, 0, tx, 0, 1);
txf.deltaTransform(ty, 0, ty, 0, 1);
double vecX[] = {.5, 0};
double vecY[] = {0, .5};
txf.deltaTransform(vecX, 0, vecX, 0, 1);
txf.deltaTransform(vecY, 0, vecY, 0, 1);
double dx = Math.max(Math.abs(vecX[0]), Math.abs(vecY[0]));
int maxX = -(int)Math.round((Math.log(dx) + Math.log(baseFrequencyX))/
Math.log(2));
double dy = Math.max(Math.abs(vecX[1]), Math.abs(vecY[1]));
int maxY = -(int)Math.round((Math.log(dy) + Math.log(baseFrequencyY))/
Math.log(2));
this.numOctaves = numOctaves > maxX? maxX : numOctaves;
this.numOctaves = this.numOctaves > maxY? maxY : this.numOctaves;
if(this.numOctaves < 1 && numOctaves > 1)
this.numOctaves = 1;
if (this.numOctaves > 8)
// beyond 8 octaves there is no significant contribution
// to the output pixel.
this.numOctaves = 8;
if (tile != null) {
//
// Adjust frequencies to the tile size
//
double lowFreq = Math.floor(tile.getWidth()*baseFrequencyX)/tile.getWidth();
double highFreq = Math.ceil(tile.getWidth()*baseFrequencyX)/tile.getWidth();
if(baseFrequencyX/lowFreq < highFreq/baseFrequencyX)
this.baseFrequencyX = lowFreq;
else
this.baseFrequencyX = highFreq;
lowFreq = Math.floor(tile.getHeight()*baseFrequencyY)/tile.getHeight();
highFreq = Math.ceil(tile.getHeight()*baseFrequencyY)/tile.getHeight();
if(baseFrequencyY/lowFreq < highFreq/baseFrequencyY)
this.baseFrequencyY = lowFreq;
else
this.baseFrequencyY = highFreq;
//
// Now, process the initial latice grid size to compute the minimum
// and maximum latice values on each axis.
//
stitchInfo = new StitchInfo();
stitchInfo.width = ((int)(tile.getWidth()*this.baseFrequencyX));
stitchInfo.height = ((int)(tile.getHeight()*this.baseFrequencyY));
stitchInfo.wrapX = ((int)(tile.getX()*this.baseFrequencyX +
PerlinN + stitchInfo.width));
stitchInfo.wrapY = ((int)(tile.getY()*this.baseFrequencyY +
PerlinN + stitchInfo.height));
// Protect agains zero frequencies. Setting values to 1
// will not affect the result of the computations.
if(stitchInfo.width == 0) stitchInfo.width = 1;
if(stitchInfo.height == 0) stitchInfo.height = 1;
// System.out.println( "minLatticeX = " + minLatticeX +
// " minLatticeY = " + minLatticeY +
// " maxLatticeX = " + maxLatticeX +
// " maxLatticeY = " + maxLatticeY);
}
initLattice(seed);
ColorModel cm;
if (alpha)
cm = new DirectColorModel
(cs, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000,
false, DataBuffer.TYPE_INT);
else
cm = new DirectColorModel
(cs, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x0,
false, DataBuffer.TYPE_INT);
int tileSize = AbstractTiledRed.getDefaultTileSize();
init((CachableRed)null, devRect, cm,
cm.createCompatibleSampleModel(tileSize, tileSize),
0, 0, null);
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: batik-dev-unsubscribe@xml.apache.org
For additional commands, e-mail: batik-dev-help@xml.apache.org