Skip to content

Commit

Permalink
improved CMYK calculations
Browse files Browse the repository at this point in the history
  • Loading branch information
i-make-robots committed Aug 29, 2024
1 parent d89b977 commit 7b83ffd
Show file tree
Hide file tree
Showing 12 changed files with 327 additions and 175 deletions.
30 changes: 10 additions & 20 deletions WeavingRadonJava/app.layout
Original file line number Diff line number Diff line change
@@ -1,39 +1,29 @@
<?xml version="1.0" ?>
<app-layout>
<layout main-frame="true" location="487,73" size="1208,922" state="0">
<layout main-frame="true" location="647,49" size="821,904" state="0">
<westToolbar>
</westToolbar>
<eastToolbar>
</eastToolbar>
<southToolbar>
</southToolbar>
<split orientation="1" divider-proportion="0.7118786573410034">
<left>
<tabbed>
<selectedTab persistentID="8e50154c-a149-4e95-9db5-4611d24cc0cc">
</selectedTab>
<tab persistentID="8e50154c-a149-4e95-9db5-4611d24cc0cc">
<properties></properties>
</tab>
<tab persistentID="e675ab55-fea9-49a5-a04d-51daa9cd31e6">
<properties></properties>
</tab>
</tabbed>
</left>
<right>
<tabbed>
<selectedTab persistentID="f2308391-8388-4f90-89f0-61caca03eb18">
</selectedTab>
<tab persistentID="f2308391-8388-4f90-89f0-61caca03eb18">
<properties></properties>
</tab>
<tab persistentID="eb1ea92b-fc66-4c54-a5a9-3e4f8203bd5d">
<properties></properties>
</tab>
</tabbed>
</right>
</split>
</layout>
<undocked>
<simple persistentID="eb1ea92b-fc66-4c54-a5a9-3e4f8203bd5d" class-name="com.marginallyclever.weavingradon.ui.DockingPanel">
<properties></properties>
</simple>
<simple persistentID="e675ab55-fea9-49a5-a04d-51daa9cd31e6" class-name="com.marginallyclever.weavingradon.ui.DockingPanel">
<properties></properties>
</simple>
<simple persistentID="f2308391-8388-4f90-89f0-61caca03eb18" class-name="com.marginallyclever.weavingradon.ui.DockingPanel">
<properties></properties>
</simple>
</undocked>
</app-layout>
6 changes: 3 additions & 3 deletions WeavingRadonJava/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.example</groupId>
<artifactId>WeavingRadonJava</artifactId>
<version>1.0-SNAPSHOT</version>
<groupId>com.marginallyclever</groupId>
<artifactId>WeavingRadon</artifactId>
<version>1.0</version>

<properties>
<maven.compiler.source>22</maven.compiler.source>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,6 @@ public class WeavingApp {
private final RadonPanel radonPanel;

private final RadonThreader myThreader;
/*
private final MonochromaticThreader radonThreaderC = new MonochromaticThreader(new Color( 0,255,255, ALPHA));
private final MonochromaticThreader radonThreaderM = new MonochromaticThreader(new Color(255, 0,255, ALPHA));
private final MonochromaticThreader radonThreaderY = new MonochromaticThreader(new Color(255,255, 0, ALPHA));
private final MonochromaticThreader radonThreaderK = new MonochromaticThreader(new Color( 0, 0, 0, ALPHA));
private final MonochromaticThreader radonThreaderW = new MonochromaticThreader(new Color(255,255,255, ALPHA));*/

private final OneLineOnImage singleLine;
private final RadonPanel singleRadon;
Expand All @@ -60,24 +54,17 @@ public WeavingApp() {
frame.setSize(DIAMETER, DIAMETER + TITLEBAR_HEIGHT + DOCKING_TAB_HEIGHT + TOOLBAR_HEIGHT);
//frame.setLocationByPlatform(true);
frame.setLocationRelativeTo(null);

/*/
myThreader = new MonochromaticThreader(new Color(255,255,255, ALPHA));
/*
/*/
MulticolorThreader mct = new MulticolorThreader();
mct.addColor(new Color( 0,255,255, ALPHA));
mct.addColor(new Color(255, 0,255, ALPHA));
mct.addColor(new Color(255,255, 0, ALPHA));
mct.addColor(new Color( 0, 0, 0, ALPHA));
mct.addColor(new Color(255,255,255, ALPHA));
mct.addThreader(new MonochromaticThreader(new Color( 0,255,255, ALPHA)));
mct.addThreader(new MonochromaticThreader(new Color(255, 0,255, ALPHA)));
mct.addThreader(new MonochromaticThreader(new Color(255,255, 0, ALPHA)));
mct.addThreader(new MonochromaticThreader(new Color( 0, 0, 0, ALPHA)));
mct.addThreader(new MonochromaticThreader(new Color(255,255,255, ALPHA)));
myThreader = mct;
*/
/*
mct.addThreader(radonThreaderC);
mct.addThreader(radonThreaderM);
mct.addThreader(radonThreaderY);
mct.addThreader(radonThreaderK);
mct.addThreader(radonThreaderW);
*/
//*/
// create panels
loomPanel = new LoomPanel();
radonPanel = new RadonPanel(loomPanel);
Expand Down Expand Up @@ -184,8 +171,7 @@ public void openFile(ActionEvent actionEvent) {
System.out.println("Open file: "+path);
try {
BufferedImage square = makeSquare(ImageIO.read(new File(path)));
// build the nails and threads
loom.reset();
loom.createNailsAndThreads();
// build a radon transform for every thread, based on the color filter for that threader.
myThreader.setLoomAndImage(loom,square);
myThreader.maskRadonTransformByAllThreads();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,17 @@ public class Loom {
public Loom(int radius,int numNails) {
this.radius = radius;
this.numNails = numNails;
reset();
createNailsAndThreads();
}

public void reset() {
public Loom(Loom other) {
this.radius = other.radius;
this.numNails = other.numNails;
createNailsAndThreads();
}

// Effectively reset the loom.
public void createNailsAndThreads() {
createNails();
createThreads();
}
Expand Down Expand Up @@ -146,4 +153,15 @@ public int getNumNails() {
public int getRadius() {
return radius;
}

public int getNailIndex(Vector2d point) {
Vector2d d = new Vector2d();
for(Vector2d n : nails) {
d.sub(n,point);
if(d.lengthSquared() < 1) {
return nails.indexOf(n);
}
}
return -1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,20 @@ public void setImage(BufferedImage referenceImage) {

/**
* get the next best thread, add it to the loom, and subtract it from the current radon image.
*
* @return
*/
@Override
public void addNextBestThread() {
if (loom.allThreads.isEmpty()) return;
public boolean addNextBestThread() {
if (loom.allThreads.isEmpty()) return false;
ThetaR tr = getBestThetaR();
//System.out.println("best thetaR: " + tr);
System.out.println("best thetaR: " + tr.intensity);
if(tr.intensity==0) return false;
LoomThread bestThread = loom.findThreadClosestToThetaR(tr);
//System.out.println("best thread: " + bestThread);
loom.selectThread(bestThread);
radonTransform.subtractThread(bestThread);
return true;
}

public Color getColor() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,47 +1,76 @@
package com.marginallyclever.weavingradon.core;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;

/**
* A GroupRadonThreader is a RadonThreader that can handle multiple colors.
*/
public class MulticolorThreader extends RadonThreader {
private final List<Color> colors = new ArrayList<>();
private final List<MonochromaticThreader> colors = new ArrayList<>();

public void addColor(Color c) {
colors.add(c);
private static class ThreaderChoice {
public MonochromaticThreader threader;
public ThetaR bestThetaR;
}

@Override
public void setLoomAndImage(Loom loom, BufferedImage image) {
for(MonochromaticThreader threader : colors) {
threader.setLoomAndImage(loom, image);
}
setLoom(loom);
}

@Override
public void maskRadonTransformByAllThreads() {
for(MonochromaticThreader threader : colors) {
threader.maskRadonTransformByAllThreads();
}
}

/**
* get the next best thread, add it to the loom, and subtract it from the current radon image.
*
* @return
*/
@Override
public void addNextBestThread() {
if (loom.allThreads.isEmpty()) return;
ThetaR tr = getBestThetaR();
LoomThread bestThread = loom.findThreadClosestToThetaR(tr);
Color c = radonTransform.getColor(bestThread.thetaR.theta, bestThread.thetaR.r);
bestThread.col = getNearestColor(c);
loom.selectThread(bestThread);
radonTransform.subtractThread(bestThread);
public boolean addNextBestThread() {
if (loom.allThreads.isEmpty()) return false;
ThreaderChoice choice = getBestThreaderChoice();
System.out.println("best thetaR: " + choice.bestThetaR.intensity);// choice.threader.getColor() + " @ "+choice.bestThetaR);
if(choice.bestThetaR.intensity==0) return false;
LoomThread bestThread = loom.findThreadClosestToThetaR(choice.bestThetaR);

choice.threader.getRadonTransform().subtractThread(bestThread);

LoomThread selection = new LoomThread(bestThread);
selection.col = choice.threader.getColor();
loom.selectThread(selection);
return true;
}

private Color getNearestColor(Color c) {
Color nearest = null;
double nearestDistanceSquared = Double.MAX_VALUE;
for(Color color : colors) {
double distanceSquared = /*Math.sqrt*/(
Math.pow(color.getRed() - c.getRed(), 2) +
Math.pow(color.getGreen() - c.getGreen(), 2) +
Math.pow(color.getBlue() - c.getBlue(), 2)
);
if (distanceSquared < nearestDistanceSquared) {
nearest = color;
nearestDistanceSquared = distanceSquared;
/**
* Finds the best thread in the best color to add to the loom.
*/
public ThreaderChoice getBestThreaderChoice() {
ThreaderChoice bestFound = new ThreaderChoice();

double intensity = 0;
for(MonochromaticThreader threader : colors) {
var tr = threader.getBestThetaR();
if(intensity < tr.intensity) {
bestFound.threader = threader;
bestFound.bestThetaR = tr;
intensity = tr.intensity;
}
}
return nearest;
return bestFound;
}

public void addThreader(MonochromaticThreader radonThreader) {
colors.add(radonThreader);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ public abstract class RadonThreader {
protected int radius;
protected RadonTransform radonTransform;

public void setLoomAndImage(Loom loom, BufferedImage image) {
setLoom(loom);
setImage(image);
}

public void setLoom(Loom loom) {
this.loom = loom;
}
Expand All @@ -23,9 +28,15 @@ public void setImage(BufferedImage referenceImage) {

/**
* get the next best thread, add it to the loom, and subtract it from the current radon image.
*
* @return false if there are no more threads to add.
*/
abstract public void addNextBestThread();
abstract public boolean addNextBestThread();

/**
* Mask the current radon image with the current threads.
* This is achieved by generating a mask of all possible threads and then masking the radon image with it.
*/
public void maskRadonTransformByAllThreads() {
System.out.println("filterRadonByThreads multicolor");
var filter = new BufferedImage(radonTransform.getWidth(), radonTransform.getHeight(), BufferedImage.TYPE_INT_ARGB);
Expand All @@ -51,7 +62,7 @@ public ThetaR getBestThetaR() {
// Find the pixel with the maximum intensity in the current radon transform
for(int r=-radius;r<radius;++r) {
for(int theta = 0; theta<180; ++theta) {
int intensity = radonTransform.getIntensity(theta, r);
double intensity = radonTransform.getIntensity(theta, r);
if (intensity > bestFound.intensity) {
bestFound.set(theta,r,intensity);
}
Expand All @@ -63,9 +74,4 @@ public ThetaR getBestThetaR() {
public RadonTransform getRadonTransform() {
return radonTransform;
}

public void setLoomAndImage(Loom loom, BufferedImage image) {
setLoom(loom);
setImage(image);
}
}
Loading

0 comments on commit 7b83ffd

Please sign in to comment.