2012-12-02 14 views
14

Impossibile capire perché il profilo del documento viene modificato su un ritaglio, ridimensionare e salvare con PIL. Sono stati testati con un'immagine che aveva sRGB come profilo colore, e dopo aver tolto un taggato RGB.PIL Python - modifica del profilo colore in RGB senza tag su ritaglio, ridimensionamento e salvataggio

def scale(self, image): 
    images = [] 

    image.seek(0) 

    try: 
     im = PIL.open(image) 
    except IOError, e: 
     logger.error(unicode(e), exc_info=True) 

    images.append({"file": image, "url": self.url, "size": "original"}) 

    for size in IMAGE_WEB_SIZES: 
     d = cStringIO.StringIO() 
     try: 
      im = crop(image, size["width"], size["height"]) 
      im.save(d, "JPEG") 
      images.append({"file": d, "url": self.scale_url(size["name"]), "size": size}) 
     except IOError, e: 
      logger.error(unicode(e), exc_info=True) 
      pass 

    return images 

io sto cercando di ottenere PIL per salvare la versione in scala con lo stesso profilo colore che l'immagine originale ha.

EDIT: Secondo questo dovrebbe essere possibile http://comments.gmane.org/gmane.comp.python.image/3215, ma ancora non funziona per me usando PIL 1.1.7

+0

Hai visto la patch menzionata nella prima risposta della discussione collegata? È necessario che la conservazione del profilo del colore funzioni, ma l'aggiornamento della versione PIL non è sufficiente (nella mia risposta di seguito, stavo usando anche la versione 1.1.7 e avevo lo stesso problema). – mgibsonbr

+1

@mgibsonbr Come posso vedere poi secondo il file Readme nell'hack di Florian Hoech non sono necessarie altre librerie. E in 1.1.7 l'hacking avrebbe dovuto essere trasformato in una funzionalità in base a http://hg.effbot.org/pil-117/commits/03e996c3b271fd3dabb008a8c694b82e3e6c5917 – Christoffer

risposta

14

PIL ha una funzione per leggere icc_profile e anche un modo per salvare con icc_profile. Quindi quello che ho fatto è stato quello di aprire il file per ottenere l'icc_profile:

try: 
    im1 = PIL.open(image) 
    icc_profile = im1.info.get("icc_profile") 

E l'aggiungerlo al file di nuovo al momento del salvataggio:

im.save(d, "JPEG", icc_profile=icc_profile) 

E il codice completo:

def scale(self, image): 
    images = [] 

    image.seek(0) 

    try: 
     im1 = PIL.open(image) 
     icc_profile = im1.info.get("icc_profile") 
    except IOError, e: 
     logger.error(unicode(e), exc_info=True) 

    images.append({"file": image, "url": self.url, "size": "original"}) 

    for size in IMAGE_WEB_SIZES: 
     d = cStringIO.StringIO() 
     try: 
      im = crop(image, size["width"], size["height"]) 

      im.save(d, "JPEG", icc_profile=icc_profile) 
      images.append({"file": d, "url": self.scale_url(size["name"]), "size": size}) 
     except IOError, e: 
      logger.error(unicode(e), exc_info=True) 
      pass 

    return images 

Ho testato con entrambe le immagini taggate (con profilo icc) e senza tag.

6

Aggiornamento: Ignorare questa risposta, @Christoffer's answer è quella corretta. A quanto pare, lo load non ha effettuato alcuna conversione, il profilo ICC è stato appena salvato da qualche altra parte.


non credo che una di queste operazioni stanno cambiando il profilo di colore, ma la conversione è stato fatto proprio sul load. Dopo l'apertura this sample image usando una versione recente di PIL (1.1.7 su Windows XP), viene immediatamente convertita in RGB:

>>> from PIL import Image 
>>> Image.open('Flower-sRGB.jpg') 
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=600x450 at 0xD3D3F0> 

Se provo a salvare di nuovo il modo in cui è (senza cambiare nulla), alcuni la qualità è persa. Se io uso un formato lossless OTOH, l'immagine risultante guarda bene a me:

>>> im = Image.open('Flower-sRGB.jpg') 
>>> im.save("Flower-RBG.jpg") 
>>> im.save("Flower-RBG.png") 

Cercando di convertire l'immagine risultante di nuovo a sRGB non ha funzionato:

>>> im = Image.open('Flower-sRGB.jpg').convert('CMYK') 
>>> im 
<PIL.Image.Image image mode=CMYK size=600x450 at 0xD73F08> 
>>> im.save("Flower-CMYK.png") 

>>> im = Image.open('Flower-sRGB.jpg').convert('sRGB') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "C:\Python27\lib\site-packages\PIL\Image.py", line 702, in convert 
    im = im.convert(mode, dither) 
ValueError: conversion from RGB to sRGB not supported 

Credo che il risparmio in sRGB sarebbe richiede alcune librerie esterne, come pyCMS o LittleCMS. Non li ho provati da solo, ma ecco uno tutorial (utilizzando lo strumento di quest'ultimo) che sembra promettente. Infine, ecco uno discussion thread sullo stesso problema che si sta affrontando (mantenendo il profilo del colore intatto durante il caricamento/salvataggio), si spera che possa darvi altri suggerimenti.

+0

Il profilo del colore viene modificato sull'immagine quando colpisce il server, quindi non è carico se capisco bene. Ma allora dovrebbe essere a im = PIL.apri (immagine) nel mio codice che il profilo di colore è cambiato. – Christoffer

+0

@Christoffer Stampa/registra la modalità di 'im' subito dopo l'apertura? Nei miei test (vedi il primo frammento) cambia immediatamente in 'RGB', quindi continuo a pensare che sia in caricamento. Dopo aver guardato più da vicino il tuo codice, per prima cosa apri 'image' creando la variabile' im', ma poi ritaglia 'image' stessa (scartando' im'). È giusto? – mgibsonbr

+1

Non pensare che sRGB sia una modalità in sé, ma solo una versione della modalità RGB. Quindi se devi controllare il profilo del colore devi loggare im.info.get ("icc_profile"). Hai ragione, ho scartato il primo im. Non sono sicuro del motivo per cui è stato lì mentre sto aggiustando il codice di qualcun altro. Ma come puoi vedere nella soluzione ho scoperto che ora lo uso;) – Christoffer

Problemi correlati