Initial commit

This commit is contained in:
josch 2011-09-28 22:56:50 +02:00
commit 445eb8f1c3
55 changed files with 6789 additions and 0 deletions

74
build.xml Normal file
View file

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<!-- By default, only the Clean and Build commands use this build script. -->
<!-- Commands such as Run, Debug, and Test only use this build script if -->
<!-- the Compile on Save feature is turned off for the project. -->
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
<!-- in the project's Project Properties dialog box.-->
<project name="ZomBDeepZoom" default="default" basedir=".">
<description>Builds, tests, and runs the project ZomBDeepZoom.</description>
<import file="nbproject/build-impl.xml"/>
<!--
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
-pre-init: called before initialization of project properties
-post-init: called after initialization of project properties
-pre-compile: called before javac compilation
-post-compile: called after javac compilation
-pre-compile-single: called before javac compilation of single file
-post-compile-single: called after javac compilation of single file
-pre-compile-test: called before javac compilation of JUnit tests
-post-compile-test: called after javac compilation of JUnit tests
-pre-compile-test-single: called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar: called before JAR building
-post-jar: called after JAR building
-post-clean: called after cleaning build products
(Targets beginning with '-' are not intended to be called on their own.)
Example of inserting an obfuscator after compilation could look like this:
<target name="-post-compile">
<obfuscate>
<fileset dir="${build.classes.dir}"/>
</obfuscate>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Another way to customize the build is by overriding existing main targets.
The targets of interest are:
-init-macrodef-javac: defines macro for javac compilation
-init-macrodef-junit: defines macro for junit execution
-init-macrodef-debug: defines macro for class debugging
-init-macrodef-java: defines macro for class execution
-do-jar-with-manifest: JAR building (if you are using a manifest)
-do-jar-without-manifest: JAR building (if you are not using a manifest)
run: execution of project
-javadoc-build: Javadoc generation
test-report: JUnit report generation
An example of overriding the target for project execution could look like this:
<target name="run" depends="ZomBDeepZoom-impl.jar">
<exec dir="bin" executable="launcher.exe">
<arg file="${dist.jar}"/>
</exec>
</target>
Notice that the overridden target depends on the jar target and not only on
the compile target as the regular run target does. Again, for a list of available
properties which you can use, check the target you are overriding in the
nbproject/build-impl.xml file.
-->
</project>

1041
nbproject/build-impl.xml Normal file

File diff suppressed because it is too large Load diff

View file

View file

@ -0,0 +1 @@
user.properties.file=C:\\Users\\Yukari Yakumo\\.netbeans\\7.0\\build.properties

View file

@ -0,0 +1,62 @@
application.title=ZomBDeepZoom
application.vendor=Administrator
build.classes.dir=${build.dir}/classes
build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
build.generated.sources.dir=${build.dir}/generated-sources
# Only compile against the classpath explicitly listed here:
build.sysclasspath=ignore
build.test.classes.dir=${build.dir}/test/classes
build.test.results.dir=${build.dir}/test/results
debug.classpath=\
${run.classpath}
debug.test.classpath=\
${run.test.classpath}
# This directory is removed when the project is cleaned:
dist.dir=dist
dist.jar=${dist.dir}/ZomBDeepZoom.jar
dist.javadoc.dir=${dist.dir}/javadoc
excludes=
includes=**
jar.compress=false
javac.classpath=
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
javac.source=1.5
javac.target=1.5
javac.test.classpath=\
${javac.classpath}:\
${build.classes.dir}:\
${libs.junit.classpath}:\
${libs.junit_4.classpath}
javadoc.additionalparam=
javadoc.author=false
javadoc.encoding=${source.encoding}
javadoc.noindex=false
javadoc.nonavbar=false
javadoc.notree=false
javadoc.private=false
javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
main.class=deepZoom.MandelAnimator
manifest.file=manifest.mf
meta.inf.dir=${src.dir}/META-INF
platform.active=default_platform
run.classpath=\
${javac.classpath}:\
${build.classes.dir}
# Space-separated list of JVM arguments used when running the project
# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
# or test-sys-prop.name=value to set system properties for unit tests):
run.jvmargs=
run.test.classpath=\
${javac.test.classpath}:\
${build.test.classes.dir}
source.encoding=UTF-8
src.dir=src
test.src.dir=test

9
src/deepZoom/Main.java Normal file
View file

@ -0,0 +1,9 @@
package deepZoom;
public class Main {
public static void main(String[] args) {
//new MandelAnimator();
}
}

View file

@ -0,0 +1,334 @@
package deepZoom;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import deepZoom.calculator.Calculator;
import deepZoom.calculator.ParallelCalculator;
import deepZoom.colorings.Coloring;
import deepZoom.colorings.SmoothIterationsColoringBad;
import deepZoom.fractals.Fractal;
import deepZoom.fractals.Mandel;
import deepZoom.fractals.MandelPrecision;
import deepZoom.parameters.ZoomAnimation;
import deepZoom.renderer.Layer;
import deepZoom.renderer.Scene;
import deepZoom.schedulers.AngularScheduler;
import deepZoom.schedulers.CRTScheduler;
import deepZoom.schedulers.ClockScheduler;
import deepZoom.schedulers.DitherScheduler;
import deepZoom.schedulers.FlowerScheduler;
import deepZoom.schedulers.ModScheduler;
import deepZoom.schedulers.PythagorasScheduler;
import deepZoom.schedulers.RadialScheduler;
import deepZoom.schedulers.RandomScheduler;
import deepZoom.schedulers.Scheduler;
import deepZoom.schedulers.SimpleScheduler;
import deepZoom.schedulers.SpiralScheduler;
import deepZoom.schedulers.SplitScheduler;
import deepZoom.schedulers.SquareSpiralScheduler;
import deepZoom.schedulers.XorScheduler;
import deepZoom.viewports.Viewport;
import digisoft.custom.NumberFunctions;
import digisoft.custom.awt.Color3f;
import digisoft.custom.swing.ImageFunctions;
import digisoft.custom.swing.RefreshListener;
import digisoft.custom.swing.RefreshThread;
import digisoft.custom.swing.gradient.Gradient;
import digisoft.custom.swing.gradient.OpaqueGradient;
import digisoft.custom.swing.window.PixelWindow;
import digisoft.custom.util.geom.DoubleDouble;
import java.io.File;
/**
* @author Zom-B
* @since 1.0
* @see date 2006/10/20
*/
public class MandelAnimator implements RefreshListener, Calculator, MouseListener {
private static final String SAVEPATH = "C:/Animation golden/";
private static final int WIDTH = (int) (1024);
private static final int HEIGHT = (int) (576);
private static int FRAME_START = 1;
private static final int FRAME_END = 3600;
private static final int FRAME_STEP = 1;
private static final boolean DO_ANTIALIAS = true;
//Traditional Wikipedia
private DoubleDouble centerX = new DoubleDouble(-0.7436438870371587, -3.628952515063387E-17);
private DoubleDouble centerY = new DoubleDouble(0.13182590420531198, -1.2892807754956678E-17);
//Line and cross
//private DoubleDouble centerX = new DoubleDouble(-0.743646040973709, -4.790419761500457E-18);
//private DoubleDouble centerY = new DoubleDouble(0.13182426946026354, 1.9785505600065397E-18);
private static final double MIN_ZOOM = 1;
private static final double MAX_ZOOM = 1e30;
private static final int NUM_FRAMES = 3600;
public static void main(String[] args) {
new MandelAnimator();
}
private static final int NUM_CPUS = Runtime.getRuntime().availableProcessors();
private PixelWindow aaWindow = new PixelWindow(10, 10, MandelAnimator.WIDTH, MandelAnimator.HEIGHT);
private PixelWindow iterWindow = new PixelWindow(10, 10, MandelAnimator.WIDTH, MandelAnimator.HEIGHT);
private PixelWindow fractalWindow = new PixelWindow(10, 10, MandelAnimator.WIDTH, MandelAnimator.HEIGHT);
private Viewport viewport = new Viewport();
private Layer layer = new Layer();
private ZoomAnimation animation = new ZoomAnimation();
private Fractal fractal = new Mandel();
private Coloring coloring = new SmoothIterationsColoringBad(makeGradient());
private Scheduler[] schedulers = {new SpiralScheduler(10)};
private int scheduler;
private Scene scene = new Scene();
private int frameNr;
private boolean antialiasStep = false;
private long runTime;
private long frameTime;
public MandelAnimator() {
File dirFile = new File(SAVEPATH);
dirFile.mkdir();
int newSave = 0;
for (int i = MandelAnimator.FRAME_START; i <= MandelAnimator.FRAME_END; i++) {
File test = new File(MandelAnimator.SAVEPATH
+ NumberFunctions.toStringFixedLength(i, 4) + ".png");
if (!test.isFile()) {
newSave = i;
break;
}
}
MandelAnimator.FRAME_START = newSave;
fractalWindow.addMouseListener(this);
iterWindow.setTitle("Iter");
aaWindow.setTitle("AA");
animation.setWidth(MandelAnimator.WIDTH);
animation.setNumFrames(MandelAnimator.NUM_FRAMES);
animation.setCenterX(centerX);
animation.setCenterY(centerY);
animation.setMagnStart(MandelAnimator.MIN_ZOOM);
animation.setMagnEnd(MandelAnimator.MAX_ZOOM);
animation.setBailout(128);
animation.init();
viewport.setSize(MandelAnimator.WIDTH, MandelAnimator.HEIGHT);
viewport.setParameters(animation);
fractal.setParameters(animation);
coloring.setParameters(animation);
for (Scheduler s : schedulers) {
s.setViewport(viewport);
}
scene.setViewport(viewport);
scene.setColorPixels(fractalWindow.pixels);
scene.setIterMap(iterWindow.pixels);
scene.setEdgeMap(aaWindow.pixels);
scene.setNumCPUs(MandelAnimator.NUM_CPUS);
{
layer.setFractal(fractal);
layer.setColoring(coloring);
scene.addLayer(layer);
}
frameNr = MandelAnimator.FRAME_START;
runTime = frameTime = System.currentTimeMillis();
ParallelCalculator.createCalculators(this, MandelAnimator.NUM_CPUS);
new RefreshThread(this, 30).start();
}
public static Gradient makeGradient() {
final Color3f[] c = {
new Color3f(14, 11, 82),
new Color3f(14, 60, 165),
new Color3f(78, 154, 220),
new Color3f(176, 229, 255),
new Color3f(249, 253, 239),
new Color3f(249, 229, 96),
new Color3f(249, 181, 15),
new Color3f(217, 108, 3),
new Color3f(134, 32, 13),
new Color3f(57, 4, 35),
new Color3f(14, 11, 82)};
final float[] f = new float[c.length];
for (int i = 0; i < c.length; i++) {
f[i] = i / (float) (c.length - 1);
f[i] = (float) StrictMath.sqrt(f[i]);
}
return new OpaqueGradient(f, c);
}
/*
public static Gradient makeGradient() {
final Color3f[] c = {new Color3f(0, 0, 0f), //
new Color3f(1, 0, 0f), //
new Color3f(1, 1, 1f), // Red
new Color3f(1, 0, 0f), //
new Color3f(0, 0, 0f), //
new Color3f(1, 0.4f, 0f), //
new Color3f(1, 1, 1f), // Orange
new Color3f(1, 0.4f, 0f), //
new Color3f(0, 0, 0f), //
new Color3f(1, 1, 0f), //
new Color3f(1, 1, 1f), // Yellow
new Color3f(1, 1, 0f), //
new Color3f(0, 0, 0f), //
new Color3f(0, 1, 0f), //
new Color3f(1, 1, 1f), // Green
new Color3f(0, 1, 0f), //
new Color3f(0, 0, 0f), //
new Color3f(0, 1, 1f), //
new Color3f(1, 1, 1f), // Cyan
new Color3f(0, 1, 1f), //
new Color3f(0, 0, 0f), //
new Color3f(0, 0, 1f), //
new Color3f(1, 1, 1f), // Blue
new Color3f(0, 0, 1f), //
new Color3f(0, 0, 0f)};
final float[] f = new float[c.length];
for (int i = 0; i < c.length; i++) {
f[i] = i / (float) (c.length - 1);
f[i] = (float) StrictMath.sqrt(f[i]);
}
return new OpaqueGradient(f, c);
} */
private void saveFrame() {
try {
ImageFunctions.savePNG(MandelAnimator.SAVEPATH + NumberFunctions.toStringFixedLength(frameNr, 4) + ".png", fractalWindow.pixels,
MandelAnimator.WIDTH, MandelAnimator.HEIGHT);
} catch (IOException e) {
e.printStackTrace();
}
}
private void destroyImage() {
System.gc();
fractalWindow.clear(0);
iterWindow.clear(0);
aaWindow.clear(0);
}
private void nextFrame() {
frameNr += MandelAnimator.FRAME_STEP;
if (frameNr > MandelAnimator.FRAME_END) {
// System.exit(0);
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@Override
public void prepareCalculation() {
scheduler = NumberFunctions.RND.nextInt(schedulers.length);
scene.setScheduler(schedulers[scheduler]);
if (!antialiasStep) {
fractalWindow.setTitle(Integer.toString(frameNr) + " First pass");
animation.setFrame(frameNr);
System.out.println("Rough: " + frameNr + " magn=" + animation.getMagn() + " maxiter=" + animation.getMaxiter());
destroyImage();
scene.initFrame();
} else {
fractalWindow.setTitle(Integer.toString(frameNr) + " Antialiasing");
animation.setFrame(frameNr);
animation.setMaxiter(animation.getMaxiter() << 2);
System.out.println("AA: " + frameNr + " magn=" + animation.getMagn() + " maxiter=" + animation.getMaxiter());
scene.calcAntialiasMask();
}
schedulers[scheduler].init();
}
@Override
public void calculate(int cpu) {
if (!antialiasStep) {
scene.render(cpu);
} else {
scene.renderAntialias(cpu);
}
}
@Override
public void calculationCompleted() {
if (!antialiasStep && MandelAnimator.DO_ANTIALIAS) {
antialiasStep = true;
} else {
antialiasStep = false;
fractalWindow.repaintNow();
iterWindow.repaintNow();
saveFrame();
long time = System.currentTimeMillis();
System.out.println("Time elapsed: " + (time - runTime) / 1e3 + " / " + (time - frameTime) / 1e3);
if (time - frameTime < 2000) {
try {
Thread.sleep(2000 - time + frameTime);
} catch (InterruptedException e) {
}
}
frameTime = System.currentTimeMillis();
nextFrame();
}
}
@Override
public void refreshing() {
fractalWindow.repaintNow();
iterWindow.repaintNow();
aaWindow.repaintNow();
if (antialiasStep) {
aaWindow.setTitle("AA " + (int) (schedulers[scheduler].getProgress() * 1000) / 10f + "%");
} else {
iterWindow.setTitle("Iter " + (int) (schedulers[scheduler].getProgress() * 1000) / 10f + "%");
}
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
if ((e.getModifiers() & InputEvent.BUTTON1_MASK) != 0) {
centerX = viewport.getPX(e.getX(), e.getY());
centerY = viewport.getPY(e.getX(), e.getY());
System.out.println("/tprivate DoubleDouble/t/t/tcenterX/t/t/t= new DoubleDouble(" + centerX.hi + ", " + centerX.lo + ");");
System.out.println("/tprivate DoubleDouble/t/t/tcenterY/t/t/t= new DoubleDouble(" + centerY.hi + ", " + centerY.lo + ");");
} else if ((e.getModifiers() & InputEvent.BUTTON3_MASK) != 0) {
}
}
@Override
public void mouseReleased(MouseEvent e) {
}
}

View file

@ -0,0 +1,32 @@
package deepZoom.animation;
import deepZoom.parameters.Parameters;
/**
* Generic animation for fractals. Implementations define which parameters are
* animated, though animation for the following quantities is supported: center,
* magnitude, maxiter and bailout. Before the animation can be calculated, the
* number of frames need also be known beforehand. After changing animation
* parameters or number of frames, the animation needs to be initialized by
* calling init().
*
* @author Zom-B
* @since 1.0
* @date May 2, 2009
*/
public abstract class Animation extends Parameters {
protected int numFrames;
public void setNumFrames(int numFrames) {
this.numFrames = numFrames;
}
/**
* Initialize the animation sequence. Call after each change to
* initial/final parameters or number of frames.
*/
public abstract void init();
public abstract void setFrame(int frameNr);
}

View file

@ -0,0 +1,69 @@
package deepZoom.animation;
import digisoft.custom.util.geom.DoubleDouble;
/**
* Animation that just zooms. The center parameters and bailout are not
* animated, and the zooming position is the center of the fractal. ie. set the
* center of the fractal to the center of thezoomed frame. The maxiter is also
* animated to account for constant detail with maximum speed throughout the
* animation. For this, the width of the frame in pixels is also required.
* Bailout is also not animated.
*
* @author Zom-B
* @since 1.0
* @date May 2, 2009
*/
public class ZoomAnimation extends Animation {
private int width;
private double magnStart;
private double magnEnd;
private double factorMagn;
public void setWidth(int width) {
this.width = width;
}
@Override
public void setNumFrames(int numFrames) {
this.numFrames = numFrames;
}
@Override
public void setCenterX(DoubleDouble centerX) {
this.centerX = centerX;
}
@Override
public void setCenterY(DoubleDouble centerY) {
this.centerY = centerY;
}
public void setMagnStart(double magnStart) {
this.magnStart = magnStart;
}
public void setMagnEnd(double magnEnd) {
this.magnEnd = magnEnd;
}
@Override
public void setBailout(double bailout) {
this.bailout = bailout;
}
@Override
public void init() {
factorMagn = StrictMath.pow(magnEnd / magnStart, 1.0 / (numFrames - 1));
}
@Override
public void setFrame(int frameNr) {
magn = magnStart * StrictMath.pow(factorMagn, frameNr - 1);
maxiter = (long) (width * StrictMath.pow(magn, -0.5));
System.out.println(magn);
}
}

View file

@ -0,0 +1,15 @@
package deepZoom.calculator;
/**
* @author Zom-B
* @since 1.0
* @date Apr 19, 2009
*/
public interface Calculator {
public void prepareCalculation();
public void calculate(int cpu);
public void calculationCompleted();
}

View file

@ -0,0 +1,93 @@
package deepZoom.calculator;
import java.util.Arrays;
/**
* @author Zom-B
* @since 1.0
* @date Apr 19, 2009
*/
public class ParallelCalculator implements Runnable {
private static int NUM_CPUS;
private static boolean[] WAIT;
private static boolean[] GO;
public static void createCalculators(Calculator calculator, int numCPUs) {
ParallelCalculator.NUM_CPUS = numCPUs;
ParallelCalculator.WAIT = new boolean[numCPUs];
ParallelCalculator.GO = new boolean[numCPUs];
for (int i = 0; i < numCPUs; i++) {
new ParallelCalculator(calculator, i);
}
}
private int cpu;
private Calculator calculator;
private ParallelCalculator(Calculator calculator, int cpu) {
this.calculator = calculator;
this.cpu = cpu;
System.out.println("Starting core " + cpu);
prepare();
new Thread(this).start();
}
public void run() {
while (true) {
calculator.calculate(cpu);
syncWithOthers();
}
}
private void prepare() {
if (cpu == 0) {
Arrays.fill(ParallelCalculator.WAIT, true);
Arrays.fill(ParallelCalculator.GO, true);
calculator.prepareCalculation();
}
}
private void syncWithOthers() {
ParallelCalculator.WAIT[cpu] = false;
if (cpu == 0) {
while (true) {
boolean done = true;
for (int i = ParallelCalculator.NUM_CPUS - 1; i >= 0; i--) {
if (ParallelCalculator.WAIT[i]) {
done = false;
break;
}
}
if (done) {
break;
}
Thread.yield();
}
// All threads done.
calculator.calculationCompleted();
prepare();
Arrays.fill(ParallelCalculator.WAIT, true);
Arrays.fill(ParallelCalculator.GO, true);
} else {
while (!ParallelCalculator.GO[cpu]) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
Thread.yield();
}
}
}
ParallelCalculator.GO[cpu] = false;
}
}

View file

@ -0,0 +1,22 @@
package deepZoom.colorings;
import deepZoom.parameters.Parameters;
import deepZoom.renderer.PointInfo;
/**
* @author Zom-B
* @since 1.0
* @date May 1, 2009
*/
public abstract class Coloring {
protected Parameters parameters;
public void setParameters(Parameters parameters) {
this.parameters = parameters;
}
public abstract void initParameters();
public abstract int getColor(PointInfo resultSet);
}

View file

@ -0,0 +1,26 @@
package deepZoom.colorings;
import deepZoom.renderer.PointInfo;
import digisoft.custom.swing.gradient.Gradient;
/**
* @author Zom-B
* @since 1.0
* @date May 2, 2009
*/
public abstract class GradientColoring extends Coloring {
protected Gradient gradient;
public GradientColoring(Gradient gradient) {
this.gradient = gradient;
}
@Override
public int getColor(PointInfo resultSet) {
return gradient.get(getIndex(resultSet) % 1);
}
public abstract float getIndex(PointInfo resultSet);
}

View file

@ -0,0 +1,37 @@
package deepZoom.colorings;
import deepZoom.renderer.PointInfo;
import digisoft.custom.math.NumberConstants;
import digisoft.custom.swing.gradient.Gradient;
import digisoft.custom.util.geom.DoubleDouble;
/**
* @author Zom-B
* @since 1.0
* @date May 1, 2009
*/
public class SmoothIterationsColoringBad extends GradientColoring {
private double logLogBailout;
public SmoothIterationsColoringBad(Gradient gradient) {
super(gradient);
}
@Override
public void initParameters() {
logLogBailout = StrictMath.log(StrictMath.log(parameters.getBailout()));
}
@Override
public float getIndex(PointInfo resultSet) {
long i = resultSet.lastIter;
DoubleDouble zx = resultSet.lastZX;
DoubleDouble zy = resultSet.lastZY;
double r = StrictMath.sqrt(zx.hi * zx.hi + zy.hi * zy.hi);
double c = i - 1.28 + (logLogBailout - StrictMath.log(StrictMath.log(r))) * NumberConstants.Q1LOG2;
return (float) (StrictMath.log(c / 64 + 1) / NumberConstants.LOG2 + 0.45);
}
}

View file

@ -0,0 +1,29 @@
package deepZoom.fractals;
import deepZoom.parameters.Parameters;
import deepZoom.renderer.PointInfo;
/**
* @author Zom-B
* @since 1.0
* @date 2009/05/01
*/
public abstract class Fractal {
protected Parameters parameters;
public void setParameters(Parameters parameters) {
this.parameters = parameters;
}
public abstract void initFrame();
/**
*
* @param x
* @param y
* @param result
* float array with {gradient index, last iter}
*/
public abstract void calcPoint(PointInfo pointInfo);
}

View file

@ -0,0 +1,119 @@
package deepZoom.fractals;
import deepZoom.renderer.PointInfo;
/**
* @author Zom-B
* @since 1.0
* @date 2009/07/09
*/
public class Mandel extends Fractal {
private static final double PRIODICITY_EPS = 1e-17;
@Override
public void initFrame() {
}
@Override
public void calcPoint(PointInfo pointInfo) {
double zx;
double zy;
double xx;
double yy;
double bailout = parameters.getBailout();
long maxiter = parameters.getMaxiter();
// Calculate viewport.
double px = pointInfo.px.hi;
double py = pointInfo.py.hi;
// Main bulb check.
zx = 4 * (px * px + py * py);
xx = 2 * px;
zy = zx + 4 * xx;
if (zy < -3.75) {
pointInfo.inside = true;
pointInfo.lastIter = maxiter;
pointInfo.lastZX.hi = px;
pointInfo.lastZY.hi = py;
return;
}
// Cardoid check.
zy = zx - xx + 0.25;
xx = xx + zy - 0.5;
xx *= xx;
if (zy > xx) {
pointInfo.inside = true;
pointInfo.lastIter = maxiter;
pointInfo.lastZX.hi = px;
pointInfo.lastZY.hi = py;
return;
}
zx = px;
zy = py;
// Initial maximum period to detect.
int check = 3;
// Maximum period doubles every iterations:
int whenupdate = 10;
// Period history registers.
double hx = 0;
double hy = 0;
// long int because maxiter goes above 2**31 bits
for (long i = 1; i <= 50000; i++) {
// Precalculate squares.
xx = zx * zx;
yy = zy * zy;
// Check bailout.
if (xx + yy > bailout) {
pointInfo.inside = false;
pointInfo.lastIter = i;
pointInfo.lastZX.hi = zx;
pointInfo.lastZY.hi = zy;
return;
}
// Iterate
zy = 2 * zx * zy + py;
zx = xx - yy + px;
// Periodicity check.
double d = zx - hx;
if (d > 0.0 ? d < Mandel.PRIODICITY_EPS : d > -Mandel.PRIODICITY_EPS) {
d = zy - hy;
if (d > 0.0 ? d < Mandel.PRIODICITY_EPS : d > -Mandel.PRIODICITY_EPS) {
// Period found.
pointInfo.inside = true;
pointInfo.lastIter = i; // & check
pointInfo.lastZX.hi = zx;
pointInfo.lastZY.hi = zy;
return;
}
}
if ((i & check) == 0) {
if (--whenupdate == 0) {
whenupdate = 10;
check <<= 1;
check++;
}
// period = 0;
hx = zx;
hy = zy;
}
}
// Maxiter reached.
pointInfo.inside = true;
pointInfo.lastIter = maxiter;
pointInfo.lastZX.hi = zx;
pointInfo.lastZY.hi = zy;
return;
}
}

View file

@ -0,0 +1,151 @@
package deepZoom.fractals;
import deepZoom.renderer.PointInfo;
import digisoft.custom.util.geom.DoubleDouble;
/**
* @author Zom-B
* @since 1.0
* @date 2009/07/09
*/
public class MandelPrecision extends Fractal {
private static final double PRIODICITY_EPS = 1e-17;
@Override
public void initFrame() {
}
@Override
public void calcPoint(PointInfo pointInfo) {
DoubleDouble zx = new DoubleDouble();
DoubleDouble zy = new DoubleDouble();
DoubleDouble xx = new DoubleDouble();
DoubleDouble yy = new DoubleDouble();
DoubleDouble temp = new DoubleDouble();
double bailout = parameters.getBailout();
long maxiter = parameters.getMaxiter();
// Calculate viewport.
// DoubleDouble px = this.viewport.getPX(x, y);
// DoubleDouble py = this.viewport.getPY(x, y);
DoubleDouble px = pointInfo.px;
DoubleDouble py = pointInfo.py;
// Main bulb check.
// zx = 4 * (px * px + py * py);
zy.set(py);
zy.sqrSelf();
zx.set(px);
zx.sqrSelf();
zx.addSelf(zy);
zx.mulSelf(4);
// temp = 2 * px
xx.set(px);
xx.mulSelf(2);
// zy = zx + 4 * temp
zy.set(xx);
zy.mulSelf(4);
zy.addSelf(zx);
if (zy.hi < -3.75) {
pointInfo.inside = true;
pointInfo.lastIter = maxiter;
pointInfo.lastZX = px;
pointInfo.lastZY = py;
return;
}
// Cardoid check.
// zy = zx - temp + 0.25;
zy.set(zx);
zy.subSelf(xx);
zy.addSelf(0.25);
// temp = (temp + zy - 0.5)**2;
xx.addSelf(zy);
xx.addSelf(-0.5);
xx.sqrSelf();
// if (zy > temp)
if (zy.hi > xx.hi) {
pointInfo.inside = true;
pointInfo.lastIter = maxiter;
pointInfo.lastZX = px;
pointInfo.lastZY = py;
return;
}
zx.set(px);
zy.set(py);
// Initial maximum period to detect.
int check = 3;
// Maximum period doubles every iterations:
int whenupdate = 10;
// Period history registers.
double hx = 0;
double hy = 0;
// long int because maxiter goes above 2**31 bits
for (long i = 1; i <= 50000; i++) {
// Precalculate squares.
xx.set(zx);
xx.sqrSelf();
yy.set(zy);
yy.sqrSelf();
// Check bailout.
temp.set(xx);
temp.addSelf(yy);
if (temp.hi > bailout) {
pointInfo.inside = false;
pointInfo.lastIter = i;
pointInfo.lastZX = zx;
pointInfo.lastZY = zy;
return;
}
// Iterate
// y' = y * x * 2 + cy
zy.mulSelf(zx);
zy.addSelf(zy);
zy.addSelf(py);
// x' = xx - yy + px
xx.subSelf(yy);
zx.set(xx);
zx.addSelf(px);
// Periodicity check.
double d = zx.hi - hx;
if (d > 0.0 ? d < MandelPrecision.PRIODICITY_EPS : d > -MandelPrecision.PRIODICITY_EPS) {
d = zy.hi - hy;
if (d > 0.0 ? d < MandelPrecision.PRIODICITY_EPS : d > -MandelPrecision.PRIODICITY_EPS) {
// Period found.
pointInfo.inside = true;
pointInfo.lastIter = i; // & check
pointInfo.lastZX = zx;
pointInfo.lastZY = zy;
return;
}
}
if ((i & check) == 0) {
if (--whenupdate == 0) {
whenupdate = 10;
check <<= 1;
check++;
}
// period = 0;
hx = zx.hi;
hy = zy.hi;
}
}
// Maxiter reached.
pointInfo.inside = true;
pointInfo.lastIter = maxiter;
pointInfo.lastZX = zx;
pointInfo.lastZY = zy;
return;
}
}

View file

@ -0,0 +1,30 @@
package deepZoom.parameters;
/**
* Generic animation for fractals. Implementations define which parameters are
* animated, though animation for the following quantities is supported: center,
* magnitude, maxiter and bailout. Before the animation can be calculated, the
* number of frames need also be known beforehand. After changing animation
* parameters or number of frames, the animation needs to be initialized by
* calling init().
*
* @author Zom-B
* @since 1.0
* @date May 2, 2009
*/
public abstract class Animation extends Parameters {
protected int numFrames;
public void setNumFrames(int numFrames) {
this.numFrames = numFrames;
}
/**
* Initialize the animation sequence. Call after each change to
* initial/final parameters or number of frames.
*/
public abstract void init();
public abstract void setFrame(int frameNr);
}

View file

@ -0,0 +1,57 @@
package deepZoom.parameters;
import digisoft.custom.util.geom.DoubleDouble;
/**
* @author Zom-B
* @since 1.0
* @date May 2, 2009
*/
public class Parameters {
protected DoubleDouble centerX = new DoubleDouble();
protected DoubleDouble centerY = new DoubleDouble();
protected double magn;
protected long maxiter;
protected double bailout;
public void setCenterX(DoubleDouble centerX) {
this.centerX = centerX;
}
public DoubleDouble getCenterX() {
return centerX;
}
public void setCenterY(DoubleDouble centerY) {
this.centerY = centerY;
}
public DoubleDouble getCenterY() {
return centerY;
}
public void setMagn(double magn) {
this.magn = magn;
}
public double getMagn() {
return magn;
}
public void setMaxiter(long maxiter) {
this.maxiter = maxiter;
}
public long getMaxiter() {
return maxiter;
}
public void setBailout(double bailout) {
this.bailout = bailout;
}
public double getBailout() {
return bailout;
}
}

View file

@ -0,0 +1,55 @@
package deepZoom.parameters;
/**
* Animation that just zooms. The center parameters and bailout are not
* animated, and the zooming position is the center of the fractal. ie. set the
* center of the fractal to the center of thezoomed frame. The maxiter is also
* animated to account for constant detail with maximum speed throughout the
* animation. For this, the width of the frame in pixels is also required.
* Bailout is also not animated.
*
* @author Zom-B
* @since 1.0
* @date May 2, 2009
*/
public class ZoomAnimation extends Animation {
private int width;
private double magnStart;
private double magnEnd;
private double factorMagn;
public void setWidth(int width) {
this.width = width;
}
@Override
public void setNumFrames(int numFrames) {
this.numFrames = numFrames;
}
public void setMagnStart(double magnStart) {
this.magnStart = magnStart;
}
public void setMagnEnd(double magnEnd) {
this.magnEnd = magnEnd;
}
@Override
public void setBailout(double bailout) {
this.bailout = bailout;
}
@Override
public void init() {
factorMagn = StrictMath.pow(magnEnd / magnStart, 1.0 / (numFrames - 1));
}
@Override
public void setFrame(int frameNr) {
magn = magnStart * StrictMath.pow(factorMagn, frameNr - 1);
maxiter = (long) (width * StrictMath.sqrt(magn));
}
}

View file

@ -0,0 +1,28 @@
package deepZoom.renderer;
import deepZoom.colorings.Coloring;
import deepZoom.fractals.Fractal;
/**
* @author Zom-B
* @since 1.0
* @date May 3, 2009
*/
public class Layer {
protected Fractal fractal;
protected Coloring coloring;
public void setFractal(Fractal fractal) {
this.fractal = fractal;
}
public void setColoring(Coloring coloring) {
this.coloring = coloring;
}
public void initFrame() {
fractal.initFrame();
coloring.initParameters();
}
}

View file

@ -0,0 +1,21 @@
package deepZoom.renderer;
import digisoft.custom.util.geom.DoubleDouble;
/**
* @author Zom-B
* @since 1.0
* @date May 2, 2009
*/
public class PointInfo {
public DoubleDouble px;
public DoubleDouble py;
public boolean inside;
public long lastIter;
public DoubleDouble lastZX = new DoubleDouble();
public DoubleDouble lastZY = new DoubleDouble();
protected int antialiasFactor;
protected int antialiasReach;
protected int antialiasArea;
}

View file

@ -0,0 +1,221 @@
package deepZoom.renderer;
import deepZoom.schedulers.PriorityPoint;
import deepZoom.schedulers.Scheduler;
import deepZoom.viewports.Viewport;
import digisoft.custom.awt.Color3f;
import digisoft.custom.awt.Color3fConst;
/**
* @author Zom-B
* @since 1.0
* @date May 2, 2009
*/
public class Scene {
private Viewport viewport;
private Scheduler scheduler;
private int[] pixels;
private int[] iterMap;
private int[] edgeMap;
private Color3f[] colors;
private int[] mask;
// Multiple layer support unfinished!
private Layer layer;
private int width;
private int height;
private int area = -1;
public void setViewport(Viewport viewport) {
this.viewport = viewport;
}
public void setScheduler(Scheduler scheduler) {
this.scheduler = scheduler;
}
public void setColorPixels(int[] pixels) {
this.pixels = pixels;
}
public void setIterMap(int[] iterMap) {
this.iterMap = iterMap;
}
public void setEdgeMap(int[] edgeMap) {
this.edgeMap = edgeMap;
}
public void addLayer(Layer layer) {
this.layer = layer;
}
public void initFrame() {
viewport.initParameters();
layer.initFrame();
width = viewport.width;
height = viewport.height;
if (area != width * height) {
area = width * height;
colors = new Color3f[area];
mask = new int[area];
for (int i = 0; i < area; i++) {
colors[i] = new Color3f();
}
}
for (int i = 0; i < area; i++) {
colors[i].set(0, 0, 0);
}
}
public void render(PointInfo pointInfo, PriorityPoint point) {
int p = point.x + point.y * width;
viewport.getPoint(point.x, point.y, pointInfo);
layer.fractal.calcPoint(pointInfo);
int iter = (int) pointInfo.lastIter;
boolean inside = pointInfo.inside;
iterMap[p] = iter;
edgeMap[p] = inside ? 0 : iter;
if (!inside) {
colors[p].addSelf(layer.coloring.getColor(pointInfo));
}
pixels[p] = colors[p].getRGB();
}
public void calcAntialiasMask() {
int p = -1;
for (int y = 0; y < height; y++) {
search:
for (int x = 0; x < width; x++) {
if (x == 0 || y == 0 || x + 1 == width || y + 1 == height) {
mask[++p] = 1;
continue;
}
mask[++p] = 0;
int iters = edgeMap[p];
for (int v = y - 1; v <= y + 1; v++) {
for (int u = x - 1; u <= x + 1; u++) {
if (u >= 0 && v >= 0 && u < width && v < height) {
int i = StrictMath.abs(edgeMap[u + v * width]);
if (i != iters) {
mask[p] = 1;
continue search;
}
}
}
}
}
}
p = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (mask[p] != 0) {
int i = 0;
for (int v = y - 1; v <= y + 1; v++) {
for (int u = x - 1; u <= x + 1; u++) {
if (u >= 0 && v >= 0 && u < width && v < height) {
int iters = StrictMath.abs(iterMap[u + v * width]);
if (i < iters) {
i = iters;
}
}
}
}
double d = 32 / StrictMath.log(i);
mask[p] = StrictMath.min((int) (d * d), 15);
}
p++;
}
}
p = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
edgeMap[p] = Color3fConst.DOS_PALETTE[mask[p++] & 0xFF];
}
}
}
public void renderAntialias(PointInfo pointInfo, PriorityPoint point) {
int p = point.x + point.y * width;
if (mask[p] != 0) {
pointInfo.antialiasFactor = 5;
pointInfo.antialiasReach = pointInfo.antialiasFactor / 2;
pointInfo.antialiasArea = pointInfo.antialiasFactor * pointInfo.antialiasFactor;
calcAntialiasPixel(pointInfo, p, point);
edgeMap[p] = (edgeMap[p] & 0xFCFCFC) >> 2;
colors[p].scaleSelf(1f / pointInfo.antialiasArea);
pixels[p] = colors[p].getRGB();
}
}
private void calcAntialiasPixel(PointInfo pointInfo, int p, PriorityPoint point) {
int reach = pointInfo.antialiasReach;
double factor = 1.0 / pointInfo.antialiasFactor;
for (int x = -reach; x <= reach; x++) {
double dx = x * factor;
for (int y = -reach; y <= reach; y++) {
double dy = y * factor;
if ((x | y) != 0) {
viewport.getPoint(point.x + dx, point.y + dy, pointInfo);
layer.fractal.calcPoint(pointInfo);
boolean inside = pointInfo.inside;
if (!inside) {
colors[p].addSelf(layer.coloring.getColor(pointInfo));
}
}
}
}
}
private PointInfo[] pointInfos;
public void setNumCPUs(int numCPUs) {
if (pointInfos == null || pointInfos.length != numCPUs) {
pointInfos = new PointInfo[numCPUs];
for (int cpu = 0; cpu < numCPUs; cpu++) {
pointInfos[cpu] = new PointInfo();
}
}
}
public void render(int cpu) {
while (true) {
PriorityPoint point = scheduler.poll();
if (point == null) {
return;
}
this.render(pointInfos[cpu], point);
}
}
public void renderAntialias(int cpu) {
while (true) {
PriorityPoint point = scheduler.poll();
if (point == null) {
return;
}
this.renderAntialias(pointInfos[cpu], point);
}
}
}

View file

@ -0,0 +1,32 @@
package deepZoom.schedulers;
/**
* @author Zom-B
* @since 1.0
* @date 2009/05/02
*/
public class AngularScheduler extends Scheduler {
private int bands;
public AngularScheduler(int bands) {
this.bands = bands;
}
@Override
protected void initImpl() {
super.clear();
for (int i = 0; i < numLayers; i++) {
for (int y = 0; y < height; y++) {
double dy = y - (height - 0.875) * 0.5;
for (int x = 0; x < width; x++) {
double dx = x - (width - 0.75) * 0.5;
double a = StrictMath.abs((StrictMath.atan2(dy, -dx) / (2 * StrictMath.PI) + 0.5) * bands % 1 - 0.5);
add(new PriorityPoint(i, x, y, -a));
}
}
}
}
}

View file

@ -0,0 +1,24 @@
package deepZoom.schedulers;
/**
* @author Zom-B
* @since 1.0
* @date 2009/05/05
*/
public class CRTScheduler extends Scheduler {
@Override
protected void initImpl() {
super.clear();
for (int i = 0; i < numLayers; i++) {
for (int y = 0; y < height; y++) {
int dy = height - y;
for (int x = 0; x < width; x++) {
int dx = width - x;
add(new PriorityPoint(i, x, y, -x * y * dx * dy));
}
}
}
}
}

View file

@ -0,0 +1,24 @@
package deepZoom.schedulers;
/**
* @author Zom-B
* @since 1.0
* @date 2009/05/02
*/
public class ClockScheduler extends Scheduler {
@Override
protected void initImpl() {
super.clear();
for (int i = 0; i < numLayers; i++) {
for (int y = 0; y < height; y++) {
double dy = y - (height - 0.875) * 0.5;
for (int x = 0; x < width; x++) {
double dx = x - (width - 0.75) * 0.5;
add(new PriorityPoint(i, x, y, Math.atan2(-dy, -dx)));
}
}
}
}
}

View file

@ -0,0 +1,25 @@
package deepZoom.schedulers;
/**
* @author Zom-B
* @since 1.0
* @date 2009/05/03
*/
public class DitherScheduler extends Scheduler {
@Override
protected void initImpl() {
super.clear();
for (int i = 0; i < numLayers; i++) {
for (int y = 0; y < height; y++) {
int dy = Integer.reverse(y) >>> 16;
for (int x = 0; x < width; x++) {
int dx = Integer.reverse(x) >>> 16;
add(new PriorityPoint(i, x, y, dx + dy));
}
}
}
}
}

View file

@ -0,0 +1,36 @@
package deepZoom.schedulers;
/**
* @author Zom-B
* @since 1.0
* @date 2009/05/03
*/
public class FlowerScheduler extends Scheduler {
private int petals;
private double petalSize;
public FlowerScheduler(int petals, double petalSize) {
this.petals = petals;
this.petalSize = 4 / petalSize + 1;
}
@Override
protected void initImpl() {
super.clear();
for (int i = 0; i < numLayers; i++) {
for (int y = 0; y < height; y++) {
double dy = y - (height - 0.875) * 0.5;
for (int x = 0; x < width; x++) {
double dx = x - (width - 0.75) * 0.5;
double a = StrictMath.atan2(dy, -dx) * petals;
double r = StrictMath.sqrt(dx * dx + dy * dy);
dx = r * (StrictMath.cos(a) + petalSize);
add(new PriorityPoint(i, x, y, dx));
}
}
}
}
}

View file

@ -0,0 +1,22 @@
package deepZoom.schedulers;
/**
* @author Zom-B
* @since 1.0
* @date 2009/05/05
*/
public class ModScheduler extends Scheduler {
@Override
protected void initImpl() {
super.clear();
for (int i = 0; i < numLayers; i++) {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
add(new PriorityPoint(i, x, y, x % (y + 1)));
}
}
}
}
}

View file

@ -0,0 +1,32 @@
package deepZoom.schedulers;
/**
* @author Zom-B
* @since 1.0
* @date 2009/04/17
*/
public class PriorityPoint implements Comparable<PriorityPoint> {
public int layer;
public int x;
public int y;
private double priority;
public PriorityPoint(int layer, int x, int y, double priority) {
this.layer = layer;
this.x = x;
this.y = y;
this.priority = priority;
}
@Override
public int compareTo(PriorityPoint other) {
double d = priority - other.priority;
return d < 0 ? -1 : d > 0 ? 1 : 0;
}
@Override
public String toString() {
return this.getClass().getSimpleName() + "[layer " + layer + ", (" + x + ", " + y + ")]";
}
}

View file

@ -0,0 +1,23 @@
package deepZoom.schedulers;
/**
* @author Zom-B
* @since 1.0
* @date 2009/05/03
*/
public class PythagorasScheduler extends Scheduler {
@Override
protected void initImpl() {
super.clear();
for (int i = 0; i < numLayers; i++) {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
add(new PriorityPoint(i, x, y, x & y));
}
}
}
}
}

View file

@ -0,0 +1,26 @@
package deepZoom.schedulers;
/**
* @author Zom-B
* @since 1.0
* @date 2009/04/17
*/
public class RadialScheduler extends Scheduler {
@Override
protected void initImpl() {
super.clear();
for (int i = 0; i < numLayers; i++) {
for (int y = 0; y < height; y++) {
double dy = y - (height - 0.875) * 0.5;
dy *= dy;
for (int x = 0; x < width; x++) {
double dx = x - (width - 0.75) * 0.5;
add(new PriorityPoint(i, x, y, dx * dx + dy));
}
}
}
}
}

View file

@ -0,0 +1,45 @@
package deepZoom.schedulers;
import digisoft.custom.NumberFunctions;
/**
* @author Zom-B
* @since 1.0
* @date 2009/05/02
*/
public class RandomScheduler extends Scheduler {
private int area = -1;
private double[] order;
private int position = 0;
@Override
protected void initImpl() {
if (area != width * height) {
area = width * height;
order = new double[area];
for (int i = 0; i < area; i++) {
order[i] = NumberFunctions.RND.nextDouble();
}
}
super.clear();
int p = position;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
for (int i = 0; i < numLayers; i++) {
add(new PriorityPoint(i, x, y, order[p]));
}
p = (p + 1) % area;
}
}
}
@Override
public PriorityPoint poll() {
position = (position + area - 1) % area;
return super.poll();
}
}

View file

@ -0,0 +1,43 @@
package deepZoom.schedulers;
import java.util.concurrent.PriorityBlockingQueue;
import deepZoom.viewports.Viewport;
import java.util.PriorityQueue;
/**
* @author Zom-B
* @since 1.0
* @date 2009/04/17
*/
public abstract class Scheduler extends PriorityBlockingQueue<PriorityPoint> {
protected int numLayers = 1;
protected int width;
protected int height;
private int total;
private Viewport viewport;
public void setNumLayers(int numLayers) {
this.numLayers = numLayers;
}
public void setViewport(Viewport viewport) {
this.viewport = viewport;
}
public void init() {
width = viewport.width;
height = viewport.height;
initImpl();
total = super.size();
}
protected abstract void initImpl();
public double getProgress() {
return (total - super.size()) / (double) total;
}
}

View file

@ -0,0 +1,23 @@
package deepZoom.schedulers;
/**
* @author Zom-B
* @since 1.0
* @date 2009/05/03
*/
public class SimpleScheduler extends Scheduler {
@Override
protected void initImpl() {
super.clear();
for (int i = 0; i < numLayers; i++) {
for (int y = 0; y < height; y++) {
int dy = y * width;
for (int x = 0; x < width; x++) {
add(new PriorityPoint(i, x, y, dy + x));
}
}
}
}
}

View file

@ -0,0 +1,33 @@
package deepZoom.schedulers;
/**
* @author Zom-B
* @since 1.0
* @date 2009/05/02
*/
public class SpiralScheduler extends Scheduler {
private double thickness;
public SpiralScheduler(double thickness) {
this.thickness = thickness;
}
@Override
protected void initImpl() {
super.clear();
for (int i = 0; i < numLayers; i++) {
for (int y = 0; y < height; y++) {
double dy = y - (height - 0.875) * 0.5;
for (int x = 0; x < width; x++) {
double dx = x - (width - 0.75) * 0.5;
double a = StrictMath.atan2(dy, -dx) / (2 * StrictMath.PI);
dx = (int) (a + StrictMath.sqrt(dx * dx + dy * dy) / thickness) * thickness - a;
add(new PriorityPoint(i, x, y, dx));
}
}
}
}
}

View file

@ -0,0 +1,23 @@
package deepZoom.schedulers;
/**
* @author Zom-B
* @since 1.0
* @date 2009/05/03
*/
public class SplitScheduler extends Scheduler {
@Override
protected void initImpl() {
super.clear();
for (int i = 0; i < numLayers; i++) {
for (int y = 0; y < height; y++) {
int dy = StrictMath.abs(y - (height >> 1)) * width;
for (int x = 0; x < width; x++) {
add(new PriorityPoint(i, x, y, dy + x));
}
}
}
}
}

View file

@ -0,0 +1,37 @@
package deepZoom.schedulers;
/**
* @author Zom-B
* @since 1.0
* @date 2009/05/04
*/
public class SquareSpiralScheduler extends Scheduler {
@Override
protected void initImpl() {
super.clear();
for (int i = 0; i < numLayers; i++) {
for (int y = 0; y < height; y++) {
int dy = y - (height >> 1);
for (int x = 0; x < width; x++) {
int dx = x - (width >> 1);
if (dx > dy) {
if (dx < -dy) {
dx = 4 * dy * dy + 7 * dy + 3 + dx;
} else {
dx = 4 * dx * dx + 3 * dx + 1 + dy;
}
} else if (dx < -dy) {
dx = 4 * dx * dx + 1 * dx - 1 - dy;
} else {
dx = 4 * dy * dy + 5 * dy + 1 - dx;
}
add(new PriorityPoint(i, x, y, dx));
}
}
}
}
}

View file

@ -0,0 +1,25 @@
package deepZoom.schedulers;
/**
* @author Zom-B
* @since 1.0
* @date 2009/05/03
*/
public class XorScheduler extends Scheduler {
@Override
protected void initImpl() {
super.clear();
for (int i = 0; i < numLayers; i++) {
for (int y = 0; y < height; y++) {
int dy = StrictMath.abs(y - (height >> 1));
for (int x = 0; x < width; x++) {
int dx = StrictMath.abs(x - (width >> 1));
add(new PriorityPoint(i, x, y, dx ^ dy));
}
}
}
}
}

View file

@ -0,0 +1,73 @@
package deepZoom.viewports;
import deepZoom.parameters.Parameters;
import deepZoom.renderer.PointInfo;
import digisoft.custom.util.geom.DoubleDouble;
/**
* Mapping from (sub)pixel coordinates to coordinates in the complex plane.
* Don't forget to call init() after changing the input or output configuration.
*
* @author Zom-B
* @since 1.0
* @date 2009/04/19
*/
public class Viewport {
// Input configuration.
public int width;
public int height;
// Output configuration.
private Parameters parameters;
// Internally used values.
private transient DoubleDouble x0d = new DoubleDouble(0);
private transient DoubleDouble x2 = new DoubleDouble(0);
private transient DoubleDouble y1d = new DoubleDouble(0);
private transient DoubleDouble y2 = new DoubleDouble(0);
public void setSize(int width, int height) {
this.width = width;
this.height = height;
}
public void setParameters(Parameters parameters) {
this.parameters = parameters;
}
/** Call each time the viewport or parameters change. */
public void initParameters() {
x0d.set(4, 0);
x0d.divSelf(parameters.getMagn());
x0d.divSelf(width);
x2.set(-2 / parameters.getMagn(), 0);
x2.addSelf(parameters.getCenterX());
y1d.set(-4, 0);
y1d.divSelf(parameters.getMagn());
y1d.divSelf(width);
y2.set(2 / parameters.getMagn() * height / width, 0);
y2.addSelf(parameters.getCenterY());
}
public DoubleDouble getPX(double x, double y) {
DoubleDouble px = new DoubleDouble(x);
px.mulSelf(x0d);
px.addSelf(x2);
return px;
}
public DoubleDouble getPY(double x, double y) {
DoubleDouble py = new DoubleDouble(y);
py.mulSelf(y1d);
py.addSelf(y2);
return py;
}
public void getPoint(double x, double y, PointInfo pointInfo) {
pointInfo.px = getPX(x, y);
pointInfo.py = getPY(x, y);
}
}

View file

@ -0,0 +1,224 @@
package digisoft.custom;
import java.security.SecureRandom;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Random;
/**
* @author Zom-B
* @since 1.0
* @date 2007/11/16
*/
public class NumberFunctions {
private static final String ZEROES = "0000000000000000000000000000000000000000000000000000000000000000";
private static SecureRandom secureRnd = null;
public static final Random RND = new Random();
public static final DecimalFormat COMMA_NUMBER = new DecimalFormat("#,###");
public static String toStringFixedLength(int i, int len) {
String out = Integer.toString(i);
return NumberFunctions.ZEROES.substring(out.length(), len) + out;
}
public static String toStringFixedLength(long i, int len) {
String out = Long.toString(i);
return NumberFunctions.ZEROES.substring(out.length(), len) + out;
}
public static String toStringFixedLength(int i, int base, int len) {
String out = Long.toString(i & 0xFFFFFFFFL, base);
if (base > 10) {
return NumberFunctions.ZEROES.substring(out.length(), len) + out.toUpperCase();
}
return NumberFunctions.ZEROES.substring(out.length(), len) + out;
}
public static String toStringFixedLength(long i, int base, int len) {
String out = Long.toString(i, base);
if (base > 10) {
return NumberFunctions.ZEROES.substring(out.length(), len) + out.toUpperCase();
}
return NumberFunctions.ZEROES.substring(out.length(), len) + out;
}
public static Random getSecureRandom() {
if (NumberFunctions.secureRnd == null) {
NumberFunctions.secureRnd = new SecureRandom();
}
return NumberFunctions.secureRnd;
}
/**
* Find primes by recording a list with some proven non-prime numbers
* (NPNs). If the NPNs are chosen carefully, the gaps between the non-prime
* numbers will be prime numbers. <br>
* The NPNs are chosen by calculating rectangles with an area which is an
* odd number. The length is stepped through every odd number in the range [
* <tt>3</tt>, <tt>sqrt(guess)</tt>]. For every length, the height is
* stepped through such numbers (also odd numbers) so the area will stay
* within the range [<tt>guess-gapSize</tt>, <tt>guess</tt>). When the
* largest gap between any two successive successive prime numbers p1 and p2
* (gap=|p2-p1|) lower than <tt>guess</tt> is smaller or equal to
* <tt>gapSize</tt>, the result will be a prime number deterministically.<br>
* <br>
* Warning: Do not use this routine as-is for finding a random prime number
* p<sup>n</sup> for any guess with equal distribution of n. The difference
* in gaps between successive prime numbers causes the distribution to bias
* greatly. Use <tt>findRandomPrime</tt> instead.
*
* @param guess
* an initial guess
* @return the largest prime smaller than or equal to guess
* @since 1.0
* @see NumberFunctions#findRandomPrime(int, int)
* @see http://www.trnicely.net/
*/
public static int findPrimeNear(int guess) {
// Make it an odd number.
if ((guess & 1) == 0) {
guess--;
}
// Find largest gap
int maxGap;
if (guess <= 523) {
// Minimum gap for <7 bits. (closest was 9.030667136 bits)
maxGap = 14;
} else if (guess <= 155921) {
// Minimum gap for <15 bits. (closest was 17.25045573 bits)
maxGap = 72;
} else if (guess <= 2147437599) // Magic number? see else block.
{
// Minimum gap for <31 bits. (closest was 31.09957781 bits)
maxGap = 292;
} else {
throw new IllegalArgumentException("guess+floor(sqrt(guess))-292 should be below 2^31-1, so guess should be below 2147437600");
}
int halfGap = maxGap >> 1;
// The list is compressed and reversed. (ie. index 0 is the guess, 1 is
// guess-2, etc.)
boolean[] primes = new boolean[halfGap];
Arrays.fill(primes, true);
int halfway = (int) StrictMath.sqrt(guess);
int minGap = guess - maxGap;
// fill the array with nonprimes
for (int i = 3; i <= halfway; i += 2) {
int max = guess / i;
int min = (minGap + i) / i;
if ((min & 1) == 0) {
min++;
}
for (int j = min; j <= max; j += 2) {
int nonPrime = j * i;
int index = guess - nonPrime >> 1;
if (index >= 0) {
primes[index] = false;
}
}
}
// Find the highest prime number in the list.
for (int a = 0; a < halfGap; a++) {
if (primes[a]) {
return guess - (a << 1);
}
}
throw new IllegalStateException("gap too small");
}
/**
* Find primes by recording a list with some proven non-prime numbers
* (NPNs). If the NPNs are chosen carefully, the gaps between the non-prime
* numbers will be prime numbers. <br>
* The NPNs are chosen by calculating rectangles with an area which is an
* odd number. The length is stepped through every odd number in the range [
* <tt>3</tt>, <tt>sqrt(guess)</tt>]. For every length, the height is
* stepped through such numbers (also odd numbers) so the area will stay
* within the range [<tt>guess-gapSize</tt>, <tt>guess</tt>). When the
* largest gap between any two successive successive prime numbers p1 and p2
* (gap=|p2-p1|) lower than <tt>guess</tt> is smaller or equal to
* <tt>gapSize</tt>, the result will be a prime number deterministically.<br>
* <br>
* Warning: Do not use this routine as-is for finding a random prime number
* p<sup>n</sup> for any guess with equal distribution of n. The difference
* in gaps between successive prime numbers causes the distribution to bias
* greatly. Use <tt>findRandomPrime</tt> instead.
*
* @param guess
* an initial guess
* @return the largest prime smaller than or equal to guess
* @since 1.0
* @see NumberFunctions#findRandomPrime(int, int)
* @see http://www.trnicely.net/
*/
public static long findPrimeNear(long guess) {
// Make it an odd number.
if ((guess & 1) == 0) {
guess--;
}
// Find largest gap
int maxGap;
if (guess <= 2147437600) {// Delegate to a faster function.
return NumberFunctions.findPrimeNear((int) guess);
} else if (guess <= 2300942549L) {
// Minimum gap for <31 bits. (closest was 31.10 bits)
maxGap = 292;
} else if (guess <= 9223372033817776756L) // Magic number? see else block.
{
// There is known gap yet for <63 bits, so I'm using the next known
// gap (85.90 bits)
maxGap = 1448;
} else {
throw new IllegalArgumentException("guess+floor(sqrt(guess))-1448 should be below 2^63-1, so guess should be below 9223372033817776757");
}
int halfGap = maxGap >> 1;
// The list is compressed and reversed. (ie. index 0 is the guess, 1 is
// guess-2, etc.)
boolean[] primes = new boolean[halfGap];
Arrays.fill(primes, true);
long halfway = (long) StrictMath.sqrt(guess);
long minGap = guess - maxGap;
// fill the array with nonprimes
for (long i = 3; i <= halfway; i += 2) {
long max = guess / i;
long min = (minGap + i) / i;
if ((min & 1) == 0) {
min++;
}
for (long j = min; j <= max; j += 2) {
long nonPrime = j * i;
int index = (int) (guess - nonPrime) >> 1;
if (index >= 0) {
primes[index] = false;
}
}
}
// Find the highest prime number in the list.
for (int a = 0; a < halfGap; a++) {
if (primes[a]) {
return guess - (a << 1);
}
}
throw new IllegalStateException("gap too small");
}
public static int factorial(int v) {
int out = 1;
for (int i = 2; i <= v; i++) {
out *= i;
}
return out;
}
}

View file

@ -0,0 +1,534 @@
package digisoft.custom.awt;
import java.awt.Color;
/**
* @author Zom-B
* @since 1.0
* @date 2005/10/03
*/
public class Color3f {
private static final float MIN_CLIP_LEVEL = -0.003921568627450980392156862745098f;
private static final float MAX_CLIP_LEVEL = 1.003921568627450980392156862745098f;
public float r;
public float g;
public float b;
/**
* Create the color opaque black
*/
public Color3f() {
this(0f, 0f, 0f);
}
/**
* Create an opaque color from packed RGB triple
*
* @param i
* @since 1.0
*/
public Color3f(int i) {
b = (i & 0xFF) / 255f;
g = ((i >>= 8) & 0xFF) / 255f;
r = (i >> 8 & 0xFF) / 255f;
}
/**
* Create an opaque color defined gray shade
*
* @param i
* @since 1.0
*/
public Color3f(float i) {
this(i, i, i);
}
/**
* Create an opaque defined color
*
* @param r
* @param g
* @param b
*/
public Color3f(float r, float g, float b) {
this.r = r;
this.g = g;
this.b = b;
}
/**
* Create an opaque defined color
*
* @param r
* @param g
* @param b
*/
public Color3f(int r, int g, int b) {
this.r = r / 255f;
this.g = g / 255f;
this.b = b / 255f;
}
/**
* @param color
* @since 1.0
*/
public Color3f(Color color) {
r = color.getRed() / 255f;
g = color.getGreen() / 255f;
b = color.getBlue() / 255f;
}
/**
* @param color
* @since 1.0
*/
public Color3f(Color3f color) {
r = color.r;
g = color.g;
b = color.b;
}
public void set(Color3f c) {
r = c.r;
g = c.g;
b = c.b;
}
public void set(int r, int g, int b) {
this.r = r;
this.g = g;
this.b = b;
}
public float getGrayValue() {
return 0.299f * r + 0.587f * g + 0.114f * b;
}
public void addSelf(int i) {
b += (i & 0xFF) / 255f;
g += ((i >>= 8) & 0xFF) / 255f;
r += (i >> 8 & 0xFF) / 255f;
}
public Color3f scale(float f) {
return new Color3f(r * f, g * f, b * f);
}
public void scaleSelf(float f) {
r *= f;
g *= f;
b *= f;
}
public Color3f interpolateLinear(Color3f c, float f) {
return new Color3f( //
r + (c.r - r) * f, //
g + (c.g - g) * f, //
b + (c.b - b) * f);
}
public void interpolateLinearSelf(Color3f c, float f) {
r = r + (c.r - r) * f;
g = g + (c.g - g) * f;
b = b + (c.b - b) * f;
}
public Color3f gamma(float gammaFactor) {
return new Color3f( //
(float) Math.pow(r, gammaFactor), //
(float) Math.pow(g, gammaFactor), //
(float) Math.pow(b, gammaFactor));
}
/**
* Converts the components of this color, as specified by the HSB model, to
* an equivalent set of values for the default RGB model.
* <p>
* The <code>saturation</code> and <code>brightness</code> components should
* be floating-point values between zero and one (numbers in the range
* 0.0-1.0). The <code>hue</code> component can be any floating-point
* number. The floor of this number is subtracted from it to create a
* fraction between 0 and 1. This fractional number is then virtually
* multiplied by 360 to produce the hue angle in the HSB color model.
* <p>
*
* @param hsb
* the Color3f containing the components hue, saturation,
* brightness and alpha in the fields of red, green, blue and
* alpha, respectively
* @return the Color3f with the RGB value of the color with the indicated
* hue, saturation, brightness and alpha.
*
* @see java.awt.Color#HSB2RGB(float, float, float)
* @see java.awt.Color#getRGB()
* @see java.awt.Color#Color(int)
* @see java.awt.image.ColorModel#getRGBdefault()
* @since 1.0
*/
public Color3f hsb2Rgb() {
if (g == 0) {
return new Color3f(b, b, b);
}
Color3f out = new Color3f(0, 0, 0);
float hue6 = (r - (float) Math.floor(r)) * 6;
float hue_f = hue6 - (float) java.lang.Math.floor(hue6);
float p = b * (1 - g);
switch ((int) hue6) {
case 0:
case 6: {
out.r = b;
out.g = b * (1 - g * (1 - hue_f));
out.b = p;
break;
}
case 1: {
out.r = b * (1 - g * hue_f);
out.g = b;
out.b = p;
break;
}
case 2: {
out.r = p;
out.g = b;
out.b = b * (1 - g * (1 - hue_f));
break;
}
case 3: {
out.r = p;
out.g = b * (1 - g * hue_f);
out.b = b;
}
break;
case 4: {
out.r = b * (1 - g * (1 - hue_f));
out.g = p;
out.b = b;
break;
}
case 5: {
out.r = b;
out.g = p;
out.b = b * (1 - g * hue_f);
}
}
return out;
}
/**
* Converts the components of this color, as specified by the default RGB
* model, to an equivalent set of values for hue, saturation, and brightness
* that are the three components of the HSB model.
*
* @see java.awt.Color#RGB2HSB(int, int, int, float[])
* @see java.awt.Color#getRGB()
* @see java.awt.Color#Color(int)
* @see java.awt.image.ColorModel#getRGBdefault()
* @since JDK1.0
*/
public Color3f rgb2Hsb() {
float cmax = r > g ? r : g;
if (b > cmax) {
cmax = b;
}
float cmin = r < g ? r : g;
if (b < cmin) {
cmin = b;
}
float dist = cmax - cmin;
Color3f out = new Color3f(0f, 0f, 0f);
out.b = cmax;
out.g = cmax != 0 ? dist / cmax : 0;
if (out.g == 0) {
out.r = 0;
} else {
if (r == cmax) {
if (g >= b) {
out.r = (g - b) / dist;
} else {
out.r = 6.0f + (g - b) / dist;
}
} else if (g == cmax) {
out.r = 2.0f + (b - r) / dist;
} else {
out.r = 4.0f + (r - g) / dist;
}
out.r /= 6.0f;
}
return out;
}
/**
* Converts the components of this color, as specified by the default RGB
* model, to an equivalent set of values for hue, saturation, and brightness
* that are the three components of the HSB model.
*
* @see java.awt.Color#RGB2HSB(int, int, int, float[])
* @see java.awt.Color#getRGB()
* @see java.awt.Color#Color(int)
* @see java.awt.image.ColorModel#getRGBdefault()
* @since JDK1.0
*/
public void rgb2HsbSelf() {
float cmax = r > g ? r : g;
if (b > cmax) {
cmax = b;
}
float cmin = r < g ? r : g;
if (b < cmin) {
cmin = b;
}
float dist = cmax - cmin;
float g = cmax != 0 ? dist / cmax : 0;
if (g == 0) {
r = 0;
} else {
if (r == cmax) {
if (this.g >= b) {
r = (this.g - b) / dist;
} else {
r = 6.0f + (this.g - b) / dist;
}
} else if (this.g == cmax) {
r = 2.0f + (b - r) / dist;
} else {
r = 4.0f + (r - this.g) / dist;
}
r /= 6.0f;
}
b = cmax;
this.g = g;
}
/**
* Convert RGB to YPbPr (the floating point version of YCbCr).
*
* @return R=Y in [0, 1]; G=Pb in [-0.5 0.5]; B=Pr in [-0.5 0.5]
* @since 1.0
*/
public Color3f rgb2YPbPr() {
return new Color3f( //
+0.29900000000000000000f * r + 0.58700000000000000000f * g + 0.114000000000000000000f * b, //
-0.16873589164785553047f * r - 0.33126410835214446952f * g + 0.500000000000000000000f * b, //
+0.50000000000000000000f * r - 0.41868758915834522111f * g - 0.081312410841654778888f * b);
}
/**
* Convert RGB to YPbPr (the floating point version of YCbCr).
*
* @return R=Y in [0, 1]; G=Pb in [-0.5 0.5]; B=Pr in [-0.5 0.5]
* @since 1.0
*/
public void rgb2YPbPrSelf() {
float r = +0.29900000000000000000f * this.r + 0.58700000000000000000f * g + 0.114000000000000000000f * b;
float g = -0.16873589164785553047f * this.r - 0.33126410835214446952f * this.g + 0.500000000000000000000f * b;
b = +0.50000000000000000000f * this.r - 0.41868758915834522111f * this.g - 0.081312410841654778888f * b;
this.r = r;
this.g = g;
}
/**
* Convert YPbPr (the floating point version of YCbCr) to RGB. Inputs: R=Y
* in [0 1]; G=Pb in [-0.5 0.5]; B=Pr in [-0.5 0.5]
*
* @return RGB colors
* @since 1.0
*/
public Color3f tPbPr2Rgb() {
return new Color3f( //
r /* ***************************** */ + 1.40200000000000000000f * b, //
r - 0.34413628620102214650f * g - 0.71413628620102214645f * b, //
r + 1.77200000000000000000f * g /*
* **********************
* ******
*/);
}
/**
* Convert RGB to YUV (the colorspace used by PAL TV).
*
* @return R=Y in [0, 1]; G=U in [-0.5 0.5]; B=V in [-0.5 0.5]
* @since 1.0
*/
public Color3f rgb2Yuv() {
return new Color3f( //
+0.29900000000000000000f * r + 0.58700000000000000000f * g + 0.11400000000000000000f * b, //
-0.14713769751693002257f * r - 0.28886230248306997742f * g + 0.43600000000000000000f * b, //
+0.61500000000000000000f * r - 0.51498573466476462197f * g - 0.10001426533523537803f * b);
}
/**
* Convert YUV (the colorspace used in PAL TV) to RGB. Inputs: R=Y in [0 1];
* G=U in [-0.5 0.5]; B=V in [-0.5 0.5]
*
* @return RGB colors
* @since 1.0
*/
public Color3f yuv2Rgb() {
return new Color3f( //
r /* ***************************** */ + 1.13983739837398373980f * b, //
r - 0.39465170435897035149f * g - 0.58059860666749768007f * b, //
r + 2.03211009174311926600f * g /*
* **********************
* ******
*/);
}
/**
* Convert RGB to YUV (the colorspace used by PAL TV).
*
* @return R=Y in [0, 1]; G=U in [-0.5 0.5]; B=V in [-0.5 0.5]
* @since 1.0
*/
public Color3f rgb2YiQ() {
return new Color3f( //
+0.29900000000000000000f * r + 0.58700000000000000000f * g + 0.11400000000000000000f * b, //
+0.59571613491277455268f * r - 0.27445283783925646357f * g - 0.32126329707351808911f * b, //
+0.21145640212011786639f * r - 0.52259104529161116836f * g + 0.31113464317149330198f * b);
}
/**
* Convert YIQ (the colorspace used in NTSC TV) to RGB. Inputs: R=Y in [0
* 1]; G=I in [-0.5 0.5]; B=Q in [-0.5 0.5]
*
* @return RGB colors
* @since 1.0
*/
public Color3f yiq2Rgb() {
return new Color3f( //
r + 0.95629483232089399045f * g + 0.62102512544472871408f * b, //
r - 0.27212147408397731948f * g - 0.64738095351761572226f * b, //
r - 1.10698990856712821590f * g + 1.70461497549882932850f * b);
}
/**
* Convert RGB to XYZ (the CIE 1931 color space).
*
* @return R=Y in [0, 1]; G=U in [0 1]; B=V in [0 1]
* @since 1.0
*/
public Color3f rgb2Xyz() {
return new Color3f( //
+0.43030294260923249074f * r + 0.34163640134469669562f * g + 0.17822777850125160973f * b, //
+0.22187495478288550304f * r + 0.70683393381661385301f * g + 0.071291111400500643890f * b, //
+0.020170450434807773004f * r + 0.12958622119971253972f * g + 0.93866630010659181124f * b);
}
/**
* Convert XYZ (the CIE 1931 color space) to RGB. Inputs: R=X in [0 1]; G=Y
* in [0 1]; B=z in [0 1]
*
* @return RGB colors
* @since 1.0
*/
public Color3f xyz2Rgb() {
return new Color3f( //
+2.0608465608465608465f * r - 0.93738977072310405639f * g - 0.32010582010582010580f * b, //
-1.1415343915343915346f * r + 2.2094356261022927693f * g + 0.048941798941798941806f * b, //
+0.080687830687830687828f * r - 0.27204585537918871252f * g + 1.2711640211640211641f * b);
}
public Color3f clip() {
float ra = r;
float ga = g;
float ba = b;
if (ra < 0) {
ra = 0;
} else if (ra > 1) {
ra = 1;
}
if (ga < 0) {
ga = 0;
} else if (ga > 1) {
ga = 1;
}
if (ba < 0) {
ba = 0;
} else if (ba > 1) {
ba = 1;
}
return new Color3f(ra, ga, ba);
}
public Color3f showClip() {
if (r < Color3f.MIN_CLIP_LEVEL || r > Color3f.MAX_CLIP_LEVEL || g < Color3f.MIN_CLIP_LEVEL || g > Color3f.MAX_CLIP_LEVEL || b < Color3f.MIN_CLIP_LEVEL
|| b > Color3f.MAX_CLIP_LEVEL) {
return new Color3f(0.5f, 0.5f, 0.5f);
}
return this;
}
public boolean isClipping() {
return r < Color3f.MIN_CLIP_LEVEL || r > Color3f.MAX_CLIP_LEVEL || g < Color3f.MIN_CLIP_LEVEL || g > Color3f.MAX_CLIP_LEVEL
|| b < Color3f.MIN_CLIP_LEVEL || b > Color3f.MAX_CLIP_LEVEL;
}
/**
* Converts this color to a color understood by the java.awt package.
*
* @return an instance of java.awt.Color with the color attributes clamped
* to {black,white}
* @see java.awt.Color
* @since 1.0
*/
public Color toColor() {
float ra = r;
float ga = g;
float ba = b;
if (ra < 0) {
ra = 0;
} else if (ra > 1) {
ra = 1;
}
if (ga < 0) {
ga = 0;
} else if (ga > 1) {
ga = 1;
}
if (ba < 0) {
ba = 0;
} else if (ba > 1) {
ba = 1;
}
return new java.awt.Color(ra, ga, ba);
}
public int getRGB() {
int ra = (int) (r * 255 + 0.5);
int ga = (int) (g * 255 + 0.5);
int ba = (int) (b * 255 + 0.5);
if (ra < 0) {
ra = 0;
} else if (ra > 255) {
ra = 255;
}
if (ga < 0) {
ga = 0;
} else if (ga > 255) {
ga = 255;
}
if (ba < 0) {
ba = 0;
} else if (ba > 255) {
ba = 255;
}
return ba + (ga + (ra << 8) << 8);
}
@Override
public String toString() {
return super.getClass().getSimpleName() + "[" + r + ", " + g + ", " + b + "]";
}
}

View file

@ -0,0 +1,184 @@
package digisoft.custom.awt;
import digisoft.custom.NumberFunctions;
/**
* @author Zom-B
* @since 1.0
* @date 2009/04/16
*/
public class Color3fConst {
public static void main(String[] args) {
int p = 0;
for (int i = 0; i < 32; i++) {
for (int j = 0; j < 8; j++) {
Color3f c = new Color3f(Color3fConst.DOS_PALETTE[p++]);
System.out.print("0x" + NumberFunctions.toStringFixedLength(c.getRGB(), 16, 6) + ", ");
}
System.out.println(" //");
}
}
public static final int[] DOS_PALETTE = {0x000000, 0x0000AA, 0x00AA00, 0x00AAAA, 0xAA0000, 0xAA00AA, 0xAA5500, 0xAAAAAA, //
0x555555, 0x5555FF, 0x55FF55, 0x55FFFF, 0xFF5555, 0xFF55FF, 0xFFFF55, 0xFFFFFF, //
0x000000, 0x141414, 0x202020, 0x2C2C2C, 0x383838, 0x454545, 0x515151, 0x616161, //
0x717171, 0x828282, 0x929292, 0xA2A2A2, 0xB6B6B6, 0xCBCBCB, 0xE3E3E3, 0xFFFFFF, //
0x0000FF, 0x4100FF, 0x7D00FF, 0xBE00FF, 0xFF00FF, 0xFF00BE, 0xFF007D, 0xFF0041, //
0xFF0000, 0xFF4100, 0xFF7D00, 0xFFBE00, 0xFFFF00, 0xBEFF00, 0x7DFF00, 0x41FF00, //
0x00FF00, 0x00FF41, 0x00FF7D, 0x00FFBE, 0x00FFFF, 0x00BEFF, 0x007DFF, 0x0041FF, //
0x7D7DFF, 0x9E7DFF, 0xBE7DFF, 0xDF7DFF, 0xFF7DFF, 0xFF7DDF, 0xFF7DBE, 0xFF7D9E, //
0xFF7D7D, 0xFF9E7D, 0xFFBE7D, 0xFFDF7D, 0xFFFF7D, 0xDFFF7D, 0xBEFF7D, 0x9EFF7D, //
0x7DFF7D, 0x7DFF9E, 0x7DFFBE, 0x7DFFDF, 0x7DFFFF, 0x7DDFFF, 0x7DBEFF, 0x7D9EFF, //
0xB6B6FF, 0xC7B6FF, 0xDBB6FF, 0xEBB6FF, 0xFFB6FF, 0xFFB6EB, 0xFFB6DB, 0xFFB6C7, //
0xFFB6B6, 0xFFC7B6, 0xFFDBB6, 0xFFEBB6, 0xFFFFB6, 0xEBFFB6, 0xDBFFB6, 0xC7FFB6, //
0xB6FFB6, 0xB6FFC7, 0xB6FFDB, 0xB6FFEB, 0xB6FFFF, 0xB6EBFF, 0xB6DBFF, 0xB6C7FF, //
0x000071, 0x1C0071, 0x380071, 0x550071, 0x710071, 0x710055, 0x710038, 0x71001C, //
0x710000, 0x711C00, 0x713800, 0x715500, 0x717100, 0x557100, 0x387100, 0x1C7100, //
0x007100, 0x00711C, 0x007138, 0x007155, 0x007171, 0x005571, 0x003871, 0x001C71, //
0x383871, 0x453871, 0x553871, 0x613871, 0x713871, 0x713861, 0x713855, 0x713845, //
0x713838, 0x714538, 0x715538, 0x716138, 0x717138, 0x617138, 0x557138, 0x457138, //
0x387138, 0x387145, 0x387155, 0x387161, 0x387171, 0x386171, 0x385571, 0x384571, //
0x515171, 0x595171, 0x615171, 0x695171, 0x715171, 0x715169, 0x715161, 0x715159, //
0x715151, 0x715951, 0x716151, 0x716951, 0x717151, 0x697151, 0x617151, 0x597151, //
0x517151, 0x517159, 0x517161, 0x517169, 0x517171, 0x516971, 0x516171, 0x515971, //
0x000041, 0x100041, 0x200041, 0x300041, 0x410041, 0x410030, 0x410020, 0x410010, //
0x410000, 0x411000, 0x412000, 0x413000, 0x414100, 0x304100, 0x204100, 0x104100, //
0x004100, 0x004110, 0x004120, 0x004130, 0x004141, 0x003041, 0x002041, 0x001041, //
0x202041, 0x282041, 0x302041, 0x382041, 0x412041, 0x412038, 0x412030, 0x412028, //
0x412020, 0x412820, 0x413020, 0x413820, 0x414120, 0x384120, 0x304120, 0x284120, //
0x204120, 0x204128, 0x204130, 0x204138, 0x204141, 0x203841, 0x203041, 0x202841, //
0x2C2C41, 0x302C41, 0x342C41, 0x3C2C41, 0x412C41, 0x412C3C, 0x412C34, 0x412C30, //
0x412C2C, 0x41302C, 0x41342C, 0x413C2C, 0x41412C, 0x3C412C, 0x34412C, 0x30412C, //
0x2C412C, 0x2C4130, 0x2C4134, 0x2C413C, 0x2C4141, 0x2C3C41, 0x2C3441, 0x2C3041, //
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, //
0x000000};
public static final Color3f[] DOS_COLORS = {new Color3f(0.0f, 0.0f, 0.0f), new Color3f(0.0f, 0.0f, 0.6666667f), //
new Color3f(0.0f, 0.6666667f, 0.0f), new Color3f(0.0f, 0.6666667f, 0.6666667f), //
new Color3f(0.6666667f, 0.0f, 0.0f), new Color3f(0.6666667f, 0.0f, 0.6666667f), //
new Color3f(0.6666667f, 0.33333334f, 0.0f), new Color3f(0.6666667f, 0.6666667f, 0.6666667f), //
new Color3f(0.33333334f, 0.33333334f, 0.33333334f), new Color3f(0.33333334f, 0.33333334f, 1.0f), //
new Color3f(0.33333334f, 1.0f, 0.33333334f), new Color3f(0.33333334f, 1.0f, 1.0f), //
new Color3f(1.0f, 0.33333334f, 0.33333334f), new Color3f(1.0f, 0.33333334f, 1.0f), //
new Color3f(1.0f, 1.0f, 0.33333334f), new Color3f(1.0f, 1.0f, 1.0f), //
new Color3f(0.0f, 0.0f, 0.0f), new Color3f(0.078431375f, 0.078431375f, 0.078431375f), //
new Color3f(0.1254902f, 0.1254902f, 0.1254902f), new Color3f(0.17254902f, 0.17254902f, 0.17254902f), //
new Color3f(0.21960784f, 0.21960784f, 0.21960784f), new Color3f(0.27058825f, 0.27058825f, 0.27058825f), //
new Color3f(0.31764707f, 0.31764707f, 0.31764707f), new Color3f(0.38039216f, 0.38039216f, 0.38039216f), //
new Color3f(0.44313726f, 0.44313726f, 0.44313726f), new Color3f(0.50980395f, 0.50980395f, 0.50980395f), //
new Color3f(0.57254905f, 0.57254905f, 0.57254905f), new Color3f(0.63529414f, 0.63529414f, 0.63529414f), //
new Color3f(0.7137255f, 0.7137255f, 0.7137255f), new Color3f(0.79607844f, 0.79607844f, 0.79607844f), //
new Color3f(0.8901961f, 0.8901961f, 0.8901961f), new Color3f(1.0f, 1.0f, 1.0f), //
new Color3f(0.0f, 0.0f, 1.0f), new Color3f(0.25490198f, 0.0f, 1.0f), //
new Color3f(0.49019608f, 0.0f, 1.0f), new Color3f(0.74509805f, 0.0f, 1.0f), //
new Color3f(1.0f, 0.0f, 1.0f), new Color3f(1.0f, 0.0f, 0.74509805f), //
new Color3f(1.0f, 0.0f, 0.49019608f), new Color3f(1.0f, 0.0f, 0.25490198f), //
new Color3f(1.0f, 0.0f, 0.0f), new Color3f(1.0f, 0.25490198f, 0.0f), //
new Color3f(1.0f, 0.49019608f, 0.0f), new Color3f(1.0f, 0.74509805f, 0.0f), //
new Color3f(1.0f, 1.0f, 0.0f), new Color3f(0.74509805f, 1.0f, 0.0f), //
new Color3f(0.49019608f, 1.0f, 0.0f), new Color3f(0.25490198f, 1.0f, 0.0f), //
new Color3f(0.0f, 1.0f, 0.0f), new Color3f(0.0f, 1.0f, 0.25490198f), //
new Color3f(0.0f, 1.0f, 0.49019608f), new Color3f(0.0f, 1.0f, 0.74509805f), //
new Color3f(0.0f, 1.0f, 1.0f), new Color3f(0.0f, 0.74509805f, 1.0f), //
new Color3f(0.0f, 0.49019608f, 1.0f), new Color3f(0.0f, 0.25490198f, 1.0f), //
new Color3f(0.49019608f, 0.49019608f, 1.0f), new Color3f(0.61960787f, 0.49019608f, 1.0f), //
new Color3f(0.74509805f, 0.49019608f, 1.0f), new Color3f(0.8745098f, 0.49019608f, 1.0f), //
new Color3f(1.0f, 0.49019608f, 1.0f), new Color3f(1.0f, 0.49019608f, 0.8745098f), //
new Color3f(1.0f, 0.49019608f, 0.74509805f), new Color3f(1.0f, 0.49019608f, 0.61960787f), //
new Color3f(1.0f, 0.49019608f, 0.49019608f), new Color3f(1.0f, 0.61960787f, 0.49019608f), //
new Color3f(1.0f, 0.74509805f, 0.49019608f), new Color3f(1.0f, 0.8745098f, 0.49019608f), //
new Color3f(1.0f, 1.0f, 0.49019608f), new Color3f(0.8745098f, 1.0f, 0.49019608f), //
new Color3f(0.74509805f, 1.0f, 0.49019608f), new Color3f(0.61960787f, 1.0f, 0.49019608f), //
new Color3f(0.49019608f, 1.0f, 0.49019608f), new Color3f(0.49019608f, 1.0f, 0.61960787f), //
new Color3f(0.49019608f, 1.0f, 0.74509805f), new Color3f(0.49019608f, 1.0f, 0.8745098f), //
new Color3f(0.49019608f, 1.0f, 1.0f), new Color3f(0.49019608f, 0.8745098f, 1.0f), //
new Color3f(0.49019608f, 0.74509805f, 1.0f), new Color3f(0.49019608f, 0.61960787f, 1.0f), //
new Color3f(0.7137255f, 0.7137255f, 1.0f), new Color3f(0.78039217f, 0.7137255f, 1.0f), //
new Color3f(0.85882354f, 0.7137255f, 1.0f), new Color3f(0.92156863f, 0.7137255f, 1.0f), //
new Color3f(1.0f, 0.7137255f, 1.0f), new Color3f(1.0f, 0.7137255f, 0.92156863f), //
new Color3f(1.0f, 0.7137255f, 0.85882354f), new Color3f(1.0f, 0.7137255f, 0.78039217f), //
new Color3f(1.0f, 0.7137255f, 0.7137255f), new Color3f(1.0f, 0.78039217f, 0.7137255f), //
new Color3f(1.0f, 0.85882354f, 0.7137255f), new Color3f(1.0f, 0.92156863f, 0.7137255f), //
new Color3f(1.0f, 1.0f, 0.7137255f), new Color3f(0.92156863f, 1.0f, 0.7137255f), //
new Color3f(0.85882354f, 1.0f, 0.7137255f), new Color3f(0.78039217f, 1.0f, 0.7137255f), //
new Color3f(0.7137255f, 1.0f, 0.7137255f), new Color3f(0.7137255f, 1.0f, 0.78039217f), //
new Color3f(0.7137255f, 1.0f, 0.85882354f), new Color3f(0.7137255f, 1.0f, 0.92156863f), //
new Color3f(0.7137255f, 1.0f, 1.0f), new Color3f(0.7137255f, 0.92156863f, 1.0f), //
new Color3f(0.7137255f, 0.85882354f, 1.0f), new Color3f(0.7137255f, 0.78039217f, 1.0f), //
new Color3f(0.0f, 0.0f, 0.44313726f), new Color3f(0.10980392f, 0.0f, 0.44313726f), //
new Color3f(0.21960784f, 0.0f, 0.44313726f), new Color3f(0.33333334f, 0.0f, 0.44313726f), //
new Color3f(0.44313726f, 0.0f, 0.44313726f), new Color3f(0.44313726f, 0.0f, 0.33333334f), //
new Color3f(0.44313726f, 0.0f, 0.21960784f), new Color3f(0.44313726f, 0.0f, 0.10980392f), //
new Color3f(0.44313726f, 0.0f, 0.0f), new Color3f(0.44313726f, 0.10980392f, 0.0f), //
new Color3f(0.44313726f, 0.21960784f, 0.0f), new Color3f(0.44313726f, 0.33333334f, 0.0f), //
new Color3f(0.44313726f, 0.44313726f, 0.0f), new Color3f(0.33333334f, 0.44313726f, 0.0f), //
new Color3f(0.21960784f, 0.44313726f, 0.0f), new Color3f(0.10980392f, 0.44313726f, 0.0f), //
new Color3f(0.0f, 0.44313726f, 0.0f), new Color3f(0.0f, 0.44313726f, 0.10980392f), //
new Color3f(0.0f, 0.44313726f, 0.21960784f), new Color3f(0.0f, 0.44313726f, 0.33333334f), //
new Color3f(0.0f, 0.44313726f, 0.44313726f), new Color3f(0.0f, 0.33333334f, 0.44313726f), //
new Color3f(0.0f, 0.21960784f, 0.44313726f), new Color3f(0.0f, 0.10980392f, 0.44313726f), //
new Color3f(0.21960784f, 0.21960784f, 0.44313726f), new Color3f(0.27058825f, 0.21960784f, 0.44313726f), //
new Color3f(0.33333334f, 0.21960784f, 0.44313726f), new Color3f(0.38039216f, 0.21960784f, 0.44313726f), //
new Color3f(0.44313726f, 0.21960784f, 0.44313726f), new Color3f(0.44313726f, 0.21960784f, 0.38039216f), //
new Color3f(0.44313726f, 0.21960784f, 0.33333334f), new Color3f(0.44313726f, 0.21960784f, 0.27058825f), //
new Color3f(0.44313726f, 0.21960784f, 0.21960784f), new Color3f(0.44313726f, 0.27058825f, 0.21960784f), //
new Color3f(0.44313726f, 0.33333334f, 0.21960784f), new Color3f(0.44313726f, 0.38039216f, 0.21960784f), //
new Color3f(0.44313726f, 0.44313726f, 0.21960784f), new Color3f(0.38039216f, 0.44313726f, 0.21960784f), //
new Color3f(0.33333334f, 0.44313726f, 0.21960784f), new Color3f(0.27058825f, 0.44313726f, 0.21960784f), //
new Color3f(0.21960784f, 0.44313726f, 0.21960784f), new Color3f(0.21960784f, 0.44313726f, 0.27058825f), //
new Color3f(0.21960784f, 0.44313726f, 0.33333334f), new Color3f(0.21960784f, 0.44313726f, 0.38039216f), //
new Color3f(0.21960784f, 0.44313726f, 0.44313726f), new Color3f(0.21960784f, 0.38039216f, 0.44313726f), //
new Color3f(0.21960784f, 0.33333334f, 0.44313726f), new Color3f(0.21960784f, 0.27058825f, 0.44313726f), //
new Color3f(0.31764707f, 0.31764707f, 0.44313726f), new Color3f(0.34901962f, 0.31764707f, 0.44313726f), //
new Color3f(0.38039216f, 0.31764707f, 0.44313726f), new Color3f(0.4117647f, 0.31764707f, 0.44313726f), //
new Color3f(0.44313726f, 0.31764707f, 0.44313726f), new Color3f(0.44313726f, 0.31764707f, 0.4117647f), //
new Color3f(0.44313726f, 0.31764707f, 0.38039216f), new Color3f(0.44313726f, 0.31764707f, 0.34901962f), //
new Color3f(0.44313726f, 0.31764707f, 0.31764707f), new Color3f(0.44313726f, 0.34901962f, 0.31764707f), //
new Color3f(0.44313726f, 0.38039216f, 0.31764707f), new Color3f(0.44313726f, 0.4117647f, 0.31764707f), //
new Color3f(0.44313726f, 0.44313726f, 0.31764707f), new Color3f(0.4117647f, 0.44313726f, 0.31764707f), //
new Color3f(0.38039216f, 0.44313726f, 0.31764707f), new Color3f(0.34901962f, 0.44313726f, 0.31764707f), //
new Color3f(0.31764707f, 0.44313726f, 0.31764707f), new Color3f(0.31764707f, 0.44313726f, 0.34901962f), //
new Color3f(0.31764707f, 0.44313726f, 0.38039216f), new Color3f(0.31764707f, 0.44313726f, 0.4117647f), //
new Color3f(0.31764707f, 0.44313726f, 0.44313726f), new Color3f(0.31764707f, 0.4117647f, 0.44313726f), //
new Color3f(0.31764707f, 0.38039216f, 0.44313726f), new Color3f(0.31764707f, 0.34901962f, 0.44313726f), //
new Color3f(0.0f, 0.0f, 0.25490198f), new Color3f(0.0627451f, 0.0f, 0.25490198f), //
new Color3f(0.1254902f, 0.0f, 0.25490198f), new Color3f(0.1882353f, 0.0f, 0.25490198f), //
new Color3f(0.25490198f, 0.0f, 0.25490198f), new Color3f(0.25490198f, 0.0f, 0.1882353f), //
new Color3f(0.25490198f, 0.0f, 0.1254902f), new Color3f(0.25490198f, 0.0f, 0.0627451f), //
new Color3f(0.25490198f, 0.0f, 0.0f), new Color3f(0.25490198f, 0.0627451f, 0.0f), //
new Color3f(0.25490198f, 0.1254902f, 0.0f), new Color3f(0.25490198f, 0.1882353f, 0.0f), //
new Color3f(0.25490198f, 0.25490198f, 0.0f), new Color3f(0.1882353f, 0.25490198f, 0.0f), //
new Color3f(0.1254902f, 0.25490198f, 0.0f), new Color3f(0.0627451f, 0.25490198f, 0.0f), //
new Color3f(0.0f, 0.25490198f, 0.0f), new Color3f(0.0f, 0.25490198f, 0.0627451f), //
new Color3f(0.0f, 0.25490198f, 0.1254902f), new Color3f(0.0f, 0.25490198f, 0.1882353f), //
new Color3f(0.0f, 0.25490198f, 0.25490198f), new Color3f(0.0f, 0.1882353f, 0.25490198f), //
new Color3f(0.0f, 0.1254902f, 0.25490198f), new Color3f(0.0f, 0.0627451f, 0.25490198f), //
new Color3f(0.1254902f, 0.1254902f, 0.25490198f), new Color3f(0.15686275f, 0.1254902f, 0.25490198f), //
new Color3f(0.1882353f, 0.1254902f, 0.25490198f), new Color3f(0.21960784f, 0.1254902f, 0.25490198f), //
new Color3f(0.25490198f, 0.1254902f, 0.25490198f), new Color3f(0.25490198f, 0.1254902f, 0.21960784f), //
new Color3f(0.25490198f, 0.1254902f, 0.1882353f), new Color3f(0.25490198f, 0.1254902f, 0.15686275f), //
new Color3f(0.25490198f, 0.1254902f, 0.1254902f), new Color3f(0.25490198f, 0.15686275f, 0.1254902f), //
new Color3f(0.25490198f, 0.1882353f, 0.1254902f), new Color3f(0.25490198f, 0.21960784f, 0.1254902f), //
new Color3f(0.25490198f, 0.25490198f, 0.1254902f), new Color3f(0.21960784f, 0.25490198f, 0.1254902f), //
new Color3f(0.1882353f, 0.25490198f, 0.1254902f), new Color3f(0.15686275f, 0.25490198f, 0.1254902f), //
new Color3f(0.1254902f, 0.25490198f, 0.1254902f), new Color3f(0.1254902f, 0.25490198f, 0.15686275f), //
new Color3f(0.1254902f, 0.25490198f, 0.1882353f), new Color3f(0.1254902f, 0.25490198f, 0.21960784f), //
new Color3f(0.1254902f, 0.25490198f, 0.25490198f), new Color3f(0.1254902f, 0.21960784f, 0.25490198f), //
new Color3f(0.1254902f, 0.1882353f, 0.25490198f), new Color3f(0.1254902f, 0.15686275f, 0.25490198f), //
new Color3f(0.17254902f, 0.17254902f, 0.25490198f), new Color3f(0.1882353f, 0.17254902f, 0.25490198f), //
new Color3f(0.20392157f, 0.17254902f, 0.25490198f), new Color3f(0.23529412f, 0.17254902f, 0.25490198f), //
new Color3f(0.25490198f, 0.17254902f, 0.25490198f), new Color3f(0.25490198f, 0.17254902f, 0.23529412f), //
new Color3f(0.25490198f, 0.17254902f, 0.20392157f), new Color3f(0.25490198f, 0.17254902f, 0.1882353f), //
new Color3f(0.25490198f, 0.17254902f, 0.17254902f), new Color3f(0.25490198f, 0.1882353f, 0.17254902f), //
new Color3f(0.25490198f, 0.20392157f, 0.17254902f), new Color3f(0.25490198f, 0.23529412f, 0.17254902f), //
new Color3f(0.25490198f, 0.25490198f, 0.17254902f), new Color3f(0.23529412f, 0.25490198f, 0.17254902f), //
new Color3f(0.20392157f, 0.25490198f, 0.17254902f), new Color3f(0.1882353f, 0.25490198f, 0.17254902f), //
new Color3f(0.17254902f, 0.25490198f, 0.17254902f), new Color3f(0.17254902f, 0.25490198f, 0.1882353f), //
new Color3f(0.17254902f, 0.25490198f, 0.20392157f), new Color3f(0.17254902f, 0.25490198f, 0.23529412f), //
new Color3f(0.17254902f, 0.25490198f, 0.25490198f), new Color3f(0.17254902f, 0.23529412f, 0.25490198f), //
new Color3f(0.17254902f, 0.20392157f, 0.25490198f), new Color3f(0.17254902f, 0.1882353f, 0.25490198f), //
new Color3f(0.0f, 0.0f, 0.0f), new Color3f(0.0f, 0.0f, 0.0f), //
new Color3f(0.0f, 0.0f, 0.0f), new Color3f(0.0f, 0.0f, 0.0f), //
new Color3f(0.0f, 0.0f, 0.0f), new Color3f(0.0f, 0.0f, 0.0f), //
new Color3f(0.0f, 0.0f, 0.0f), new Color3f(0.0f, 0.0f, 0.0f), //
new Color3f(0.0f, 0.0f, 0.0f)};
}

View file

@ -0,0 +1,58 @@
package digisoft.custom.math;
/**
* @author Zom-B
* @since 1.0
* @date 2009/04/26
*/
public interface NumberConstants {
public static final double COS1 = 0.54030230586813971740093660744297660373231042061792; // Knuth31
public static final double CUBERT2 = 1.25992104989487316476721060727822835057025146470151; // Knuth05
public static final double CUBERT3 = 1.44224957030740838232163831078010958839186925349935; // Knuth06
public static final double DEG_TO_RAD = 0.01745329251994329576923690768488612713442871888542; // Knuth18
public static final double E = 2.71828182845904523536028747135266249775724709369996; // Knuth24
public static final double EULERGAMMA = 0.57721566490153286060651209008240243104215933593992; // Knuth27
public static final double EXP_EULERGAMMA = 1.7810724179901979852365041031071795491696452143034; // Knuth28
public static final double EXP_PI025 = 2.19328005073801545655976965927873822346163764199427; // Knuth29
public static final double E_SQR = 7.38905609893065022723042746057500781318031557055185; // Knuth26
public static final double GAMMA033 = 2.6789385347077476336556929409746776441286893779573; // Knuth22
public static final double GAMMA05 = 1.7724538509055160272981674833411451827975494561224; // Knuth21
public static final double GAMMA067 = 1.3541179394264004169452880281545137855193272660568; // Knuth23
public static final double LOG10 = 2.30258509299404568401799145468436420760110148862877; // Knuth11
public static final double LOG2 = 0.69314718055994530941723212145817656807550013436026; // Knuth09
public static final double LOG3 = 1.09861228866810969139524523692252570464749055782275; // Knuth10
public static final double LOGPHI = 0.48121182505960344749775891342436842313518433438566; // Knuth13
public static final double LOGPI = 1.14472988584940017414342735135305871164729481291531; // Knuth12
public static final double LOGR10 = 0.43429448190325182765112891891660508229439700580367;
public static final double LOGR2 = 1.44269504088896340735992468100189213742664595415299;
public static final double NLOGLOG2 = 0.36651292058166432701243915823266946945426344783711; // Knuth33
public static final double PHI = 1.61803398874989484820458683436563811772030917980576; // Knuth08
public static final double PI = 3.14159265358979323846264338327950288419716939937511; // Knuth17
public static final double PI05 = 1.57079632679489661923132169163975144209858469968755;
public static final double PI2 = 6.28318530717958647692528676655900576839433879875021;
public static final double PI_SQR = 9.86960440108935861883449099987615113531369940724079; // Knuth20
public static final double Q05LOG10 = 0.21714724095162591382556445945830254114719850290183;
public static final double Q05LOG2 = 0.72134752044448170367996234050094606871332297707649;
public static final double Q05PI = 0.15915494309189533576888376337251436203445964574046;
public static final double Q1_3 = 0.33333333333333333333333333333333333333333333333333;
public static final double Q1_6 = 0.16666666666666666666666666666666666666666666666667;
public static final double Q1E = 0.36787944117144232159552377016146086744581113103177; // Knuth25
public static final double Q1LOG10 = 0.43429448190325182765112891891660508229439700580367; // Knuth15
public static final double Q1LOG2 = 1.44269504088896340735992468100189213742664595415299; // Knuth14
public static final double Q1LOGPHI = 2.07808692123502753760132260611779576774219226778328; // Knuth16
public static final double Q1PI = 0.31830988618379067153776752674502872406891929148091; // Knuth19
public static final double Q2PI = 0.63661977236758134307553505349005744813783858296183; //
public static final double Q2POW025 = 1.18920711500272106671749997056047591529297209246382; // Knuth07
public static final double Q2SQRT5 = 0.89442719099991587856366946749251049417624734384461;
public static final double RAD_TO_DEG = 57.2957795130823208767981548141051703324054724665643;
public static final double SIN1 = 0.84147098480789650665250232163029899962256306079837; // Knuth30
public static final double SQRT02 = 0.44721359549995793928183473374625524708812367192231;
public static final double SQRT05 = 0.70710678118654752440084436210484903928483593768847;
public static final double SQRT075 = 0.86602540378443864676372317075293618347140262690519;
public static final double SQRT10 = 3.16227766016837933199889354443271853371955513932522; // Knuth04
public static final double SQRT2 = 1.41421356237309504880168872420969807856967187537695; // Knuth01
public static final double SQRT3 = 1.73205080756887729352744634150587236694280525381038; // Knuth02
public static final double SQRT5 = 2.23606797749978969640917366873127623544061835961153; // Knuth03
public static final double ZETA3 = 1.2020569031595942853997381615114499907649862923405; // Knuth32
}

View file

@ -0,0 +1,87 @@
package digisoft.custom.swing;
import java.awt.BasicStroke;
import java.awt.DisplayMode;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.RenderingHints;
import javax.swing.UIManager;
/**
* @author Zom-B
* @since 1.0
* @date 2007/12/01
*/
public class GraphicsFunctions {
public static final BasicStroke DEFAULT_SQUARE_STROKE = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER);
public static final BasicStroke DEFAULT_ROUND_STROKE = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
public static void setNiceLookAndFeel() {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
} catch (Exception e) {
}
}
public static void setAntialiased(Graphics2D g, boolean antialiased) {
if (antialiased && g.getRenderingHint(RenderingHints.KEY_ANTIALIASING) != RenderingHints.VALUE_ANTIALIAS_ON) {
g.translate(0.5, 0.5);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
}
if (!antialiased && g.getRenderingHint(RenderingHints.KEY_ANTIALIASING) == RenderingHints.VALUE_ANTIALIAS_ON) {
g.translate(-0.5, -0.5);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_DEFAULT);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_DEFAULT);
g.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DEFAULT);
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_DEFAULT);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT);
g.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_DEFAULT);
g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
}
}
public static GraphicsDevice getDisplayDevice() {
return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
}
public static DisplayMode getDisplayMode(int width, int height) {
DisplayMode currentMode = GraphicsFunctions.getDisplayDevice().getDisplayMode();
DisplayMode[] modes = GraphicsFunctions.getDisplayDevice().getDisplayModes();
int bitDepth = currentMode.getBitDepth();
int refreshRate = currentMode.getRefreshRate();
for (DisplayMode mode : modes) {
if (mode.getHeight() == height && mode.getWidth() == width && mode.getBitDepth() == bitDepth && mode.getRefreshRate() == refreshRate) {
return mode;
}
}
refreshRate = Integer.MAX_VALUE;
int index = -1;
for (int i = modes.length - 1; i >= 0; i--) {
DisplayMode mode = modes[i];
if (mode.getHeight() == height && mode.getWidth() == width && mode.getBitDepth() == bitDepth) {
if (refreshRate > mode.getRefreshRate()) {
refreshRate = mode.getRefreshRate();
index = i;
}
}
}
return index < 0 ? null : modes[index];
}
}

View file

@ -0,0 +1,100 @@
package digisoft.custom.swing;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
/**
* @author Zom-B
* @since 1.0
* @date 2009/04/28
*/
public class ImageFunctions {
public static final int SCALE_HINT_ALWAYS = 0;
public static final int SCALE_HINT_FIT_INSIDE = 1;
public static final int SCALE_HINT_WHEN_NECESSARY = 2;
public static ImageIcon scaleImage(ImageIcon imageIcon, int width, int height, int scalingHint) {
switch (scalingHint) {
case SCALE_HINT_WHEN_NECESSARY: {
if (imageIcon.getIconWidth() <= width && imageIcon.getIconHeight() <= height) {
return imageIcon;
}
// Fall through.
}
case SCALE_HINT_ALWAYS: {
return ImageFunctions.scaleImage(imageIcon, width, height);
}
case SCALE_HINT_FIT_INSIDE: {
Image image = imageIcon.getImage();
double wf = (double) width / image.getWidth(null);
double hf = (double) height / image.getHeight(null);
if (wf > hf) {
height = (int) (wf * image.getHeight(null) + 0.5);
} else if (hf > wf) {
width = (int) (hf * image.getWidth(null) + 0.5);
}
// imageIcon.setImage(image.getScaledInstance(width, height,
// Image.SCALE_AREA_AVERAGING));
// return imageIcon;
return new ImageIcon(image.getScaledInstance(width, height, Image.SCALE_AREA_AVERAGING));
}
}
throw new IllegalArgumentException("Illegal scalingHint. Must be one of SCALE_HINT_ALWAYS, SCALE_HINT_FIT_INSIDE, SCALE_HINT_WHEN_NECESSARY");
}
public static ImageIcon scaleImage(ImageIcon imageIcon, int width, int height) {
Image image = imageIcon.getImage();
double wf = (double) width / image.getWidth(null);
double hf = (double) height / image.getHeight(null);
if (wf < hf) {
height = (int) (wf * image.getHeight(null) + 0.5);
} else if (hf < wf) {
width = (int) (hf * image.getWidth(null) + 0.5);
}
// imageIcon.setImage(image.getScaledInstance(width, height,
// Image.SCALE_AREA_AVERAGING));
// return imageIcon;
return new ImageIcon(image.getScaledInstance(width, height, Image.SCALE_AREA_AVERAGING));
}
public static void saveJPEG(String filename, int[] pixels, int width, int height) throws IOException {
BufferedImage saveImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
saveImage.setRGB(0, 0, width, height, pixels, 0, width);
OutputStream out = new BufferedOutputStream(new FileOutputStream(filename));
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(saveImage);
param.setQuality(0.95f, false);
encoder.setJPEGEncodeParam(param);
encoder.encode(saveImage);
out.close();
}
public static void savePNG(String filename, int[] pixels, int width, int height) throws IOException {
BufferedImage saveImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
saveImage.setRGB(0, 0, width, height, pixels, 0, width);
OutputStream out = new BufferedOutputStream(new FileOutputStream(filename));
ImageIO.write(saveImage, "png", out);
out.close();
}
}

View file

@ -0,0 +1,11 @@
package digisoft.custom.swing;
/**
* @author Zom-B
* @since 1.0
* @date 2008/12/27
*/
public interface RefreshListener {
public void refreshing();
}

View file

@ -0,0 +1,39 @@
package digisoft.custom.swing;
/**
* @author Zom-B
* @since 1.0
* @date 2009/04/16
*/
public class RefreshThread extends Thread {
private double delay;
private RefreshListener runnable;
public RefreshThread(RefreshListener refreshListener, int fps) {
super();
runnable = refreshListener;
delay = 1e9 / fps;
}
@Override
public void run() {
try {
double t = System.nanoTime();
while (true) {
runnable.refreshing();
t += delay;
long sleepTime = (long) ((t - System.nanoTime()) / 1e6);
if (sleepTime > 0) {
Thread.sleep(sleepTime);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

View file

@ -0,0 +1,19 @@
package digisoft.custom.swing.gradient;
/**
* @author Zom-B
* @since 1.0
* @date 2009/04/19
*/
public interface Gradient {
public boolean hasTransparency();
public int getLength();
public int get(int index);
public int get(double position);
public int getOverflow();
}

View file

@ -0,0 +1,108 @@
package digisoft.custom.swing.gradient;
import digisoft.custom.awt.Color3f;
/**
* @author Zom-B
* @since 1.0
* @date 2009/04/05
*/
public class OpaqueGradient implements Gradient {
private static final int MAX_GRADIENT_ARRAY_SIZE = 5000;
private static final int GRADIENT_SIZE = 256;
private float[] fractions;
private int gradientOverflow;
private float[] intervals;
private int gradientLength;
private int[] gradient;
public OpaqueGradient(float[] fractions, Color3f[] colors) {
this.fractions = fractions;
gradientOverflow = colors[colors.length - 1].getRGB();
intervals = new float[fractions.length - 1];
for (int i = 0; i < intervals.length; i++) {
intervals[i] = fractions[i + 1] - fractions[i];
}
calculateGradientFractions(colors);
}
private void calculateGradientFractions(Color3f[] colors) {
int n = intervals.length;
// Find smallest interval
float Imin = 1;
for (int i = 0; i < n; i++) {
if (Imin > intervals[i]) {
Imin = intervals[i];
}
}
calculateSingleArrayGradient(colors, Imin);
}
private void calculateSingleArrayGradient(Color3f[] colors, float Imin) {
gradientLength = (int) (OpaqueGradient.GRADIENT_SIZE / Imin + 0.5);
if (gradientLength > OpaqueGradient.MAX_GRADIENT_ARRAY_SIZE) {
gradientLength = OpaqueGradient.MAX_GRADIENT_ARRAY_SIZE;
}
gradient = new int[gradientLength + 1];
int part = 0;
for (int i = 0; i <= gradientLength; i++) {
// Fraction of the gradient.
float f = (float) i / gradientLength;
// Select interval.
while (f > fractions[part + 1]) {
part++;
}
// Fraction of the current interval.
float p = (f - fractions[part]) / intervals[part];
// 2 colors to interpolate
Color3f c1 = colors[part];
Color3f c2 = colors[part + 1];
gradient[i] = interpolate(c1, c2, p);
}
}
private int interpolate(Color3f c1, Color3f c2, float p) {
return 0xFF000000 //
| (int) ((c1.r + (c2.r - c1.r) * p) * 255 + .5) << 16 //
| (int) ((c1.g + (c2.g - c1.g) * p) * 255 + .5) << 8//
| (int) ((c1.b + (c2.b - c1.b) * p) * 255 + .5);
}
@Override
public boolean hasTransparency() {
return false;
}
@Override
public int getLength() {
return gradientLength;
}
@Override
public int get(int index) {
return gradient[index];
}
@Override
public int get(double position) {
return gradient[(int) (position * gradientLength + 0.5)];
}
@Override
public int getOverflow() {
return gradientOverflow;
}
}

View file

@ -0,0 +1,165 @@
package digisoft.custom.swing.window;
import java.awt.DisplayMode;
import java.awt.GraphicsDevice;
import java.awt.Rectangle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import digisoft.custom.swing.GraphicsFunctions;
import digisoft.custom.swing.window.canvas.GraphicsCanvas;
/**
* @author Zom-B
* @since 1.0
* @date 2009/03/22
*/
public class CanvasWindow extends JFrame {
/**
* Creates a fullscreen CanvasWindow using a given GraphicsCanvas
*
*
* @param canvas
* the GraphicsCanvas defining the drawing method
* @param x
* the x-position of the upper-left corner of the window
* @param y
* the y-position of the upper-left corner of the window
* @param width
* the width of the drawable area of the window
* @param height
* the height of the drawable area of the window
*/
public CanvasWindow(GraphicsCanvas canvas, int x, int y, int width, int height) {
super();
this.setup(canvas, width, height);
super.setResizable(false);
super.pack();
super.setLocation(x, y);
super.setVisible(true);
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
Logger.getLogger(CanvasWindow.class.getName()).log(Level.SEVERE, null, ex);
}
canvas.requestFocus();
}
/**
* Creates a fullscreen CanvasWindow using a given GraphicsCanvas
*
*
* @param canvas
* the GraphicsCanvas defining the drawing method
* @param width
* the width of the drawable area of the window
* @param height
* the height of the drawable area of the window
*/
public CanvasWindow(GraphicsCanvas canvas, int width, int height) {
super();
this.setup(canvas, width, height);
super.setResizable(false);
super.pack();
super.setLocationRelativeTo(null);
super.setVisible(true);
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
Logger.getLogger(CanvasWindow.class.getName()).log(Level.SEVERE, null, ex);
}
canvas.requestFocus();
}
/**
* Creates a fullscreen CanvasWindow using a given GraphicsCanvas
*
* @param canvas
* the GraphicsCanvas defining the drawing method
* @param exclusive
* when this is set, the window becomes fullscreen, otherwise, it
* will stretch to fit the screen.
*/
public CanvasWindow(GraphicsCanvas canvas, boolean exclusive) {
super();
GraphicsDevice displayDevice = GraphicsFunctions.getDisplayDevice();
DisplayMode mode = displayDevice.getDisplayMode();
int width = mode.getWidth();
int height = mode.getHeight();
this.setup(canvas, width, height);
super.invalidate();
super.setUndecorated(true);
super.setResizable(false);
super.pack();
super.setLocationRelativeTo(null);
if (exclusive) {
displayDevice.setFullScreenWindow(this);
} else {
super.setBounds(new Rectangle(0, 0, width, height));
super.setVisible(true);
}
canvas.requestFocus();
}
public CanvasWindow(GraphicsCanvas canvas, DisplayMode mode) {
super();
GraphicsDevice displayDevice = GraphicsFunctions.getDisplayDevice();
int width = mode.getWidth();
int height = mode.getHeight();
this.setup(canvas, width, height);
super.invalidate();
super.setUndecorated(true);
super.setResizable(false);
super.pack();
super.setLocationRelativeTo(null);
displayDevice.setFullScreenWindow(this);
displayDevice.setDisplayMode(mode);
canvas.requestFocus();
}
private void setup(GraphicsCanvas canvas, int width, int height) {
super.setName(this.getClass().getSimpleName());
super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
super.setLayout(null);
{
canvas.init(width, height, false);
super.setContentPane(canvas);
}
}
public void setExclusive(boolean b) {
GraphicsFunctions.getDisplayDevice().setFullScreenWindow(b ? this : null);
GraphicsCanvas canvas = (GraphicsCanvas) this.getContentPane();
if (b) {
super.setBounds(new Rectangle(0, 0, canvas.width, canvas.height));
} else {
super.pack();
}
}
}

View file

@ -0,0 +1,96 @@
package digisoft.custom.swing.window;
import java.awt.DisplayMode;
import digisoft.custom.swing.GraphicsFunctions;
import digisoft.custom.swing.window.canvas.MemoryImageSourceCanvas;
/**
* @author Zom-B
* @since 1.0
* @date 2009/04/04
*/
public class PixelWindow extends MemoryImageSourceCanvas {
private CanvasWindow window;
private DisplayMode backupMode = null;
/**
* Creates a fullscreen CanvasWindow using a given GraphicsCanvas
*
*
* @param x
* the x-position of the upper-left corner of the window
* @param y
* the y-position of the upper-left corner of the window
* @param width
* the width of the drawable area of the window
* @param height
* the height of the drawable area of the window
*/
public PixelWindow(int x, int y, int width, int height) {
super();
window = new CanvasWindow(this, x, y, width, height);
}
/**
* Creates a fullscreen CanvasWindow using a given GraphicsCanvas
*
*
* @param width
* the width of the drawable area of the window
* @param height
* the height of the drawable area of the window
*/
public PixelWindow(int width, int height) {
super();
window = new CanvasWindow(this, width, height);
}
/**
* Creates a fullscreen CanvasWindow using a given GraphicsCanvas
*
* @param exclusive
* when this is set, the window becomes fullscreen, otherwise, it
* will stretch to fit the screen.
*/
public PixelWindow(boolean exclusive) {
super();
window = new CanvasWindow(this, exclusive);
}
public PixelWindow(DisplayMode mode) {
super();
backupMode = GraphicsFunctions.getDisplayDevice().getDisplayMode();
window = new CanvasWindow(this, mode);
while (pixels == null) {
Thread.yield();
}
}
public void setExclusive(boolean b) {
window.setExclusive(b);
}
public void setFullscreen(DisplayMode mode) {
if (backupMode == null) {
window.setExclusive(true);
backupMode = GraphicsFunctions.getDisplayDevice().getDisplayMode();
GraphicsFunctions.getDisplayDevice().setDisplayMode(mode);
} else {
GraphicsFunctions.getDisplayDevice().setDisplayMode(backupMode);
window.setExclusive(false);
backupMode = null;
}
}
public void setTitle(String name) {
window.setTitle(name);
}
}

View file

@ -0,0 +1,131 @@
package digisoft.custom.swing.window.canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import javax.swing.JPanel;
/**
* @author Zom-B
* @since 1.0
* @date 2009/03/22
*/
public abstract class GraphicsCanvas extends JPanel implements ComponentListener {
public int width;
public int height;
public int halfWidth;
public int halfHeight;
private volatile boolean resizeRequest;
protected Graphics pg = null;
// ////////////////////////////////////////////////////////////
public GraphicsCanvas() {
addComponentListener(this);
}
public void init(int width, int height, boolean painting) {
if (this.width != width || this.height != height) {
setPreferredSize(new Dimension(width, height));
initImpl(width, height);
this.width = width;
this.height = height;
halfWidth = width >> 1;
halfHeight = height >> 1;
g = null;
if (painting) {
resized();
}
}
}
// ////////////////////////////////////////////////////////////
public void clear(Paint paint) {
throw new Error("Engine " + this.getClass().getSimpleName() + " has no clear(Paint paint)");
}
public void clear(int rgb) {
throw new Error("Engine " + this.getClass().getSimpleName() + " has no clear(int rgb)");
}
public void clear(int rgba, boolean hasAlpha) {
throw new Error("Engine " + this.getClass().getSimpleName() + " has no clear(int rgba, boolean hasAlpha)");
}
public void pset(int x, int y, int rgb) {
throw new Error("Engine " + this.getClass().getSimpleName() + " has no pset(int x, int y, int rgb)");
}
public int pget(int x, int y) {
throw new Error("Engine " + this.getClass().getSimpleName() + " has no pget(int x, int y)");
}
public Graphics2D graphics() {
throw new Error("Engine " + this.getClass().getSimpleName() + " has no 2D graphics. Only pixel access supported.");
}
public void setAntialiased(boolean b) {
throw new Error("Engine " + this.getClass().getSimpleName() + " has no 2D graphics. No antialiasing supported.");
}
protected abstract void initImpl(int width, int height);
protected abstract void paintImpl(Graphics g);
public boolean ready() {
return true;
}
// ////////////////////////////////////////////////////////////
public void resized() {
}
// ////////////////////////////////////////////////////////////
@Override
public void paint(Graphics g) {
if (resizeRequest) {
init(super.getWidth(), super.getHeight(), true);
resizeRequest = false;
} else {
paintImpl(g);
}
}
private Graphics2D g = null;
public void repaintNow() {
if (g == null) {
g = (Graphics2D) getGraphics();
}
paint(g);
}
@Override
public void componentResized(ComponentEvent e) {
System.out.println("componentResized " + width + "\t" + height);
if (width != super.getWidth() || height != super.getHeight()) {
resizeRequest = true;
}
super.repaint();
}
@Override
public void componentHidden(ComponentEvent arg0) {
}
@Override
public void componentMoved(ComponentEvent arg0) {
}
@Override
public void componentShown(ComponentEvent arg0) {
}
}

View file

@ -0,0 +1,69 @@
package digisoft.custom.swing.window.canvas;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.ColorModel;
import java.awt.image.DirectColorModel;
import java.awt.image.MemoryImageSource;
import java.util.Arrays;
/**
* @author Zom-B
* @since 1.0
* @date 2009/03/22
*/
public class MemoryImageSourceCanvas extends GraphicsCanvas {
private Image image;
public int[] pixels;
public int pixelCount;
private ColorModel cm;
private MemoryImageSource source;
// ////////////////////////////////////////////////////////////
@Override
public void clear(int backgroundColor) {
Arrays.fill(pixels, backgroundColor);
}
@Override
public void pset(int x, int y, int rgb) {
pixels[y * width + x] = rgb;
}
@Override
public int pget(int x, int y) {
return pixels[y * width + x];
}
// ////////////////////////////////////////////////////////////
@Override
protected void initImpl(int width, int height) {
pixelCount = width * height;
if (pixels == null || pixels.length < pixelCount) {
pixels = new int[pixelCount];
}
cm = new DirectColorModel(32, 0x00ff0000, 0x0000ff00, 0x000000ff);
source = new MemoryImageSource(width, height, pixels, 0, width);
source.setFullBufferUpdates(true);
source.setAnimated(true);
image = Toolkit.getDefaultToolkit().createImage(source);
}
@Override
public void paintImpl(Graphics g) {
if (source != null) {
source.newPixels(pixels, cm, 0, width);
}
if (image != null) {
g.drawImage(image, 0, 0, null);
// force repaint now (proper method)
// Toolkit.getDefaultToolkit().sync();
}
}
}

File diff suppressed because it is too large Load diff