diff --git a/pom.xml b/pom.xml index 2d29ce54c..184b6b3d4 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.marginallyclever Makelangelo - 7.47.0 + 7.47.1 Makelangelo Makelangelo Software is a Java program that prepares art for CNC plotters. It is especially designed for the Makelangelo Robot. It pairs really well with Marlin-polargraph, the code in the brain of the robot that receives instructions and moves the motors. @@ -20,7 +20,7 @@ It pairs really well with Marlin-polargraph, the code in the brain of the robot GPLv2 - http://opensource.org/licenses/GPL-2.0 + https://opensource.org/licenses/GPL-2.0 repo @@ -353,7 +353,7 @@ It pairs really well with Marlin-polargraph, the code in the brain of the robot commons-io commons-io - 2.8.0 + 2.11.0 @@ -365,12 +365,12 @@ It pairs really well with Marlin-polargraph, the code in the brain of the robot org.jogamp.gluegen gluegen-rt-main - 2.4.0 + 2.5.0-rc-20230523 org.jogamp.jogl jogl-all-main - 2.4.0 + 2.5.0-rc-20230523 @@ -382,13 +382,13 @@ It pairs really well with Marlin-polargraph, the code in the brain of the robot org.apache.httpcomponents httpcore - 4.4.14 + 4.4.15 org.apache.httpcomponents httpmime - 4.5.13 + 4.5.14 @@ -412,19 +412,19 @@ It pairs really well with Marlin-polargraph, the code in the brain of the robot ch.qos.logback logback-classic - 1.2.10 + 1.4.7 org.codehaus.janino janino - 3.1.6 + 3.1.9 org.slf4j slf4j-api - 1.7.32 + 2.0.5 @@ -447,7 +447,7 @@ It pairs really well with Marlin-polargraph, the code in the brain of the robot org.jetbrains annotations - 20.1.0 + 24.0.1 @@ -459,7 +459,7 @@ It pairs really well with Marlin-polargraph, the code in the brain of the robot org.apache.xmlgraphics batik-all - 1.16 + 1.17 org.assertj @@ -477,25 +477,19 @@ It pairs really well with Marlin-polargraph, the code in the brain of the robot me.saharnooby qoi-java - 1.2.0 + 1.2.1 me.saharnooby qoi-java-awt - 1.2.0 - - - - com.github.marginallyclever - nodegraphcore - 1.0.19 + 1.2.1 com.formdev flatlaf - 2.1 + 3.2.1 @@ -503,18 +497,35 @@ It pairs really well with Marlin-polargraph, the code in the brain of the robot org.locationtech.jts jts-core - 1.18.2 + 1.19.0 + + + io.github.classgraph + classgraph + 4.8.161 + + + org.reflections + reflections + 0.10.2 + compile + + + com.github.marginallyclever + nodegraphcore + 1.0.21 + compile UTF-8 3.8.1 - 15 + 17 2.4.0-rc-20200307 true ${minimum.java.version} ${minimum.java.version} ${minimum.java.version} - + \ No newline at end of file diff --git a/src/main/java/com/marginallyclever/makelangelo/MainMenu.java b/src/main/java/com/marginallyclever/makelangelo/MainMenu.java index 8e9923b47..adae885b9 100644 --- a/src/main/java/com/marginallyclever/makelangelo/MainMenu.java +++ b/src/main/java/com/marginallyclever/makelangelo/MainMenu.java @@ -327,10 +327,12 @@ private JMenu createToolsMenu() { logger.debug("PiCaptureAction unavailable."); } - TurtleModifierAction a6 = new ResizeTurtleToPaperAction(app.getPaper(),false,Translator.get("ConvertImagePaperFit")); - TurtleModifierAction a7 = new ResizeTurtleToPaperAction(app.getPaper(),true,Translator.get("ConvertImagePaperFill")); - a6.setSource(app); a6.addModifierListener(app::setTurtle); menu.add(a6); - a7.setSource(app); a7.addModifierListener(app::setTurtle); menu.add(a7); + TurtleModifierAction paperFit = new ResizeTurtleToPaperAction(app.getPaper(),false,Translator.get("ConvertImagePaperFit")); + TurtleModifierAction paperFill = new ResizeTurtleToPaperAction(app.getPaper(),true,Translator.get("ConvertImagePaperFill")); + TurtleModifierAction paperCenter = new CenterTurtleToPaperAction(Translator.get("ConvertImagePaperCenter")); + paperFit.setSource(app); paperFit.addModifierListener(app::setTurtle); menu.add(paperFit); + paperFill.setSource(app); paperFill.addModifierListener(app::setTurtle); menu.add(paperFill); + paperCenter.setSource(app); paperCenter.addModifierListener(app::setTurtle); menu.add(paperCenter); JMenuItem translate = new JMenuItem(Translator.get("Translate")); menu.add(translate); diff --git a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/AddTurtles.java b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/AddTurtles.java index 0718256ea..0ca2dafd0 100644 --- a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/AddTurtles.java +++ b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/AddTurtles.java @@ -1,13 +1,15 @@ 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; public class AddTurtles extends Node { - private final NodeVariable turtleA = NodeVariable.newInstance("A", Turtle.class, new Turtle(),true,false); - private final NodeVariable turtleB = NodeVariable.newInstance("B", Turtle.class, new Turtle(),true,false); - private final NodeVariable output = NodeVariable.newInstance("output", Turtle.class, new Turtle(),false,true); + private final DockReceiving turtleA = new DockReceiving<>("A", Turtle.class, new Turtle()); + private final DockReceiving turtleB = new DockReceiving<>("B", Turtle.class, new Turtle()); + private final DockShipping output = new DockShipping<>("output", Turtle.class, new Turtle()); public AddTurtles() { super("AddTurtles"); @@ -17,12 +19,14 @@ public AddTurtles() { } @Override - public void update() throws Exception { + public void update() { + if(turtleA.hasPacketWaiting()) turtleA.receive(); + if(turtleB.hasPacketWaiting()) turtleB.receive(); + Turtle a = turtleA.getValue(); Turtle b = turtleB.getValue(); Turtle sum = new Turtle(a); sum.add(b); - output.setValue(sum); - cleanAllInputs(); + output.send(new Packet<>(sum)); } } diff --git a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/ColorTurtle.java b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/ColorTurtle.java index edea7ab32..ea2cfe087 100644 --- a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/ColorTurtle.java +++ b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/ColorTurtle.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.MovementType; import com.marginallyclever.makelangelo.turtle.Turtle; import com.marginallyclever.makelangelo.turtle.TurtleMove; +import com.marginallyclever.nodegraphcore.Packet; public class ColorTurtle extends Node { - private final NodeVariable turtle = NodeVariable.newInstance("turtle", Turtle.class,new Turtle(),true,false); - private final NodeVariable red = NodeVariable.newInstance("red",Number.class,0,true,false); - private final NodeVariable green = NodeVariable.newInstance("green",Number.class,0,true,false); - private final NodeVariable blue = NodeVariable.newInstance("blue",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 red = new DockReceiving<>("red",Number.class,0); + private final DockReceiving green = new DockReceiving<>("green",Number.class,0); + private final DockReceiving blue = new DockReceiving<>("blue",Number.class,0); + private final DockShipping output = new DockShipping<>("output", Turtle.class,new Turtle()); public ColorTurtle() { super("ColorTurtle"); @@ -24,11 +26,16 @@ public ColorTurtle() { } @Override - public void update() throws Exception { + public void update() { + if(turtle.hasPacketWaiting()) turtle.receive(); + if(red.hasPacketWaiting()) red.receive(); + if(green.hasPacketWaiting()) green.receive(); + if(blue.hasPacketWaiting()) blue.receive(); + Turtle input = turtle.getValue(); int r = red.getValue().intValue(); - int b = blue.getValue().intValue(); int g = green.getValue().intValue(); + int b = blue.getValue().intValue(); ColorRGB c = new ColorRGB(r, g, b); Turtle moved = new Turtle(); for( TurtleMove m : input.history ) { @@ -38,7 +45,6 @@ public void update() throws Exception { moved.history.add(new TurtleMove(m)); } } - output.setValue(moved); - cleanAllInputs(); + output.send(new Packet<>(moved)); } } diff --git a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/LoadTurtle.java b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/LoadTurtle.java index c4c7af314..c0aabff96 100644 --- a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/LoadTurtle.java +++ b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/LoadTurtle.java @@ -2,17 +2,19 @@ import com.marginallyclever.makelangelo.makeart.io.TurtleFactory; 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.geom.Rectangle2D; public class LoadTurtle extends Node { - private final NodeVariable filename = NodeVariable.newInstance("filename",String.class,null,true,false); - private final NodeVariable contents = NodeVariable.newInstance("contents", Turtle.class, new Turtle(),false,true); - private final NodeVariable w = NodeVariable.newInstance("width", Number.class, 0,false,true); - private final NodeVariable h = NodeVariable.newInstance("height", Number.class, 0,false,true); - private final NodeVariable length = NodeVariable.newInstance("length", Number.class, 0,false,true); + private final DockReceiving filename = new DockReceiving<>("filename",String.class,null); + private final DockShipping contents = new DockShipping<>("contents", Turtle.class, new Turtle()); + private final DockShipping w = new DockShipping<>("width", Number.class, 0); + private final DockShipping h = new DockShipping<>("height", Number.class, 0); + private final DockShipping length = new DockShipping<>("length", Number.class, 0); public LoadTurtle() { @@ -24,13 +26,18 @@ public LoadTurtle() { } @Override - public void update() throws Exception { - Turtle t = TurtleFactory.load(filename.getValue()); - contents.setValue(t); - Rectangle2D r = t.getBounds(); - w.setValue(r.getWidth()); - h.setValue(r.getHeight()); - length.setValue(t.getDrawDistance()); - cleanAllInputs(); + public void update() { + if(filename.hasPacketWaiting()) filename.receive(); + + try { + Turtle t = TurtleFactory.load(filename.getValue()); + contents.send(new Packet<>(t)); + Rectangle2D r = t.getBounds(); + w.send(new Packet<>(r.getWidth())); + h.send(new Packet<>(r.getHeight())); + length.send(new Packet<>(t.getDrawDistance())); + } catch (Exception e) { + e.printStackTrace(); + } } } diff --git a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/PathImageMask.java b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/PathImageMask.java index 4688df1c9..56738df53 100644 --- a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/PathImageMask.java +++ b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/PathImageMask.java @@ -2,8 +2,10 @@ import com.marginallyclever.convenience.*; 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.image.BufferedImage; @@ -14,12 +16,12 @@ * @since 2022-03-08 */ public class PathImageMask extends Node { - private final NodeVariable image = NodeVariable.newInstance("image", BufferedImage.class,new BufferedImage(1,1,BufferedImage.TYPE_INT_RGB),true,false); - private final NodeVariable turtle = NodeVariable.newInstance("turtle", Turtle.class,new Turtle(),true,false); - private final NodeVariable stepSize = NodeVariable.newInstance("stepSize", Number.class, 5,true,false); - private final NodeVariable threshold = NodeVariable.newInstance("threshold", Number.class, 128,true,false); - private final NodeVariable outputAbove = NodeVariable.newInstance("above", Turtle.class,new Turtle(),false,true); - private final NodeVariable outputBelow = NodeVariable.newInstance("below", Turtle.class,new Turtle(),false,true); + private final DockReceiving image = new DockReceiving<>("image", BufferedImage.class,new BufferedImage(1,1,BufferedImage.TYPE_INT_RGB)); + private final DockReceiving turtle = new DockReceiving<>("turtle", Turtle.class,new Turtle()); + private final DockReceiving stepSize = new DockReceiving<>("stepSize", Number.class, 5); + private final DockReceiving threshold = new DockReceiving<>("threshold", Number.class, 128); + private final DockShipping outputAbove = new DockShipping<>("above", Turtle.class,new Turtle()); + private final DockShipping outputBelow = new DockShipping<>("below", Turtle.class,new Turtle()); private final LineCollection listAbove = new LineCollection(); private final LineCollection listBelow = new LineCollection(); @@ -35,7 +37,12 @@ public PathImageMask() { } @Override - public void update() throws Exception { + public void update() { + if(image.hasPacketWaiting()) image.receive(); + if(turtle.hasPacketWaiting()) turtle.receive(); + if(stepSize.hasPacketWaiting()) stepSize.receive(); + if(threshold.hasPacketWaiting()) threshold.receive(); + Turtle myTurtle = turtle.getValue(); if(myTurtle==null || myTurtle.history.isEmpty()) return; @@ -54,13 +61,11 @@ public void update() throws Exception { Turtle resultAbove = new Turtle(); resultAbove.addLineSegments(listAbove); - outputAbove.setValue(resultAbove); + outputAbove.send(new Packet<>(resultAbove)); Turtle resultBelow = new Turtle(); resultBelow.addLineSegments(listBelow); - outputBelow.setValue(resultBelow); - - cleanAllInputs(); + outputBelow.send(new Packet<>(resultBelow)); } /** diff --git a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/PatternOnPath.java b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/PatternOnPath.java index d668dfb5a..ba4c338bf 100644 --- a/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/PatternOnPath.java +++ b/src/main/java/com/marginallyclever/makelangelo/donatelloimpl/nodes/PatternOnPath.java @@ -2,14 +2,16 @@ 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; public class PatternOnPath extends Node { - private final NodeVariable pattern = NodeVariable.newInstance("pattern", Turtle.class, new Turtle(),true,false); - private final NodeVariable path = NodeVariable.newInstance("path", Turtle.class, new Turtle(),true,false); - private final NodeVariable count = NodeVariable.newInstance("count", Number.class, 10,true,false); - private final NodeVariable output = NodeVariable.newInstance("output", Turtle.class, new Turtle(),false,true); + private final DockReceiving pattern = new DockReceiving<>("pattern", Turtle.class, new Turtle()); + private final DockReceiving path = new DockReceiving<>("path", Turtle.class, new Turtle()); + private final DockReceiving count = new DockReceiving<>("count", Number.class, 10); + private final DockShipping 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