Browse Source

Started work on database integration. Cleaned up caching of thumbnails and improved performance of the thumb path method.

master
Drew Short 10 years ago
parent
commit
0fcad44e4e
  1. 55
      pom.xml
  2. 87
      src/main/resources/application.conf
  3. 34
      src/main/resources/hibernate.cfg.xml
  4. 23
      src/main/scala/com/sothr/imagetools/image/ImageService.scala
  5. 87
      src/test/resources/application.conf
  6. 9
      todo

55
pom.xml

@ -26,9 +26,6 @@
</pluginRepositories>
<properties>
<project.version.major>0</project.version.major>
<project.version.minor>1</project.version.minor>
<project.version.tag>DEV</project.version.tag>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jdk.version>1.7</jdk.version>
<lib.junit.version>3.8.1</lib.junit.version>
@ -46,6 +43,8 @@
<lib.jtransforms.version>2.4.0</lib.jtransforms.version>
<lib.typesafe-config.version>1.2.0</lib.typesafe-config.version>
<lib.thumbnailator.version>[0.4, 0.5)</lib.thumbnailator.version>
<lib.h2database.version>1.3.175</lib.h2database.version>
<lib.hibernate.version>4.3.0.Final</lib.hibernate.version>
</properties>
<dependencies>
@ -62,19 +61,19 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${lib.logback.version}</version>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${lib.logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${lib.logback.version}</version>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${lib.logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
<version>${lib.logback.version}</version>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
<version>${lib.logback.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
@ -107,9 +106,9 @@
<version>${lib.jtransforms.version}</version>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>${lib.commons-cli.version}</version>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>${lib.commons-cli.version}</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
@ -132,9 +131,24 @@
<version>${lib.akka.version}</version>
</dependency>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-slf4j_2.10</artifactId>
<version>${lib.akka.version}</version>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-slf4j_2.10</artifactId>
<version>${lib.akka.version}</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${lib.h2database.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${lib.hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>${lib.hibernate.version}</version>
</dependency>
</dependencies>
@ -336,7 +350,10 @@
<execution>
<phase>process-resources</phase>
<configuration>
<tasks>
<tasks>
<copy todir="${basedir}/src/test/resources/hibernate">
<fileset dir="${basedir}/src/main/resources/hibernate" includes="**/*" />
</copy>
<copy file="${project.build.directory}/version.info" toFile="${basedir}/version.info" overwrite="true" />
<copy file="${project.build.directory}/name.info" toFile="${basedir}/name.info" overwrite="true" />
<copy file="${project.build.directory}/LICENSE" toFile="${basedir}/LICENSE" overwrite="true" />

87
src/main/resources/application.conf

@ -8,48 +8,53 @@ akka {
//Default App Settings
app {
version.current = "${build-version}"
timed = false
engine {
//Concurrency Settings
concurrent {
similarity.limit = 15
processing.limit = 15
}
version.current = "${build-version}"
timed = false
engine {
//Concurrency Settings
concurrent {
similarity.limit = 15
processing.limit = 15
}
#Default Image Settings
image {
//images must be 90% similar
differenceThreshold = 0.90
//control generation of hashes for new images.
hash {
precision=64
}
ahash {
use = true
weight = 0.70
precision = 8
tolerence = 8
}
dhash {
use = true
weight = 0.85
precision = 8
tolerence = 8
}
phash {
//set to false if hashing images is taking too long
use = true
weight = 1.0
precision = 32
tolerence = 8
}
}
#Default Image Settings
image {
//images must be 90% similar
differenceThreshold = 0.90
//control generation of hashes for new images.
hash {
precision=64
}
//Default Thumbnail Settings
thumbnail {
//Directory where to store thumbnails
directory = ".cache/thumbnails/"
//Size of the thumbnail to generate and store
size = 128
ahash {
use = true
weight = 0.70
precision = 8
tolerence = 8
}
dhash {
use = true
weight = 0.85
precision = 8
tolerence = 8
}
phash {
//set to false if hashing images is taking too long
use = true
weight = 1.0
precision = 32
tolerence = 8
}
}
//Default Thumbnail Settings
thumbnail {
//Directory where to store thumbnails
directory = ".cache/thumbnails/"
//Size of the thumbnail to generate and store
size = 128
}
//Default Database Settings
database {
location = ".cache/database.db"
inMemory = false
}
}

34
src/main/resources/hibernate.cfg.xml

@ -0,0 +1,34 @@
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<!-- a SessionFactory instance listed as /jndi/name -->
<session-factory
name="java:hibernate/SessionFactory">
<!-- properties -->
<property name="connection.driver_class">org.h2.Driver</property>
<property name="connection.datasource">jdbc:h2:.cache/database.db</property>
<property name="dialect">org.hibernate.dialect.H2Dialect</property>
<property name="show_sql">false</property>
<property name="transaction.factory_class">
org.hibernate.transaction.JTATransactionFactory
</property>
<property name="jta.UserTransaction">java:comp/UserTransaction</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- mapping files -->
<!--<mapping resource="hibernate/"/>-->
<!-- cache settings -->
<!--<class-cache class="org.hibernate.auction.Item" usage="read-write"/>
<class-cache class="org.hibernate.auction.Bid" usage="read-only"/>
<collection-cache collection="org.hibernate.auction.Item.bids" usage="read-write"/>-->
</session-factory>
</hibernate-configuration>

23
src/main/scala/com/sothr/imagetools/image/ImageService.scala

@ -14,7 +14,6 @@ import com.sothr.imagetools.util.{PropertiesEnum, PropertiesService}
object ImageService extends Logging {
val imageCache = AppConfig.cacheManager.getCache("images")
val thumbnailCache = AppConfig.cacheManager.getCache("thumbnails")
private def lookupImage(file:File):Image = {
var image:Image = null
@ -45,7 +44,7 @@ object ImageService extends Logging {
val bufferedImage = ImageIO.read(file)
val hashes = HashService.getImageHashes(bufferedImage, file.getAbsolutePath)
var thumbnailPath = lookupThumbnailPath(hashes.md5)
if (thumbnailPath == null) thumbnailPath = saveThumbnail(hashes.md5, getThumbnail(bufferedImage, hashes.md5))
if (thumbnailPath == null) thumbnailPath = getThumbnail(bufferedImage, hashes.md5)
val imageSize = { (bufferedImage.getWidth, bufferedImage.getHeight) }
val image = new Image(file.getAbsolutePath, thumbnailPath, imageSize, hashes)
debug(s"Created image: $image")
@ -61,8 +60,9 @@ object ImageService extends Logging {
def calculateThumbPath(md5:String):String = {
//break the path down into 4 char parts
val split:List[String] = md5.grouped(4).toList
var path:String = PropertiesService.get(PropertiesEnum.ThumbnailDirectory.toString) + PropertiesService.get(PropertiesEnum.ThumbnailSize.toString) + "/"
for (seg <- split) path += seg + "/"
var dirPath = ""
for (seg <- split) dirPath += seg + "/"
var path:String = s"${PropertiesService.get(PropertiesEnum.ThumbnailDirectory.toString)}${PropertiesService.get(PropertiesEnum.ThumbnailSize.toString)}/$dirPath"
try {
val dir = new File(path)
if (!dir.exists()) dir.mkdirs()
@ -76,13 +76,6 @@ object ImageService extends Logging {
def lookupThumbnailPath(md5:String):String = {
var thumbPath:String = null
if (md5 != null) {
//get from memory cache if possible
try {
if (thumbnailCache.isKeyInCache(md5)) thumbPath = thumbnailCache.get(md5).getObjectValue.asInstanceOf[String]
} catch {
case npe:NullPointerException => error(s"Error grabbing \'$md5\' from cache. thumbPath: \'$thumbPath\'", npe)
}
//get from datastore if possible
//check for the actual file
val checkPath = calculateThumbPath(md5)
if (new File(checkPath).exists) thumbPath = checkPath
@ -108,14 +101,6 @@ object ImageService extends Logging {
path
}
def saveThumbnail(md5:String, thumbnailPath:String):String = {
if (md5 == null || thumbnailPath == null) error(s"Error trying to save a md5: $md5 path: $thumbnailPath")
//save to cache
thumbnailCache.put(new Element(md5, thumbnailPath))
//save to datastore
thumbnailPath
}
/**
* Get the raw data for an image
*/

87
src/test/resources/application.conf

@ -8,48 +8,53 @@ akka {
//Default App Settings
app {
version.current = "${build-version}"
timed = false
engine {
//Concurrency Settings
concurrent {
similarity.limit = 2
processing.limit = 2
}
version.current = "${build-version}"
timed = false
engine {
//Concurrency Settings
concurrent {
similarity.limit = 2
processing.limit = 2
}
#Default Image Settings
image {
//images must be 90% similar
differenceThreshold = 0.90
//control generation of hashes for new images.
hash {
precision=64
}
ahash {
use = true
weight = 0.70
precision = 8
tolerence = 8
}
dhash {
use = true
weight = 0.85
precision = 8
tolerence = 8
}
phash {
//set to false if hashing images is taking too long
use = true
weight = 1.0
precision = 32
tolerence = 8
}
}
#Default Image Settings
image {
//images must be 90% similar
differenceThreshold = 0.90
//control generation of hashes for new images.
hash {
precision=64
}
//Default Thumbnail Settings
thumbnail {
//Directory where to store thumbnails
directory = ".cache/thumbnails/"
//Size of the thumbnail to generate and store
size = 128
ahash {
use = true
weight = 0.70
precision = 8
tolerence = 8
}
dhash {
use = true
weight = 0.85
precision = 8
tolerence = 8
}
phash {
//set to false if hashing images is taking too long
use = true
weight = 1.0
precision = 32
tolerence = 8
}
}
//Default Thumbnail Settings
thumbnail {
//Directory where to store thumbnails
directory = ".cache/thumbnails/"
//Size of the thumbnail to generate and store
size = 128
}
//Default Database Settings
database {
location = ".cache/database.db"
inMemory = false
}
}

9
todo

@ -6,4 +6,11 @@ Add functionality to ImageService
-Generate thumbnails
Improve functionality of the PropertiesService
-Getters and Setters for sepcific values with proper cascading and type awareness
-Nicer debugging?
-Nicer debugging?
Hibernate - H2 intergration
- setup hibernate
- setup h2
- setup C3P0 connection pool
- transfer configuration files
- autoload configuration files?
- map DTO's
Loading…
Cancel
Save