PIL, GIF und Transparenz

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
Spacegate

Hallo,

wenn ich mit der PIL ein GIF89a öffne und dann in eine neue Datei speichere, sind Bildpunkte die zuvor vollständig transparent sind, plötzlich weiß und opak.

Hier das relevante Codefragment:

Code: Alles auswählen

import Image
im = Image.open('Test.gif')
im.save('Testkopie.gif', 'GIF')
Was mach ich falsch?

Im Handbuch zur PIL kann man unter 'save' nachlesen, daß man 'save' auch mit 'options' für den 'writer' aufrufen kann. Dann gibt es einen Verweis auf eine spätere Textstelle im Handbuch, an der die 'options' definiert sein sollen. Die referenzierte Textstelle kann ich aber beim besten Willen nicht finden.

Danke für eure Hinweise.

Edit (Leonidas): Code in Python-Tags gesetzt.
BlackJack

Man muss wohl das Schlüsselwort-Argument `transparency` mit dem Farbindex, der Transparent sein soll aufrufen. Den Index findet man im `Image.info` Attribut (ein Dictionary) vom geladenen Bild.
Spacegate

Danke für Deine Antwort BlackJack.

Ich versteh es immer noch nicht: Das mit dem Schlüssel 'transparency' habe ich dank Deiner Hilfe jetzt auch gefunden oder hoffe dies zumindest. Was aber heißt 'mit dem Farbindex, der transparent sein soll, aufrufen'.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Es ist so: ein einem GIF kannst du eine arbe definieren, die Transparent sein soll. Diese wird dann nicht mehr als eigentliche Farbe dargestellt, sondern als durchsichtig.

Klingt komisch, ist aber GIF.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Gast

Jetzt ist wieder alles klar auf der Andrea Doria ...

Spacegate
Spacegate

Hallo,

jetzt hab ich es durchprobiert und es kommt kein transparentes Bild aus meiner Klasse Bild. Den Farbindex für die transparente Farbe zu setzen hilft entweder nix oder ich hab es falsch gemacht. Ich habe es mit der Anweisung
'bildname'.info[transparency] = 225
probiert und zwar sowohl bei laden des Bildes als auch vor den abspeichern. Außerdem habe ich es mit und ohne den Wechsel des Bildmodus von 'P' auf 'RGBA' versucht. nix hilft. Nach dem save hat das Bild die Transparenz verloren.

Der folgende Code funktioniert bis auf die Transparenz. Die Klassen Urbild und Bild sorgen in einem CGI dafür, daß Bilder, die der Client benötigt, entsprechend verkleinert und gedreht auf dem Server vorliegen. Meine Stümpereien mit dem Transparency-Attribut habe ich wieder rausgeschmissen, damit Du das nicht machen mußt, wenn Du mir zeigen willst wie es geht.

Code: Alles auswählen


import Image, os
MEDIEN = ' Pfadname'

class Urbild:

    URBILDPFAD = MEDIEN + 'Urbilder/'

    def __init__(self, urbild):
        self.bildart = '.gif'
        pfad = self.URBILDPFAD + urbild  + self.bildart
        if not os.path.exists(pfad):
            self.bildart = '.jpg'
            pfad = self.URBILDPFAD + urbild + '.jpg'
        self.bild = Image.open(pfad)


class Bild:

    BILDERSUB = 'Bilder/'
    BILDPFAD = MEDIEN + BILDERSUB

    def __init__(self, urbildname, verkleinerung, drehwinkel):
        urbild = Urbild(urbildname)
        self.bildname = urbildname + '-' + str(verkleinerung) + \
                        '-' + str(drehwinkel) + urbild.bildart
        self.pfad = self.BILDPFAD + self.bildname
        if not os.path.exists(self.pfad):
            ausdehnung = urbild.bild.size
            kleinbild = urbild.bild.resize((ausdehnung[0] - 2 * verkleinerung, \
                                            ausdehnung[1] - 2 * verkleinerung) )
            drehbild = kleinbild.rotate(drehwinkel)
            if urbild.bildart == '.gif':
                drehbild.save(self.pfad, 'GIF')
            else:
                drehbild.save(self.pfad, 'JPEG')

    def webpfad(self):
        return MEDIENPFAD + self.BILDERSUB + self.bildname

    def dateiname(self):
        return self.bildname

Edit (Leonidas): Code in Python-Tags gesetzt.
Olliminatore
User
Beiträge: 55
Registriert: Montag 30. Mai 2005, 16:03
Wohnort: schönsten Stadt Deutschlands
Kontaktdaten:

PIL-handbook hat geschrieben:The library reads GIF87a and GIF89a versions of the GIF file format. The library writes
run-length encoded GIF87a files.
Das normale PIL kann leider keine transparenten/komprimierten GIFs speichern.
Ich habe mal irgendwo was von Zusatz-Modulen gelesen die das können.
Ob es das (kommerzielle)PIL-Plus noch gibt weiss ich auch nicht. Ich bin zwar in der "Image-SIG mailing list" aber bekomme so gut wie nie eine Antwort :evil:.

Fredrik Lundh ist ja noch recht aktiv aber von einer :shock: 10 Jahre alten Library könnte man dann doch mehr erwarten.

[edit] Als transparente alternative gibt es nur PNG.
[size=84][url=http://de.wikipedia.org/wiki/Jamba]Love Jamba[/url] <!--Olliminatore-->input<?/> [url=http://www.spreeblick.com/blog/index.php?p=324]Boycott Jamba[/url][code]def olliminiert(optimiert, eliminiert, terminiert):[/code][/size]
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Olliminatore hat geschrieben:
PIL-handbook hat geschrieben:The library reads GIF87a and GIF89a versions of the GIF file format. The library writes
run-length encoded GIF87a files.
Das normale PIL kann leider keine transparenten/komprimierten GIFs speichern.
Und RLE ist keine Komprimierung? ;)
Olliminatore hat geschrieben:Ich habe mal irgendwo was von Zusatz-Modulen gelesen die das können.
Ob es das (kommerzielle)PIL-Plus noch gibt weiss ich auch nicht. Ich bin zwar in der "Image-SIG mailing list" aber bekomme so gut wie nie eine Antwort :evil:.

Fredrik Lundh ist ja noch recht aktiv aber von einer :shock: 10 Jahre alten Library könnte man dann doch mehr erwarten.
Wenn PIL das nicht kann, warum steht dann in der Changelog von 1.1.4, das der Bug im GIF-Writer im Zusammenspiel mit Transparenzen entfernt wurde?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Olliminatore
User
Beiträge: 55
Registriert: Montag 30. Mai 2005, 16:03
Wohnort: schönsten Stadt Deutschlands
Kontaktdaten:

Leonidas hat geschrieben:Und RLE ist keine Komprimierung? :wink:
Ja doch, ich meinte diese 2. Komprimierung. :P
Ich habe mir mal das GifImagePlugin angesehn und das zur Komprimierung gefunden:

Code: Alles auswählen

def _save_netpbm(im, fp, filename):

    #
    # If you need real GIF compression and/or RGB quantization, you
    # can use the external NETPBM/PBMPLUS utilities.  See comments
    # below for information on how to enable this.

    import os
    file = im._dump()
    if im.mode != "RGB":
        os.system("ppmtogif %s >%s" % (file, filename))
    else:
        os.system("ppmquant 256 %s | ppmtogif >%s" % (file, filename))
    try: os.unlink(file)
    except: pass
Wenn PIL das nicht kann, warum steht dann in der Changelog von 1.1.4, das der Bug im GIF-Writer im Zusammenspiel mit Transparenzen entfernt wurde?
Ohu* Ja, ich habe hier nur das 1.3 Handbook :oops:. (war schon ziemlich spät :P)
Ich bekomme es jedenfalls auch nicht hin. :?
Im GifImagePlugin steht ja auch was von "save transparency".
[size=84][url=http://de.wikipedia.org/wiki/Jamba]Love Jamba[/url] <!--Olliminatore-->input<?/> [url=http://www.spreeblick.com/blog/index.php?p=324]Boycott Jamba[/url][code]def olliminiert(optimiert, eliminiert, terminiert):[/code][/size]
Olliminatore
User
Beiträge: 55
Registriert: Montag 30. Mai 2005, 16:03
Wohnort: schönsten Stadt Deutschlands
Kontaktdaten:

Ich habe es nur mit einer Änderung im GifImagePlugin Zeile 268 erfolgreich geschafft.
Keine Ahnung warum "im.encoderinfo" beim speichern leer ist. (habe es mit print getestet)

Code: Alles auswählen

 >>>       transparency = im.encoderinfo["transparency"]  # old
       transparency = im.info["transparency"]  # new


Im original Code (von Denis Benoit) steht es auch so (im.info).

Wie könnte ich diese Frage (in english) am besten in der "Image-SIG mailing list" stellen, so das ich auch eine Antwort erhalte?
Ich habe nur eine 5 in Englisch (auch kein Abi).

[edit english=on] Vieleicht so!?:
Topic: GIF transparency
Hey folks,

I tried to save a GIF with transparency unsuccessfully.
Which are the options for this?
I has only success if i change the GifImagePlugin line 268 to
> transparency = im.info["transparency"]
Is that a Bug?
[size=84][url=http://de.wikipedia.org/wiki/Jamba]Love Jamba[/url] <!--Olliminatore-->input<?/> [url=http://www.spreeblick.com/blog/index.php?p=324]Boycott Jamba[/url][code]def olliminiert(optimiert, eliminiert, terminiert):[/code][/size]
Spacegate

Ohne eure Hilfe würde ich jetzt total im Wald stehen. Mein Pythonprogramm mit mehreren tausend LOCs, müsste ich in den Eimer treten und wüßte gar nicht so recht warum eigentlich.
Philipp, der mir beim Entwickeln hilft, ist ein eingefleischter PHP-Fan. Er sagt eigentlich jeden Tag zu mir: "Warum denn ausgerechnet Python? Wenn man Python benutzt, steht man doch ganz alleine da!" Dank euch kann ich jetzt beweisen, daß dem nicht so ist. Ich kann mein Python weiter nutzen und muß es nicht durch was Semiprofessionelles wie PHP ersetzen.

Das mit der PIL ist allerdings ein echter Hammer. An die Mailingliste und die Emailadresse für den kostenlosen Support habe ich mich trotz mäßigen Englisch schon gewandt und keine Antwort erhalten. Da die Transparenz für mich unverzichtbar ist, werde ich nun versuchen die PIL+ zu kaufen. Falls ich das schaffe, bekommt ihr beide eine private Email von mir mit einem "Erfolgsbericht".

Spacegate

PS.: Einen Fünfer in Englisch hast Du wirklich nicht verdient, Olliminatore. Trotzdem sind in Deiner Mail Fehler. Ich versuche mal, Deinen Text zu verbessern. Aber Achtung: Ich kann auch nur Filserenglisch:
Topic: GIF transparency
Hallo folks,
I have tried to save a GIF containing transparent pixel in different attempts and had no success, since I could not figure out the right options for the save.
Is there any option ensuring transparent pixel to be saved as transparent or is there any other way to ship around this edge?
To overcome the transparency problem I have inspected the code of your GifImagePlugin. By fortunity I found that transparent pixel will be saved right, if I will change line 268 of the plugin to
> transparency = im.info["transparency"]
Will this solution work in any case?
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Spacegate hat geschrieben: Das mit der PIL ist allerdings ein echter Hammer.
Hi Spacegate!

Kann es sein, dass du eine zu alte PIL-Version einsetzt? Welche PIL-Version verwendest du?

Die Version bekommst du raus, wenn du in einer Python-Konsole folgende Zeilen eingibst:

Code: Alles auswählen

import Image
print Image.VERSION
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Spacegate

Wir nutzen hier Python 2.4 mit der passenden Version der PIL. Haben wir beim Update von Python 2.3 auf Python 2.4 frisch downgeloaded. An altbackener Software kann es also nicht liegen. Dann schon eher an unseren Programmierkünsten.
Im Übrigen hat ist der Olliminatore der Ursache des Problems bis auf den Grund nachgegangen. Er hat die Source der PIL inspiziert (siehe oben). Es ist ein Bug in der PIL, der - na sagen wir mal, ganz vielleicht nicht rein zufällig da reingerutscht ist.

Trotzdem: Herzlichen Dank für Deinen Hinweis
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Spacegate hat geschrieben: Im Übrigen hat ist der Olliminatore der Ursache des Problems bis auf den Grund nachgegangen. Er hat die Source der PIL inspiziert (siehe oben). Es ist ein Bug in der PIL, der - na sagen wir mal, ganz vielleicht nicht rein zufällig da reingerutscht ist.
Hi Spacegate!

Das hatte ich irgendwie überlesen...

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
BlackJack

Also ich benutze hier PIL 1.1.5 und das hat keinen Bug. Ich kann GIFs mit Transparenz speichern.

Olliminatores "Fehlerbeseitigung" ist auch keine wenn ich das richtig sehe, weil bei mir die Zeile, die er beseitigt bzw. ersetzt hat auch so drin steht. Wenn das im original so stand, dann wird das wahrscheinlich genau der Bug gewesen sein, der laut ChangeLog gefixt wurde. Olliminatore hat ihn also wieder eingebaut!

Wenn in `im.encoderinfo` nichts drinsteht, dann liegt das höchstwahrscheinlich daran, das man die Optionen beim `im.save()` nicht angegeben hat. Sonst wüsste ich nicht wieso es leer sein könnte.
Spacegate

Hallo BlackJack, hallo gerold,

danke für euere Beiträge!

Vermutlich hat BlackJack recht mit seiner Bug-Theorie. Das nehm ich aber ganz pragmatisch. Wenn es mit Ollimatore rekonstruierten Bug funkt und das tut es, bin ich über eine echte Krise weg. Außerdem hat der Ollimatore die Stelle im Sourcecode lokalisiert, an der es brennt. Das ist ganz unabhängig von Bug oder nicht Bug eine echte Leistung. Ehre, wem Ehre gebührt!

Spacegate
Olliminatore
User
Beiträge: 55
Registriert: Montag 30. Mai 2005, 16:03
Wohnort: schönsten Stadt Deutschlands
Kontaktdaten:

Hallo @Spacegate,
vielen Dank :)
(auch wenn ich "noch" nicht so ein "Könner" bin).

Ja, BlackJack hat vollkommen recht. Nach seinem (noch maligen)letzten Hinweis klappt es bei mir jetzt auch.
Deshalb auch nochmal Danke BlackJack.
Man hätte ja auch einen (klärenden) Beispiel-code posten können :P, die mir (für PIL) etwas schwer zu finden (zu scheinen) sind.
(Was ich hiermit bei dieser Gelegenheit tun möchte. Der Vollständigkeit halber und um noch ein paar Unklarheiten zu eliminieren.)

Code: Alles auswählen

im.save(filename,"gif",**{"transparency":1,"optimize":1})
Richtig?
Wobei ich kein GIF optimieren konnte, die "optimze" Option scheint, (trotzdem auch) nicht richtig zu funktionieren!?!
Beim öffnen des Resultates hat sich auch mein (Grafik)Viewer mit einem Fehler terminiert.
[size=84][url=http://de.wikipedia.org/wiki/Jamba]Love Jamba[/url] <!--Olliminatore-->input<?/> [url=http://www.spreeblick.com/blog/index.php?p=324]Boycott Jamba[/url][code]def olliminiert(optimiert, eliminiert, terminiert):[/code][/size]
BlackJack

Olliminatore hat geschrieben:

Code: Alles auswählen

im.save(filename,"gif",**{"transparency":1,"optimize":1}))
Wenn man die Angaben "von Hand" macht, dann sind einfache keyword-Parameter vielleicht einfacher zu lesen:

Code: Alles auswählen

im.save(filename,"gif", transparency=1, optimize=1)
Ansonsten kann man unter Umständen die Informationen aus dem `info` Attribut einfach wiederverwenden:

Code: Alles auswählen

im.save(filename,"gif", **im.info)
oscar15
User
Beiträge: 67
Registriert: Freitag 3. März 2006, 15:43
Wohnort: Kölle

Ich hab aber kein modul namens Image!??!
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

oscar15 hat geschrieben:Ich hab aber kein modul namens Image!??!
Du musst ja auch die Python Imaging Library (PIL) installiert haben, siehe Topic ;) Die stellt eben unter anderen Image bereit
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten