2010-11-18 3 views
2

Я хотел бы получить содержимое каталога, содержащего произвольные файлы (типичный каталог «Загрузки») и определить программно, если данный файл является изображением любого типа.Как определить, является ли файл изображением на JVM?

Я работаю в Clojure, но все, что доступно на JVM, - это честная игра.

Заранее благодарен!

+1

Вот полезная ссылка: http://webcache.googleusercontent.com/search?q=cache:2Gkd-GcGI5AJ:forums.sun.com/thread.jspa%3FthreadID%3D5398376 + java + define + if + a + file + is + an + image & cd = 1 & hl = sv & ct = clnk & gl = se & client = firefox-a –

ответ

2

Законченный способ решить это, объединив комментарий по вашему вопросу вместе с моим более ранним ответом от 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 [email protected]: type = 5 ColorModel: #pixelBits = 24 numComponents = 3 color space = java.awt.color.ICC_Color\ 
[email protected] transparency = 1 has alpha = false isAlphaPre = false ByteInterleavedRaster: width = 32 height = 32 #numDataElements 3 \ 
dataOff[0] = 2> 

]

+0

Отличный ответ. Как только я займусь игрой с кодом, я, вероятно, Примите. Большое спасибо. –

2

Очевидно, что самая простая задача - посмотреть расширение файла. Конечно, это не обязательно надежно, но в некоторых случаях этого может быть достаточно.

Не прочитав всего изображения, вы можете прочитать первые несколько байтов файла, чтобы идентифицировать его по его «магическому числу». Например, файлы JPEG всегда начинаются с двух байтов 0xFFD8 и заканчиваются 0xFFD9; PDF-файлы всегда начинаются со строки «% PDF».

Это экономит ваше время на создание изображения в памяти и может ускорить ваш ввод-вывод (так как вам нужно всего несколько байтов файла).

Если вы не хотите исследовать все эти магические числа самостоятельно, вы можете попробовать библиотеку, такую ​​как jMimeMagic. Я никогда не использовал его, поэтому я не могу ручаться за его качество или полноту, но это LGPL. Я уверен, что вы можете найти и другие альтернативы.

+0

tika library имеет более подходящую лицензию ;-) –

+0

Я бы не сказал, какая лицензия больше всего подходит для чужого проекта, но тика выглядит как прочная и хорошо развитая библиотека. Спасибо за предложение. – eaj

+0

Это очень просто, просто сделайте (используйте «tika» (файл типа «тип-mime»), но вместо файла вы можете использовать строку, url или InputStream. –

2

Вы можете использовать Tika library, который способен обнаруживать многие типы файлов, а также извлекать метаданные из многих из них. У меня очень просто Clojure wrapper для него

+0

Не могли бы вы предоставить некоторый пример кода для эффекта '(фильтр -image (file-seq "dir") '? Я так думаю, что я хочу, чтобы функция выглядела так, как работает в каталоге. –

Смежные вопросы