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.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.ProgressBar?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.image.ImageView?>
@ -10,15 +11,7 @@
<?import javafx.scene.layout.VBox?>
<?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">
<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>
<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">
<bottom>
<HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" prefWidth="800.0" BorderPane.alignment="CENTER">
<children>
@ -38,49 +31,50 @@
</VBox>
<VBox prefHeight="200.0" prefWidth="150.0">
<children>
<TextField id="rows" prefHeight="31.0" prefWidth="87.0" promptText="Rows">
<TextField id="rows" prefHeight="31.0" promptText="Rows">
<VBox.margin>
<Insets top="5.0" />
<Insets left="5.0" top="5.0" />
</VBox.margin>
</TextField>
<TextField id="cols" promptText="Columns">
<TextField id="cols" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="31.0" promptText="Columns">
<VBox.margin>
<Insets top="5.0" />
<Insets left="5.0" top="5.0" />
</VBox.margin>
</TextField>
<CheckBox id="scale" mnemonicParsing="false" text="scale images">
<VBox.margin>
<Insets left="5.0" top="5.0" />
</VBox.margin>
</CheckBox>
</children>
</VBox>
<VBox prefHeight="200.0" prefWidth="200.0">
<children>
<ProgressBar id="progress" minHeight="-Infinity" minWidth="-Infinity" prefHeight="31.0" prefWidth="180.0" progress="0.0">
<VBox.margin>
<Insets top="5.0" />
<Insets left="5.0" top="5.0" />
</VBox.margin>
<padding>
<Insets left="20.0" />
</padding>
</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>
<Insets left="20.0" top="5.0" />
<Insets left="5.0" top="5.0" />
</VBox.margin>
</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>
<Insets left="20.0" top="5.0" />
<Insets left="5.0" top="5.0" />
</VBox.margin>
</Button>
</children>
</VBox>
<TextFlow id="log" prefHeight="200.0" prefWidth="200.0">
<opaqueInsets>
<Insets />
</opaqueInsets>
<HBox.margin>
<Insets left="85.0" />
</HBox.margin>
</TextFlow>
<TextFlow id="log" prefHeight="200.0" />
</children>
</HBox>
</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>

View File

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

View File

@ -13,7 +13,6 @@ public class chunk {
chunk(BufferedImage Img){
this.img = Img;
this.average = this.average();
}
@ -68,8 +67,8 @@ public class chunk {
temprgb[1] = g;
temprgb[2] = b;
this.average= temprgb;
//System.out.println(r + " , " + g + " , " + b + " , " + a);
return new int[]{r,g,b,a};
return temprgb;
}
//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
*/
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.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.ProgressBar?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.image.ImageView?>
@ -10,15 +11,7 @@
<?import javafx.scene.layout.VBox?>
<?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">
<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>
<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">
<bottom>
<HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" prefWidth="800.0" BorderPane.alignment="CENTER">
<children>
@ -38,49 +31,50 @@
</VBox>
<VBox prefHeight="200.0" prefWidth="150.0">
<children>
<TextField id="rows" prefHeight="31.0" prefWidth="87.0" promptText="Rows">
<TextField id="rows" prefHeight="31.0" promptText="Rows">
<VBox.margin>
<Insets top="5.0" />
<Insets left="5.0" top="5.0" />
</VBox.margin>
</TextField>
<TextField id="cols" promptText="Columns">
<TextField id="cols" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="31.0" promptText="Columns">
<VBox.margin>
<Insets top="5.0" />
<Insets left="5.0" top="5.0" />
</VBox.margin>
</TextField>
<CheckBox id="scale" mnemonicParsing="false" text="scale images">
<VBox.margin>
<Insets left="5.0" top="5.0" />
</VBox.margin>
</CheckBox>
</children>
</VBox>
<VBox prefHeight="200.0" prefWidth="200.0">
<children>
<ProgressBar id="progress" minHeight="-Infinity" minWidth="-Infinity" prefHeight="31.0" prefWidth="180.0" progress="0.0">
<VBox.margin>
<Insets top="5.0" />
<Insets left="5.0" top="5.0" />
</VBox.margin>
<padding>
<Insets left="20.0" />
</padding>
</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>
<Insets left="20.0" top="5.0" />
<Insets left="5.0" top="5.0" />
</VBox.margin>
</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>
<Insets left="20.0" top="5.0" />
<Insets left="5.0" top="5.0" />
</VBox.margin>
</Button>
</children>
</VBox>
<TextFlow id="log" prefHeight="200.0" prefWidth="200.0">
<opaqueInsets>
<Insets />
</opaqueInsets>
<HBox.margin>
<Insets left="85.0" />
</HBox.margin>
</TextFlow>
<TextFlow id="log" prefHeight="200.0" />
</children>
</HBox>
</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>