Browse Source

More refactoring

master
Drew Short 10 years ago
parent
commit
783a3a4aba
  1. 2
      cli/version.info
  2. 3
      engine/pom.xml
  3. 10
      engine/src/main/java/com/sothr/imagetools/engine/AppConfig.java
  4. 21
      engine/src/main/java/com/sothr/imagetools/engine/errors/ImageToolsException.java
  5. 2
      engine/src/main/java/com/sothr/imagetools/engine/util/ResourceLoader.java
  6. 9
      engine/src/main/resources/hibernate.cfg.xml
  7. 3
      engine/src/main/resources/hibernate/Image.hbm.xml
  8. 16
      engine/src/main/scala/com/sothr/imagetools/engine/ConcurrentEngine.scala
  9. 10
      engine/src/main/scala/com/sothr/imagetools/engine/Engine.scala
  10. 3
      engine/src/main/scala/com/sothr/imagetools/engine/SequentialEngine.scala
  11. 29
      engine/src/main/scala/com/sothr/imagetools/engine/dto/ImageHashDTO.scala
  12. 18
      engine/src/main/scala/com/sothr/imagetools/engine/hash/HashService.scala
  13. 38
      engine/src/main/scala/com/sothr/imagetools/engine/image/Image.scala
  14. 5
      engine/src/main/scala/com/sothr/imagetools/engine/image/ImageService.scala
  15. 1
      engine/src/main/scala/com/sothr/imagetools/engine/util/PropertiesService.scala
  16. 12
      engine/src/test/java/com/sothr/imagetools/engine/AppTest.java
  17. 9
      engine/src/test/resources/hibernate.cfg.xml
  18. 3
      engine/src/test/resources/hibernate/Image.hbm.xml
  19. 24
      engine/src/test/scala/com/sothr/imagetools/engine/EngineTest.scala
  20. 75
      engine/src/test/scala/com/sothr/imagetools/engine/hash/HashServiceTest.scala
  21. 16
      engine/src/test/scala/com/sothr/imagetools/engine/image/ImageFilterTest.scala
  22. 6
      gui/src/main/java/com/sothr/imagetools/ui/App.java
  23. 74
      gui/src/main/resources/fxml/mainapp/MainApp.fxml
  24. 3
      gui/src/main/scala/com/sothr/imagetools/ui/component/ImageTileFactory.scala
  25. 2
      gui/src/main/scala/com/sothr/imagetools/ui/controller/AppController.scala
  26. 2
      gui/version.info

2
cli/version.info

@ -1 +1 @@
0.1.1-DEV-13-661ba6d
0.1.1-DEV-15-15ce4f1

3
engine/pom.xml

@ -194,7 +194,8 @@
<fileset dir="${basedir}/src/main/resources/hibernate" includes="**/*"/>
</copy>
<copy file="${project.build.directory}/LICENSE" toFile="${basedir}/LICENSE" overwrite="true"/>
<copy file="${project.build.directory}/version.info" toFile="${basedir}/../version.info" overwrite="true" />
<copy file="${project.build.directory}/version.info" toFile="${basedir}/../version.info"
overwrite="true"/>
<copy file="${project.build.directory}/README.md" toFile="${basedir}/../README.md" overwrite="true"/>
</tasks>
</configuration>

10
engine/src/main/java/com/sothr/imagetools/engine/AppConfig.java

@ -37,8 +37,14 @@ public class AppConfig {
// The Main App
private static Stage primaryStage = null;
public static Stage getPrimaryStage() { return primaryStage; }
public static void setPrimaryStage(Stage newPrimaryStage) { primaryStage = newPrimaryStage; }
public static Stage getPrimaryStage() {
return primaryStage;
}
public static void setPrimaryStage(Stage newPrimaryStage) {
primaryStage = newPrimaryStage;
}
public static ActorSystem getAppActorSystem() {
return appSystem;

21
engine/src/main/java/com/sothr/imagetools/engine/errors/ImageToolsException.java

@ -2,14 +2,25 @@ package com.sothr.imagetools.engine.errors;
/**
* Simple Exception
*
* <p/>
* Created by drew on 12/31/13.
*/
public class ImageToolsException extends Exception {
public ImageToolsException() { super(); }
public ImageToolsException(String message) { super(message); }
public ImageToolsException(String message, Throwable cause) { super(message, cause); }
public ImageToolsException(Throwable cause) { super(cause); }
public ImageToolsException() {
super();
}
public ImageToolsException(String message) {
super(message);
}
public ImageToolsException(String message, Throwable cause) {
super(message, cause);
}
public ImageToolsException(Throwable cause) {
super(cause);
}
}

2
engine/src/main/java/com/sothr/imagetools/engine/util/ResourceLoader.java

@ -8,7 +8,7 @@ import java.net.URL;
/**
* Seamlessly handle resource loading
*
* <p/>
* Created by drew on 1/5/14.
*/
public class ResourceLoader {

9
engine/src/main/resources/hibernate.cfg.xml

@ -25,15 +25,18 @@
<!-- Enable the second-level cache -->
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</property>
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
</property>
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="c3p0.acquire_increment">1</property>
<property name="c3p0.idle_test_period">100</property> <!-- seconds -->
<property name="c3p0.idle_test_period">100</property>
<!-- seconds -->
<property name="c3p0.max_size">50</property>
<property name="c3p0.max_statements">0</property>
<property name="c3p0.min_size">5</property>
<property name="c3p0.timeout">100</property> <!-- seconds -->
<property name="c3p0.timeout">100</property>
<!-- seconds -->
<!-- mapping files -->
<mapping resource="hibernate/Image.hbm.xml"/>

3
engine/src/main/resources/hibernate/Image.hbm.xml

@ -11,6 +11,7 @@
<property name="thumbnailPath" column="thumbnail_path" type="string" not-null="true"/>
<property name="width" column="width" type="int" not-null="true"/>
<property name="height" column="height" type="int" not-null="true"/>
<many-to-one name="hashes" column="hashes" unique="true" class="com.sothr.imagetools.engine.dto.ImageHashDTO" cascade="save-update, delete" not-null="true" lazy="false"/>
<many-to-one name="hashes" column="hashes" unique="true" class="com.sothr.imagetools.engine.dto.ImageHashDTO"
cascade="save-update, delete" not-null="true" lazy="false"/>
</class>
</hibernate-mapping>

16
engine/src/main/scala/com/sothr/imagetools/engine/ConcurrentEngine.scala

@ -8,8 +8,7 @@ import akka.pattern.ask
import akka.routing.{Broadcast, RoundRobinRouter, SmallestMailboxRouter}
import akka.util.Timeout
import com.sothr.imagetools.engine.hash.HashService
import com.sothr.imagetools.engine.image.{SimilarImages, ImageService, Image}
import com.sothr.imagetools.image.SimilarImages
import com.sothr.imagetools.engine.image.{Image, ImageService, SimilarImages}
import com.sothr.imagetools.engine.util._
import scala.collection.mutable
@ -118,17 +117,23 @@ class ConcurrentEngine extends Engine with grizzled.slf4j.Logging {
// external cases //
case class SetNewListener(listenerType: ActorRef)
case object EngineStart
// processing files into images
case class EngineProcessFile(file: File)
case object EngineNoMoreFiles
case object EngineIsProcessingFinished
case object EngineGetProcessingResults
//internal cases
case class EngineFileProcessed(image: Image)
case object EngineActorProcessingFinished
case object EngineActorReactivate
class ConcurrentEngineProcessingController extends Actor with ActorLogging {
@ -244,6 +249,7 @@ class ConcurrentEngineProcessingController extends Actor with ActorLogging {
class ConcurrentEngineProcessingActor extends Actor with ActorLogging {
var ignoreMessages = false
override def receive = {
case command: EngineProcessFile => processFile(command)
case EngineNoMoreFiles => finishedProcessingFiles()
@ -272,10 +278,15 @@ class ConcurrentEngineProcessingActor extends Actor with ActorLogging {
//finding similarities between images
case class EngineCompareImages(image1: Image, images: List[Image])
case class EngineCompareImagesComplete(similarImages: SimilarImages)
case object EngineNoMoreComparisons
case object EngineIsSimilarityFinished
case object EngineGetSimilarityResults
case object EngineActorCompareImagesFinished
class ConcurrentEngineSimilarityController extends Actor with ActorLogging {
@ -399,6 +410,7 @@ class ConcurrentEngineSimilarityController extends Actor with ActorLogging {
class ConcurrentEngineSimilarityActor extends Actor with ActorLogging {
var ignoreMessages = false
override def receive = {
case command: EngineCompareImages => compareImages(command)
case EngineNoMoreComparisons => finishedComparisons()

10
engine/src/main/scala/com/sothr/imagetools/engine/Engine.scala

@ -3,9 +3,7 @@ package com.sothr.imagetools.engine
import java.io.File
import akka.actor.{Actor, ActorLogging, ActorRef, ActorSystem}
import AppConfig
import com.sothr.imagetools.engine.image.{SimilarImages, ImageFilter, Image}
import com.sothr.imagetools.image.SimilarImages
import com.sothr.imagetools.engine.image.{Image, ImageFilter, SimilarImages}
import com.sothr.imagetools.engine.util.DirectoryFilter
import grizzled.slf4j.Logging
@ -22,6 +20,7 @@ abstract class Engine extends Logging {
val imageCache = AppConfig.cacheManager.getCache("images")
def setProcessedListener(listenerType: ActorRef)
def setSimilarityListener(listenerType: ActorRef)
def getAllImageFiles(directoryPath: String, recursive: Boolean = false, recursiveDepth: Int = 500): List[File] = {
@ -59,8 +58,11 @@ abstract class Engine extends Logging {
}
case class SubmitMessage(message: String)
case class ScannedFileCount(count: Integer, total: Integer, message: String = null)
case class ComparedFileCount(count: Integer, total: Integer, message: String = null)
abstract class EngineListener extends Actor with ActorLogging {
override def receive: Actor.Receive = {
case command: SubmitMessage => handleMessage(command)
@ -70,7 +72,9 @@ abstract class EngineListener extends Actor with ActorLogging {
}
def handleMessage(command: SubmitMessage)
def handleScannedFileCount(command: ScannedFileCount)
def handleComparedFileCount(command: ComparedFileCount)
}

3
engine/src/main/scala/com/sothr/imagetools/engine/SequentialEngine.scala

@ -3,8 +3,7 @@ package com.sothr.imagetools.engine
import java.io.File
import akka.actor.{ActorRef, Props}
import com.sothr.imagetools.engine.image.{SimilarImages, ImageService, Image}
import com.sothr.imagetools.image.SimilarImages
import com.sothr.imagetools.engine.image.{Image, ImageService, SimilarImages}
import grizzled.slf4j.Logging
import scala.collection.mutable

29
engine/src/main/scala/com/sothr/imagetools/engine/dto/ImageHashDTO.scala

@ -13,17 +13,36 @@ class ImageHashDTO(var ahash:Long, var dhash:Long, var phash:Long, var md5:Strin
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
var id: Int = _
def getId: Int = id
def setId(newId:Int) = { id = newId }
def setId(newId: Int) = {
id = newId
}
def getAhash: Long = ahash
def setAhash(hash:Long) = { ahash = hash}
def setAhash(hash: Long) = {
ahash = hash
}
def getDhash: Long = dhash
def setDhash(hash:Long) = { dhash = hash}
def setDhash(hash: Long) = {
dhash = hash
}
def getPhash: Long = phash
def setPhash(hash:Long) = { phash = hash}
def setPhash(hash: Long) = {
phash = hash
}
def getMd5: String = md5
def setMd5(hash:String) = { md5 = hash}
def setMd5(hash: String) = {
md5 = hash
}
def cloneHashes: ImageHashDTO = {
new ImageHashDTO(ahash, dhash, phash, md5)

18
engine/src/main/scala/com/sothr/imagetools/engine/hash/HashService.scala

@ -135,22 +135,19 @@ object HashService extends Logging {
var weightedHammingTotal: Float = 0
var methodsTotal = 0
if (useAhash)
{
if (useAhash) {
val hamming = Hamming.getDistance(imageHash1.ahash, imageHash2.ahash)
weightedHammingTotal += hamming * aHashWeight
//debug(s"hash1: ${imageHash1.ahash} hash2: ${imageHash1.ahash} tolerence: $aHashTolerance hamming distance: $hamming weight: $aHashWeight")
methodsTotal += 1
}
if (useDhash)
{
if (useDhash) {
val hamming = Hamming.getDistance(imageHash1.dhash, imageHash2.dhash)
weightedHammingTotal += hamming * dHashWeight
//debug(s"hash1: ${imageHash1.dhash} hash2: ${imageHash1.dhash} tolerence: $dHashTolerance hamming distance: $hamming weight: $dHashWeight")
methodsTotal += 1
}
if (usePhash)
{
if (usePhash) {
val hamming = Hamming.getDistance(imageHash1.phash, imageHash2.phash)
weightedHammingTotal += hamming * pHashWeight
//debug(s"hash1: ${imageHash1.phash} hash2: ${imageHash1.phash} tolerence: $pHashTolerance hamming distance: $hamming weight: $pHashWeight")
@ -179,20 +176,17 @@ object HashService extends Logging {
var weightedToleranceTotal: Float = 0
var methodsTotal = 0
if (useAhash)
{
if (useAhash) {
weightedToleranceTotal += aHashTolerance * aHashWeight
//debug(s"Ahash Tolerance: $aHashTolerance Current Weighted Tolerance: $weightedToleranceTotal")
methodsTotal += 1
}
if (useDhash)
{
if (useDhash) {
weightedToleranceTotal += dHashTolerance * dHashWeight
//debug(s"Dhash Tolerance: $dHashTolerance Current Weighted Tolerance: $weightedToleranceTotal")
methodsTotal += 1
}
if (usePhash)
{
if (usePhash) {
weightedToleranceTotal += pHashTolerance * pHashWeight
//debug(s"Phash Tolerance: $pHashTolerance Current Weighted Tolerance: $weightedToleranceTotal")
methodsTotal += 1

38
engine/src/main/scala/com/sothr/imagetools/engine/image/Image.scala

@ -14,23 +14,49 @@ class Image(val image:String, val thumbnail:String, val size:(Int, Int), val ima
@Id
var imagePath: String = image
def getImagePath: String = imagePath
def setImagePath(path:String) = { imagePath = path}
def setImagePath(path: String) = {
imagePath = path
}
var thumbnailPath: String = thumbnail
def getThumbnailPath: String = thumbnailPath
def setThumbnailPath(path:String) = { thumbnailPath = path}
def setThumbnailPath(path: String) = {
thumbnailPath = path
}
var width: Int = size._1
def getWidth: Int = width
def setWidth(size:Int) = { width = size}
def setWidth(size: Int) = {
width = size
}
var height: Int = size._2
def getHeight: Int = height
def setHeight(size:Int) = { height = size}
def setHeight(size: Int) = {
height = size
}
var hashes: ImageHashDTO = imageHashes
def getHashes: ImageHashDTO = hashes
def setHashes(newHashes:ImageHashDTO) = { hashes = newHashes}
def setHashes(newHashes: ImageHashDTO) = {
hashes = newHashes
}
@transient
var imageSize:(Int, Int) = { new Tuple2(width, height) }
var imageSize: (Int, Int) = {
new Tuple2(width, height)
}
@transient
var imageName: String = ""

5
engine/src/main/scala/com/sothr/imagetools/engine/image/ImageService.scala

@ -3,6 +3,7 @@ package com.sothr.imagetools.engine.image
import java.awt.image.{BufferedImage, ColorConvertOp, DataBufferByte}
import java.io.{File, IOException}
import javax.imageio.ImageIO
import com.sothr.imagetools.engine.AppConfig
import com.sothr.imagetools.engine.dao.ImageDAO
import com.sothr.imagetools.engine.hash.HashService
@ -64,7 +65,9 @@ object ImageService extends Logging {
val hashes = HashService.getImageHashes(bufferedImage, file.getAbsolutePath)
var thumbnailPath = lookupThumbnailPath(hashes.md5)
if (thumbnailPath == null) thumbnailPath = getThumbnail(bufferedImage, hashes.md5)
val imageSize = { (bufferedImage.getWidth, bufferedImage.getHeight) }
val imageSize = {
(bufferedImage.getWidth, bufferedImage.getHeight)
}
val image = new Image(file.getAbsolutePath, thumbnailPath, imageSize, hashes)
debug(s"Created image: $image")
return saveImage(image)

1
engine/src/main/scala/com/sothr/imagetools/engine/util/PropertiesService.scala

@ -15,6 +15,7 @@ object PropertiesService extends Logging {
private var userConf: Config = null
private var newUserConf: Properties = new Properties()
private var version: Version = null
def getVersion: Version = this.version
//specific highly used properties

12
engine/src/test/java/com/sothr/imagetools/engine/AppTest.java

@ -7,31 +7,27 @@ import junit.framework.TestSuite;
/**
* Unit test for simple App.
*/
public class AppTest extends TestCase
{
public class AppTest extends TestCase {
/**
* Create the test case
*
* @param testName name of the test case
*/
public AppTest( String testName )
{
public AppTest(String testName) {
super(testName);
}
/**
* @return the suite of tests being tested
*/
public static Test suite()
{
public static Test suite() {
return new TestSuite(AppTest.class);
}
/**
* Rigourous Test :-)
*/
public void testApp()
{
public void testApp() {
assertTrue(true);
}
}

9
engine/src/test/resources/hibernate.cfg.xml

@ -22,15 +22,18 @@
<!-- Enable the second-level cache -->
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</property>
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
</property>
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="c3p0.acquire_increment">1</property>
<property name="c3p0.idle_test_period">100</property> <!-- seconds -->
<property name="c3p0.idle_test_period">100</property>
<!-- seconds -->
<property name="c3p0.max_size">50</property>
<property name="c3p0.max_statements">0</property>
<property name="c3p0.min_size">5</property>
<property name="c3p0.timeout">100</property> <!-- seconds -->
<property name="c3p0.timeout">100</property>
<!-- seconds -->
<!-- mapping files -->
<mapping resource="hibernate/Image.hbm.xml"/>

3
engine/src/test/resources/hibernate/Image.hbm.xml

@ -11,6 +11,7 @@
<property name="thumbnailPath" column="thumbnail_path" type="string" not-null="true"/>
<property name="width" column="width" type="int" not-null="true"/>
<property name="height" column="height" type="int" not-null="true"/>
<many-to-one name="hashes" column="hashes" unique="true" class="com.sothr.imagetools.engine.dto.ImageHashDTO" cascade="save-update, delete" not-null="true" lazy="false"/>
<many-to-one name="hashes" column="hashes" unique="true" class="com.sothr.imagetools.engine.dto.ImageHashDTO"
cascade="save-update, delete" not-null="true" lazy="false"/>
</class>
</hibernate-mapping>

24
engine/src/test/scala/com/sothr/imagetools/engine/EngineTest.scala

@ -8,25 +8,37 @@ package com.sothr.imagetools.engine
class EngineTest extends BaseTest {
test("SequentialEngine Test getImagesForDirectory for sample directory") {
val engine: Engine = new SequentialEngine()
assertResult(3) { engine.getImagesForDirectory("sample").length }
assertResult(3) {
engine.getImagesForDirectory("sample").length
}
}
test("SequentialEngine Test getSimilarImagesForDirectory for sample directory") {
val engine = new SequentialEngine()
val similarImages = engine.getSimilarImagesForDirectory("sample")
assertResult(1) { similarImages.length }
assertResult(2) { similarImages(0).similarImages.length }
assertResult(1) {
similarImages.length
}
assertResult(2) {
similarImages(0).similarImages.length
}
}
test("ConcurrentEngine Test getImagesForDirectory for sample directory") {
val engine: Engine = new ConcurrentEngine()
assertResult(3) { engine.getImagesForDirectory("sample").length }
assertResult(3) {
engine.getImagesForDirectory("sample").length
}
}
test("ConcurrentEngine Test getSimilarImagesForDirectory for sample directory") {
val engine = new ConcurrentEngine()
val similarImages = engine.getSimilarImagesForDirectory("sample")
assertResult(1) { similarImages.length }
assertResult(2) { similarImages(0).similarImages.length }
assertResult(1) {
similarImages.length
}
assertResult(2) {
similarImages(0).similarImages.length
}
}
}

75
engine/src/test/scala/com/sothr/imagetools/engine/hash/HashServiceTest.scala

@ -3,9 +3,8 @@ package com.sothr.imagetools.engine.hash
import java.io.File
import javax.imageio.ImageIO
import com.sothr.imagetools.engine.{TestParams, BaseTest, AppConfig}
import com.sothr.imagetools.engine.dto.ImageHashDTO
import com.sothr.imagetools.TestParams
import com.sothr.imagetools.engine.{AppConfig, BaseTest, TestParams}
import net.sf.ehcache.Element
import scala.collection.mutable
@ -31,21 +30,27 @@ class HashServiceTest extends BaseTest {
info("DHash Large Image 3684x2736")
val time = new mutable.MutableList[Long]()
for (runNum <- 0 until benchmarkRuns) {
time += getTime { dhashTestCase(TestParams.LargeSampleImage1) }
time += getTime {
dhashTestCase(TestParams.LargeSampleImage1)
}
}
val largeMean = getMean(time.toArray[Long])
info(s"The mean time of ${time.size} tests for large was: $largeMean ms")
time.clear()
info("DHash Medium Image 1824x1368")
for (runNum <- 0 until benchmarkRuns) {
time += getTime { dhashTestCase(TestParams.MediumSampleImage1) }
time += getTime {
dhashTestCase(TestParams.MediumSampleImage1)
}
}
val mediumMean = getMean(time.toArray[Long])
info(s"The mean time of ${time.size} tests for medium was: $mediumMean ms")
time.clear()
info("DHash Small Image 912x684")
for (runNum <- 0 until benchmarkRuns) {
time += getTime { dhashTestCase(TestParams.SmallSampleImage1) }
time += getTime {
dhashTestCase(TestParams.SmallSampleImage1)
}
}
val smallMean = getMean(time.toArray[Long])
info(s"The mean time of ${time.size} tests for small was: $smallMean ms")
@ -121,21 +126,27 @@ class HashServiceTest extends BaseTest {
info("AHash Large Image 3684x2736")
val time = new mutable.MutableList[Long]()
for (runNum <- 0 until benchmarkRuns) {
time += getTime { ahashTestCase(TestParams.LargeSampleImage1) }
time += getTime {
ahashTestCase(TestParams.LargeSampleImage1)
}
}
val largeMean = getMean(time.toArray[Long])
info(s"The mean time of ${time.size} tests for large was: $largeMean ms")
time.clear()
info("AHash Medium Image 1824x1368")
for (runNum <- 0 until benchmarkRuns) {
time += getTime { ahashTestCase(TestParams.MediumSampleImage1) }
time += getTime {
ahashTestCase(TestParams.MediumSampleImage1)
}
}
val mediumMean = getMean(time.toArray[Long])
info(s"The mean time of ${time.size} tests for medium was: $mediumMean ms")
time.clear()
info("AHash Small Image 912x684")
for (runNum <- 0 until benchmarkRuns) {
time += getTime { ahashTestCase(TestParams.SmallSampleImage1) }
time += getTime {
ahashTestCase(TestParams.SmallSampleImage1)
}
}
val smallMean = getMean(time.toArray[Long])
info(s"The mean time of ${time.size} tests for small was: $smallMean ms")
@ -196,21 +207,27 @@ class HashServiceTest extends BaseTest {
info("PHash Large Image 3684x2736")
val time = new mutable.MutableList[Long]()
for (runNum <- 0 until benchmarkRuns) {
time += getTime { phashTestCase(TestParams.LargeSampleImage1) }
time += getTime {
phashTestCase(TestParams.LargeSampleImage1)
}
}
val largeMean = getMean(time.toArray[Long])
info(s"The mean time of ${time.size} tests for large was: $largeMean ms")
time.clear()
info("PHash Medium Image 1824x1368")
for (runNum <- 0 until benchmarkRuns) {
time += getTime { phashTestCase(TestParams.MediumSampleImage1) }
time += getTime {
phashTestCase(TestParams.MediumSampleImage1)
}
}
val mediumMean = getMean(time.toArray[Long])
info(s"The mean time of ${time.size} tests for medium was: $mediumMean ms")
time.clear()
info("PHash Small Image 912x684")
for (runNum <- 0 until benchmarkRuns) {
time += getTime { phashTestCase(TestParams.SmallSampleImage1) }
time += getTime {
phashTestCase(TestParams.SmallSampleImage1)
}
}
val smallMean = getMean(time.toArray[Long])
info(s"The mean time of ${time.size} tests for small was: $smallMean ms")
@ -269,21 +286,27 @@ class HashServiceTest extends BaseTest {
info("MD5 Large Image 3684x2736")
val time = new mutable.MutableList[Long]()
for (runNum <- 0 until benchmarkRuns) {
time += getTime { md5TestCase(TestParams.LargeSampleImage1) }
time += getTime {
md5TestCase(TestParams.LargeSampleImage1)
}
}
val largeMean = getMean(time.toArray[Long])
info(s"The mean time of ${time.size} tests for large was: $largeMean ms")
time.clear()
info("MD5 Medium Image 1824x1368")
for (runNum <- 0 until benchmarkRuns) {
time += getTime { md5TestCase(TestParams.MediumSampleImage1) }
time += getTime {
md5TestCase(TestParams.MediumSampleImage1)
}
}
val mediumMean = getMean(time.toArray[Long])
info(s"The mean time of ${time.size} tests for medium was: $mediumMean ms")
time.clear()
info("MD5 Small Image 912x684")
for (runNum <- 0 until benchmarkRuns) {
time += getTime { md5TestCase(TestParams.SmallSampleImage1) }
time += getTime {
md5TestCase(TestParams.SmallSampleImage1)
}
}
val smallMean = getMean(time.toArray[Long])
info(s"The mean time of ${time.size} tests for small was: $smallMean ms")
@ -333,21 +356,27 @@ class HashServiceTest extends BaseTest {
info("getImageHashes with cache Large Image 3684x2736")
val time = new mutable.MutableList[Long]()
for (runNum <- 0 until benchmarkRuns) {
time += getTime { imageHashTestWithCacheCase(TestParams.LargeSampleImage1) }
time += getTime {
imageHashTestWithCacheCase(TestParams.LargeSampleImage1)
}
}
val largeMean = getMean(time.toArray[Long])
info(s"The mean time of ${time.size} tests for large was: $largeMean ms")
time.clear()
info("getImageHashes with cache Medium Image 1824x1368")
for (runNum <- 0 until benchmarkRuns) {
time += getTime { imageHashTestWithCacheCase(TestParams.MediumSampleImage1) }
time += getTime {
imageHashTestWithCacheCase(TestParams.MediumSampleImage1)
}
}
val mediumMean = getMean(time.toArray[Long])
info(s"The mean time of ${time.size} tests for medium was: $mediumMean ms")
time.clear()
info("getImageHashes with cache Small Image 912x684")
for (runNum <- 0 until benchmarkRuns) {
time += getTime { imageHashTestWithCacheCase(TestParams.SmallSampleImage1) }
time += getTime {
imageHashTestWithCacheCase(TestParams.SmallSampleImage1)
}
}
val smallMean = getMean(time.toArray[Long])
info(s"The mean time of ${time.size} tests for small was: $smallMean ms")
@ -360,21 +389,27 @@ class HashServiceTest extends BaseTest {
info("getImageHashes Large Image 3684x2736")
val time = new mutable.MutableList[Long]()
for (runNum <- 0 until benchmarkRuns) {
time += getTime { imageHashTestCase(TestParams.LargeSampleImage1) }
time += getTime {
imageHashTestCase(TestParams.LargeSampleImage1)
}
}
val largeMean = getMean(time.toArray[Long])
info(s"The mean time of ${time.size} tests for large was: $largeMean ms")
time.clear()
info("getImageHashes Medium Image 1824x1368")
for (runNum <- 0 until benchmarkRuns) {
time += getTime { imageHashTestCase(TestParams.MediumSampleImage1) }
time += getTime {
imageHashTestCase(TestParams.MediumSampleImage1)
}
}
val mediumMean = getMean(time.toArray[Long])
info(s"The mean time of ${time.size} tests for medium was: $mediumMean ms")
time.clear()
info("getImageHashes Small Image 912x684")
for (runNum <- 0 until benchmarkRuns) {
time += getTime { imageHashTestCase(TestParams.SmallSampleImage1) }
time += getTime {
imageHashTestCase(TestParams.SmallSampleImage1)
}
}
val smallMean = getMean(time.toArray[Long])
info(s"The mean time of ${time.size} tests for small was: $smallMean ms")

16
engine/src/test/scala/com/sothr/imagetools/engine/image/ImageFilterTest.scala

@ -25,10 +25,18 @@ class ImageFilterTest extends BaseTest{
test("Confirm ImageFiler Fails") {
val filter: ImageFilter = new ImageFilter()
val bogusDirectory = new File(".")
assertResult(false) { filter.accept(bogusDirectory,"test") }
assertResult(false) { filter.accept(bogusDirectory,"test.mp4") }
assertResult(false) { filter.accept(bogusDirectory,"test.gif.mp4") }
assertResult(false) { filter.accept(bogusDirectory,"") }
assertResult(false) {
filter.accept(bogusDirectory, "test")
}
assertResult(false) {
filter.accept(bogusDirectory, "test.mp4")
}
assertResult(false) {
filter.accept(bogusDirectory, "test.gif.mp4")
}
assertResult(false) {
filter.accept(bogusDirectory, "")
}
}
}

6
gui/src/main/java/com/sothr/imagetools/ui/App.java

@ -17,15 +17,13 @@ import java.util.List;
/**
* Image Tools
*/
public class App extends Application
{
public class App extends Application {
private static Logger logger;
private static final String MAINGUI_FXML = "fxml/mainapp/MainApp.fxml";
public static void main( String[] args )
{
public static void main(String[] args) {
AppConfig.configureApp();
try {

74
gui/src/main/resources/fxml/mainapp/MainApp.fxml

@ -5,9 +5,12 @@
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.Font?>
<AnchorPane fx:id="rootPane" minHeight="600.0" minWidth="1024.0" prefHeight="600.0" prefWidth="1024.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sothr.imagetools.ui.controller.AppController">
<AnchorPane fx:id="rootPane" minHeight="600.0" minWidth="1024.0" prefHeight="600.0" prefWidth="1024.0"
xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="com.sothr.imagetools.ui.controller.AppController">
<children>
<MenuBar fx:id="rootMenuBar" minWidth="-Infinity" prefHeight="30.0" prefWidth="600.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<MenuBar fx:id="rootMenuBar" minWidth="-Infinity" prefHeight="30.0" prefWidth="600.0" AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
@ -27,27 +30,35 @@
</Menu>
</menus>
</MenuBar>
<VBox id="VBox" alignment="CENTER" spacing="5.0" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="30.0">
<VBox id="VBox" alignment="CENTER" spacing="5.0" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="30.0">
<children>
<SplitPane dividerPositions="0.2181996086105675" focusTraversable="true" prefHeight="569.0" prefWidth="1024.0" visible="true" VBox.vgrow="ALWAYS">
<SplitPane dividerPositions="0.2181996086105675" focusTraversable="true" prefHeight="569.0" prefWidth="1024.0"
visible="true" VBox.vgrow="ALWAYS">
<items>
<TabPane maxWidth="220.0" minHeight="0.0" minWidth="220.0" prefHeight="567.0" prefWidth="220.0" tabClosingPolicy="UNAVAILABLE">
<TabPane maxWidth="220.0" minHeight="0.0" minWidth="220.0" prefHeight="567.0" prefWidth="220.0"
tabClosingPolicy="UNAVAILABLE">
<tabs>
<Tab closable="false" text="Folders">
<content>
<BorderPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minWidth="200.0" prefWidth="200.0">
<BorderPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minWidth="200.0"
prefWidth="200.0">
<top>
<Button maxWidth="1.7976931348623157E308" minWidth="200.0" mnemonicParsing="false" onAction="#browseFolders" text="Browse" BorderPane.alignment="CENTER" />
<Button maxWidth="1.7976931348623157E308" minWidth="200.0" mnemonicParsing="false"
onAction="#browseFolders" text="Browse" BorderPane.alignment="CENTER"/>
</top>
<center>
<FlowPane prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<children>
<Label maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minWidth="210.0" text="Selected Folder:">
<Label maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minWidth="210.0"
text="Selected Folder:">
<padding>
<Insets left="5.0" right="5.0"/>
</padding>
</Label>
<Label fx:id="selectedDirectoryLabel" alignment="TOP_LEFT" lineSpacing="2.0" maxHeight="1.7976931348623157E308" maxWidth="210.0" minWidth="210.0" prefWidth="210.0" text="&lt;SELECTED&gt;" wrapText="true">
<Label fx:id="selectedDirectoryLabel" alignment="TOP_LEFT" lineSpacing="2.0"
maxHeight="1.7976931348623157E308" maxWidth="210.0" minWidth="210.0"
prefWidth="210.0" text="&lt;SELECTED&gt;" wrapText="true">
<font>
<Font name="System Bold" size="12.0"/>
</font>
@ -59,14 +70,17 @@
</FlowPane>
</center>
<bottom>
<FlowPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="60.0" prefWidth="220.0" BorderPane.alignment="CENTER">
<FlowPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="60.0"
prefWidth="220.0" BorderPane.alignment="CENTER">
<children>
<Button maxWidth="1.7976931348623157E308" minWidth="220.0" mnemonicParsing="false" onAction="#showAllImages" text="Show All Images">
<Button maxWidth="1.7976931348623157E308" minWidth="220.0" mnemonicParsing="false"
onAction="#showAllImages" text="Show All Images">
<FlowPane.margin>
<Insets bottom="5.0"/>
</FlowPane.margin>
</Button>
<Button maxWidth="200.0" minWidth="220.0" mnemonicParsing="false" onAction="#showSimilarImages" text="Show Similar Images" />
<Button maxWidth="200.0" minWidth="220.0" mnemonicParsing="false"
onAction="#showSimilarImages" text="Show Similar Images"/>
</children>
</FlowPane>
</bottom>
@ -80,17 +94,27 @@
<content>
<AnchorPane id="Content" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<AnchorPane id="AnchorPane" maxHeight="50.0" prefHeight="50.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="5.0">
<AnchorPane id="AnchorPane" maxHeight="50.0" prefHeight="50.0" AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="5.0">
<children>
<TextField layoutY="0.0" prefWidth="200.0" text="" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" />
<Button layoutY="27.0" mnemonicParsing="false" prefWidth="192.0" text="Filter" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" />
<TextField layoutY="0.0" prefWidth="200.0" text="" AnchorPane.leftAnchor="20.0"
AnchorPane.rightAnchor="20.0"/>
<Button layoutY="27.0" mnemonicParsing="false" prefWidth="192.0" text="Filter"
AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0"/>
</children>
</AnchorPane>
<ListView fx:id="tagListView" prefHeight="385.0" prefWidth="198.0" AnchorPane.bottomAnchor="60.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="60.0" />
<AnchorPane id="AnchorPane" prefWidth="192.0" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
<ListView fx:id="tagListView" prefHeight="385.0" prefWidth="198.0"
AnchorPane.bottomAnchor="60.0" AnchorPane.leftAnchor="10.0"
AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="60.0"/>
<AnchorPane id="AnchorPane" prefWidth="192.0" AnchorPane.bottomAnchor="5.0"
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
<children>
<Button layoutY="2.0" mnemonicParsing="false" prefWidth="192.0" text="View All Images In Tags" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" />
<Button layoutY="28.0" mnemonicParsing="false" prefWidth="192.0" text="Search For Similarities In Tags" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" />
<Button layoutY="2.0" mnemonicParsing="false" prefWidth="192.0"
text="View All Images In Tags" AnchorPane.leftAnchor="20.0"
AnchorPane.rightAnchor="20.0"/>
<Button layoutY="28.0" mnemonicParsing="false" prefWidth="192.0"
text="Search For Similarities In Tags" AnchorPane.leftAnchor="20.0"
AnchorPane.rightAnchor="20.0"/>
</children>
</AnchorPane>
</children>
@ -111,9 +135,14 @@
<Insets bottom="-5.0"/>
</VBox.margin>
</ToolBar>
<ScrollPane id="ScrollPane" fitToHeight="true" fitToWidth="true" minWidth="600.0" pannable="false" prefViewportHeight="567.0" prefViewportWidth="766.0" vbarPolicy="AS_NEEDED" VBox.vgrow="ALWAYS">
<ScrollPane id="ScrollPane" fitToHeight="true" fitToWidth="true" minWidth="600.0" pannable="false"
prefViewportHeight="567.0" prefViewportWidth="766.0" vbarPolicy="AS_NEEDED"
VBox.vgrow="ALWAYS">
<content>
<TilePane fx:id="imageTilePane" hgap="5.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minWidth="-1.0" prefColumns="6" prefHeight="-1.0" prefTileHeight="160.0" prefTileWidth="160.0" prefWidth="-1.0" tileAlignment="TOP_LEFT" vgap="5.0" />
<TilePane fx:id="imageTilePane" hgap="5.0" maxHeight="1.7976931348623157E308"
maxWidth="1.7976931348623157E308" minWidth="-1.0" prefColumns="6" prefHeight="-1.0"
prefTileHeight="160.0" prefTileWidth="160.0" prefWidth="-1.0" tileAlignment="TOP_LEFT"
vgap="5.0"/>
</content>
<VBox.margin>
<Insets/>
@ -125,7 +154,8 @@
</SplitPane>
</children>
</VBox>
<ToolBar maxHeight="30.0" maxWidth="1.7976931348623157E308" minHeight="30.0" orientation="HORIZONTAL" prefHeight="30.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
<ToolBar maxHeight="30.0" maxWidth="1.7976931348623157E308" minHeight="30.0" orientation="HORIZONTAL"
prefHeight="30.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
<items>
<Label text="Progress:"/>
<Separator orientation="VERTICAL" prefHeight="200.0"/>

3
gui/src/main/scala/com/sothr/imagetools/ui/component/ImageTileFactory.scala

@ -7,7 +7,6 @@ import javafx.scene.control.{Label, Tooltip}
import javafx.scene.image.{Image, ImageView}
import javafx.scene.input.MouseEvent
import com.sothr.imagetools.engine.image
import grizzled.slf4j.Logging
import resource._
@ -18,7 +17,7 @@ import resource._
*/
object ImageTileFactory extends Logging {
def get(image:image.Image):ImageTile = {
def get(image: com.sothr.imagetools.engine.image.Image): ImageTile = {
val imageTile = new ImageTile()
imageTile.setImageData(image)
//set tile size

2
gui/src/main/scala/com/sothr/imagetools/ui/controller/AppController.scala

@ -10,9 +10,9 @@ import javafx.scene.web.WebView
import javafx.scene.{Group, Node, Scene}
import javafx.stage.{DirectoryChooser, Stage, StageStyle}
import com.sothr.imagetools.engine.util.{PropertiesService, ResourceLoader}
import com.sothr.imagetools.engine.{ConcurrentEngine, Engine}
import com.sothr.imagetools.ui.component.ImageTileFactory
import com.sothr.imagetools.engine.util.{PropertiesService, ResourceLoader}
import grizzled.slf4j.Logging
import org.markdown4j.Markdown4jProcessor

2
gui/version.info

@ -1 +1 @@
0.1.1-DEV-13-661ba6d
0.1.1-DEV-15-15ce4f1
Loading…
Cancel
Save