2010-06-11 4 views
0

J'ai utilisé ce petit extrait pour sélectionner des images aléatoires. Cependant, je voudrais le changer pour ne sélectionner que des images d'une certaine taille. Je rencontre des problèmes pour vérifier la taille de l'image. Si j'utilise get_image_dimensions(), j'ai besoin d'une instruction conditionnelle, ce qui nécessite d'autoriser les exceptions. Donc, je suppose que j'ai besoin de quelques indications sur la limitation par les dimensions de l'image. Merci.Comment sélectionner une image aléatoire de taille spécifique en utilisant Django/Python?

import os 
import random 
import posixpath 
from django import template 
from django.conf import settings 

register = template.Library() 

def is_image_file(filename): 
    """Does `filename` appear to be an image file?""" 
    img_types = [".jpg", ".jpeg", ".png", ".gif"] 
    ext = os.path.splitext(filename)[1] 
    return ext in img_types 

@register.simple_tag 
def random_image(path): 
    """ 
    Select a random image file from the provided directory 
    and return its href. `path` should be relative to MEDIA_ROOT. 

    Usage: <img src='{% random_image "images/whatever/" %}'> 
    """ 
    fullpath = os.path.join(settings.MEDIA_ROOT, path) 
    filenames = [f for f in os.listdir(fullpath) if is_image_file(f)] 
    pick = random.choice(filenames) 
    return posixpath.join(settings.MEDIA_URL, path, pick) 

Répondre

1

Eh bien, d'une manière plus directe pour obtenir les dimensions de l'image est d'utiliser la Python Imaging Library (qui est ce que Django utilise pour get_image_dimensions dans le back-end de toute façon).

Alors, vous l'utilisez comme:

>> import Image 
>> img = Image.open("foo.png") 
>> img.size 
(1729,828) 

Et votre solution la plus simple serait quelque chose comme:

img_dimensions = lambda f: Image.open(f).size 
filenames = filter(lambda f: is_image_file(f) and img_dimensions(f)==my_dimensions, os.listdir(fullpath)) 

où my_dimensions sont - vos dimensions.

Le problème est, que cette (ainsi que toute autre méthode qui vérifie les dimensions du fichier) doit réellement ouvrir et lire les images à chaque fois, ce qui n'est pas intelligent à faire à plusieurs reprises. Donc, en fonction de la charge de votre application, vous voudrez probablement mettre img_dimensions() dans une vraie fonction séparée et la mémoriser (http://code.activestate.com/recipes/52201-memoizing-cacheing-function-return-values/). Ou si cela va être une tâche commune, il suffit de mettre des images dans des dossiers pré-classés par dimensions.

+0

Donc, quand j'implémente ce changement, j'obtiens l'erreur de syntaxe 'lambda ne peut pas contenir d'affectation.' En outre, comment est-il différent vraiment de quelque chose comme ceci: = filenames [f pour f dans os.listdir (fullpath) si is_image_file (f) et get_image_dimensions (f) = my_dimensions] – Jonathan

+0

Doh! Devrait être: filenames = filtre (lambda f: fichier_image_ (f) et img_dimensions (f) == mes_dimensions, os.listdir (chemin complet)). Avec un double signe égal pour la comparaison au lieu de l'affectation. Pour ce qui est de votre deuxième question, c'est simplement stylistique - je n'aime pas les longues listes de compréhension. – gilesc

Questions connexes