2016-02-15 8 views
5

Sto lavorando con Pillow, Django e django-imagekit.Come convertire un'immagine in una dimensione di file specifica?

Sto cercando di avere un campo modello immagine del profilo (probabilmente usando la classe ProcessedImageField da imagekit) che prenderà qualsiasi immagine, convertirà in JPEG, la ritaglia in 150x150, e renderà le sue dimensioni del file 5KB.

I primi due sono facili:

profile_picture = imagekit.models.ProcessedImageField(upload_to=get_profile_picture_file_path, 
                 format='JPEG', 
                 processors=[ResizeToFill(height=150, width=150)] 
                ) 

ma come faccio a garantire la dimensione del file è di 5 KB? Potrei usare qualcosa come il parametro options={'quality': 60} in ProcessedImageField, ma ciò sembra essere solo relativo alla dimensione del file originale (a mia conoscenza).

Le soluzioni non devono utilizzare django-imagekit, ma sarebbe preferibile.

risposta

0

Forse in questo modo. Verificare le dimensioni dell'immagine dopo caricato e rimuoverlo o diminuire più override save metodo:

class Images(models.Model): 
    profile_picture = imagekit.models.ProcessedImageField(upload_to=get_profile_picture_file_path, 
                format='JPEG', 
                processors=[ResizeToFill(height=150, width=150)] 
               ) 

    def save(self, force_insert=False, force_update=False, using=None, 
      update_fields=None): 

     if os.stat(get_profile_picture_file_path + "/" + self.profile_picture.new_name).st_size > max_size: 
      do_something_further_image_processing_to_decrease_size 

     super(Images, self).save() 
+0

Questo è un buon inizio nel verificare che il file è troppo grande, ma la logica di 'do_something_further_image_processing_to_decrease_size' è davvero la parte rilevante della questione. Come puoi assicurarti di ridurre le dimensioni del file a una dimensione specifica, ogni volta (anche con immagini di risoluzioni/qualità JPEG diverse)? – dcgoss

+0

Probabilmente aggiungerò qui una funzione iterativa che diminuisce la risoluzione del 10% o un altro fattore corrispondente alla dimensione corrente dell'immagine prodotta ogni iterazione. 'PIL' ti dà questa possibilità. – Magnar

0

Ho usato per avere un problema simile, così ho deciso di ottimizzare le immagini utilizzando gli strumenti del sistema operativo (jpegoptim, optipng, ecc) chiamato da django dopo aver salvato il modello usando i segnali (si può fare anche il metodo di salvataggio sovrascritto). Questi strumenti ottimizzano ed eliminano i metadati dalle tue immagini. D'altra parte puoi studiare il rapporto di compressione medio e la dimensione per i file jpg di 150x150 e provare a indovinare la migliore qualità per verificare questo: (jpeg compression ratio)

Questo è il mio codice per ottimizzare i file dopo averli salvati, I ' m utilizzando semplici miniature biblioteca che fornirmi segnali dopo risparmia:

@receiver(saved_file) 
def optimize_file(sender, fieldfile, **kwargs): 
    optimize(fieldfile.path) 


# thumbnail optimization 
@receiver(thumbnail_created) 
def optimize_thumbnail(sender, **kwargs): 
    optimize(sender.path) 

def optimize(path): 
    """ 
    install image utilities 
    apt-get install jpegoptim optipng pngcrush advancecomp 
    :param path: 
    :return: 
    """ 
    # taken from trimage (http://trimage.org/) 
    runString = { 
     ".jpeg": u"jpegoptim -f --strip-all '%(file)s' ; chmod 644 '%(file)s'", 
     ".jpg": u"jpegoptim -f --strip-all '%(file)s' ; chmod 644 '%(file)s'", 
     ".png": u"optipng -force -o7 '%(file)s' && advpng -z4 '%(file)s' && pngcrush -rem gAMA -rem alla -rem cHRM -rem iCCP -rem sRGB -rem time '%(file)s' '%(file)s.bak' && mv '%(file)s.bak' '%(file)s' ; chmod 644 '%(file)s'" 
    } 

    ext = splitext(path)[1].lower() 
    if ext in runString: 
     subprocess.Popen(runString[ext] % {'file': path}, shell=True) 
Problemi correlati