2010-11-18 14 views
2

Je voudrais obtenir le contenu d'un répertoire qui contient des fichiers arbitraires (un répertoire "Téléchargements" typique) et déterminer par programme si un fichier donné est une Image de n'importe quel type. Je travaille dans Clojure mais tout ce qui est disponible sur la JVM est un jeu équitable.Comment puis-je déterminer si un fichier est une image sur la machine virtuelle Java?

Merci d'avance!

+1

Voici un lien utile: http://webcache.googleusercontent.com/search?q=cache:2Gkd-GcGI5AJ:forums.sun.com/thread.jspa%3FthreadID%3D5398376 + java + déterminer + si + un + fichier + est + an + image & cd = 1 & hl = sv & ct = clnk & gl = se & client = firefox-a –

Répondre

2

A fini de pouvoir résoudre ceci en combinant le commentaire sur votre question avec ma réponse antérieure de here. Modification mineure au code le laisser fonctionner avec des images qui ne sont pas des images.

Je ne l'ai pas changé pour recurse aux sous-répertoires. Serait assez facile à faire.

(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]) 

Après avoir réfléchi à ce sujet pour un peu il se sent sale de combiner le contrôle d'un fichier étant une image avec le tirant sur la largeur et la hauteur. Vous pouvez également définir une fonction qui effectue ce filtrage séparément et vous donne une suite d'images.

(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

Une bonne réponse: dès que je vais jouer avec le code, je vais probablement accepter, merci beaucoup. –

2

Évidemment, la chose la plus facile à faire est de regarder l'extension du nom de fichier. Bien sûr, ce n'est pas nécessairement fiable, mais cela peut suffire dans certaines circonstances. À moins de lire toute l'image, vous pouvez lire les premiers octets du fichier pour l'identifier par son «numéro magique». Par exemple, les fichiers JPEG commencent toujours par les deux octets 0xFFD8 et se terminent par 0xFFD9; Les fichiers PDF commencent toujours par la chaîne "% PDF". Cela vous évite d'avoir à créer une image en mémoire et pourrait aussi accélérer vos E/S (puisque vous n'avez besoin que de quelques octets du fichier).

Si vous ne voulez pas rechercher vous-même tous ces nombres magiques, vous pouvez essayer une bibliothèque telle que jMimeMagic. Je ne l'ai jamais utilisé, donc je ne peux pas garantir sa qualité ou son exhaustivité, mais c'est LGPL. Je suis sûr que vous pouvez trouver d'autres alternatives.

+0

tika bibliothèque a une licence plus appropriée ;-) –

+0

Je ne voudrais pas dire quelle licence est la plus approprié pour le projet de quelqu'un d'autre, mais tika ressemble à une bibliothèque robuste et bien développée. Merci pour la suggestion. – eaj

+0

c'est très simple, faites juste (utilisez 'tika) (fichier type-detect-mime), mais au lieu de fichier vous pouvez utiliser string, url ou InputStream –

2

Vous pouvez utiliser le Tika library capable de détecter de nombreux types de fichiers et d'extraire des métadonnées de plusieurs d'entre eux. J'ai très simple Clojure wrapper pour cela

+0

Pourriez-vous fournir un exemple de code à l'effet de '(filter is -image (file-seq "dir") '? Je pense que c'est comme ça que je veux que la fonction apparaisse qui fonctionne dans le répertoire –