From 26c183c1e583cc88223586acf65706689c3672cc Mon Sep 17 00:00:00 2001 From: Peery Date: Sun, 10 Sep 2017 15:11:11 +0200 Subject: [PATCH] Initial Commit WIP --- .gitignore | 5 + src/peery/file/FileHandler.java | 140 ++++++++++++++++++++++++++++ src/peery/log/Log.java | 84 +++++++++++++++++ src/peery/log/LogLevel.java | 9 ++ src/peery/picture/Classifier.java | 67 +++++++++++++ src/peery/window/MosaicDisplay.java | 26 ++++++ src/peery/window/Window.java | 18 ++++ 7 files changed, 349 insertions(+) create mode 100644 .gitignore create mode 100644 src/peery/file/FileHandler.java create mode 100644 src/peery/log/Log.java create mode 100644 src/peery/log/LogLevel.java create mode 100644 src/peery/picture/Classifier.java create mode 100644 src/peery/window/MosaicDisplay.java create mode 100644 src/peery/window/Window.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..227de35 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +bin +resources +.classpath +.project +.settings diff --git a/src/peery/file/FileHandler.java b/src/peery/file/FileHandler.java new file mode 100644 index 0000000..a3bc4be --- /dev/null +++ b/src/peery/file/FileHandler.java @@ -0,0 +1,140 @@ +package peery.file; + +import java.awt.Dimension; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; + +import javax.imageio.ImageIO; + +import peery.log.Log; +import peery.log.LogLevel; + +public class FileHandler { + + public File sourceFolder, InputImagesFolder, TargetImageFile, OutputFolder; + /* + * sourcePath/ -> all ressources + * sourcePath/Images/ -> Input pictures folder + * sourcePath/Target -> Target picture file + * sourcePath/Output/ -> Output picture folder + */ + + public FileHandler(String sourcePath){ + 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"); + Log.initLog(this.sourceFolder.getAbsolutePath()); + this.validateFolderStructure(); + } + + public boolean validateFolderStructure(){ + if(this.sourceFolder.isDirectory()){ + Log.log(LogLevel.Debug, "Detected sourcefolder 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()); + return true; + }else{ + Log.log(LogLevel.Critical, "No Target Image found! Exiting..."); + System.exit(1); + } + }else{ + Log.log(LogLevel.Info, "No Output folder found."); + Log.log(LogLevel.Info, "Creating one at "+this.OutputFolder.getAbsolutePath()); + this.OutputFolder.mkdirs(); + } + }else{ + Log.log(LogLevel.Critical, "No Input folder found."); + Log.log(LogLevel.Critical, "Creating one at "+this.InputImagesFolder.getAbsolutePath()); + this.InputImagesFolder.mkdirs(); + } + }else{ + Log.log(LogLevel.Critical, "No source folder found."); + Log.log(LogLevel.Critical, "Creating one at "+this.sourceFolder.getAbsolutePath()); + this.sourceFolder.mkdirs(); + } + Log.log(LogLevel.Critical, "Folder validation failed. There could be a permission problem " + + "or a folder needed to be created! Please look for earlier errors."); + return false; + } + + public BufferedImage loadImage(File file){ + if(file.isFile() && file.canRead()){ + BufferedImage img; + try { + img = ImageIO.read(file); + return img; + } catch (IOException e) { + Log.log(LogLevel.Debug, "File "+file.getPath()+" failed to load as an Image. What did I just read?"); + e.printStackTrace(); + return null; + } + } + else{ + Log.log(LogLevel.Info, "Can't read file "+file.getPath()+" ! It could be a directory or no read permissions."); + return null; + } + } + + public Dimension loadBiggestDimension(){ + File[] files = this.InputImagesFolder.listFiles(); + int width = 0, height = 0, img_count = 0; + for(File f: files){ + if(f.isFile() && f.canRead()){ + BufferedImage img = loadImage(f); + if(img == null){ + continue; + } + img_count++; + if(width < img.getWidth()){ + width = img.getWidth(); + } + if(height < img.getHeight()){ + height = img.getHeight(); + } + } + else{ + Log.log(LogLevel.Info, "Can't read file"+f.toString()+"! It could be a directory or no read permissions."); + } + } + Log.log(LogLevel.Info, img_count+" image(s) were loaded..."); + if(width == 0 || height == 0){ + Log.log(LogLevel.Critical, "Incomplete or no dimension values! Could I load any Image?"); + } + Log.log(LogLevel.Debug, "Biggest dimension is "+width+"x"+height); + return new Dimension(width, height); + } + + // Would probably kill memory (and performance). + @Deprecated + public BufferedImage[] loadAllImages(){ + File[] files = this.InputImagesFolder.listFiles(); + ArrayList imgs = new ArrayList(); + int img_count = 0; + for(File f: files){ + BufferedImage img = loadImage(f); + if(img == null){ + continue; + } + imgs.add(img); + img_count++; + } + if(imgs.size() == 0){ + Log.log(LogLevel.Critical, "No Images found in "+this.InputImagesFolder.getAbsolutePath()); + return null; + } + Log.log(LogLevel.Info, img_count+" image(s) were loaded..."); + BufferedImage[] bfs = new BufferedImage[imgs.size()]; + for(int i = 0; i < imgs.size(); i++){ + bfs[i] = imgs.get(i); + } + return bfs; + } + +} diff --git a/src/peery/log/Log.java b/src/peery/log/Log.java new file mode 100644 index 0000000..3e890c5 --- /dev/null +++ b/src/peery/log/Log.java @@ -0,0 +1,84 @@ +package peery.log; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +public class Log { + + public static Log log; + public static final boolean silenceDebug = false, + appendEvents = true, appendErrors = false; + + public final File eventFile, errorFile; + private BufferedWriter eventWriter, errorWriter; + + + public Log(String location){ + this.eventFile = new File(location+"/eventLog.log"); + this.errorFile = new File(location+"/ERROR.log"); + + try { + if(!this.eventFile.exists()){ + this.eventFile.createNewFile(); + } + if(!this.errorFile.exists()){ + this.errorFile.createNewFile(); + } + this.eventWriter = new BufferedWriter(new FileWriter(eventFile, appendEvents)); + this.errorWriter = new BufferedWriter(new FileWriter(errorFile, appendErrors)); + } catch (IOException e) { + e.printStackTrace(); + System.exit(1); + } + } + + public static void initLog(String location){ + if(Log.log != null){ + return; + } + + Log.log = new Log(location); + } + + public static void log(int logLvl, String message){ + Log.log.logs(logLvl, message); + } + + public static void log(LogLevel lv, String message){ + Log.log.logs(lv.ordinal(), message); + } + + @SuppressWarnings("unused") + public void logs(int logLvl, String message){ + String prefix = LogLevel.values()[logLvl].toString(); + prefix = "["+prefix+"]"; + BufferedWriter logWriter; + if(silenceDebug && logLvl == LogLevel.Debug.ordinal()){ + return; + } + + if(logLvl == LogLevel.Error.ordinal()){ + logWriter = this.errorWriter; + } + else{ + logWriter = this.eventWriter; + } + String timeStamp = new java.util.Date().toString(); + String msg = "["+timeStamp+"]"+prefix+" "+message; + System.out.println(msg); + try { + logWriter.write(msg+"\n"); + 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"); + } +} diff --git a/src/peery/log/LogLevel.java b/src/peery/log/LogLevel.java new file mode 100644 index 0000000..2dfce12 --- /dev/null +++ b/src/peery/log/LogLevel.java @@ -0,0 +1,9 @@ +package peery.log; + +public enum LogLevel { + Info, + Debug, + Critical, + Error + +} diff --git a/src/peery/picture/Classifier.java b/src/peery/picture/Classifier.java new file mode 100644 index 0000000..721586b --- /dev/null +++ b/src/peery/picture/Classifier.java @@ -0,0 +1,67 @@ +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()); + } + +} diff --git a/src/peery/window/MosaicDisplay.java b/src/peery/window/MosaicDisplay.java new file mode 100644 index 0000000..e296990 --- /dev/null +++ b/src/peery/window/MosaicDisplay.java @@ -0,0 +1,26 @@ +package peery.window; + +import java.awt.Canvas; +import java.awt.Graphics2D; +//import java.awt.Rectangle; +import java.awt.image.BufferedImage; + +public class MosaicDisplay extends Canvas{ + + private Graphics2D g2 = (Graphics2D) this.getGraphics(); + + public MosaicDisplay(int width, int height){ + this.setSize(width, height); + } + + public void drawImage(BufferedImage img, int x, int y){ + + g2.drawImage(img, null, x, y); + } + + public void clear(){ + //g2.draw(new Rectangle(this.getWidth(), this.getHeight())); + this.invalidate(); + } + +} diff --git a/src/peery/window/Window.java b/src/peery/window/Window.java new file mode 100644 index 0000000..7b4dfeb --- /dev/null +++ b/src/peery/window/Window.java @@ -0,0 +1,18 @@ +package peery.window; + +import java.awt.Component; + +import javax.swing.JFrame; + +public class Window extends JFrame{ + + public Window(String name, int width, int height, Component display){ + this.setSize(width, height); + this.setName(name); + this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + this.add(display); + + this.setVisible(true); + } + +}