added option to scale or not scale replacements

This commit is contained in:
Patrice Matz 2018-08-03 13:50:22 +02:00
parent e7a7ab27f1
commit 6d440f1a90
4 changed files with 124 additions and 112 deletions

View File

@ -2,6 +2,7 @@
<?import javafx.geometry.Insets?> <?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?> <?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.ProgressBar?> <?import javafx.scene.control.ProgressBar?>
<?import javafx.scene.control.TextField?> <?import javafx.scene.control.TextField?>
<?import javafx.scene.image.ImageView?> <?import javafx.scene.image.ImageView?>
@ -10,15 +11,7 @@
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.TextFlow?> <?import javafx.scene.text.TextFlow?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1"> <BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1">
<center>
<HBox fillHeight="false" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="800.0" BorderPane.alignment="CENTER">
<children>
<ImageView id="image1" fitHeight="400.0" fitWidth="400.0" pickOnBounds="true" preserveRatio="true" />
<ImageView id="image2" fitHeight="400.0" fitWidth="400.0" pickOnBounds="true" preserveRatio="true" />
</children>
</HBox>
</center>
<bottom> <bottom>
<HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" prefWidth="800.0" BorderPane.alignment="CENTER"> <HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" prefWidth="800.0" BorderPane.alignment="CENTER">
<children> <children>
@ -38,49 +31,50 @@
</VBox> </VBox>
<VBox prefHeight="200.0" prefWidth="150.0"> <VBox prefHeight="200.0" prefWidth="150.0">
<children> <children>
<TextField id="rows" prefHeight="31.0" prefWidth="87.0" promptText="Rows"> <TextField id="rows" prefHeight="31.0" promptText="Rows">
<VBox.margin> <VBox.margin>
<Insets top="5.0" /> <Insets left="5.0" top="5.0" />
</VBox.margin> </VBox.margin>
</TextField> </TextField>
<TextField id="cols" promptText="Columns"> <TextField id="cols" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="31.0" promptText="Columns">
<VBox.margin> <VBox.margin>
<Insets top="5.0" /> <Insets left="5.0" top="5.0" />
</VBox.margin> </VBox.margin>
</TextField> </TextField>
<CheckBox id="scale" mnemonicParsing="false" text="scale images">
<VBox.margin>
<Insets left="5.0" top="5.0" />
</VBox.margin>
</CheckBox>
</children> </children>
</VBox> </VBox>
<VBox prefHeight="200.0" prefWidth="200.0"> <VBox prefHeight="200.0" prefWidth="200.0">
<children> <children>
<ProgressBar id="progress" minHeight="-Infinity" minWidth="-Infinity" prefHeight="31.0" prefWidth="180.0" progress="0.0"> <ProgressBar id="progress" minHeight="-Infinity" minWidth="-Infinity" prefHeight="31.0" prefWidth="180.0" progress="0.0">
<VBox.margin> <VBox.margin>
<Insets top="5.0" /> <Insets left="5.0" top="5.0" />
</VBox.margin> </VBox.margin>
<padding>
<Insets left="20.0" />
</padding>
</ProgressBar> </ProgressBar>
<Button id="run" mnemonicParsing="false" prefHeight="32.0" prefWidth="160.0" text="Run replacement"> <Button id="run" mnemonicParsing="false" prefHeight="32.0" prefWidth="180.0" text="Run replacement">
<VBox.margin> <VBox.margin>
<Insets left="20.0" top="5.0" /> <Insets left="5.0" top="5.0" />
</VBox.margin> </VBox.margin>
</Button> </Button>
<Button id="save" mnemonicParsing="false" prefHeight="32.0" prefWidth="160.0" text="Save File"> <Button id="save" mnemonicParsing="false" prefHeight="32.0" prefWidth="180.0" text="Save File">
<VBox.margin> <VBox.margin>
<Insets left="20.0" top="5.0" /> <Insets left="5.0" top="5.0" />
</VBox.margin> </VBox.margin>
</Button> </Button>
</children> </children>
</VBox> </VBox>
<TextFlow id="log" prefHeight="200.0" prefWidth="200.0"> <TextFlow id="log" prefHeight="200.0" />
<opaqueInsets>
<Insets />
</opaqueInsets>
<HBox.margin>
<Insets left="85.0" />
</HBox.margin>
</TextFlow>
</children> </children>
</HBox> </HBox>
</bottom> </bottom>
<left>
<ImageView id="image1" fitHeight="400.0" fitWidth="400.0" pickOnBounds="true" preserveRatio="true" BorderPane.alignment="CENTER" />
</left>
<right>
<ImageView id="image2" fitHeight="400.0" fitWidth="400.0" pickOnBounds="true" preserveRatio="true" BorderPane.alignment="CENTER" />
</right>
</BorderPane> </BorderPane>

View File

@ -14,6 +14,7 @@ import javafx.scene.text.TextFlow;
import javafx.stage.DirectoryChooser; import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import javafx.stage.Stage; import javafx.stage.Stage;
import javafx.scene.control.CheckBox;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.awt.*; import java.awt.*;
@ -34,12 +35,11 @@ public class Main extends Application {
private Button save; private Button save;
private ProgressBar progress; private ProgressBar progress;
private TextFlow log; private TextFlow log;
private javafx.scene.control.CheckBox scaleing;
private int rows = 150; private int rows = 150;
private int cols = 150; private int cols = 150;
private boolean scale = false;
private int chunkWidth;
private int chunkHeight;
private File file; private File file;
private ArrayList<String> repPaths; private ArrayList<String> repPaths;
@ -63,83 +63,105 @@ public class Main extends Application {
save = (Button)primaryStage.getScene().lookup("#save"); save = (Button)primaryStage.getScene().lookup("#save");
progress = (ProgressBar)primaryStage.getScene().lookup("#progress"); progress = (ProgressBar)primaryStage.getScene().lookup("#progress");
log = (TextFlow)primaryStage.getScene().lookup("#log"); log = (TextFlow)primaryStage.getScene().lookup("#log");
scaleing = (javafx.scene.control.CheckBox)primaryStage.getScene().lookup("#scale");
hanleEvents(primaryStage); handleEvents(primaryStage);
} }
private void hanleEvents(Stage primaryStage) throws Exception{ private void handleEvents(Stage primaryStage) throws Exception{
picture.setOnAction(e -> { picture.setOnAction(e -> {
FileChooser fileChooser = new FileChooser(); FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Open Image"); fileChooser.setTitle("Open Image");
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("PNG", "*.png"));
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("JPEG", "*.jpeg"));
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("JPG", "*.jpg"));
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("GIF", "*.gif"));
file = fileChooser.showOpenDialog(primaryStage); file = fileChooser.showOpenDialog(primaryStage);
FileInputStream fis; FileInputStream fis;
log.getChildren().add(new Text("loading image\n"));
log.getChildren().add(0, new Text("loading image\n"));
try { try {
fis = new FileInputStream(file); fis = new FileInputStream(file);
try { try {
BufferedImage image = ImageIO.read(fis); BufferedImage image = ImageIO.read(fis);
image1.setImage(SwingFXUtils.toFXImage(image, null)); image1.setImage(SwingFXUtils.toFXImage(image, null));
log.getChildren().add(new Text("loaded image\n")); log.getChildren().add(new Text("loaded image\n"));
} catch (IOException e1) { } catch (Exception e1) {
e1.printStackTrace(); e1.printStackTrace();
log.getChildren().add(0, new Text("Error while loading Image\n"));
} }
} catch (FileNotFoundException e1) { } catch (Exception e1) {
e1.printStackTrace(); e1.printStackTrace();
log.getChildren().add(0, new Text("Error while loading Image\n"));
} }
}); });
replacements.setOnAction(e -> { replacements.setOnAction(e -> {
DirectoryChooser fileChooser = new DirectoryChooser(); DirectoryChooser fileChooser = new DirectoryChooser();
fileChooser.setTitle("Coose replacement images"); fileChooser.setTitle("Choose replacement images");
File tempfile = fileChooser.showDialog(primaryStage); File tempfile = fileChooser.showDialog(primaryStage);
try { try {
repPaths = getAllImages(tempfile); repPaths = getAllImages(tempfile);
} catch (IOException e1) { } catch (Exception e1) {
e1.printStackTrace(); e1.printStackTrace();
log.getChildren().add(0, new Text("Error while loading replacement images\n"));
} }
}); });
run.setOnAction(e -> { run.setOnAction(e -> {
if(file != null && repPaths != null){
if(file == null || repPaths == null){
}
else{
try { try {
cols = Integer.parseInt(col.getText()); if(!col.getText().equals("")){
rows = Integer.parseInt(row.getText()); cols = Integer.parseInt(col.getText());
}
if(!row.getText().equals("")){
rows = Integer.parseInt(row.getText());
}
scale = scaleing.isSelected();
main(); main();
image2.setImage(SwingFXUtils.toFXImage(combined, null)); image2.setImage(SwingFXUtils.toFXImage(combined, null));
} catch (IOException e1) { } catch (Exception e1) {
e1.printStackTrace(); e1.printStackTrace();
log.getChildren().add(0, new Text("Error while calculating new image \n"));
} }
} }
else{
log.getChildren().add(0, new Text("Image or replacement images not selected \n"));
}
}); });
save.setOnAction(e -> { save.setOnAction(e -> {
FileChooser fileChooser = new FileChooser(); FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Save Image"); fileChooser.setTitle("Save Image");
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("PNG", "*.png"));
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("JPEG", "*.jpeg"));
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("JPG", "*.jpg"));
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("GIF", "*.gif"));
File file = fileChooser.showSaveDialog(primaryStage); File file = fileChooser.showSaveDialog(primaryStage);
try { try {
ImageIO.write(combined, "PNG", file); ImageIO.write(combined, "PNG", file);
} catch (IOException e1) { } catch (Exception e1) {
e1.printStackTrace(); e1.printStackTrace();
log.getChildren().add(0, new Text("Error while saving \n"));
} }
}); });
} }
public void main() throws IOException { public void main() throws Exception {
FileInputStream fis = new FileInputStream(file); FileInputStream fis = new FileInputStream(file);
BufferedImage image = ImageIO.read(fis); //reading the image file BufferedImage image = ImageIO.read(fis); //reading the image file
chunkWidth = image.getWidth() / cols; // determines the chunk width and height int chunkWidth = image.getWidth() / cols;
chunkHeight = image.getHeight() / rows; int chunkHeight = image.getHeight() / rows;
int count = 0; int count = 0;
int repCount = repPaths.size(); int repCount = repPaths.size();
@ -164,8 +186,8 @@ public class Main extends Application {
chunks[count-1].average(); chunks[count-1].average();
} }
} }
log.getChildren().add(new Text("splitting done \n")); log.getChildren().add(0, new Text("splitting done \n"));
//System.out.println("splitting done");
//load replacement images into array //load replacement images into array
for (int i = 0; i < repCount; i++) { for (int i = 0; i < repCount; i++) {
// read file from path // read file from path
@ -175,21 +197,30 @@ public class Main extends Application {
// scale loaded image to fit chunk // scale loaded image to fit chunk
BufferedImage img = ImageIO.read(tempfis); BufferedImage img = ImageIO.read(tempfis);
Image tmp = img.getScaledInstance(chunkWidth, chunkHeight, Image.SCALE_SMOOTH);
BufferedImage dimg = new BufferedImage(chunkWidth, chunkHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = dimg.createGraphics(); if(scale){
g2d.drawImage(tmp, 0, 0, null); Image tmp = img.getSubimage(0,0,chunkWidth,chunkHeight);
g2d.dispose(); BufferedImage dimg = new BufferedImage(chunkWidth, chunkHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = dimg.createGraphics();
g2d.drawImage(tmp, 0, 0, null);
g2d.dispose();
// fill array of chunks with read images
replacements[i] = new chunk(dimg);
}
else{
// fill array of chunks with read images
replacements[i] = new chunk(img);
}
log.getChildren().add(0, new Text(Integer.toString((i*100)/(repCount)) + "\n"));
// fill array of chunks with read images
replacements[i] = new chunk(dimg);
log.getChildren().add(new Text(Integer.toString((i*100)/(repCount)) + "\n"));
//System.out.println((i*100)/(repCount));
progress.setProgress((i*100)/(repCount)); progress.setProgress((i*100)/(repCount));
} }
log.getChildren().add(new Text("images loaded \n")); log.getChildren().add(0, new Text("images loaded \n"));
//System.out.println("images loaded");
//for each chunk, calculate the euclidean distance to every possible replacement //for each chunk, calculate the euclidean distance to every possible replacement
for (int i = 0; i < cols*rows; i++) { for (int i = 0; i < cols*rows; i++) {
@ -197,21 +228,14 @@ public class Main extends Application {
int minEuclid; int minEuclid;
for (int j = 0; j < repCount; j++) { for (int j = 0; j < repCount; j++) {
distances[j] = replacements[j].euclideanDistance(chunks[i].getAverage()); distances[j] = chunks[i].euclideanDistance(replacements[j].getAverage());
//int[] a = replacements[j].getAverage();
//int[] b = chunks[i].getAverage();
//System.out.println( a[0]+ " " + a[1]+ " " +a[2]+ " " + b[0]+ " " + b[1]+ " " +b[2] + " " + replacements[j].euclideanDistance(chunks[i].getAverage()));
} }
minEuclid = getMinValue(distances); minEuclid = getIndexofLowest(distances);
g.drawImage(replacements[minEuclid].getImg(), ((i%cols)*chunkWidth), ((i/cols)*chunkHeight), null); g.drawImage(replacements[minEuclid].getImg(), ((i%cols)* chunkWidth), ((i/cols)* chunkHeight), null);
} }
log.getChildren().add(new Text("replacement done \n")); log.getChildren().add(0, new Text("replacement done \n"));
//System.out.println("done");
} }
/** /**
@ -219,9 +243,9 @@ public class Main extends Application {
* Source: http://www.java2s.com/Code/Java/2D-Graphics-GUI/Returnsalljpgimagesfromadirectoryinanarray.htm * Source: http://www.java2s.com/Code/Java/2D-Graphics-GUI/Returnsalljpgimagesfromadirectoryinanarray.htm
* @param directory the directory to start with * @param directory the directory to start with
* @return an ArrayList<String> containing all the file paths or nul if none are found.. * @return an ArrayList<String> containing all the file paths or nul if none are found..
* @throws IOException * @throws Exception
*/ */
private static ArrayList<String> getAllImages(File directory) throws IOException { private static ArrayList<String> getAllImages(File directory) throws Exception {
ArrayList<String> resultList = new ArrayList<String>(256); ArrayList<String> resultList = new ArrayList<String>(256);
File[] f = directory.listFiles(); File[] f = directory.listFiles();
for (File file : f) { for (File file : f) {
@ -239,7 +263,7 @@ public class Main extends Application {
* @param numbers array with float values * @param numbers array with float values
* @return int index of smallest value * @return int index of smallest value
*/ */
private static int getMinValue(float[] numbers){ private static int getIndexofLowest(float[] numbers){
float minValue = numbers[0]; float minValue = numbers[0];
int index = 0; int index = 0;
for(int i=1;i<numbers.length;i++){ for(int i=1;i<numbers.length;i++){
@ -248,7 +272,7 @@ public class Main extends Application {
index = i; index = i;
} }
} }
//System.out.println(minValue);
return index; return index;
} }
} }

View File

@ -13,7 +13,6 @@ public class chunk {
chunk(BufferedImage Img){ chunk(BufferedImage Img){
this.img = Img; this.img = Img;
this.average = this.average(); this.average = this.average();
} }
@ -68,8 +67,8 @@ public class chunk {
temprgb[1] = g; temprgb[1] = g;
temprgb[2] = b; temprgb[2] = b;
this.average= temprgb; this.average= temprgb;
//System.out.println(r + " , " + g + " , " + b + " , " + a);
return new int[]{r,g,b,a}; return temprgb;
} }
//TODO: include alpha in calc. //TODO: include alpha in calc.
/** /**
@ -78,6 +77,7 @@ public class chunk {
* @return a Float with the quadratic distance between given rgb vector and rgb vector of this * @return a Float with the quadratic distance between given rgb vector and rgb vector of this
*/ */
public float euclideanDistance(int[] a){ public float euclideanDistance(int[] a){
return ((this.average[0] - a[0])*(this.average[0] - a[0]) + (this.average[1] - a[1])*(this.average[1] - a[1]) + (this.average[2] - a[2])*(this.average[2] - a[2])); return ((this.average[0] - a[0])*(this.average[0] - a[0]) + (this.average[1] - a[1])*(this.average[1] - a[1]) +
(this.average[2] - a[2])*(this.average[2] - a[2]));
} }
} }

View File

@ -2,6 +2,7 @@
<?import javafx.geometry.Insets?> <?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?> <?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.ProgressBar?> <?import javafx.scene.control.ProgressBar?>
<?import javafx.scene.control.TextField?> <?import javafx.scene.control.TextField?>
<?import javafx.scene.image.ImageView?> <?import javafx.scene.image.ImageView?>
@ -10,15 +11,7 @@
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.TextFlow?> <?import javafx.scene.text.TextFlow?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1"> <BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1">
<center>
<HBox fillHeight="false" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="800.0" BorderPane.alignment="CENTER">
<children>
<ImageView id="image1" fitHeight="400.0" fitWidth="400.0" pickOnBounds="true" preserveRatio="true" />
<ImageView id="image2" fitHeight="400.0" fitWidth="400.0" pickOnBounds="true" preserveRatio="true" />
</children>
</HBox>
</center>
<bottom> <bottom>
<HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" prefWidth="800.0" BorderPane.alignment="CENTER"> <HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" prefWidth="800.0" BorderPane.alignment="CENTER">
<children> <children>
@ -38,49 +31,50 @@
</VBox> </VBox>
<VBox prefHeight="200.0" prefWidth="150.0"> <VBox prefHeight="200.0" prefWidth="150.0">
<children> <children>
<TextField id="rows" prefHeight="31.0" prefWidth="87.0" promptText="Rows"> <TextField id="rows" prefHeight="31.0" promptText="Rows">
<VBox.margin> <VBox.margin>
<Insets top="5.0" /> <Insets left="5.0" top="5.0" />
</VBox.margin> </VBox.margin>
</TextField> </TextField>
<TextField id="cols" promptText="Columns"> <TextField id="cols" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="31.0" promptText="Columns">
<VBox.margin> <VBox.margin>
<Insets top="5.0" /> <Insets left="5.0" top="5.0" />
</VBox.margin> </VBox.margin>
</TextField> </TextField>
<CheckBox id="scale" mnemonicParsing="false" text="scale images">
<VBox.margin>
<Insets left="5.0" top="5.0" />
</VBox.margin>
</CheckBox>
</children> </children>
</VBox> </VBox>
<VBox prefHeight="200.0" prefWidth="200.0"> <VBox prefHeight="200.0" prefWidth="200.0">
<children> <children>
<ProgressBar id="progress" minHeight="-Infinity" minWidth="-Infinity" prefHeight="31.0" prefWidth="180.0" progress="0.0"> <ProgressBar id="progress" minHeight="-Infinity" minWidth="-Infinity" prefHeight="31.0" prefWidth="180.0" progress="0.0">
<VBox.margin> <VBox.margin>
<Insets top="5.0" /> <Insets left="5.0" top="5.0" />
</VBox.margin> </VBox.margin>
<padding>
<Insets left="20.0" />
</padding>
</ProgressBar> </ProgressBar>
<Button id="run" mnemonicParsing="false" prefHeight="32.0" prefWidth="160.0" text="Run replacement"> <Button id="run" mnemonicParsing="false" prefHeight="32.0" prefWidth="180.0" text="Run replacement">
<VBox.margin> <VBox.margin>
<Insets left="20.0" top="5.0" /> <Insets left="5.0" top="5.0" />
</VBox.margin> </VBox.margin>
</Button> </Button>
<Button id="save" mnemonicParsing="false" prefHeight="32.0" prefWidth="160.0" text="Save File"> <Button id="save" mnemonicParsing="false" prefHeight="32.0" prefWidth="180.0" text="Save File">
<VBox.margin> <VBox.margin>
<Insets left="20.0" top="5.0" /> <Insets left="5.0" top="5.0" />
</VBox.margin> </VBox.margin>
</Button> </Button>
</children> </children>
</VBox> </VBox>
<TextFlow id="log" prefHeight="200.0" prefWidth="200.0"> <TextFlow id="log" prefHeight="200.0" />
<opaqueInsets>
<Insets />
</opaqueInsets>
<HBox.margin>
<Insets left="85.0" />
</HBox.margin>
</TextFlow>
</children> </children>
</HBox> </HBox>
</bottom> </bottom>
<left>
<ImageView id="image1" fitHeight="400.0" fitWidth="400.0" pickOnBounds="true" preserveRatio="true" BorderPane.alignment="CENTER" />
</left>
<right>
<ImageView id="image2" fitHeight="400.0" fitWidth="400.0" pickOnBounds="true" preserveRatio="true" BorderPane.alignment="CENTER" />
</right>
</BorderPane> </BorderPane>