Alpha-0.1 Commit

Tested working on Linux system in development environment.
Input pictures are stretched to fit their slots.
Configuration lies within the source files.
dev
Peery 7 years ago
parent 26c183c1e5
commit 9152b37c9f

@ -0,0 +1,122 @@
package peery;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import peery.file.FileHandler;
import peery.log.Log;
import peery.log.LogLevel;
import peery.picture.ImageAnalyzer;
public class Mosaic {
public static final String versionString = "Alpha-0.1";
private static final String outputName = "Output";
private static final int gridX = 100, gridY = 100, targetMulti = 4,
alphaThreshhold = 30,
adaptionCount = 300;
private static final double adaptionStep = 1.1, gridErrorThresh = 0.15;
/*
*
* TODO improve performance during closest match search. -> Loads ALOT of images
* TODO investigate picture stretching -> is ImageUtils.resizeImage() even used?
* TODO investigate why so few slots are actually present, I specified way more! <---
*
*
* TODO alphaThreshhold is currently dead
*/
public FileHandler fh;
public ImageAnalyzer ia;
public Mosaic(){
fh = new FileHandler("resources");
Log.log(LogLevel.Info, "Starting Mosaic "+versionString);
ia = new ImageAnalyzer(fh);
createMosaic();
}
public void createMosaic(){
ia.rasterizeTarget(gridX, gridY, targetMulti, gridErrorThresh, adaptionCount, adaptionStep);
HashMap<String, Integer> index = fh.loadIndex();
//Loading index
if(index == null){
Log.log(LogLevel.Info, "No index loaded. Working with empty one ...");
index = new HashMap<String, Integer>();
}
//
//Preparing Setup
ArrayList<String> fileList = fh.listInputFiles();
Log.log(LogLevel.Info, "Starting classification of Input now ...");
int count = 0;
for(String path: fileList){
Log.log(LogLevel.Info, "Processing file "+(count++)+"/"+fileList.size()+" ...");
File file = new File(path);
BufferedImage img = fh.loadImage(file);
if(img == null){
continue;
}
int rgb = ia.classifyImage(img, file, alphaThreshhold);
fh.appendToIndex(index, file, rgb);
}
Log.log(LogLevel.Info, "Finished classification. Index is ready for production. Reloading index ...");
index = fh.loadIndex();
Log.log(LogLevel.Debug, "Canvas is "+ia.canvas.getWidth()+"x"+ia.canvas.getHeight()+" big.");
Log.log(LogLevel.Debug, "Grid will span "+ia.slotWidth*gridX+"x"+ia.slotHeight*gridY+" .");
Log.log(LogLevel.Info, "Starting classification of target slots.");
count = 0;
int maxSlot = ia.slotX*ia.slotY;
int[][] slotRGBs = new int[ia.slotX][ia.slotY];
for(int x = 0; x < ia.slotX; x++){
for(int y = 0; y < ia.slotY; y++){
Log.log(LogLevel.Info, "Processing slot "+(count++)+"/"+maxSlot+" ...");
slotRGBs[x][y] = ia.classifySlot(x, y, ia.target);
}
}
Log.log(LogLevel.Info, "Finished classification of target slots.");
Log.log(LogLevel.Info, "Matching indexed Images on slots ...");
count = 0;
ArrayList<File> fileHolder = new ArrayList<File>();
ArrayList<BufferedImage> imgHolder = new ArrayList<BufferedImage>();
for(int x = 0; x < slotRGBs.length; x++){
for(int y = 0; y < slotRGBs[x].length; y++){
Log.log(LogLevel.Info, "Matching slot "+(count++)+"/"+maxSlot+" ...");
HashMap<String, Integer> matches = ia.matchClosestIndex(index, slotRGBs[x][y], 0);
String match = matches.keySet().toArray()[0].toString();
File file = new File(fh.InputImagesFolder+fh.fs+match);
/*
BufferedImage plain = new BufferedImage(ia.slotWidth, ia.slotHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = (Graphics2D) plain.getGraphics();
g2.setColor(new Color(slotRGBs[x][y]));
g2.fillRect(0, 0, plain.getWidth(), plain.getHeight());
g2.dispose();
ia.placeImage(x, y, plain);
*/
BufferedImage img;
if(!fileHolder.contains(file)){
fileHolder.add(file);
img = fh.loadImage(file);
imgHolder.add(img);
}else{
int i = fileHolder.indexOf(file);
img = imgHolder.get(i);
}
ia.placeImage(x, y, img);
}
}
Log.log(LogLevel.Info, "Finished matching. Output is done ...");
fh.saveImage(ia.canvas, new File(fh.OutputFolder+fh.fs+outputName+"-"+fh.OutputFolder.listFiles().length+".png"));
}
public static void main(String[] args){
new Mosaic();
}
}

@ -2,9 +2,16 @@ package peery.file;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;
import javax.imageio.ImageIO;
@ -13,33 +20,52 @@ import peery.log.LogLevel;
public class FileHandler {
public File sourceFolder, InputImagesFolder, TargetImageFile, OutputFolder;
public File sourceFolder, InputImagesFolder, TargetImageFile, OutputFolder, indexFile;
/*
* sourcePath/ -> all ressources
* sourcePath/Images/ -> Input pictures folder
* sourcePath/Target -> Target picture file
* sourcePath/Output/ -> Output picture folder
*/
public final String fs;
public FileHandler(String sourcePath){
if(!System.getProperty("os.name").startsWith("Windows")){
fs = "/";
}else{
fs = "\\";
}
this.sourceFolder = new File(sourcePath);
this.InputImagesFolder = new File(sourceFolder.getAbsolutePath()+"/Images");
this.TargetImageFile = new File(sourceFolder.getAbsolutePath()+"/Target");
this.OutputFolder = new File(sourceFolder.getAbsolutePath()+"/Output");
this.InputImagesFolder = new File(sourceFolder.getAbsolutePath()+fs+"Images");
this.TargetImageFile = new File(sourceFolder.getAbsolutePath()+fs+"Target");
this.OutputFolder = new File(sourceFolder.getAbsolutePath()+fs+"Output");
this.indexFile = new File(this.InputImagesFolder.getAbsolutePath()+"Index.txt");
Log.initLog(this.sourceFolder.getAbsolutePath());
if(fs == "\\"){
Log.log(LogLevel.Debug, "Assumed Windows like Folder declaration. Therefore using "+fs+" as a separator.");
}else{
Log.log(LogLevel.Debug, "Detected Linux or OSX.");
}
this.validateFolderStructure();
}
public boolean validateFolderStructure(){
if(this.sourceFolder.isDirectory()){
Log.log(LogLevel.Debug, "Detected sourcefolder at "+this.sourceFolder.getAbsolutePath());
Log.log(LogLevel.Debug, "Detected source folder at "+this.sourceFolder.getAbsolutePath());
if(this.InputImagesFolder.isDirectory()){
Log.log(LogLevel.Debug, "Detected Input folder at "+this.InputImagesFolder.getAbsolutePath());
if(this.OutputFolder.isDirectory()){
Log.log(LogLevel.Debug, "Detected Output folder at "+this.OutputFolder.getAbsolutePath());
if(this.TargetImageFile.isFile()){
Log.log(LogLevel.Debug, "Detected Target Image at "+this.TargetImageFile.getAbsolutePath());
if(!this.indexFile.isDirectory()){
Log.log(LogLevel.Debug, "Found no directory blocking the index file.");
return true;
}
else{
Log.log(LogLevel.Error, "Following folder collides with the index file name: "+this.indexFile.getAbsolutePath());
System.exit(1);
}
}else{
Log.log(LogLevel.Critical, "No Target Image found! Exiting...");
System.exit(1);
@ -64,11 +90,24 @@ public class FileHandler {
return false;
}
public ArrayList<String> listInputFiles(){
Log.log(LogLevel.Info, "Listing files inside "+this.InputImagesFolder.getName()+" ...");
ArrayList<String> fileList = new ArrayList<String>();
for(File f: this.InputImagesFolder.listFiles()){
if(f.isFile()){
fileList.add(f.getAbsolutePath());
}
}
return fileList;
}
public BufferedImage loadImage(File file){
Log.log(LogLevel.Info, "Loading image "+file.getName()+" ...");
if(file.isFile() && file.canRead()){
BufferedImage img;
try {
img = ImageIO.read(file);
Log.log(LogLevel.Debug, "Loaded image "+file.getName()+" !");
return img;
} catch (IOException e) {
Log.log(LogLevel.Debug, "File "+file.getPath()+" failed to load as an Image. What did I just read?");
@ -82,6 +121,96 @@ public class FileHandler {
}
}
public void saveImage(BufferedImage img, File file){
Log.log(LogLevel.Info, "Saving image as file "+file.getAbsolutePath());
try {
ImageIO.write(img, "png", file);
} catch (IOException e) {
Log.log(LogLevel.Critical, "Couldn't write image "+file.getName()+" to file! Are write permissions missing?"
+ " Attempted to write at "+file.getAbsolutePath());
e.printStackTrace();
}
}
public void appendToIndex(HashMap<String, Integer> index, File file, int rgb){
try {
Log.log(LogLevel.Debug, "Checking index entries for "+file.getName());
if(!indexFile.createNewFile() && loadIndexEntry(index, file) != null){
Log.log(LogLevel.Debug, "An Entry seems to already exist for "+file.getName());
return;
}
BufferedWriter bw = new BufferedWriter(new FileWriter(indexFile, true));
bw.write(rgb+";"+file.getName()+"\n");
bw.flush();
bw.close();
Log.log(LogLevel.Info, "Wrote index entry for "+file.getName()+" !");
} catch (IOException e) {
Log.log(LogLevel.Critical, "Couldn't create or write index file "+indexFile.getAbsolutePath()+" ."
+ "Are write permissions missing?");
e.printStackTrace();
return;
}
}
/**
* Loads an index entry for a single file.
*
* Loads and parses the whole index in the background if not given the indexData.
* @param indexData
* @param file
* @return
*/
public Integer loadIndexEntry(HashMap<String, Integer> indexData, File file){
Log.log(LogLevel.Debug, "Searching for index data of "+file.getName()+" ...");
if(indexData == null){
indexData = loadIndex();
}
return indexData.get(file.getName());
}
/**
* Loads the whole index file into a Hashmap.
* The second value (file name) is used as a String-key, the rgb value is the int-value.
* @param file
* @return
*/
public HashMap<String, Integer> loadIndex(){
if(!this.indexFile.exists()){
Log.log(LogLevel.Info, "No Index file found. Nothing to load then...");
return null;
}
HashMap<String, Integer> indexData = new HashMap<String, Integer>();
try {
Scanner sc = new Scanner(new BufferedReader(new FileReader(this.indexFile)));
while(sc.hasNext()){
@SuppressWarnings("rawtypes")
ArrayList data = parseIndexData(sc.nextLine());
indexData.put((String)data.get(1), (int)data.get(0));
}
sc.close();
} catch (FileNotFoundException e) {
Log.log(LogLevel.Critical, "Could not open index file! Do I have read permissions?");
e.printStackTrace();
}
return indexData;
}
/**
* Parses a line of indexData into an ArrayList containing the rgb int and the name
* @param indexData
* @return
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
private ArrayList parseIndexData(String indexData){
String[] data = indexData.split(";");
ArrayList result = new ArrayList();
result.add(Integer.parseInt(data[0]));
result.add(data[1]);
return result;
}
// could use a single image variant to check synchronized to the classification (saves IO)
public Dimension loadBiggestDimension(){
File[] files = this.InputImagesFolder.listFiles();
int width = 0, height = 0, img_count = 0;

@ -9,7 +9,7 @@ public class Log {
public static Log log;
public static final boolean silenceDebug = false,
appendEvents = true, appendErrors = false;
appendEvents = false, appendErrors = false;
public final File eventFile, errorFile;
private BufferedWriter eventWriter, errorWriter;
@ -42,6 +42,19 @@ public class Log {
Log.log = new Log(location);
}
public static void shutdownLog(){
if(Log.log == null){
return;
}
try {
Log.log.errorWriter.close();
Log.log.eventWriter.close();
Log.log = null;
} catch (IOException e) {
e.printStackTrace();
}
}
public static void log(int logLvl, String message){
Log.log.logs(logLvl, message);
}
@ -70,15 +83,17 @@ public class Log {
System.out.println(msg);
try {
logWriter.write(msg+"\n");
if(LogLevel.Info.ordinal() < logLvl){ //Saves perfomance?
logWriter.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
/*
public static void main(String[] args){
Log.initLog("/home/peery/Software_Projects/EclipseWorkspace/Picture Mosaic/resources/");
Log.log(LogLevel.Debug, "Test!");
Log.log(LogLevel.Error, "TEST ERROR");
}
}*/
}

@ -1,67 +0,0 @@
package peery.picture;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.io.File;
import peery.file.FileHandler;
import peery.log.Log;
import peery.log.LogLevel;
public class Classifier {
public BufferedImage target;
public Classifier(FileHandler fh){
BufferedImage target = fh.loadImage(fh.TargetImageFile);
}
public void rasterizeTarget(){
}
/**
* Plain calculation of average Color of an Image via RGB.
* Takes average of RGB values of each pixel.
* Does not account for alpha.
* @param img Image to process
* @param alphaThreshhold value under which pixels are discarded
* @return RGB value of the average color
*/
public int classifyImage(BufferedImage img, File file, int alphaTreshhold){
int width = img.getWidth();
int height = img.getHeight();
Log.log(LogLevel.Debug, "Starting classification of "+file.getPath()+" with width:"+
width+" and height:"+height+" ...");
ColorModel cm = ColorModel.getRGBdefault();
float red = 0, green = 0, blue = 0;
int pixels = 0;
for(int x = 0; x < img.getWidth(); x++){
for(int y = 0; y < img.getHeight(); y++){
int rgb = img.getRGB(x, y);
red += cm.getRed(rgb);
blue += cm.getBlue(rgb);
green += cm.getGreen(rgb);
pixels++;
}
}
red = red/pixels;
green = green/pixels;
blue = blue/pixels;
int rgb = new Color((int)red, (int)green, (int)blue).getRGB();
Log.log(LogLevel.Debug, "Classified "+file.getPath()+" with following rgb result: value:"+rgb+
" red:"+red+", green:"+green+", blue:"+blue);
return rgb;
}
public static void main(String[] args){
FileHandler fh = new FileHandler("/home/peery/Software_Projects/EclipseWorkspace/Picture Mosaic/resources");
BufferedImage[] bfs = fh.loadAllImages();
Classifier cl = new Classifier(fh);
cl.classifyImage(bfs[0], new File("DEBUG_VALUE"), 30);
System.out.println(fh.loadBiggestDimension());
}
}

@ -0,0 +1,238 @@
package peery.picture;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.io.File;
import java.text.DecimalFormat;
import java.util.HashMap;
import peery.file.FileHandler;
import peery.log.Log;
import peery.log.LogLevel;
public class ImageAnalyzer {
public BufferedImage target;
private FileHandler fh;
private Dimension /*biggestInputSize,*/ targetSize;
public int slotWidth, slotHeight, slotX, slotY;
public BufferedImage canvas;
public ImageAnalyzer(FileHandler fh){
this.fh = fh;
this.target = fh.loadImage(fh.TargetImageFile);
}
public void rasterizeTarget(int gridX, int gridY, float targetSizeMultiplier, double gridErrorThresh, int adaptionThreshhold, double adaptionStep){
Log.log(LogLevel.Info, "Rasterizing target image ...");
Log.log(LogLevel.Info, "Aiming for "+gridX+"*"+gridY+"="+(gridX*gridY)+" tiles ...");
//this.biggestInputSize = this.fh.loadBiggestDimension();
this.targetSize = new Dimension(this.target.getWidth(), this.target.getHeight());
//TMP
int count = 0;
DecimalFormat df = new DecimalFormat("#");
while(true){
double realSlotWidth = ((targetSize.width*targetSizeMultiplier)/gridX);
double realSlotHeight = ((targetSize.height*targetSizeMultiplier)/gridY);
Log.log(LogLevel.Debug, "Perfect slot Size would be "+realSlotWidth+"x"+realSlotHeight);
double widthLoss = Math.abs(realSlotWidth - Double.parseDouble(df.format(realSlotWidth)));
double heightLoss = Math.abs(realSlotHeight - Double.parseDouble(df.format(realSlotHeight)));
if(widthLoss > gridErrorThresh || heightLoss > gridErrorThresh){
Log.log(LogLevel.Critical, "Grid misplacement error exceeded threshhold! Error is width:"+widthLoss+" height:"+heightLoss);
if(widthLoss > gridErrorThresh){
gridX *= adaptionStep;
}
if(heightLoss > gridErrorThresh){
gridY *= adaptionStep;
}
Log.log(LogLevel.Info, "This is the "+(++count)+". adaption to ease the error.");
Log.log(LogLevel.Info, "Aiming for "+gridX+"*"+gridY+"="+(gridX*gridY)+" tiles ...");
if(count > adaptionThreshhold){
Log.log(LogLevel.Critical, "Could not adapt to grid misplacement error! The result might be cut off or missing parts!");
break;
}
continue;
}else{
break;
}
}
slotWidth = (int) ((targetSize.width*targetSizeMultiplier)/gridX);
slotHeight = (int) ((targetSize.height*targetSizeMultiplier)/gridY);
//
Log.log(LogLevel.Debug, "Target will be "+(int)(targetSize.width*targetSizeMultiplier)
+"x"+(int)(targetSize.height*targetSizeMultiplier)+" big.");
Log.log(LogLevel.Debug, "Slots are "+slotWidth+"x"+slotHeight+" big.");
slotX = gridX;
slotY = gridY;
//ia.slotWidth*gridX+"x"+ia.slotHeight*gridY
//canvas = new BufferedImage((int)(targetSize.getWidth()*targetSizeMultiplier), (int)(targetSize.getHeight()*targetSizeMultiplier), BufferedImage.TYPE_INT_ARGB);
canvas = new BufferedImage(slotWidth*gridX, slotHeight*gridY, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = (Graphics2D) canvas.getGraphics();
g2.setColor(Color.BLACK);
g2.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
}
/**
* Compares the given rgb value with the index and returns a HashMap of the closest hits.
* Unlikely to yield more than 1 result without deviationPercentage
* @param index
* @param rgb
* @param deviation How much the matches can be different from the perfect match, and still be taken.
* @return
*/
public HashMap<String, Integer> matchClosestIndex(HashMap<String, Integer> index, int rgb, int deviation){
Log.log(LogLevel.Debug, "Searching for closest match for rgb:"+rgb+" in the index with deviation of "+deviation+".");
assert(deviation < 100 && 0 <= deviation);
if(index == null){
Log.log(LogLevel.Critical, "No Index was given for rgb matching. Loading it from file ...");
index = this.fh.loadIndex();
}
HashMap<String, Double> metrics = new HashMap<String, Double>();
double currBest = -1;
for(String key: index.keySet()){
double metric = getMetric(index.get(key), rgb);
metrics.put(key, metric);
if(currBest > metric || currBest == -1){
currBest = metric;
}
}
Log.log(LogLevel.Info, "Calculated all metrics for rgb:"+rgb+" !");
HashMap<String, Integer> matches = new HashMap<String, Integer>();
for(String key: metrics.keySet()){
if(metrics.get(key) == currBest || metrics.get(key) < currBest+(currBest*(deviation/(double)100))){
matches.put(key, index.get(key));
}
}
Log.log(LogLevel.Debug, "Grabbed all good matches for rgb:"+rgb+" ! Got "+matches.size()+" ...");
return matches;
}
/**
* Calculates the euclidian metric of two given rgb values.
* @param rgb1
* @param rgb2
* @return
*/
private double getMetric(int rgb1, int rgb2){
ColorModel cm = ColorModel.getRGBdefault();
double result = Math.sqrt(Math.pow((cm.getRed(rgb1)-cm.getRed(rgb2)), 2)+
Math.pow(cm.getGreen(rgb1)-cm.getGreen(rgb2), 2)+
Math.pow(cm.getBlue(rgb1)-cm.getBlue(rgb2), 2));
return result;
}
/**
* Places the given input in its specified slot (gridX, gridY) on the canvas.
* Assumes and checks boundaries calculated by rasterizeTarget().
* @param gridX
* @param gridY
* @param input
* @param canvas
* @return
*/
public void placeImage(int gridX, int gridY, BufferedImage input){
assert(gridX < slotX && gridY < slotY);
assert(input.getWidth() < slotWidth && input.getHeight() < slotHeight);
Graphics2D g2 = (Graphics2D)canvas.getGraphics();
g2.drawImage(input, gridX*slotWidth, gridY*slotHeight, slotWidth, slotHeight, null);
g2.dispose();
}
/**
* Plain calculation of average Color of an Image via RGB.
* Takes average of RGB values of each pixel.
* Does not account for alpha.
* @param img Image to process
* @param alphaThreshhold value under which pixels are discarded
* @return RGB value of the average color
*/
public int classifyImage(BufferedImage img, File file, int alphaTreshhold){
int width = img.getWidth();
int height = img.getHeight();
Log.log(LogLevel.Debug, "Starting classification of "+file.getName()+" with width:"+
width+" and height:"+height+" ...");
ColorModel cm = ColorModel.getRGBdefault();
float red = 0, green = 0, blue = 0;
int pixels = 0;
for(int x = 0; x < img.getWidth(); x++){
for(int y = 0; y < img.getHeight(); y++){
int rgb = img.getRGB(x, y);
red += cm.getRed(rgb);
blue += cm.getBlue(rgb);
green += cm.getGreen(rgb);
pixels++;
}
}
red = red/pixels;
green = green/pixels;
blue = blue/pixels;
int rgb = new Color((int)red, (int)green, (int)blue).getRGB();
Log.log(LogLevel.Info, "Classified "+file.getPath()+" with following rgb result: value:"+rgb+
" red:"+red+", green:"+green+", blue:"+blue);
return rgb;
}
public int classifySlot(int gridX, int gridY, BufferedImage target){
int slotWidth = target.getWidth()/slotX,
slotHeight = target.getHeight()/slotY;
BufferedImage subImage = target.getSubimage(gridX*slotWidth, gridY*slotHeight, slotWidth, slotHeight);
Log.log(LogLevel.Debug, "Slicing slot "+gridX+"x"+gridY+" out of the target for classification ...");
ColorModel cm = ColorModel.getRGBdefault();
float red = 0, green = 0, blue = 0;
int pixels = 0;
for(int x = 0; x < subImage.getWidth(); x++){
for(int y = 0; y < subImage.getHeight(); y++){
int rgb = subImage.getRGB(x, y);
red += cm.getRed(rgb);
green += cm.getGreen(rgb);
blue += cm.getBlue(rgb);
pixels++;
}
}
red = red/pixels;
green = green/pixels;
blue = blue/pixels;
int rgb = new Color((int)red, (int)green, (int)blue).getRGB();
Log.log(LogLevel.Debug, "Classified slot "+gridX+"x"+gridY+" with following rgb result: value:"+rgb+
" red:"+red+", green:"+green+", blue:"+blue);
return rgb;
}
/*
public static void main(String[] args){
System.out.println("ZHE DEBUG");
/*
FileHandler fh = new FileHandler("/home/peery/Software_Projects/EclipseWorkspace/Picture Mosaic/resources");
ImageAnalyzer ia = new ImageAnalyzer(fh);
HashMap<String, Integer> index = fh.loadIndex();
for(File f: fh.InputImagesFolder.listFiles()){
BufferedImage img = fh.loadImage(f);
if(img == null){
continue;
}
int indexValue = ia.classifyImage(img, f, 30);
fh.appendToIndex(index, f, indexValue);
}
index = fh.loadIndex();
System.out.println(index.get("Peery-sketch.png"));
System.out.println(index.get("rasd"));
System.out.println(index.get("Larry the Tiger - Candy Shop Logo (Gift).png"));
System.out.println(ia.matchClosestIndex(index, -10744103, 5));
//BufferedImage img = ImageUtils.resizeImage(fh.loadImage(fh.InputImagesFolder.listFiles()[0]), new Dimension(500, 300), false);
//fh.saveImage(img, new File("/home/peery/Software_Projects/EclipseWorkspace/Picture Mosaic/resources/resize-test.png"));
}*/
}

@ -0,0 +1,41 @@
package peery.picture;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
public class ImageUtils {
public static BufferedImage resizeImage(BufferedImage input, Dimension targetSize, boolean keepRatio){
Image tmp;
BufferedImage img;
if(!keepRatio){
tmp = input.getScaledInstance((int)targetSize.getWidth(), (int)targetSize.getHeight(), Image.SCALE_SMOOTH);
img = new BufferedImage(tmp.getWidth(null), tmp.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = (Graphics2D) img.getGraphics();
g2.drawImage(tmp, 0, 0, null);
g2.dispose();
return img;
}
if(targetSize.getWidth() > targetSize.getHeight()){
tmp = input.getScaledInstance(-1, (int)targetSize.getHeight(), Image.SCALE_SMOOTH);
img = new BufferedImage(tmp.getWidth(null), tmp.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = (Graphics2D) img.getGraphics();
g2.drawImage(tmp, 0, 0, null);
g2.dispose();
return img;
}else{
tmp = input.getScaledInstance((int)targetSize.getWidth(), -1, Image.SCALE_SMOOTH);
img = new BufferedImage(tmp.getWidth(null), tmp.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = (Graphics2D) img.getGraphics();
g2.drawImage(tmp, 0, 0, null);
g2.dispose();
return img;
}
}
}
Loading…
Cancel
Save