You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
5.5 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. package com.sothr.imagetools.engine.image
  2. import java.awt.image.BufferedImage
  3. import java.io.{File, IOException}
  4. import javax.imageio.ImageIO
  5. import com.sothr.imagetools.engine.AppConfig
  6. import com.sothr.imagetools.engine.dao.ImageDAO
  7. import com.sothr.imagetools.engine.util.{PropertiesService, PropertyEnum}
  8. import com.sothr.imagetools.engine.vo.ImageHashVO
  9. import com.sothr.imagetools.hash.{HashService, ImageHash}
  10. import com.sothr.imagetools.hash.util.ImageUtil
  11. import grizzled.slf4j.Logging
  12. import net.sf.ehcache.Element
  13. import org.hibernate.HibernateException
  14. object ImageService extends Logging {
  15. val imageCache = AppConfig.cacheManager.getCache("images")
  16. private val imageDAO = new ImageDAO()
  17. def getImage(file: File): Image = {
  18. try {
  19. val image = lookupImage(file)
  20. if (image != null) {
  21. debug(s"${file.getAbsolutePath} was already processed")
  22. return image
  23. } else {
  24. debug(s"Processing image: ${file.getAbsolutePath}")
  25. val bufferedImage = ImageIO.read(file)
  26. val hashes = HashService.getImageHashes(
  27. PropertiesService.aHashSettings,
  28. PropertiesService.dHashSettings,
  29. PropertiesService.pHashSettings,
  30. bufferedImage,
  31. file.getAbsolutePath)
  32. var thumbnailPath = lookupThumbnailPath(hashes.fileHash)
  33. if (thumbnailPath == null) thumbnailPath = getThumbnail(bufferedImage, hashes.fileHash)
  34. val imageSize = {
  35. (bufferedImage.getWidth, bufferedImage.getHeight)
  36. }
  37. val image = new Image(file.getAbsolutePath, thumbnailPath, imageSize, ImageService.convertToImageHashVO(hashes))
  38. debug(s"Created image: $image")
  39. return saveImage(image)
  40. }
  41. } catch {
  42. case ioe: IOException => error(s"Error processing ${file.getAbsolutePath}... ${ioe.getMessage}")
  43. case ex: Exception => error(s"Error processing ${file.getAbsolutePath}... ${ex.getMessage}", ex)
  44. }
  45. null
  46. }
  47. def convertToImageHashDTO(imageHashVO: ImageHashVO): ImageHash = {
  48. new ImageHash(imageHashVO.ahash, imageHashVO.dhash, imageHashVO.phash, imageHashVO.fileHash)
  49. }
  50. def convertToImageHashVO(imageHashDTO: ImageHash): ImageHashVO = {
  51. new ImageHashVO(imageHashDTO.ahash, imageHashDTO.dhash, imageHashDTO.phash, imageHashDTO.fileHash)
  52. }
  53. private def lookupImage(file: File): Image = {
  54. var image: Image = null
  55. var found = false
  56. //get from memory cache if possible
  57. try {
  58. if (imageCache.isKeyInCache(file.getAbsolutePath)) {
  59. image = imageCache.get(file.getAbsolutePath).getObjectValue.asInstanceOf[Image]
  60. found = true
  61. }
  62. } catch {
  63. case npe: NullPointerException => debug(s"\'${file.getAbsolutePath}\' was supposed to be in the cache, but was not")
  64. }
  65. //get from datastore if possible
  66. if (!found) {
  67. try {
  68. val tempImage = imageDAO.find(file.getAbsolutePath)
  69. if (tempImage != null) image = tempImage
  70. } catch {
  71. case ex: Exception => error(s"Error looking up \'${file.getAbsolutePath}\' was supposed to be in the database, but was not", ex)
  72. }
  73. }
  74. image
  75. }
  76. private def saveImage(image: Image): Image = {
  77. //save to cache
  78. imageCache.put(new Element(image.imagePath, image))
  79. //save to datastore
  80. try {
  81. imageDAO.save(image)
  82. } catch {
  83. case ex: Exception => error(s"Error saving \'${image.imagePath}\' to database", ex)
  84. }
  85. image
  86. }
  87. def lookupThumbnailPath(md5: String): String = {
  88. var thumbPath: String = null
  89. if (md5 != null) {
  90. //check for the actual file
  91. val checkPath = calculateThumbPath(md5)
  92. if (new File(checkPath).exists) thumbPath = checkPath
  93. } else {
  94. error("Null md5 passed in")
  95. }
  96. thumbPath
  97. }
  98. def calculateThumbPath(md5: String): String = {
  99. //break the path down into 4 char parts
  100. val subPath = md5.substring(0, 3)
  101. var path: String = s"${PropertiesService.get(PropertyEnum.ThumbnailDirectory.toString)}${PropertiesService.get(PropertyEnum.ThumbnailSize.toString)}/$subPath/"
  102. try {
  103. val dir = new File(path)
  104. if (!dir.exists()) dir.mkdirs()
  105. } catch {
  106. case ioe: IOException => error(s"Unable to create dirs for path: \'$path\'", ioe)
  107. }
  108. path += md5 + ".jpg"
  109. path
  110. }
  111. def getThumbnail(image: BufferedImage, md5: String): String = {
  112. //create thumbnail
  113. val thumb = ImageUtil.resize(image, PropertiesService.get(PropertyEnum.ThumbnailSize.toString).toInt, forced = false)
  114. //calculate path
  115. val path = calculateThumbPath(md5)
  116. // save thumbnail to path
  117. try {
  118. ImageIO.write(thumb, "png", new File(path))
  119. debug(s"Wrote thumbnail to $path")
  120. } catch {
  121. case ioe: IOException => error(s"Unable to save thumbnail to $path", ioe)
  122. }
  123. // return path
  124. path
  125. }
  126. def deleteImage(image: Image) = {
  127. debug(s"Attempting to delete all traces of image: ${image.getImagePath}")
  128. try {
  129. val imageFile = new File(image.imagePath)
  130. //try to delete the file
  131. imageFile.delete()
  132. //purge the file from the database and cache
  133. this.imageCache.remove(imageFile.getAbsolutePath)
  134. this.imageDAO.delete(image)
  135. } catch {
  136. case se: SecurityException => error(s"Unable to delete file: ${image.getImagePath} due to a security exception", se)
  137. case ise: IllegalStateException => error(s"Unable to delete file: ${image.getImagePath} due to an illegal state exception", ise)
  138. case he: HibernateException => error(s"Unable to delete file: ${image.getImagePath} due to a hibernate exception", he)
  139. }
  140. }
  141. }