【问题标题】:How can I determine if a file is an image on the JVM?如何确定文件是否是 JVM 上的图像?
【发布时间】:2010-11-18 17:54:39
【问题描述】:

我想获取包含任意文件的目录(典型的“下载”目录)的内容,并以编程方式确定给定文件是否是任何类型的图像。

我在 Clojure 工作,但 JVM 上可用的任何东西都是公平的游戏。

提前致谢!

【问题讨论】:

标签: image clojure jvm


【解决方案1】:

最终能够通过将您对问题的评论与我之前在here 的回答相结合来解决这个问题。对代码的微小改动让它可以处理非图像的图像。

我没有将其更改为递归到子目录。很容易做到。

(defn files-in-dir [dir]                                                                                                               
  (filter #(not (.isDirectory %))                                                                                                      
          (.listFiles (java.io.File. dir))))                                                                                           

(defn figure-out-height-width                                                                                                          
  [files]                                                                                                                              
  (remove nil?                                                                                                                         
          (map (fn [file]                                                                                                               
                 (with-open [r (java.io.FileInputStream. file)]                                                                        
                   (if-let [img (javax.imageio.ImageIO/read r)]                                                                        
                     [file (.getWidth img) (.getHeight img)])))                                                                        
               files)))                                                                                                                

user> (pprint (files-in-dir "/home/jmccrary/Downloads/"))                                                                              
(#<File /home/jmccrary/Downloads/Girl_Talk_-_All_Day_(IA123)_mp3s.zip>                                                                 
 #<File /home/jmccrary/Downloads/CSS3-for-Web-Designers.zip>                                                                           
 #<File /home/jmccrary/Downloads/manual.pdf>                                                                                           
 #<File /home/jmccrary/Downloads/test.jpeg>                                                                                            
 #<File /home/jmccrary/Downloads/nautilus-dropbox_0.6.7_amd64.deb>                                                                     
 #<File /home/jmccrary/Downloads/rubygems-1.3.7.tgz>                                                                                   
 #<File /home/jmccrary/Downloads/HTML5-FOR-WEB-DESIGNERS.zip>                                                                          
 #<File /home/jmccrary/Downloads/bcompare-3.1.11.12238.tar.gz>                                                                         
 #<File /home/jmccrary/Downloads/shared_ptr_example.cpp>)                                                                              
nil                                                                                                                                    
user> (figure-out-height-width (files-in-dir "/home/jmccrary/Downloads"))                                                              
([#<File /home/jmccrary/Downloads/test.jpeg> 32 32])

考虑了一下之后,将检查文件是否为图像与提取宽度和高度结合起来感觉很脏。或者,您可以定义一个单独执行此过滤并为您提供一系列图像的函数。

(defn filter-images                                                                                                                    
  [files]                                                                                                                              
  (reduce (fn [res file]                                                                                                                
            (if-let [img (javax.imageio.ImageIO/read file)]                                                                            
              (conj res img)                                                                                                           
              res))                                                                                                                    
          []                                                                                                                           
          files))

user> (filter-images (files-in-dir "/home/jmccrary/Downloads"))                                                                        
[#<BufferedImage BufferedImage@24753433: type = 5 ColorModel: #pixelBits = 24 numComponents = 3 color space = java.awt.color.ICC_Color\
Space@43036651 transparency = 1 has alpha = false isAlphaPre = false ByteInterleavedRaster: width = 32 height = 32 #numDataElements 3 \
dataOff[0] = 2>

]

【讨论】:

  • 很好的答案。一旦我开始使用代码,我可能会接受。非常感谢。
【解决方案2】:

显然,最简单的方法是查看文件扩展名。当然,它不一定可靠,但在某些情况下可能就足够了。

除了读取整个图像之外,您还可以读取文件的前几个字节以通过其“幻数”来识别它。例如,JPEG 文件总是以两个字节 0xFFD8 开始,以 0xFFD9 结束; PDF 始终以字符串“%PDF”开头。

这可以节省您在内存中创建图像的开销,并且还可以加快您的 I/O(因为您只需要文件的几个字节)。

如果您不想自己研究所有这些神奇数字,可以尝试使用 jMimeMagic 之类的库。我从未使用过它,所以我不能保证它的质量或完整性,但它是 LGPL。我相信您也可以找到其他替代方案。

【讨论】:

  • tika 库有更合适的许可证 ;-)
  • 我不会说哪种许可证最适合其他人的项目,但 tika 看起来像一个健壮且开发良好的库。感谢您的建议。
  • 这很简单,只要做(使用'tika)(检测-mime-type文件),但可以使用字符串、url或InputStream代替文件
【解决方案3】:

您可以使用Tika library,它能够检测多种类型的文件,还可以从其中提取元数据。我有很简单的Clojure wrapper

【讨论】:

  • 您介意提供一些示例代码以达到(filter is-image (file-seq "dir") 的效果吗?我在想这就是我希望我在目录上运行的功能。
猜你喜欢
  • 2010-10-14
  • 1970-01-01
  • 2012-06-19
  • 2012-03-10
  • 2015-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-13
相关资源
最近更新 更多