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.

180 lines
6.2 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
10 years ago
  1. package com.sothr.imagetools.engine
  2. import java.io.File
  3. import akka.actor._
  4. import com.sothr.imagetools.engine.image.{Image, ImageFilter, ImageService, SimilarImages}
  5. import com.sothr.imagetools.engine.util.DirectoryFilter
  6. import grizzled.slf4j.Logging
  7. import scala.collection.mutable
  8. /**
  9. * Engine definition
  10. *
  11. * Created by drew on 1/26/14.
  12. */
  13. abstract class Engine extends Logging {
  14. val system = ActorSystem("EngineActorSystem")
  15. val imageFilter: ImageFilter = new ImageFilter()
  16. val imageCache = AppConfig.cacheManager.getCache("images")
  17. //file search listener
  18. var searchedListener = system.actorOf(Props[DefaultLoggingEngineListener],
  19. name = "SearchedEngineListener")
  20. def setSearchedListener(listenerRef: ActorRef) = {
  21. this.searchedListener = listenerRef
  22. }
  23. def setProcessedListener(listenerType: ActorRef)
  24. def setSimilarityListener(listenerType: ActorRef)
  25. def getAllImageFiles(directoryPath: String, recursive: Boolean = false, recursiveDepth: Int = 500): List[File] = {
  26. val fileList = new mutable.MutableList[File]()
  27. if (directoryPath != null && directoryPath != "") {
  28. val directory: File = new File(directoryPath)
  29. val imageFilter = new ImageFilter
  30. if (directory.isDirectory) {
  31. val files = directory.listFiles(imageFilter)
  32. if (files != null) {
  33. fileList ++= files
  34. debug(s"Found ${files.length} files that are images in directory: $directoryPath")
  35. if (recursive) {
  36. val directoryFilter = new DirectoryFilter
  37. val directories = directory.listFiles(directoryFilter)
  38. for (directory <- directories) {
  39. fileList ++= getAllImageFiles(directory.getAbsolutePath, recursive, recursiveDepth - 1)
  40. this.searchedListener ! SubmitMessage(s"Found ${fileList.length} files to process")
  41. }
  42. } else {
  43. this.searchedListener ! SubmitMessage(s"Found ${fileList.length} files to process")
  44. }
  45. }
  46. }
  47. }
  48. fileList.toList
  49. }
  50. /**
  51. * Get all images for a directory with hashes
  52. */
  53. def getImagesForDirectory(directoryPath: String, recursive: Boolean = false, recursiveDepth: Int = 500): List[Image]
  54. /**
  55. * Get all similar images for a directory with hashes
  56. */
  57. def getSimilarImagesForDirectory(directoryPath: String, recursive: Boolean = false, recursiveDepth: Int = 500): List[SimilarImages]
  58. def deleteImage(image: Image): Unit = {
  59. ImageService.deleteImage(image)
  60. }
  61. def deleteImages(images: List[Image]): Unit = {
  62. for (image <- images) {
  63. deleteImage(image)
  64. }
  65. }
  66. /**
  67. * Go through the list of similarities and group them so that they represent actual similarities
  68. *
  69. * For example. A is similar to B and C is similar to B but A is was not considered similar to C. Therefore A B and C should be considered similar unless otherwise noted.
  70. *
  71. * @param similarList a list of detected similar images
  72. * @return a grouped and combined list of similar images
  73. */
  74. def processSimilarities(similarList: List[SimilarImages]): List[SimilarImages] = {
  75. //process the result into a list we want in cleanedSimilarImages
  76. var count = 0
  77. val cleanedSimilarImages = new mutable.MutableList[SimilarImages]()
  78. val ignoreSet = new mutable.HashSet[Image]()
  79. for (similarImages <- similarList) {
  80. count += 1
  81. if (count % 25 == 0 || count == similarList.length) debug(s"Cleaning similar image $count/${similarList.length} ${similarList.length - count} left to clean")
  82. if (!ignoreSet.contains(similarImages.rootImage)) {
  83. cleanedSimilarImages += similarImages
  84. ignoreSet += similarImages.rootImage
  85. for (image <- similarImages.similarImages) {
  86. ignoreSet += image
  87. }
  88. }
  89. //rewrite todo:
  90. /*
  91. Go through all the images. If a similar image for the image doesn't exist, create it. if it does,
  92. add it to that similar image. The end result is that all images should be grouped according to
  93. their similar images and images that are similar to them.
  94. */
  95. }
  96. //return a non mutable cleaned list
  97. cleanedSimilarImages.toList
  98. }
  99. }
  100. case class SubmitMessage(message: String)
  101. case class ScannedFileCount(count: Integer, total: Integer, message: String = null)
  102. case class ComparedFileCount(count: Integer, total: Integer, message: String = null)
  103. abstract class EngineListener extends Actor with ActorLogging {
  104. override def receive: Actor.Receive = {
  105. case command: SubmitMessage => handleMessage(command)
  106. case command: ScannedFileCount => handleScannedFileCount(command)
  107. case command: ComparedFileCount => handleComparedFileCount(command)
  108. case _ => log.info("received unknown message")
  109. }
  110. def handleMessage(command: SubmitMessage)
  111. def handleScannedFileCount(command: ScannedFileCount)
  112. def handleComparedFileCount(command: ComparedFileCount)
  113. }
  114. /**
  115. * Actor for logging output information
  116. */
  117. class DefaultLoggingEngineListener extends EngineListener with ActorLogging {
  118. override def handleComparedFileCount(command: ComparedFileCount): Unit = {
  119. if (command.message != null) {
  120. log.info(command.message)
  121. }
  122. log.info("Processed {}/{}", command.count, command.total)
  123. }
  124. override def handleScannedFileCount(command: ScannedFileCount): Unit = {
  125. if (command.message != null) {
  126. log.info(command.message)
  127. }
  128. log.info("Scanned {}/{} For Similarities", command.count, command.total)
  129. }
  130. override def handleMessage(command: SubmitMessage): Unit = {
  131. log.info(command.message)
  132. }
  133. }
  134. /**
  135. * Actor for writing progress out to the commandline
  136. */
  137. class CLIEngineListener extends EngineListener with ActorLogging {
  138. override def handleComparedFileCount(command: ComparedFileCount): Unit = {
  139. if (command.message != null) {
  140. System.out.println(command.message)
  141. }
  142. System.out.println(s"Processed ${command.count}/${command.total}")
  143. }
  144. override def handleScannedFileCount(command: ScannedFileCount): Unit = {
  145. if (command.message != null) {
  146. System.out.println(command.message)
  147. }
  148. System.out.println(s"Scanned ${command.count}/${command.total} For Similarities")
  149. }
  150. override def handleMessage(command: SubmitMessage): Unit = {
  151. System.out.println(command.message)
  152. }
  153. }