output = new DockShipping<>("output", Turtle.class, new Turtle());
public PatternOnPath() {
super("PatternOnPath");
@@ -17,11 +19,14 @@ public PatternOnPath() {
addVariable(path);
addVariable(count);
addVariable(output);
- pattern.setIsDirty(true);
}
@Override
- public void update() throws Exception {
+ public void update() {
+ if(pattern.hasPacketWaiting()) pattern.receive();
+ if(path.hasPacketWaiting()) path.receive();
+ if(count.hasPacketWaiting()) count.receive();
+
Turtle sum = new Turtle();
Turtle myPattern = pattern.getValue();
Turtle myPath = path.getValue();
@@ -42,7 +47,6 @@ public void update() throws Exception {
sum.add(stamp);
}
}
- output.setValue(sum);
- cleanAllInputs();
+ output.send(new Packet<>(sum));
}
}
diff --git a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/PointOnPath.java b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/PointOnPath.java
index 8610e94fd..17d2e6696 100644
--- a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/PointOnPath.java
+++ b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/PointOnPath.java
@@ -2,8 +2,10 @@
import com.marginallyclever.convenience.Point2D;
import com.marginallyclever.makelangelo.turtle.Turtle;
+import com.marginallyclever.nodegraphcore.DockReceiving;
+import com.marginallyclever.nodegraphcore.DockShipping;
import com.marginallyclever.nodegraphcore.Node;
-import com.marginallyclever.nodegraphcore.NodeVariable;
+import com.marginallyclever.nodegraphcore.Packet;
/**
* (px,py) = path(index), where path(0) is the start and path(path.length) is the end.
@@ -14,12 +16,12 @@
* path.length can be obtained from LoadTurtle.
*/
public class PointOnPath extends Node {
- private final NodeVariable path = NodeVariable.newInstance("path", Turtle.class, new Turtle(),true,false);
- private final NodeVariable index = NodeVariable.newInstance("index", Number.class, 0,true,false);
- private final NodeVariable px = NodeVariable.newInstance("px", Number.class, 0,false,true);
- private final NodeVariable py = NodeVariable.newInstance("py", Number.class, 0,false,true);
- private final NodeVariable nx = NodeVariable.newInstance("nx", Number.class, 0,false,true);
- private final NodeVariable ny = NodeVariable.newInstance("ny", Number.class, 0,false,true);
+ private final DockReceiving path = new DockReceiving<>("path", Turtle.class, new Turtle());
+ private final DockReceiving index = new DockReceiving<>("index", Number.class, 0);
+ private final DockShipping px = new DockShipping<>("px", Number.class, 0);
+ private final DockShipping py = new DockShipping<>("py", Number.class, 0);
+ private final DockShipping nx = new DockShipping<>("nx", Number.class, 0);
+ private final DockShipping ny = new DockShipping<>("ny", Number.class, 0);
public PointOnPath() {
super("PointOnPath");
@@ -33,8 +35,10 @@ public PointOnPath() {
private static final double EPSILON=0.00001;
@Override
- public void update() throws Exception {
- Turtle sum = new Turtle();
+ public void update() {
+ if(path.hasPacketWaiting()) path.receive();
+ if(index.hasPacketWaiting()) index.receive();
+
Turtle myPath = path.getValue();
double total = myPath.getDrawDistance();
if(total!=0) {
@@ -42,12 +46,11 @@ public void update() throws Exception {
if (c0 > 0) {
double c1 = c0 + EPSILON;
Point2D p0 = myPath.interpolate(c0);
- px.setValue(p0.x);
- px.setValue(p0.y);
+ px.send(new Packet<>(p0.x));
+ px.send(new Packet<>(p0.y));
Point2D p1;
if(c1>total) {
- c1=total;
p1 = myPath.interpolate(total);
p0 = myPath.interpolate(total-EPSILON);
} else {
@@ -57,15 +60,14 @@ public void update() throws Exception {
double dy = p1.y - p0.y;
Point2D n = new Point2D(dx,dy);
n.normalize();
- nx.setValue(n.x);
- ny.setValue(n.y);
+ nx.send(new Packet<>(n.x));
+ ny.send(new Packet<>(n.y));
}
} else {
- px.setValue(0);
- px.setValue(0);
- nx.setValue(1);
- ny.setValue(0);
+ px.send(new Packet<>(0));
+ px.send(new Packet<>(0));
+ nx.send(new Packet<>(1));
+ ny.send(new Packet<>(0));
}
- cleanAllInputs();
}
}
diff --git a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/PrintTurtle.java b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/PrintTurtle.java
index 5ca53f6e3..ce4aee394 100644
--- a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/PrintTurtle.java
+++ b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/PrintTurtle.java
@@ -3,18 +3,19 @@
import com.marginallyclever.convenience.ColorRGB;
import com.marginallyclever.makelangelo.turtle.Turtle;
import com.marginallyclever.makelangelo.turtle.TurtleMove;
+import com.marginallyclever.nodegraphcore.DockReceiving;
+import com.marginallyclever.nodegraphcore.DockShipping;
import com.marginallyclever.nodegraphcore.PrintWithGraphics;
import com.marginallyclever.nodegraphcore.Node;
-import com.marginallyclever.nodegraphcore.NodeVariable;
import java.awt.*;
public class PrintTurtle extends Node implements PrintWithGraphics {
- private final NodeVariable turtle = NodeVariable.newInstance("turtle", Turtle.class,new Turtle(),true,false);
- private final NodeVariable px = NodeVariable.newInstance("X",Number.class,0,true,false);
- private final NodeVariable py = NodeVariable.newInstance("Y",Number.class,0,true,false);
- private final NodeVariable travelColor = NodeVariable.newInstance("travel color",Color.class,Color.GREEN,true,false);
- private final NodeVariable showTravel = NodeVariable.newInstance("show travel",Boolean.class,false,true,false);
+ private final DockReceiving turtle = new DockReceiving<>("turtle", Turtle.class,new Turtle());
+ private final DockReceiving px = new DockReceiving<>("X",Number.class,0);
+ private final DockReceiving py = new DockReceiving<>("Y",Number.class,0);
+ private final DockReceiving travelColor = new DockReceiving<>("travel color",Color.class,Color.GREEN);
+ private final DockShipping showTravel = new DockShipping<>("show travel",Boolean.class,false);
public PrintTurtle() {
super("PrintTurtle");
@@ -24,12 +25,15 @@ public PrintTurtle() {
}
@Override
- public void update() throws Exception {
- cleanAllInputs();
- }
+ public void update() {}
@Override
public void print(Graphics g) {
+ if(turtle.hasPacketWaiting()) turtle.receive();
+ if(px.hasPacketWaiting()) px.receive();
+ if(py.hasPacketWaiting()) py.receive();
+ if(travelColor.hasPacketWaiting()) travelColor.receive();
+
Turtle myTurtle = turtle.getValue();
if(myTurtle==null || myTurtle.history.isEmpty()) return;
diff --git a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/SaveTurtle.java b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/SaveTurtle.java
index 9ed9fa0fc..02b5840d6 100644
--- a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/SaveTurtle.java
+++ b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/SaveTurtle.java
@@ -1,7 +1,8 @@
package com.marginallyclever.makelangelo.donatelloimpl.nodes;
+import com.marginallyclever.nodegraphcore.DockReceiving;
+import com.marginallyclever.nodegraphcore.DockShipping;
import com.marginallyclever.nodegraphcore.Node;
-import com.marginallyclever.nodegraphcore.NodeVariable;
import com.marginallyclever.makelangelo.makeart.io.TurtleFactory;
import com.marginallyclever.makelangelo.turtle.Turtle;
import org.slf4j.Logger;
@@ -11,8 +12,8 @@ public class SaveTurtle extends Node {
private static final Logger logger = LoggerFactory.getLogger(SaveTurtle.class);
- private final NodeVariable filename = NodeVariable.newInstance("filename",String.class,null,true,false);
- private final NodeVariable turtle = NodeVariable.newInstance("turtle", Turtle.class,new Turtle(),true,false);
+ private final DockReceiving filename = new DockReceiving<>("filename",String.class,null);
+ private final DockShipping turtle = new DockShipping<>("turtle", Turtle.class,new Turtle());
public SaveTurtle() {
super("SaveTurtle");
@@ -21,12 +22,13 @@ public SaveTurtle() {
}
@Override
- public void update() throws Exception {
+ public void update() {
+ if(filename.hasPacketWaiting()) filename.receive();
+
if(filename.getValue().isEmpty()) return;
try {
TurtleFactory.save(turtle.getValue(),filename.getValue());
- cleanAllInputs();
} catch (Exception e) {
logger.warn("Failed to update, ignoring", e);
}
diff --git a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/TransformTurtle.java b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/TransformTurtle.java
index db0e63d68..245da0473 100644
--- a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/TransformTurtle.java
+++ b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/TransformTurtle.java
@@ -1,17 +1,19 @@
package com.marginallyclever.makelangelo.donatelloimpl.nodes;
+import com.marginallyclever.nodegraphcore.DockReceiving;
+import com.marginallyclever.nodegraphcore.DockShipping;
import com.marginallyclever.nodegraphcore.Node;
-import com.marginallyclever.nodegraphcore.NodeVariable;
import com.marginallyclever.makelangelo.turtle.Turtle;
+import com.marginallyclever.nodegraphcore.Packet;
public class TransformTurtle extends Node {
- private final NodeVariable turtle = NodeVariable.newInstance("turtle", Turtle.class,new Turtle(),true,false);
- private final NodeVariable sx = NodeVariable.newInstance("scale x",Number.class,1,true,false);
- private final NodeVariable sy = NodeVariable.newInstance("scale y",Number.class,1,true,false);
- private final NodeVariable rotate = NodeVariable.newInstance("rotate degrees",Number.class,0,true,false);
- private final NodeVariable tx = NodeVariable.newInstance("translate x",Number.class,0,true,false);
- private final NodeVariable ty = NodeVariable.newInstance("translate y",Number.class,0,true,false);
- private final NodeVariable output = NodeVariable.newInstance("output", Turtle.class,new Turtle(),false,true);
+ private final DockReceiving turtle = new DockReceiving<>("turtle", Turtle.class,new Turtle());
+ private final DockReceiving sx = new DockReceiving<>("scale x",Number.class,1);
+ private final DockReceiving sy = new DockReceiving<>("scale y",Number.class,1);
+ private final DockReceiving rotate = new DockReceiving<>("rotate degrees",Number.class,0);
+ private final DockReceiving tx = new DockReceiving<>("translate x",Number.class,0);
+ private final DockReceiving ty = new DockReceiving<>("translate y",Number.class,0);
+ private final DockShipping output = new DockShipping<>("output", Turtle.class,new Turtle());
public TransformTurtle() {
super("TransformTurtle");
@@ -25,13 +27,19 @@ public TransformTurtle() {
}
@Override
- public void update() throws Exception {
+ public void update() {
+ if(turtle.hasPacketWaiting()) turtle.receive();
+ if(sx.hasPacketWaiting()) sx.receive();
+ if(sy.hasPacketWaiting()) sy.receive();
+ if(rotate.hasPacketWaiting()) rotate.receive();
+ if(tx.hasPacketWaiting()) tx.receive();
+ if(ty.hasPacketWaiting()) ty.receive();
+
Turtle input = turtle.getValue();
Turtle moved = new Turtle(input);
moved.scale(sx.getValue().doubleValue(),sy.getValue().doubleValue());
moved.rotate(rotate.getValue().doubleValue());
moved.translate(tx.getValue().doubleValue(),ty.getValue().doubleValue());
- output.setValue(moved);
- cleanAllInputs();
+ output.send(new Packet<>(moved));
}
}
diff --git a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/TurtleToBufferedImage.java b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/TurtleToBufferedImage.java
index e9ff86f75..d4fe74fdb 100644
--- a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/TurtleToBufferedImage.java
+++ b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/TurtleToBufferedImage.java
@@ -1,18 +1,20 @@
package com.marginallyclever.makelangelo.donatelloimpl.nodes;
+import com.marginallyclever.nodegraphcore.DockReceiving;
+import com.marginallyclever.nodegraphcore.DockShipping;
import com.marginallyclever.nodegraphcore.Node;
-import com.marginallyclever.nodegraphcore.NodeVariable;
import com.marginallyclever.convenience.ColorRGB;
import com.marginallyclever.makelangelo.turtle.Turtle;
import com.marginallyclever.makelangelo.turtle.TurtleMove;
+import com.marginallyclever.nodegraphcore.Packet;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
public class TurtleToBufferedImage extends Node {
- private final NodeVariable turtle = NodeVariable.newInstance("turtle", Turtle.class,new Turtle(),true,false);
- private final NodeVariable output = NodeVariable.newInstance("output", BufferedImage.class, new BufferedImage(1,1,BufferedImage.TYPE_INT_ARGB),false,true);
+ private final DockReceiving turtle = new DockReceiving<>("turtle", Turtle.class,new Turtle());
+ private final DockShipping output = new DockShipping<>("output", BufferedImage.class, new BufferedImage(1,1,BufferedImage.TYPE_INT_ARGB));
public TurtleToBufferedImage() {
super("TurtleToImage");
@@ -21,7 +23,9 @@ public TurtleToBufferedImage() {
}
@Override
- public void update() throws Exception {
+ public void update() {
+ if(turtle.hasPacketWaiting()) turtle.receive();
+
Turtle myTurtle = turtle.getValue();
if(myTurtle!=null && !myTurtle.history.isEmpty()) {
Rectangle2D r = myTurtle.getBounds();
@@ -55,8 +59,7 @@ public void update() throws Exception {
}
}
}
- output.setValue(img);
- cleanAllInputs();
+ output.send(new Packet<>(img));
}
}
}
diff --git a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/TurtleToRectangle.java b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/TurtleToRectangle.java
index 207260dd6..2def144d6 100644
--- a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/TurtleToRectangle.java
+++ b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/TurtleToRectangle.java
@@ -1,8 +1,10 @@
package com.marginallyclever.makelangelo.donatelloimpl.nodes;
import com.marginallyclever.makelangelo.turtle.Turtle;
+import com.marginallyclever.nodegraphcore.DockReceiving;
+import com.marginallyclever.nodegraphcore.DockShipping;
import com.marginallyclever.nodegraphcore.Node;
-import com.marginallyclever.nodegraphcore.NodeVariable;
+import com.marginallyclever.nodegraphcore.Packet;
import java.awt.*;
@@ -12,8 +14,8 @@
* @since 2022-04-14
*/
public class TurtleToRectangle extends Node {
- private final NodeVariable turtle = NodeVariable.newInstance("turtle", Turtle.class,new Turtle(),true,false);
- private final NodeVariable output = NodeVariable.newInstance("output", Rectangle.class, new Rectangle(0,0,0,0),false,true);
+ private final DockReceiving turtle = new DockReceiving<>("turtle", Turtle.class,new Turtle());
+ private final DockShipping output = new DockShipping<>("output", Rectangle.class, new Rectangle(0,0,0,0));
public TurtleToRectangle() {
super("TurtleToRectangle");
@@ -22,11 +24,12 @@ public TurtleToRectangle() {
}
@Override
- public void update() throws Exception {
+ public void update() {
+ if(turtle.hasPacketWaiting()) turtle.receive();
+
Turtle myTurtle = turtle.getValue();
if(myTurtle!=null ) {
- output.setValue(myTurtle.getBounds());
- cleanAllInputs();
+ output.send(new Packet<>(myTurtle.getBounds()));
}
}
}
diff --git a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/shapes/Circle.java b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/shapes/Circle.java
index ac4b6c968..571fe8bff 100644
--- a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/shapes/Circle.java
+++ b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/shapes/Circle.java
@@ -1,16 +1,18 @@
package com.marginallyclever.makelangelo.donatelloimpl.nodes.shapes;
import com.marginallyclever.makelangelo.turtle.Turtle;
+import com.marginallyclever.nodegraphcore.DockReceiving;
+import com.marginallyclever.nodegraphcore.DockShipping;
import com.marginallyclever.nodegraphcore.Node;
-import com.marginallyclever.nodegraphcore.NodeVariable;
+import com.marginallyclever.nodegraphcore.Packet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Circle extends Node {
private static final Logger logger = LoggerFactory.getLogger(Circle.class);
- private final NodeVariable radius = NodeVariable.newInstance("radius", Number.class, 50,true,false);
- private final NodeVariable contents = NodeVariable.newInstance("contents", Turtle.class, new Turtle(),false,true);
+ private final DockReceiving radius = new DockReceiving<>("radius", Number.class, 50);
+ private final DockShipping contents = new DockShipping<>("contents", Turtle.class, new Turtle());
public Circle() {
super("Circle");
@@ -20,6 +22,8 @@ public Circle() {
@Override
public void update() {
+ if(radius.hasPacketWaiting()) radius.receive();
+
try {
Turtle t = new Turtle();
double r = radius.getValue().doubleValue()/2.0;
@@ -31,8 +35,7 @@ public void update() {
}
t.jumpTo(r,0);
t.penUp();
- contents.setValue(t);
- cleanAllInputs();
+ contents.send(new Packet<>(t));
} catch (Exception e) {
logger.warn("Failed to update, ignoring", e);
}
diff --git a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/shapes/Line.java b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/shapes/Line.java
index 2be427c9b..f4c230912 100644
--- a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/shapes/Line.java
+++ b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/shapes/Line.java
@@ -1,19 +1,18 @@
package com.marginallyclever.makelangelo.donatelloimpl.nodes.shapes;
import com.marginallyclever.makelangelo.turtle.Turtle;
-import com.marginallyclever.nodegraphcore.Node;
-import com.marginallyclever.nodegraphcore.NodeVariable;
+import com.marginallyclever.nodegraphcore.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Line extends Node {
private static final Logger logger = LoggerFactory.getLogger(Line.class);
- private final NodeVariable x0 = NodeVariable.newInstance("x0", Number.class, 0,true,false);
- private final NodeVariable y0 = NodeVariable.newInstance("y0", Number.class, 0,true,false);
- private final NodeVariable x1 = NodeVariable.newInstance("x1", Number.class, 1,true,false);
- private final NodeVariable y1 = NodeVariable.newInstance("y1", Number.class, 0,true,false);
- private final NodeVariable contents = NodeVariable.newInstance("contents", Turtle.class, new Turtle(),false,true);
+ private final DockReceiving x0 = new DockReceiving<>("x0", Number.class, 0);
+ private final DockReceiving y0 = new DockReceiving<>("y0", Number.class, 0);
+ private final DockReceiving x1 = new DockReceiving<>("x1", Number.class, 1);
+ private final DockReceiving y1 = new DockReceiving<>("y1", Number.class, 0);
+ private final DockShipping contents = new DockShipping<>("contents", Turtle.class, new Turtle());
public Line() {
super("Line");
@@ -26,13 +25,17 @@ public Line() {
@Override
public void update() {
+ if(x0.hasPacketWaiting()) x0.receive();
+ if(y0.hasPacketWaiting()) y0.receive();
+ if(x1.hasPacketWaiting()) x1.receive();
+ if(y1.hasPacketWaiting()) y1.receive();
+
try {
Turtle t = new Turtle();
t.jumpTo(x0.getValue().doubleValue(),y0.getValue().doubleValue());
t.moveTo(x1.getValue().doubleValue(),y1.getValue().doubleValue());
t.penUp();
- contents.setValue(t);
- cleanAllInputs();
+ contents.send(new Packet<>(t));
} catch (Exception e) {
logger.warn("Failed to update, ignoring", e);
}
diff --git a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/shapes/NGon.java b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/shapes/NGon.java
index 8418d1d1f..832424d0d 100644
--- a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/shapes/NGon.java
+++ b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/shapes/NGon.java
@@ -1,17 +1,19 @@
package com.marginallyclever.makelangelo.donatelloimpl.nodes.shapes;
import com.marginallyclever.makelangelo.turtle.Turtle;
+import com.marginallyclever.nodegraphcore.DockReceiving;
+import com.marginallyclever.nodegraphcore.DockShipping;
import com.marginallyclever.nodegraphcore.Node;
-import com.marginallyclever.nodegraphcore.NodeVariable;
+import com.marginallyclever.nodegraphcore.Packet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class NGon extends Node {
private static final Logger logger = LoggerFactory.getLogger(NGon.class);
- private final NodeVariable radius = NodeVariable.newInstance("radius", Number.class, 10,true,true);
- private final NodeVariable steps = NodeVariable.newInstance("steps", Number.class, 4,true,true);
- private final NodeVariable contents = NodeVariable.newInstance("contents", Turtle.class, new Turtle(),false,true);
+ private final DockReceiving radius = new DockReceiving<>("radius", Number.class, 10);
+ private final DockReceiving steps = new DockReceiving<>("steps", Number.class, 4);
+ private final DockShipping contents = new DockShipping<>("contents", Turtle.class, new Turtle());
public NGon() {
super("NGon");
@@ -22,6 +24,9 @@ public NGon() {
@Override
public void update() {
+ if(radius.hasPacketWaiting()) radius.receive();
+ if(steps.hasPacketWaiting()) steps.receive();
+
try {
Turtle t = new Turtle();
double r = radius.getValue().doubleValue();
@@ -33,8 +38,7 @@ public void update() {
t.moveTo(Math.cos(v), Math.sin(v));
}
t.penUp();
- contents.setValue(t);
- cleanAllInputs();
+ contents.send(new Packet<>(t));
} catch (Exception e) {
logger.warn("Failed to update, ignoring", e);
}
diff --git a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/shapes/Rectangle.java b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/shapes/Rectangle.java
index a5f1c1fc6..a363c78ee 100644
--- a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/shapes/Rectangle.java
+++ b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/shapes/Rectangle.java
@@ -1,17 +1,19 @@
package com.marginallyclever.makelangelo.donatelloimpl.nodes.shapes;
import com.marginallyclever.makelangelo.turtle.Turtle;
+import com.marginallyclever.nodegraphcore.DockReceiving;
+import com.marginallyclever.nodegraphcore.DockShipping;
import com.marginallyclever.nodegraphcore.Node;
-import com.marginallyclever.nodegraphcore.NodeVariable;
+import com.marginallyclever.nodegraphcore.Packet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Rectangle extends Node {
private static final Logger logger = LoggerFactory.getLogger(Rectangle.class);
- private final NodeVariable w = NodeVariable.newInstance("width", Number.class, 100,true,true);
- private final NodeVariable h = NodeVariable.newInstance("height", Number.class, 100,true,true);
- private final NodeVariable contents = NodeVariable.newInstance("contents", Turtle.class, new Turtle(),false,true);
+ private final DockReceiving w = new DockReceiving<>("width", Number.class, 100);
+ private final DockReceiving h = new DockReceiving<>("height", Number.class, 100);
+ private final DockShipping contents = new DockShipping<>("contents", Turtle.class, new Turtle());
public Rectangle() {
super("Rectangle");
@@ -22,6 +24,9 @@ public Rectangle() {
@Override
public void update() {
+ if(w.hasPacketWaiting()) w.receive();
+ if(h.hasPacketWaiting()) h.receive();
+
try {
Turtle t = new Turtle();
double ww = w.getValue().doubleValue()/2.0;
@@ -32,8 +37,7 @@ public void update() {
t.moveTo(-ww, hh);
t.moveTo(-ww,-hh);
t.penUp();
- contents.setValue(t);
- cleanAllInputs();
+ contents.send(new Packet<>(t));
} catch (Exception e) {
logger.warn("Failed to update, ignoring", e);
}
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/TurtleModifierAction.java b/src/main/java/com/marginallyclever/makelangelo/makeart/TurtleModifierAction.java
index 248ac4f96..c7771a882 100644
--- a/src/main/java/com/marginallyclever/makelangelo/makeart/TurtleModifierAction.java
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/TurtleModifierAction.java
@@ -17,8 +17,6 @@ public abstract class TurtleModifierAction extends AbstractAction {
private final ArrayList listeners = new ArrayList();
private Makelangelo myMakelangelo;
- public TurtleModifierAction() {}
-
public TurtleModifierAction(String string) {
super(string);
}
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_Boxxy.java b/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_Boxxy.java
index 097cae7d6..e3239f6dd 100644
--- a/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_Boxxy.java
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_Boxxy.java
@@ -3,7 +3,7 @@
import com.marginallyclever.makelangelo.Translator;
import com.marginallyclever.makelangelo.makeart.TransformedImage;
-import com.marginallyclever.makelangelo.makeart.imagefilter.Filter_Greyscale;
+import com.marginallyclever.makelangelo.makeart.imagefilter.FilterDesaturate;
import com.marginallyclever.makelangelo.paper.Paper;
import com.marginallyclever.makelangelo.select.SelectSlider;
import com.marginallyclever.makelangelo.turtle.Turtle;
@@ -59,8 +59,8 @@ public int getCutoff() {
public void start(Paper paper, TransformedImage image) {
super.start(paper, image);
- Filter_Greyscale bw = new Filter_Greyscale(255);
- TransformedImage img = bw.filter(myImage);
+ FilterDesaturate bw = new FilterDesaturate(myImage);
+ TransformedImage img = bw.filter();
double yBottom = myPaper.getMarginBottom();
double yTop = myPaper.getMarginTop();
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_CMYK_Circles.java b/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_CMYK_Circles.java
index 2b78da39d..b490136cd 100644
--- a/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_CMYK_Circles.java
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_CMYK_Circles.java
@@ -5,7 +5,7 @@
import com.marginallyclever.convenience.Point2D;
import com.marginallyclever.makelangelo.Translator;
import com.marginallyclever.makelangelo.makeart.TransformedImage;
-import com.marginallyclever.makelangelo.makeart.imagefilter.Filter_CMYK;
+import com.marginallyclever.makelangelo.makeart.imagefilter.FilterCMYK;
import com.marginallyclever.makelangelo.makeart.tools.InfillTurtle;
import com.marginallyclever.makelangelo.makeart.tools.RemoveExtraColorChangesFromTurtle;
import com.marginallyclever.makelangelo.paper.Paper;
@@ -59,8 +59,8 @@ public void setMaxCircleSize(int value) {
public void start(Paper paper, TransformedImage image) {
super.start(paper, image);
- Filter_CMYK cmyk = new Filter_CMYK();
- cmyk.filter(myImage);
+ FilterCMYK cmyk = new FilterCMYK(myImage);
+ cmyk.filter();
turtle = new Turtle();
// remove extra change color at the start of the turtle
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_CMYK_Crosshatch.java b/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_CMYK_Crosshatch.java
index 0b103b4ad..0d347f9ee 100644
--- a/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_CMYK_Crosshatch.java
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_CMYK_Crosshatch.java
@@ -3,7 +3,7 @@
import com.marginallyclever.convenience.ColorRGB;
import com.marginallyclever.makelangelo.Translator;
import com.marginallyclever.makelangelo.makeart.TransformedImage;
-import com.marginallyclever.makelangelo.makeart.imagefilter.Filter_CMYK;
+import com.marginallyclever.makelangelo.makeart.imagefilter.FilterCMYK;
import com.marginallyclever.makelangelo.paper.Paper;
import com.marginallyclever.makelangelo.select.SelectReadOnlyText;
import com.marginallyclever.makelangelo.select.SelectSlider;
@@ -55,8 +55,8 @@ public void setPasses(int value) {
public void start(Paper paper, TransformedImage image) {
super.start(paper, image);
- Filter_CMYK cmyk = new Filter_CMYK();
- cmyk.filter(myImage);
+ FilterCMYK cmyk = new FilterCMYK(myImage);
+ cmyk.filter();
turtle = new Turtle();
// remove extra change color at the start of the turtle
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_CMYK_Spiral.java b/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_CMYK_Spiral.java
index ba9249205..f7a329e78 100644
--- a/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_CMYK_Spiral.java
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_CMYK_Spiral.java
@@ -3,7 +3,7 @@
import com.marginallyclever.convenience.ColorRGB;
import com.marginallyclever.makelangelo.Translator;
import com.marginallyclever.makelangelo.makeart.TransformedImage;
-import com.marginallyclever.makelangelo.makeart.imagefilter.Filter_CMYK;
+import com.marginallyclever.makelangelo.makeart.imagefilter.FilterCMYK;
import com.marginallyclever.makelangelo.paper.Paper;
import com.marginallyclever.makelangelo.select.SelectBoolean;
import com.marginallyclever.makelangelo.turtle.Turtle;
@@ -53,8 +53,8 @@ public void setToCorners(boolean arg0) {
public void start(Paper paper, TransformedImage image) {
super.start(paper, image);
- Filter_CMYK cmyk = new Filter_CMYK();
- cmyk.filter(myImage);
+ FilterCMYK cmyk = new FilterCMYK(myImage);
+ cmyk.filter();
double separation;
float h2 = (float)myPaper.getPaperHeight();
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_Crosshatch.java b/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_Crosshatch.java
index a3ce41309..75773dd49 100644
--- a/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_Crosshatch.java
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_Crosshatch.java
@@ -2,7 +2,7 @@
import com.marginallyclever.makelangelo.Translator;
import com.marginallyclever.makelangelo.makeart.TransformedImage;
-import com.marginallyclever.makelangelo.makeart.imagefilter.Filter_Greyscale;
+import com.marginallyclever.makelangelo.makeart.imagefilter.FilterDesaturate;
import com.marginallyclever.makelangelo.paper.Paper;
import com.marginallyclever.makelangelo.select.SelectSlider;
import com.marginallyclever.makelangelo.turtle.Turtle;
@@ -85,8 +85,8 @@ public double getPass45() {
public void start(Paper paper, TransformedImage image) {
super.start(paper, image);
- Filter_Greyscale bw = new Filter_Greyscale(255);
- TransformedImage img = bw.filter(myImage);
+ FilterDesaturate bw = new FilterDesaturate(myImage);
+ TransformedImage img = bw.filter();
turtle = new Turtle();
finishPass(new int[]{(int)pass90},90,img);
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_EdgeDetection.java b/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_EdgeDetection.java
index 731c872db..d396e26cb 100644
--- a/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_EdgeDetection.java
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/imageconverter/Converter_EdgeDetection.java
@@ -3,7 +3,9 @@
import com.marginallyclever.convenience.Point2D;
import com.marginallyclever.makelangelo.Translator;
import com.marginallyclever.makelangelo.makeart.TransformedImage;
-import com.marginallyclever.makelangelo.makeart.imagefilter.Filter_Greyscale;
+import com.marginallyclever.makelangelo.makeart.imagefilter.FilterDesaturate;
+import com.marginallyclever.makelangelo.makeart.imagefilter.FilterExtendedDifferenceOfGaussians;
+import com.marginallyclever.makelangelo.makeart.imagefilter.FilterGaussianBlur;
import com.marginallyclever.makelangelo.paper.Paper;
import com.marginallyclever.makelangelo.select.SelectSlider;
import com.marginallyclever.makelangelo.turtle.Turtle;
@@ -66,12 +68,20 @@ public int getSampleSize() {
public void start(Paper paper, TransformedImage image) {
super.start(paper, image);
- Filter_Greyscale bw = new Filter_Greyscale(255);
- img = bw.filter(myImage);
+ FilterDesaturate desaturates = new FilterDesaturate(myImage);
+ img = desaturates.filter();
+
+ FilterGaussianBlur blur1 = new FilterGaussianBlur(img, 1);
+ FilterGaussianBlur blur2 = new FilterGaussianBlur(img, 4);
+ TransformedImage img1 = blur1.filter();
+ TransformedImage img2 = blur2.filter();
+ FilterExtendedDifferenceOfGaussians dog = new FilterExtendedDifferenceOfGaussians(img1,img2,20);
+ img = dog.filter();
+
+
turtle = new Turtle();
int edgeStep = 255/(passes+1);
- int d = 40;
edge = 255-edgeStep;
for(int i=0;ijava.awt.image.BufferedImage this filter is using as source material.
+ */
+ public FilterCMYK(TransformedImage img) {
+ super();
+ this.img = img;
}
@@ -50,11 +56,10 @@ public TransformedImage getK() {
/**
* Converts an image to 4 greyscale images, one for each channel of CMYK.
* See RGB to CMYK
- * @param img the java.awt.image.BufferedImage
this filter is using as source material.
* @return the original image.
*/
@Override
- public TransformedImage filter(TransformedImage img) {
+ public TransformedImage filter() {
int h = img.getSourceImage().getHeight();
int w = img.getSourceImage().getWidth();
int px, py;
@@ -167,9 +172,9 @@ public TransformedImage processViaHistogram(TransformedImage img) {
}
public static void main(String[] args) throws IOException {
- TransformedImage src = new TransformedImage( ImageIO.read(new FileInputStream("src/test/resources/Lenna.png")) );
- Filter_CMYK f = new Filter_CMYK();
- f.filter(src);
+ TransformedImage src = new TransformedImage( ImageIO.read(new FileInputStream("src/test/resources/mandrill.png")) );
+ FilterCMYK f = new FilterCMYK(src);
+ f.filter();
JTabbedPane tabs = new JTabbedPane();
tabs.addTab("Original", new JLabel(new ImageIcon(src.getSourceImage())));
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_ContrastAdjust.java b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterContrastAdjust.java
similarity index 82%
rename from src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_ContrastAdjust.java
rename to src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterContrastAdjust.java
index 59d2ae8f9..3d3d6ad03 100644
--- a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_ContrastAdjust.java
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterContrastAdjust.java
@@ -16,7 +16,8 @@
* @author Dan Royer
* @since 7.39.9
*/
-public class Filter_ContrastAdjust extends ImageFilter {
+public class FilterContrastAdjust extends ImageFilter {
+ private final TransformedImage img;
private final int bottom;
private final float range;
@@ -25,13 +26,15 @@ public class Filter_ContrastAdjust extends ImageFilter {
* @param bottom the new bottom range
* @param top the new top range.
*/
- public Filter_ContrastAdjust(int bottom,int top) {
+ public FilterContrastAdjust(TransformedImage img, int bottom, int top) {
super();
+ this.img = img;
this.bottom = bottom;
range = 255f / (top-bottom);
}
- public TransformedImage filter(TransformedImage img) {
+ @Override
+ public TransformedImage filter() {
int h = img.getSourceImage().getHeight();
int w = img.getSourceImage().getWidth();
BufferedImage bi = img.getSourceImage();
@@ -59,7 +62,7 @@ private int adjust(int color) {
}
public static void main(String[] args) throws IOException {
- TransformedImage src = new TransformedImage( ImageIO.read(new FileInputStream("src/test/resources/Lenna.png")) );
+ TransformedImage src = new TransformedImage( ImageIO.read(new FileInputStream("src/test/resources/mandrill.png")) );
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
@@ -69,9 +72,8 @@ public static void main(String[] args) throws IOException {
panel.add(slider,BorderLayout.NORTH);
slider.addChangeListener(e->{
- Filter_ContrastAdjust f = new Filter_ContrastAdjust(slider.getValue(),slider.getUpperValue());
- TransformedImage dest = f.filter(src);
- ResizableImagePanel rip = new ResizableImagePanel(dest.getSourceImage());
+ FilterContrastAdjust f = new FilterContrastAdjust(src,slider.getValue(),slider.getUpperValue());
+ ResizableImagePanel rip = new ResizableImagePanel(f.filter().getSourceImage());
BorderLayout layout = (BorderLayout)panel.getLayout();
Component c = layout.getLayoutComponent(BorderLayout.CENTER);
if(c!=null) panel.remove(c);
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterDesaturate.java b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterDesaturate.java
new file mode 100644
index 000000000..05a04d572
--- /dev/null
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterDesaturate.java
@@ -0,0 +1,66 @@
+package com.marginallyclever.makelangelo.makeart.imagefilter;
+
+import com.marginallyclever.convenience.ResizableImagePanel;
+import com.marginallyclever.makelangelo.makeart.TransformedImage;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+/**
+ * Converts an image to greyscale.
+ * @author Dan Royer
+ */
+public class FilterDesaturate extends ImageFilter {
+ private final TransformedImage img;
+
+ public FilterDesaturate(TransformedImage img) {
+ super();
+ this.img = img;
+ }
+
+ @Override
+ public TransformedImage filter() {
+ int h = img.getSourceImage().getHeight();
+ int w = img.getSourceImage().getWidth();
+
+ BufferedImage bi = img.getSourceImage();
+ TransformedImage after = new TransformedImage(img);
+ BufferedImage afterBI = after.getSourceImage();
+
+ int x, y;
+ for (y = 0; y < h; ++y) {
+ for (x = 0; x < w; ++x) {
+ double pixel = decode32bit(bi.getRGB(x, y));
+ //double v2 = sRGBtoLinear(pixel);
+ double v2 = toneControl(pixel);
+ int rgb = (int) Math.min(255, Math.max(0, v2));
+ afterBI.setRGB(x, y, ImageFilter.encode32bit(rgb));
+ }
+ }
+ return after;
+ }
+
+ private double sRGBtoLinear(double b) {
+ b /= 255.0;
+ if (b <= 0.04045) b /= 12.92;
+ else b = Math.pow((b + 0.055) / 1.055, 2.4);
+ return b * 255.0;
+ }
+
+ /**
+ * accepts and returns a number between 0 and 255, inclusive.
+ */
+ private double toneControl(double b) {
+ b /= 255.0;
+ b = 0.017 * Math.exp(3.29 * b) + 0.005 * Math.exp(7.27 * b);
+ return Math.min(1, Math.max(0, b)) * 255.0;
+ }
+
+ public static void main(String[] args) throws IOException {
+ TransformedImage src = new TransformedImage( ImageIO.read(new FileInputStream("src/test/resources/mandrill.png")) );
+ FilterDesaturate f = new FilterDesaturate(src);
+ ResizableImagePanel.showImage(f.filter().getSourceImage(), "FilterDesaturate" );
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterDifference.java b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterDifference.java
new file mode 100644
index 000000000..7dda7a8e3
--- /dev/null
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterDifference.java
@@ -0,0 +1,52 @@
+package com.marginallyclever.makelangelo.makeart.imagefilter;
+
+import com.marginallyclever.convenience.ColorRGB;
+import com.marginallyclever.makelangelo.makeart.TransformedImage;
+
+import java.awt.image.BufferedImage;
+
+/**
+ * Calculate abs(a-b) for every pixel
+ * @author Dan Royer
+ * @since 7.46.0
+ */
+public class FilterDifference extends ImageFilter {
+ private final TransformedImage a,b;
+
+ public FilterDifference(TransformedImage a, TransformedImage b) {
+ this.a = a;
+ this.b = b;
+ }
+
+ @Override
+ public TransformedImage filter() {
+ TransformedImage result = new TransformedImage(a);
+ BufferedImage aa = a.getSourceImage();
+ BufferedImage bb = b.getSourceImage();
+ int w = aa.getWidth();
+ int h = aa.getHeight();
+ if(w != bb.getWidth() || h != bb.getHeight()) {
+ throw new RuntimeException("Images must be the same size.");
+ }
+
+ BufferedImage rr = result.getSourceImage();
+
+ for (int y = 0; y < h; ++y) {
+ for (int x = 0; x < w; ++x) {
+ ColorRGB diff = new ColorRGB(aa.getRGB(x, y));
+ ColorRGB other = new ColorRGB(bb.getRGB(x, y));
+ diff.red = modify(diff.red , other.red );
+ diff.green = modify(diff.green, other.green);
+ diff.blue = modify(diff.blue , other.blue );
+ rr.setRGB(x, y, diff.toInt());
+ }
+ }
+
+ return result;
+ }
+
+ private int modify(int a,int b) {
+ double v = Math.abs(a-b);
+ return (int)Math.max(0,Math.min(255, v));
+ }
+}
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_DitherFloydSteinberg.java b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterDitherFloydSteinberg.java
similarity index 88%
rename from src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_DitherFloydSteinberg.java
rename to src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterDitherFloydSteinberg.java
index 281cef805..aa13337cc 100644
--- a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_DitherFloydSteinberg.java
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterDitherFloydSteinberg.java
@@ -14,16 +14,20 @@
* @author Dan
* See http://en.literateprograms.org/Floyd-Steinberg_dithering_%28C%29 and http://www.home.unix-ag.org/simon/gimp/fsdither.c
*/
-public class Filter_DitherFloydSteinberg extends ImageFilter {
+public class FilterDitherFloydSteinberg extends ImageFilter {
private long tone;
+ private final TransformedImage img;
+ public FilterDitherFloydSteinberg(TransformedImage img) {
+ super();
+ this.img = img;
+ }
private int quantizeColor(int original) {
int i = (int) Math.min(Math.max(original, 0), 255);
return (i > tone) ? 255 : 0;
}
-
private void ditherDirection(TransformedImage img, BufferedImage after, int y, int[] error, int[] nexterror, int direction) {
int w = img.getSourceImage().getWidth();
int oldPixel, newPixel, quant_error;
@@ -64,8 +68,8 @@ private void ditherDirection(TransformedImage img, BufferedImage after, int y, i
}
}
-
- public TransformedImage filter(TransformedImage img) {
+ @Override
+ public TransformedImage filter() {
int y, x;
int h = img.getSourceImage().getHeight();
int w = img.getSourceImage().getWidth();
@@ -104,9 +108,9 @@ public TransformedImage filter(TransformedImage img) {
}
public static void main(String[] args) throws IOException {
- TransformedImage src = new TransformedImage( ImageIO.read(new FileInputStream("src/test/resources/Lenna.png")) );
- Filter_DitherFloydSteinberg f = new Filter_DitherFloydSteinberg();
- TransformedImage dest = f.filter(src);
+ TransformedImage src = new TransformedImage( ImageIO.read(new FileInputStream("src/test/resources/mandrill.png")) );
+ FilterDitherFloydSteinberg f = new FilterDitherFloydSteinberg(src);
+ TransformedImage dest = f.filter();
ResizableImagePanel.showImage(dest.getSourceImage(), "Filter_DitherFloydSteinberg" );
}
}
\ No newline at end of file
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_DitherFloydSteinbergColor.java b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterDitherFloydSteinbergColor.java
similarity index 86%
rename from src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_DitherFloydSteinbergColor.java
rename to src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterDitherFloydSteinbergColor.java
index 7bcabef3d..a47f5764c 100644
--- a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_DitherFloydSteinbergColor.java
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterDitherFloydSteinbergColor.java
@@ -16,10 +16,13 @@
*
* @author Dan Royer
*/
-public class Filter_DitherFloydSteinbergColor extends ImageFilter {
+public class FilterDitherFloydSteinbergColor extends ImageFilter {
public final ColorRGB[] palette;
+ private final TransformedImage img;
- public Filter_DitherFloydSteinbergColor() {
+ public FilterDitherFloydSteinbergColor(TransformedImage img) {
+ super();
+ this.img = img;
palette = new ColorRGB[]{
new ColorRGB(0, 0, 0),
new ColorRGB(0, 0, 255),
@@ -32,7 +35,8 @@ public Filter_DitherFloydSteinbergColor() {
};
}
- public TransformedImage filter(TransformedImage img) {
+ @Override
+ public TransformedImage filter() {
BufferedImage src = img.getSourceImage();
int h = src.getHeight();
int w = src.getWidth();
@@ -81,9 +85,9 @@ private ColorRGB findClosestPaletteColor(ColorRGB c) {
}
public static void main(String[] args) throws IOException {
- TransformedImage src = new TransformedImage(ImageIO.read(new FileInputStream("src/test/resources/Lenna.png")));
- Filter_DitherFloydSteinbergColor f = new Filter_DitherFloydSteinbergColor();
- TransformedImage dest = f.filter(src);
+ TransformedImage src = new TransformedImage(ImageIO.read(new FileInputStream("src/test/resources/mandrill.png")));
+ FilterDitherFloydSteinbergColor f = new FilterDitherFloydSteinbergColor(src);
+ TransformedImage dest = f.filter();
ResizableImagePanel.showImage(dest.getSourceImage(), "Filter_DitherFloydSteinbergColor");
}
}
\ No newline at end of file
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterExtendedDifferenceOfGaussians.java b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterExtendedDifferenceOfGaussians.java
new file mode 100644
index 000000000..7e7166b02
--- /dev/null
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterExtendedDifferenceOfGaussians.java
@@ -0,0 +1,81 @@
+package com.marginallyclever.makelangelo.makeart.imagefilter;
+
+import com.marginallyclever.convenience.ColorRGB;
+import com.marginallyclever.convenience.ResizableImagePanel;
+import com.marginallyclever.makelangelo.makeart.TransformedImage;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+/**
+ * Calculate the extended difference of gaussians.
+ * (1+tau)* G(sigma) - tau * G(k*sigma)
+ * where G is a gaussian blur.
+ * @author Dan Royer
+ * @since 7.46.0
+ */
+public class FilterExtendedDifferenceOfGaussians extends ImageFilter {
+ private final TransformedImage imgA, imgB;
+ private final double phi;
+
+ /**
+ *
+ * @param imgA an image blurred with a small sigma
+ * @param imgB an image blurred with a larger sigma
+ * @param phi a value between 0 and 1
+ */
+ public FilterExtendedDifferenceOfGaussians(TransformedImage imgA, TransformedImage imgB, double phi) {
+ this.imgA = imgA;
+ this.imgB = imgB;
+ this.phi = phi;
+ }
+
+ @Override
+ public TransformedImage filter() {
+ BufferedImage aa = imgA.getSourceImage();
+ BufferedImage bb = imgB.getSourceImage();
+ int w = aa.getWidth();
+ int h = aa.getHeight();
+ if(w != bb.getWidth() || h != bb.getHeight()) {
+ throw new RuntimeException("Images must be the same size.");
+ }
+
+ TransformedImage result = new TransformedImage(imgA);
+ BufferedImage rr = result.getSourceImage();
+
+ ColorRGB diff = new ColorRGB();
+ for (int y = 0; y < h; ++y) {
+ for (int x = 0; x < w; ++x) {
+ ColorRGB colorA = new ColorRGB(aa.getRGB(x, y));
+ ColorRGB colorB = new ColorRGB(bb.getRGB(x, y));
+ diff.red = modify(colorA.red, colorB.red );
+ diff.green = modify(colorA.green, colorB.green);
+ diff.blue = modify(colorA.blue, colorB.blue );
+ rr.setRGB(x, y, diff.toInt());
+ }
+ }
+
+ return result;
+ }
+
+ int modify(double a,double b) {
+ a/=255.0;
+ b/=255.0;
+ double v = (1.0+phi)*a - phi*b;
+ v*=255.0;
+ return (int)Math.max(0,Math.min(255, v));
+ }
+
+ public static void main(String[] args) throws IOException {
+ TransformedImage src = new TransformedImage(ImageIO.read(new FileInputStream("src/test/resources/mandrill.png")));
+ FilterGaussianBlur a = new FilterGaussianBlur(src,4);
+ FilterGaussianBlur b = new FilterGaussianBlur(src,6);
+ TransformedImage a2 = a.filter();
+ TransformedImage b2 = b.filter();
+ FilterExtendedDifferenceOfGaussians f = new FilterExtendedDifferenceOfGaussians(a2,b2,50.0);
+ TransformedImage dest = f.filter();
+ ResizableImagePanel.showImage(dest.getSourceImage(), "Filter_ExtendedDifferenceOfGaussians");
+ }
+}
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_GaussianBlur.java b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterGaussianBlur.java
similarity index 83%
rename from src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_GaussianBlur.java
rename to src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterGaussianBlur.java
index 7e27d6ea0..0443c9020 100644
--- a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_GaussianBlur.java
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterGaussianBlur.java
@@ -2,8 +2,6 @@
import com.marginallyclever.convenience.ResizableImagePanel;
import com.marginallyclever.makelangelo.makeart.TransformedImage;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import javax.imageio.ImageIO;
import javax.swing.*;
@@ -20,19 +18,21 @@
*
* @author Dan
*/
-public class Filter_GaussianBlur extends ImageFilter {
- private static final Logger logger = LoggerFactory.getLogger(Filter_GaussianBlur.class);
- int radius = 1;
+public class FilterGaussianBlur extends ImageFilter {
+ private final TransformedImage img;
+ private final int radius;
- public Filter_GaussianBlur(int radius) {
+ public FilterGaussianBlur(TransformedImage img, int radius) {
+ super();
+ this.img = img;
assert (radius >= 1);
this.radius = radius;
}
@Override
- public TransformedImage filter(TransformedImage img) {
- BufferedImage src = img.getSourceImage();
+ public TransformedImage filter() {
TransformedImage after = new TransformedImage(img);
+ BufferedImage src = img.getSourceImage();
BufferedImage dest = after.getSourceImage();
BufferedImage inter = new BufferedImage(src.getWidth(), src.getHeight(), src.getType());
getGaussianBlurFilter(true).filter(src,inter);
@@ -45,6 +45,7 @@ public ConvolveOp getGaussianBlurFilter(boolean horizontal) {
int size = radius * 2 + 1;
float[] data = new float[size];
+ // sigma here is the lowercase σ, not the uppercase Σ.
float sigma = radius / 3.0f;
float twoSigmaSquare = 2.0f * sigma * sigma;
float sigmaRoot = (float) Math.sqrt(twoSigmaSquare * Math.PI);
@@ -71,7 +72,7 @@ public ConvolveOp getGaussianBlurFilter(boolean horizontal) {
}
public static void main(String[] args) throws IOException {
- TransformedImage src = new TransformedImage( ImageIO.read(new FileInputStream("src/test/resources/Lenna.png")) );
+ TransformedImage src = new TransformedImage( ImageIO.read(new FileInputStream("src/test/resources/mandrill.png")) );
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
@@ -80,8 +81,8 @@ public static void main(String[] args) throws IOException {
panel.add(slider,BorderLayout.NORTH);
slider.addChangeListener(e->{
- Filter_GaussianBlur f = new Filter_GaussianBlur(slider.getValue());
- TransformedImage dest = f.filter(src);
+ FilterGaussianBlur f = new FilterGaussianBlur(src,slider.getValue());
+ TransformedImage dest = f.filter();
ResizableImagePanel rip = new ResizableImagePanel(dest.getSourceImage());
BorderLayout layout = (BorderLayout)panel.getLayout();
Component c = layout.getLayoutComponent(BorderLayout.CENTER);
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_Invert.java b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterInvert.java
similarity index 74%
rename from src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_Invert.java
rename to src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterInvert.java
index aa839f9d1..ab3640b84 100644
--- a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_Invert.java
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterInvert.java
@@ -15,8 +15,15 @@
*
* @author Dan
*/
-public class Filter_Invert extends ImageFilter {
- public TransformedImage filter(TransformedImage img) {
+public class FilterInvert extends ImageFilter {
+ private final TransformedImage img;
+
+ public FilterInvert(TransformedImage img) {
+ super();
+ this.img = img;
+ }
+
+ public TransformedImage filter() {
BufferedImage src = img.getSourceImage();
int h = src.getHeight();
int w = src.getWidth();
@@ -39,9 +46,8 @@ public TransformedImage filter(TransformedImage img) {
}
public static void main(String[] args) throws IOException {
- TransformedImage src = new TransformedImage( ImageIO.read(new FileInputStream("src/test/resources/Lenna.png")) );
- Filter_Invert f = new Filter_Invert();
- TransformedImage dest = f.filter(src);
- ResizableImagePanel.showImage(dest.getSourceImage(), "Filter_Invert" );
+ TransformedImage src = new TransformedImage( ImageIO.read(new FileInputStream("src/test/resources/mandrill.png")) );
+ FilterInvert f = new FilterInvert(src);
+ ResizableImagePanel.showImage(f.filter().getSourceImage(), "Filter_Invert" );
}
}
\ No newline at end of file
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_JumpFlood.java b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterJumpFlood.java
similarity index 88%
rename from src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_JumpFlood.java
rename to src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterJumpFlood.java
index 26be4394b..67351b031 100644
--- a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_JumpFlood.java
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterJumpFlood.java
@@ -15,18 +15,21 @@
* Converts an image to N shades of grey.
* @author Dan Royer
*/
-public class Filter_JumpFlood extends ImageFilter {
- private static final Logger logger = LoggerFactory.getLogger(Filter_JumpFlood.class);
+public class FilterJumpFlood extends ImageFilter {
+ private static final Logger logger = LoggerFactory.getLogger(FilterJumpFlood.class);
// Initialize the list of points
private final List points = new ArrayList<>();
private int stepSize;
private int scale;
+ private final TransformedImage img;
- public Filter_JumpFlood() {
+ public FilterJumpFlood(TransformedImage img) {
super();
+ this.img = img;
}
- public TransformedImage filter(TransformedImage img) {
+ @Override
+ public TransformedImage filter() {
BufferedImage src = img.getSourceImage();
TransformedImage after = new TransformedImage(img);
BufferedImage dest = after.getSourceImage();
@@ -89,11 +92,11 @@ public static void main(String[] args) throws IOException {
}
TransformedImage src = new TransformedImage( image );
/*/
- TransformedImage src = new TransformedImage( ImageIO.read(new FileInputStream("src/test/resources/Lenna.png")) );
+ TransformedImage src = new TransformedImage( ImageIO.read(new FileInputStream("src/test/resources/mandrill.png")) );
//*/
- Filter_JumpFlood f = new Filter_JumpFlood();
- TransformedImage dest = f.filter(src);
+ FilterJumpFlood f = new FilterJumpFlood(src);
+ TransformedImage dest = f.filter();
ResizableImagePanel.showImage(dest.getSourceImage(), "Filter_JumpFlood" );
}
}
\ No newline at end of file
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_Greyscale.java b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterLevels.java
similarity index 80%
rename from src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_Greyscale.java
rename to src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterLevels.java
index dcddb7a84..2f0460283 100644
--- a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_Greyscale.java
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterLevels.java
@@ -11,19 +11,23 @@
import java.io.IOException;
/**
- * Converts an image to N shades of grey.
+ * Converts an image to N levels.
* @author Dan Royer
*/
-public class Filter_Greyscale extends ImageFilter {
- private static final Logger logger = LoggerFactory.getLogger(Filter_Greyscale.class);
- private double levels = 2;
- private int mode = 1;
-
- public Filter_Greyscale(int _levels) {
- levels = (double) _levels;
+public class FilterLevels extends ImageFilter {
+ private static final Logger logger = LoggerFactory.getLogger(FilterLevels.class);
+ private final TransformedImage img;
+ private final double levels;
+ private final int mode = 1;
+
+ public FilterLevels(TransformedImage img, int levels) {
+ super();
+ this.img = img;
+ this.levels = levels;
}
- public TransformedImage filter(TransformedImage img) {
+ @Override
+ public TransformedImage filter() {
return switch (mode) {
case 0 -> filterLevels(img);
case 1 -> filterTone(img);
@@ -54,11 +58,6 @@ protected TransformedImage filterLevels(TransformedImage img) {
if (levels != 0)
ilevels = 1.0 / levels;
- // logger.debug("min_intensity="+min_intensity);
- // logger.debug("max_intensity="+max_intensity);
- // logger.debug("levels="+levels);
- // logger.debug("inverse="+ilevels);
-
double pixel;
TransformedImage after = new TransformedImage(img);
@@ -67,11 +66,9 @@ protected TransformedImage filterLevels(TransformedImage img) {
for (y = 0; y < h; ++y) {
for (x = 0; x < w; ++x) {
pixel = decode32bit(bi.getRGB(x, y));
-
double a = (pixel - min_intensity) / intensity_range;
double c = a * levels * ilevels;
int b = (int) Math.max(Math.min(c * 255.0, 255), 0);
- // if(b==255) logger.debug(x+"\t"+y+"\t"+i+"\t"+b);
afterBI.setRGB(x, y, ImageFilter.encode32bit(b));
}
}
@@ -107,8 +104,8 @@ public TransformedImage filterTone(TransformedImage img) {
for (y = 0; y < h; ++y) {
for (x = 0; x < w; ++x) {
double pixel = decode32bit(bi.getRGB(x, y));
- double v2 = sRGBtoLinear(pixel);
- //double v2 = toneControl(pixel);
+ //double v2 = sRGBtoLinear(pixel);
+ double v2 = toneControl(pixel);
int rgb = (int) Math.min(255, Math.max(0, v2));
afterBI.setRGB(x, y, ImageFilter.encode32bit(rgb));
}
@@ -136,9 +133,8 @@ public TransformedImage filterSimple(TransformedImage img) {
}
public static void main(String[] args) throws IOException {
- TransformedImage src = new TransformedImage( ImageIO.read(new FileInputStream("src/test/resources/Lenna.png")) );
- Filter_Greyscale f = new Filter_Greyscale(255);
- TransformedImage dest = f.filter(src);
- ResizableImagePanel.showImage(dest.getSourceImage(), "Filter_Greyscale" );
+ TransformedImage src = new TransformedImage( ImageIO.read(new FileInputStream("src/test/resources/mandrill.png")) );
+ FilterLevels f = new FilterLevels(src,255);
+ ResizableImagePanel.showImage(f.filter().getSourceImage(), "Filter_Greyscale" );
}
}
\ No newline at end of file
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterScale.java b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterScale.java
new file mode 100644
index 000000000..e3eaec989
--- /dev/null
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterScale.java
@@ -0,0 +1,43 @@
+package com.marginallyclever.makelangelo.makeart.imagefilter;
+
+import com.marginallyclever.convenience.ColorRGB;
+import com.marginallyclever.makelangelo.makeart.TransformedImage;
+
+import java.awt.image.BufferedImage;
+
+/**
+ * Scale every pixel in the image by a value.
+ * @author Dan Royer
+ * @since 7.46.0
+ */
+public class FilterScale extends ImageFilter {
+ private final TransformedImage a;
+ private final double scale;
+
+ public FilterScale(TransformedImage a, double scale) {
+ this.a = a;
+ this.scale = scale;
+ }
+
+ @Override
+ public TransformedImage filter() {
+ TransformedImage result = new TransformedImage(a);
+ BufferedImage aa = a.getSourceImage();
+ int w = aa.getWidth();
+ int h = aa.getHeight();
+
+ BufferedImage rr = result.getSourceImage();
+
+ for (int y = 0; y < h; ++y) {
+ for (int x = 0; x < w; ++x) {
+ ColorRGB diff = new ColorRGB(aa.getRGB(x, y));
+ diff.red = (int)Math.max(0,Math.min(255,diff.red * scale));
+ diff.green = (int)Math.max(0,Math.min(255,diff.green * scale));
+ diff.blue = (int)Math.max(0,Math.min(255,diff.blue * scale));
+ rr.setRGB(x, y, diff.toInt());
+ }
+ }
+
+ return result;
+ }
+}
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterSubtract.java b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterSubtract.java
new file mode 100644
index 000000000..ca2719681
--- /dev/null
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterSubtract.java
@@ -0,0 +1,52 @@
+package com.marginallyclever.makelangelo.makeart.imagefilter;
+
+import com.marginallyclever.convenience.ColorRGB;
+import com.marginallyclever.makelangelo.makeart.TransformedImage;
+
+import java.awt.image.BufferedImage;
+
+/**
+ * Calculate a-b for every pixel.
+ * @author Dan Royer
+ * @since 7.46.0
+ */
+public class FilterSubtract extends ImageFilter {
+ private final TransformedImage a,b;
+
+ public FilterSubtract(TransformedImage a, TransformedImage b) {
+ this.a = a;
+ this.b = b;
+ }
+
+ @Override
+ public TransformedImage filter() {
+ TransformedImage result = new TransformedImage(a);
+ BufferedImage aa = a.getSourceImage();
+ BufferedImage bb = b.getSourceImage();
+ int w = aa.getWidth();
+ int h = aa.getHeight();
+ if(w != bb.getWidth() || h != bb.getHeight()) {
+ throw new RuntimeException("Images must be the same size.");
+ }
+
+ BufferedImage rr = result.getSourceImage();
+
+ for (int y = 0; y < h; ++y) {
+ for (int x = 0; x < w; ++x) {
+ ColorRGB diff = new ColorRGB(aa.getRGB(x, y));
+ ColorRGB other = new ColorRGB(bb.getRGB(x, y));
+ diff.red = modify(diff.red , other.red );
+ diff.green = modify(diff.green, other.green);
+ diff.blue = modify(diff.blue , other.blue );
+ rr.setRGB(x, y, diff.toInt());
+ }
+ }
+
+ return result;
+ }
+
+ private int modify(int a,int b) {
+ double v = a-b;
+ return (int)Math.max(0,Math.min(255, v));
+ }
+}
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterThreshold.java b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterThreshold.java
new file mode 100644
index 000000000..c7a64a65b
--- /dev/null
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterThreshold.java
@@ -0,0 +1,47 @@
+package com.marginallyclever.makelangelo.makeart.imagefilter;
+
+import com.marginallyclever.convenience.ColorRGB;
+import com.marginallyclever.makelangelo.makeart.TransformedImage;
+
+import java.awt.image.BufferedImage;
+
+/**
+ * Any pixel above the threshold is made white. Everything else is made black.
+ * @author Dan Royer
+ * @since 7.46.0
+ */
+public class FilterThreshold extends ImageFilter {
+ private final TransformedImage a;
+ private final int threshold;
+
+ public FilterThreshold(TransformedImage a, int threshold) {
+ this.a = a;
+ this.threshold = threshold;
+ }
+
+ @Override
+ public TransformedImage filter() {
+ TransformedImage result = new TransformedImage(a);
+ int w = a.getSourceImage().getWidth();
+ int h = a.getSourceImage().getHeight();
+
+ BufferedImage aa = a.getSourceImage();
+ BufferedImage rr = result.getSourceImage();
+
+ for (int y = 0; y < h; ++y) {
+ for (int x = 0; x < w; ++x) {
+ ColorRGB diff = new ColorRGB(aa.getRGB(x, y));
+ diff.red = modify(diff.red );
+ diff.green = modify(diff.green);
+ diff.blue = modify(diff.blue );
+ rr.setRGB(x, y, diff.toInt());
+ }
+ }
+
+ return result;
+ }
+
+ int modify(int input) {
+ return input >= threshold ? 255 : 0;
+ }
+}
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterThresholdFancy.java b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterThresholdFancy.java
new file mode 100644
index 000000000..7b6b14375
--- /dev/null
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterThresholdFancy.java
@@ -0,0 +1,66 @@
+package com.marginallyclever.makelangelo.makeart.imagefilter;
+
+import com.marginallyclever.convenience.ColorRGB;
+import com.marginallyclever.makelangelo.makeart.TransformedImage;
+
+import java.awt.image.BufferedImage;
+
+/**
+ * For any pixel u 0...1,
+ *
+ * - if u >= e, then v = 1
+ * - if u < e, then v = 1 + tanh(phi*(u-e))
+ *
+ * @author Dan Royer
+ * @since 7.46.0
+ */
+public class FilterThresholdFancy extends ImageFilter {
+ private final TransformedImage a;
+ private final int threshold;
+ private final double phi;
+
+ /**
+ * @param a source image
+ * @param threshold 0...255
+ * @param phi >=0
+ */
+ public FilterThresholdFancy(TransformedImage a, int threshold, double phi) {
+ this.a = a;
+ this.threshold = threshold;
+ this.phi = phi;
+ }
+
+ @Override
+ public TransformedImage filter() {
+ TransformedImage result = new TransformedImage(a);
+ int w = a.getSourceImage().getWidth();
+ int h = a.getSourceImage().getHeight();
+
+ BufferedImage aa = a.getSourceImage();
+ BufferedImage rr = result.getSourceImage();
+
+ for (int y = 0; y < h; ++y) {
+ for (int x = 0; x < w; ++x) {
+ ColorRGB diff = new ColorRGB(aa.getRGB(x, y));
+ diff.red = modify(diff.red );
+ diff.green = modify(diff.green);
+ diff.blue = modify(diff.blue );
+ rr.setRGB(x, y, diff.toInt());
+ }
+ }
+
+ return result;
+ }
+
+ int modify(double input) {
+ if(input >= threshold) return 255;
+ // diff will always be <0
+ double diff = input - threshold;
+ double diffUnit = diff / 255.0;
+ double temp = phi * diffUnit;
+ // if tau>=0 then tanh will always be -1...0
+ double vUnit = 1.0 + Math.tanh(temp);
+ double v = vUnit * 255.0;
+ return (int)Math.max( 0, Math.min(255,v) );
+ }
+}
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/ImageFilter.java b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/ImageFilter.java
index a0513e2cd..59d0f2594 100644
--- a/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/ImageFilter.java
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/imagefilter/ImageFilter.java
@@ -8,20 +8,20 @@
* Filters modify a {@link TransformedImage}.
* @author dan Royer
*/
-public class ImageFilter {
- public static int red32(int color) {
+public abstract class ImageFilter {
+ protected static int red32(int color) {
return ((color >> 16) & 0xff);
}
- public static int green32(int color) {
+ protected static int green32(int color) {
return ((color >> 8) & 0xff);
}
- public static int blue32(int color) {
+ protected static int blue32(int color) {
return ((color) & 0xff);
}
- public static int alpha32(int color) {
+ protected static int alpha32(int color) {
return ((color >> 24) & 0xff);
}
@@ -45,7 +45,7 @@ public static int decode32bit(int color) {
* @param alpha 0-255
* @return RGB color
*/
- public static int encode32bit(int red,int green,int blue,int alpha) {
+ protected static int encode32bit(int red,int green,int blue,int alpha) {
red &= 0xff;
green &= 0xff;
blue &= 0xff;
@@ -57,7 +57,7 @@ public static int encode32bit(int red,int green,int blue,int alpha) {
* @param greyscale 0-255
* @return RGB fully opaque
*/
- public static int encode32bit(int greyscale) {
+ protected static int encode32bit(int greyscale) {
greyscale &= 0xff;
return encode32bit(greyscale,greyscale,greyscale,0xff);
}
@@ -66,7 +66,7 @@ public static int encode32bit(int greyscale) {
* @param color RGBA
* @return grayscale value
*/
- public static int decodeColor(Color color) {
+ protected static int decodeColor(Color color) {
int r = color.getRed();
int g = color.getGreen();
int b = color.getBlue();
@@ -88,12 +88,10 @@ private static int average(int r, int g, int b, double a) {
return (r2 + g2 + b2) / 3;
}
-
+
/**
- * @param img the java.awt.image.BufferedImage
this filter is using as source material.
+ * Apply this filter and return the result as an image.
* @return the altered image
*/
- public TransformedImage filter(TransformedImage img) {
- return img;
- }
+ abstract public TransformedImage filter();
}
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/io/LoadSVG.java b/src/main/java/com/marginallyclever/makelangelo/makeart/io/LoadSVG.java
index 578515b45..95164319e 100644
--- a/src/main/java/com/marginallyclever/makelangelo/makeart/io/LoadSVG.java
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/io/LoadSVG.java
@@ -19,13 +19,12 @@
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.vecmath.Matrix3d;
import javax.vecmath.Vector3d;
-import java.awt.geom.Rectangle2D;
import java.io.InputStream;
import java.util.List;
/**
* @author Dan Royer
- * See https://www.w3.org/TR/SVG/paths.html
+ * See w3
*/
public class LoadSVG implements TurtleLoader {
private static final Logger logger = LoggerFactory.getLogger(LoadSVG.class);
@@ -164,7 +163,7 @@ private void parseLineElements(NodeList node) throws Exception {
private ColorRGB getStroke(Element element) {
if(element.hasAttribute("style")) {
- String style = element.getAttribute("style").toLowerCase().replace("\s","");
+ String style = element.getAttribute("style").toLowerCase().replace("\\s+","");
if(!style.contains(LABEL_STROKE)) {
// default SVG stroke is "none", which isn't even transparent - it's nothing!
return null;
@@ -175,7 +174,7 @@ private ColorRGB getStroke(Element element) {
}
}
if(element.hasAttribute("stroke")) {
- String strokeStyleName = element.getAttribute("stroke").toLowerCase().replace("\s","");
+ String strokeStyleName = element.getAttribute("stroke").toLowerCase().replace("\\s+","");
return stringToColor(strokeStyleName);
}
return null;
@@ -196,7 +195,7 @@ private ColorRGB stringToColor(String strokeName) {
return new ColorRGB(r,g,b);
}
} else if(strokeName.startsWith("rgb(")) {
- strokeName.substring(4,strokeName.length()-1);
+ strokeName = strokeName.substring(4,strokeName.length()-1);
if(strokeName.contains("%")) {
strokeName = strokeName.replace("%","");
String [] parts = strokeName.split(",");
@@ -220,15 +219,16 @@ private ColorRGB stringToColor(String strokeName) {
/**
* Draw rectangles that may have rounded corners.
* given corners
+ *
* x0 x1 x2 x3
* y0 a b
* y1 c i j d
* y2 e m k f
* y3 g h
+ *
* draw a-b-d-f-h-g-e-c-a.
- *
- * See https://developer.mozilla.org/en-US/docs/Web/SVG/Element/rect
- * @param node
+ * See mozilla
+ * @param node the source of the elements
*/
private void parseRectElements(NodeList node) throws Exception {
int pathNodeCount = node.getLength();
@@ -280,7 +280,7 @@ private void parseRectElements(NodeList node) throws Exception {
/**
*
- * @param turtle
+ * @param turtle the drawing tool
* @param cx center position
* @param cy center position
* @param rx radius on X
@@ -292,7 +292,7 @@ private void arcTurtle(Turtle turtle,double cx,double cy,double rx,double ry,dou
Vector3d v2;
double steps=1;
if(rx>0 && ry>0) {
- double r = rx>ry?rx:ry;
+ double r = Math.max(rx, ry);
double circ = Math.PI*r*2.0; // radius to circumference
steps = Math.ceil(circ/4.0); // 1/4 circumference
steps = Math.max(steps,1);
@@ -403,7 +403,7 @@ private void parsePathElements(NodeList paths) throws Exception {
case SVGPathSeg.PATHSEG_LINETO_ABS -> doLineToAbs(item,m); // L H V
case SVGPathSeg.PATHSEG_LINETO_REL -> doLineToRel(item,m); // l h v
case SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS -> doCubicCurveAbs(item,m); // C c
- case SVGPathSeg.PATHSEG_CLOSEPATH -> doClosePath(m); // Z z
+ case SVGPathSeg.PATHSEG_CLOSEPATH -> doClosePath(); // Z z
default -> throw new Exception("Found unknown SVGPathSeg type "+((SVGItem)item).getValueAsString());
}
}
@@ -469,12 +469,12 @@ private void doMoveToAbs(SVGPathSeg item, Matrix3d m) {
Vector3d p = transform(path.getX(),path.getY(),m);
logger.debug("Move Abs {}", p);
pathPoint.set(p);
- if(isNewPath==true) pathFirstPoint.set(pathPoint);
+ if(isNewPath) pathFirstPoint.set(pathPoint);
myTurtle.jumpTo(p.x,p.y);
isNewPath=false;
}
- private void doClosePath(Matrix3d m) {
+ private void doClosePath() {
logger.debug("Close path");
myTurtle.moveTo(pathFirstPoint.x,pathFirstPoint.y);
isNewPath=true;
@@ -487,24 +487,22 @@ private Vector3d transform(double x, double y, Matrix3d m) {
}
private Matrix3d getMatrixFromElement(Element element) {
+ Matrix3d m = new Matrix3d();
+
if(!(element instanceof SVGGraphicsElement)) {
- Matrix3d m = new Matrix3d();
m.setIdentity();
return m;
}
- Matrix3d m = new Matrix3d();
-
try {
SVGGraphicsElement svgge = (SVGGraphicsElement)element;
-
SVGMatrix svgMatrix = svgge.getCTM();
// [ a c e ]
// [ b d f ]
// [ 0 0 1 ]
- m.m00 = svgMatrix.getA(); m.m10 = svgMatrix.getB(); m.m20 = 0;
- m.m01 = svgMatrix.getC(); m.m11 = svgMatrix.getD(); m.m21 = 0;
- m.m02 = svgMatrix.getE(); m.m12 = svgMatrix.getF(); m.m22 = 1;
+ m.m00 = svgMatrix.getA(); m.m01 = svgMatrix.getC(); m.m02 = svgMatrix.getE();
+ m.m10 = svgMatrix.getB(); m.m11 = svgMatrix.getD(); m.m12 = svgMatrix.getF();
+ m.m20 = 0; m.m21 = 0; m.m22 = 1;
}
catch(Exception e) {
m.setIdentity();
@@ -515,10 +513,8 @@ private Matrix3d getMatrixFromElement(Element element) {
/**
* Enhance the SVG DOM for the given document to provide CSS- and
* SVG-specific DOM interfaces.
- *
- * @param document
- * The document to enhance.
- * @link https://cwiki.apache.org/confluence/display/XMLGRAPHICSBATIK/BootSvgAndCssDom
+ * See apache
+ * @param document The document to enhance.
*/
private void initSVGDOM(Document document) {
UserAgent userAgent = new UserAgentAdapter();
diff --git a/src/main/java/com/marginallyclever/makelangelo/makeart/tools/CenterTurtleToPaperAction.java b/src/main/java/com/marginallyclever/makelangelo/makeart/tools/CenterTurtleToPaperAction.java
new file mode 100644
index 000000000..afe43c1e0
--- /dev/null
+++ b/src/main/java/com/marginallyclever/makelangelo/makeart/tools/CenterTurtleToPaperAction.java
@@ -0,0 +1,31 @@
+package com.marginallyclever.makelangelo.makeart.tools;
+
+import com.marginallyclever.makelangelo.makeart.TurtleModifierAction;
+import com.marginallyclever.makelangelo.turtle.Turtle;
+
+import java.awt.geom.Rectangle2D;
+
+/**
+ * Center the input {@link Turtle} to the origin.
+ * @author Dan Royer
+ */
+public class CenterTurtleToPaperAction extends TurtleModifierAction {
+
+ public CenterTurtleToPaperAction(String name) {
+ super(name);
+ }
+
+ @Override
+ public Turtle run(Turtle turtle) {
+ Rectangle2D.Double turtleBounds = turtle.getBounds(); // image bounds
+
+ double ix = turtleBounds.getCenterX();
+ double iy = turtleBounds.getCenterY();
+
+ // apply
+ Turtle result = new Turtle(turtle);
+ result.translate(-ix,-iy);
+
+ return result;
+ }
+}
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java
index d982b6ebd..e03460b9e 100644
--- a/src/main/java/module-info.java
+++ b/src/main/java/module-info.java
@@ -4,7 +4,7 @@
requires jssc;
requires java.desktop;
requires jogl.all;
- requires logback.core;
+ requires ch.qos.logback.core;
requires org.json;
requires org.apache.commons.io;
requires org.apache.commons.compress;
@@ -28,7 +28,7 @@
opens com.marginallyclever.makelangelo.plotter.plottercontrols;
opens com.marginallyclever.makelangelo.turtle;
- exports com.marginallyclever.convenience.log to logback.core;
+ exports com.marginallyclever.convenience.log to ch.qos.logback.core;
exports com.marginallyclever.makelangelo.donatelloimpl to com.marginallyclever.nodegraphcore;
exports com.marginallyclever.makelangelo.donatelloimpl.nodes to com.marginallyclever.nodegraphcore;
diff --git a/src/main/resources/languages/english.xml b/src/main/resources/languages/english.xml
index 41a790ca7..81b392c3b 100644
--- a/src/main/resources/languages/english.xml
+++ b/src/main/resources/languages/english.xml
@@ -33,8 +33,11 @@
StartAtExactlyDo nothing special
ConfirmQuitQuestionAre you sure you want to quit?
ConfirmQuitTitleExit
+
ConvertImagePaperFillFill entire paper
ConvertImagePaperFitFit image on paper
+ ConvertImagePaperCenterCenter image
+
LoadFilePanel.titleLoad file preview
OKOK
CancelCancel
diff --git a/src/test/java/com/marginallyclever/makelangelo/donatelloimpl/TestNodeGraphMakelangelo.java b/src/test/java/com/marginallyclever/makelangelo/donatelloimpl/TestNodeGraphMakelangelo.java
index 96ab935a3..c03bb4b43 100644
--- a/src/test/java/com/marginallyclever/makelangelo/donatelloimpl/TestNodeGraphMakelangelo.java
+++ b/src/test/java/com/marginallyclever/makelangelo/donatelloimpl/TestNodeGraphMakelangelo.java
@@ -3,9 +3,9 @@
import com.marginallyclever.makelangelo.donatelloimpl.nodes.TurtleDAO4JSON;
import com.marginallyclever.makelangelo.turtle.Turtle;
import com.marginallyclever.nodegraphcore.DAO4JSONFactory;
+import com.marginallyclever.nodegraphcore.DockReceiving;
+import com.marginallyclever.nodegraphcore.Graph;
import com.marginallyclever.nodegraphcore.NodeFactory;
-import com.marginallyclever.nodegraphcore.NodeGraph;
-import com.marginallyclever.nodegraphcore.NodeVariable;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -22,7 +22,7 @@
public class TestNodeGraphMakelangelo {
private static final Logger logger = LoggerFactory.getLogger(TestNodeGraphMakelangelo.class);
- private static NodeGraph model = new NodeGraph();
+ private static Graph model = new Graph();
@BeforeAll
public static void beforeAll() throws Exception {
@@ -47,8 +47,8 @@ public void beforeEach() {
}
private void testNodeVariableToJSONAndBack(Class myClass,T instA,T instB) throws Exception {
- NodeVariable> a = NodeVariable.newInstance(myClass.getSimpleName(),myClass,instA,false,false);
- NodeVariable> b = NodeVariable.newInstance(myClass.getSimpleName(),myClass,instB,false,false);
+ DockReceiving> a = new DockReceiving<>(myClass.getSimpleName(),myClass,instA);
+ DockReceiving> b = new DockReceiving<>(myClass.getSimpleName(),myClass,instB);
b.parseJSON(a.toJSON());
assertEquals(a.toString(),b.toString());
diff --git a/src/test/java/com/marginallyclever/makelangelo/Filter_CMYKTest.java b/src/test/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterCMYKTest.java
similarity index 81%
rename from src/test/java/com/marginallyclever/makelangelo/Filter_CMYKTest.java
rename to src/test/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterCMYKTest.java
index 598b72fa5..43f23b947 100644
--- a/src/test/java/com/marginallyclever/makelangelo/Filter_CMYKTest.java
+++ b/src/test/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterCMYKTest.java
@@ -1,7 +1,6 @@
-package com.marginallyclever.makelangelo;
+package com.marginallyclever.makelangelo.makeart.imagefilter;
import com.marginallyclever.makelangelo.makeart.TransformedImage;
-import com.marginallyclever.makelangelo.makeart.imagefilter.Filter_CMYK;
import com.marginallyclever.util.PreferencesHelper;
import javax.imageio.ImageIO;
@@ -9,7 +8,7 @@
import java.io.FileInputStream;
import java.io.IOException;
-public class Filter_CMYKTest {
+public class FilterCMYKTest {
//@Test
public void testConversion() throws IOException {
PreferencesHelper.start();
@@ -18,8 +17,8 @@ public void testConversion() throws IOException {
File file = new File(PATH_NAME + "." + EXT);
assert (file.isFile());
TransformedImage img = new TransformedImage(ImageIO.read(new FileInputStream(file)));
- Filter_CMYK filter = new Filter_CMYK();
- filter.filter(img);
+ FilterCMYK filter = new FilterCMYK(img);
+ filter.filter();
ImageIO.write(filter.getC().getSourceImage(), EXT, new File(PATH_NAME + "C." + EXT));
ImageIO.write(filter.getM().getSourceImage(), EXT, new File(PATH_NAME + "M." + EXT));
diff --git a/src/test/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_InvertTest.java b/src/test/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterInvertTest.java
similarity index 76%
rename from src/test/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_InvertTest.java
rename to src/test/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterInvertTest.java
index 50d2fb3b0..158b74eef 100644
--- a/src/test/java/com/marginallyclever/makelangelo/makeart/imagefilter/Filter_InvertTest.java
+++ b/src/test/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterInvertTest.java
@@ -9,7 +9,7 @@
import java.io.FileInputStream;
import java.io.IOException;
-public class Filter_InvertTest {
+public class FilterInvertTest {
// pixel-to-pixel comparison
public static void compareBitmaps(BufferedImage a,BufferedImage b) {
int h = a.getHeight();
@@ -25,12 +25,12 @@ public static void compareBitmaps(BufferedImage a,BufferedImage b) {
@Test
public void test() throws IOException {
- TransformedImage src = new TransformedImage( ImageIO.read(new FileInputStream("src/test/resources/Lenna.png")) );
- Filter_Invert f = new Filter_Invert();
- TransformedImage dest = f.filter(src);
- //ImageIO.write(dest.getSourceImage(), "png", new java.io.File("src/test/resources/test_invert.png"));
+ TransformedImage src = new TransformedImage( ImageIO.read(new FileInputStream("src/test/resources/mandrill.png")) );
+ FilterInvert f = new FilterInvert(src);
+ TransformedImage dest = f.filter();
+ //ImageIO.write(dest.getSourceImage(), "png", new java.io.File("src/test/resources/mandrill-inverse.png"));
- TransformedImage compare = new TransformedImage( ImageIO.read(new FileInputStream("src/test/resources/test_invert.png")) );
+ TransformedImage compare = new TransformedImage( ImageIO.read(new FileInputStream("src/test/resources/mandrill-inverse.png")) );
compareBitmaps(compare.getSourceImage(),dest.getSourceImage());
}
}
diff --git a/src/test/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterTresholdFancyTest.java b/src/test/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterTresholdFancyTest.java
new file mode 100644
index 000000000..aa65723c8
--- /dev/null
+++ b/src/test/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterTresholdFancyTest.java
@@ -0,0 +1,23 @@
+package com.marginallyclever.makelangelo.makeart.imagefilter;
+
+import com.marginallyclever.makelangelo.makeart.TransformedImage;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import javax.imageio.ImageIO;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+public class FilterTresholdFancyTest {
+ @Test
+ public void test() throws IOException {
+ TransformedImage src = new TransformedImage( ImageIO.read(new FileInputStream("src/test/resources/chicken.png")) );
+ for(int thresholdValue=1;thresholdValue<255;++thresholdValue) {
+ FilterThresholdFancy threshold = new FilterThresholdFancy(src, thresholdValue, 50.0);
+ for (int i = 0; i < 255; ++i) {
+ if (i >= thresholdValue) Assertions.assertEquals(255, threshold.modify(i));
+ else Assertions.assertTrue(threshold.modify(i) < 255);
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterTresholdTest.java b/src/test/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterTresholdTest.java
new file mode 100644
index 000000000..92de0155a
--- /dev/null
+++ b/src/test/java/com/marginallyclever/makelangelo/makeart/imagefilter/FilterTresholdTest.java
@@ -0,0 +1,20 @@
+package com.marginallyclever.makelangelo.makeart.imagefilter;
+
+import com.marginallyclever.makelangelo.makeart.TransformedImage;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import javax.imageio.ImageIO;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+public class FilterTresholdTest {
+ @Test
+ public void test() throws IOException {
+ TransformedImage src = new TransformedImage( ImageIO.read(new FileInputStream("src/test/resources/chicken.png")) );
+ FilterThreshold threshold = new FilterThreshold(src, 8);
+ for(int i=0;i<255;++i) {
+ Assertions.assertEquals(i<8?0:255,threshold.modify(i));
+ }
+ }
+}
diff --git a/src/test/resources/Lenna.png b/src/test/resources/Lenna.png
deleted file mode 100644
index 59ef68aab..000000000
Binary files a/src/test/resources/Lenna.png and /dev/null differ
diff --git a/src/test/resources/cameraman.jpg b/src/test/resources/cameraman.jpg
new file mode 100644
index 000000000..684c6446a
Binary files /dev/null and b/src/test/resources/cameraman.jpg differ
diff --git a/src/test/resources/chicken.png b/src/test/resources/chicken.png
new file mode 100644
index 000000000..ad716af8f
Binary files /dev/null and b/src/test/resources/chicken.png differ
diff --git a/src/test/resources/mandrill-inverse.png b/src/test/resources/mandrill-inverse.png
new file mode 100644
index 000000000..76b6e75f8
Binary files /dev/null and b/src/test/resources/mandrill-inverse.png differ
diff --git a/src/test/resources/mandrill.png b/src/test/resources/mandrill.png
new file mode 100644
index 000000000..7246a1d2c
Binary files /dev/null and b/src/test/resources/mandrill.png differ
diff --git a/src/test/resources/peppers.jpg b/src/test/resources/peppers.jpg
new file mode 100644
index 000000000..da056bff8
Binary files /dev/null and b/src/test/resources/peppers.jpg differ
diff --git a/src/test/resources/test_invert.png b/src/test/resources/test_invert.png
deleted file mode 100644
index 825746943..000000000
Binary files a/src/test/resources/test_invert.png and /dev/null differ