2010-11-18 21 views
4

Imaginez un cercle rouge avec un ombres à paupières noires qui disparaît sur un fond entièrement transparent. Lorsque j'ouvre et réenregistre l'image avec PIL, l'arrière-plan reste entièrement transparent, mais l'ombre à gouttes devient complètement noire.Python PIL - Toutes les zones de PNG avec opacité> 0 ont leur opacité définie sur 1

Le problème apparaît sans même altérer l'image:

image = Image.open('input.png') 
image = image.convert('RGBA') 
image.save('output.png') 

Je veux garder l'image à la recherche exactement comme l'original pour que je puisse rogner ou redimensionner.

EDIT: Voici un fichier PNG qui illustre l'effet. Il a été converti en 8 bits en utilisant PNGNQ.

alt text

Lorsque vous utilisez le code Python ci-dessus, il est comme ce qui suit:

alt text

+0

@Kyle: voulez-vous poster 'input.png' et 'output.png'? Je n'arrive pas à reproduire le problème. – unutbu

+0

J'ai édité le fichier pour "rédiger" des choses sensibles et l'image réenregistrée a bien fonctionné. J'ai donc réalisé que input.png est un PNG 8 bits et je pense que c'est trop d'efforts pour les prendre en compte étant donné qu'ils sont assez rares en dehors des graphismes web. –

+0

Quelle est la saveur du format '.png' est' input.png' - dans quel format est-il pour commencer? – martineau

Répondre

6

Il semble que la couche PIL ne supporte pas actuellement l'alpha complet pour le format PNG8.

Il y a un patch ici pour un support en lecture seule: http://mail.python.org/pipermail/image-sig/2010-October/006533.html

Si vous vous sentez méchant, vous pouvez PIL monkey-patch:

from PIL import Image, ImageFile, PngImagePlugin 

def patched_chunk_tRNS(self, pos, len): 
    i16 = PngImagePlugin.i16 
    s = ImageFile._safe_read(self.fp, len) 
    if self.im_mode == "P": 
     self.im_info["transparency"] = map(ord, s) 
    elif self.im_mode == "L": 
     self.im_info["transparency"] = i16(s) 
    elif self.im_mode == "RGB": 
     self.im_info["transparency"] = i16(s), i16(s[2:]), i16(s[4:]) 
    return s 
PngImagePlugin.PngStream.chunk_tRNS = patched_chunk_tRNS 

def patched_load(self): 
    if self.im and self.palette and self.palette.dirty: 
     apply(self.im.putpalette, self.palette.getdata()) 
     self.palette.dirty = 0 
     self.palette.rawmode = None 
     try: 
      trans = self.info["transparency"] 
     except KeyError: 
      self.palette.mode = "RGB" 
     else: 
      try: 
       for i, a in enumerate(trans): 
        self.im.putpalettealpha(i, a) 
      except TypeError: 
       self.im.putpalettealpha(trans, 0) 
      self.palette.mode = "RGBA" 
    if self.im: 
     return self.im.pixel_access(self.readonly) 
Image.Image.load = patched_load 

Image.open('kHrY6.png').convert('RGBA').save('kHrY6-out.png') 
+0

Cela fonctionne comme un charme! Merci! –

0

Je pense que le problème a été quelque peu résolu, mais est-il possible que vous devez définir la profondeur de la couche alpha?