bmp nach ppm

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
IgelaufReisen
User
Beiträge: 49
Registriert: Montag 29. Oktober 2007, 20:10
Wohnort: Berlin
Kontaktdaten:

Hallöchen liebe Community.
Ich habe ein bmp-Bild und möchte dies mit Hilfe von Python und PIL in eine ppm-Datei umwandeln. Da kann man bestimmt irgendwas mit convert oder tostring machen, aber ich bin Neuling im Programmieren und verstehe den Text in der Erläuterung dazu nicht, da mein Englisch zu schlecht ist und den Inhalt ähnlicher Threads verstehe ich auch nicht wirklich.
Kann mir da irgendwer helfen?
Liebe Grüße
Der Igel
BlackJack

Auf Dauer solltest Du Dein Englisch verbessern. Ohne ist man beim Programmieren aufgeschmissen.

Code: Alles auswählen

In [90]: from PIL import Image

In [91]: img = Image.open('test.bmp')

In [92]: img.save('test.ppm')
IgelaufReisen
User
Beiträge: 49
Registriert: Montag 29. Oktober 2007, 20:10
Wohnort: Berlin
Kontaktdaten:

Ok...
Ich trag mich morgen für nen Volkshochschulkurs Englisch ein.
Aber danke für die Hilfe.
Aber kriegt man das auch irgendwie hin, dass die ppm-Datei nich aus den ASCII-Zeichen besteht, sondern aus den Ordnungszahlen derselbigen? Mit denen kann ich besser umgehen.
BlackJack

PIL unterstützt nur die "raw"-Formate und nicht die "plain"-Formate von PPM/PGM/PBM.
IgelaufReisen
User
Beiträge: 49
Registriert: Montag 29. Oktober 2007, 20:10
Wohnort: Berlin
Kontaktdaten:

Das is ja doof.
Und wie baut man aus ner Bmp-Datei ne PPM im 'Plain'-Format ohne PIL?
Gibt es da noch mehr MOdule?
IgelaufReisen
User
Beiträge: 49
Registriert: Montag 29. Oktober 2007, 20:10
Wohnort: Berlin
Kontaktdaten:

Da keine weitere Hilfe mehr kam, wollte ich das jetzt selbst in die Hand nehmen. Habe dazu das folgende Programm geschrieben. Für kleine Bilder funktioniert es auch (11 * 11). Aber für größere Bilder geht es nicht (340*486). Da zeigt er mir dann nur noch den oberen Teil des Bildes an. Ich weiß nicht, woran das liegt, und hoffe, dass mich jemand auf meinen grundlegenden Fehler aufmerksam machen kann.
Gruß
Igel

Code: Alles auswählen

from PIL import Image
class neu:
    def __init__(self):
        self.bild=[]
        self.karl=[]
    
    def dat_lesen(self,datei):
        f = file(datei,"r")    
        li = f.readlines()
        f.close()
        return li
    
    def dat_schreiben(self,text,datei):
        f = file(datei,"w")
        f.writelines(text)
        f.close()
    
    def eins(self,datei):
        self.bild_2 = Image.open(datei)
        self.bild_2.save('neu_karl.ppm')
        self.bild = self.dat_lesen('neu_karl.ppm')
        vorn = self.bild[:3]
        vorn[1] = vorn[1].split(' ')
        reihen = vorn[1][0]
        spalten = vorn[1][1]
        self.bild = self.bild[3:]
        self.bild = self.bild[0].strip() 
        op1 = 0
        while op1 < len(self.bild):
            self.karl.append(ord(self.bild[op1]))
            op1 += 1


        aufloesung = str(reihen) + (' ') + str(spalten)
        text=''
        c = []
        c.append('P3\n')
        c.append('# Created by IrfanView\n')
        c.append(aufloesung)
        c.append('255\n')
        
        op1 = 0
        op2 = 1
        while op1 < len(self.karl):
            text += str(self.karl[op1])
            if (op2%9)==0:text += '\n'
            text += ' '
            op1 += 1
            op2 += 1
        c.append(text)
        self.dat_schreiben(c,'neu.ppm')
        
        print 'fertig'
        
horst = neu()
horst.eins('test.bmp')
BlackJack

Das liegt daran, das der Quelltext so verdammt "unpythonisch" ist und an der Namensgebung.

Na gut nicht wirklich, aber der Compiler sollte solchen Code echt zurückweisen. :twisted:

Warum steckt das ganze in einer Klasse?

Wenn man Namen wie `karl`, `horst`, und `eins` verwendet, hat man sich offenbar nicht genug Gedanken um die Funktion der Objekte gemacht, sonst hätte man aussagekräftige Namen gefunden.

Die beiden ``while``-Schleifen mit manuell verwaltetem Index sind zwar Python-Syntax, aber eindeutig nicht idiomatisches Python. Man kann bei "iterables" direkt mit ``for`` über die Elemente iterieren.
IgelaufReisen
User
Beiträge: 49
Registriert: Montag 29. Oktober 2007, 20:10
Wohnort: Berlin
Kontaktdaten:

Die beiden ``while``-Schleifen mit manuell verwaltetem Index sind zwar Python-Syntax, aber eindeutig nicht idiomatisches Python. Man kann bei "iterables" direkt mit ``for`` über die Elemente iterieren.
Tut mir leid, aber ich weiß wirklich nicht, was damit gemeint ist. Ich bin Pythonneuling und programmiere eben so, wie ich es weiß.
Und liegt der Fehler also wirklich an den while-Schleifen? Würde es also mit

Code: Alles auswählen

for i in range(0,len(self.bild)):
...
funktionieren?
IgelaufReisen
User
Beiträge: 49
Registriert: Montag 29. Oktober 2007, 20:10
Wohnort: Berlin
Kontaktdaten:

Code: Alles auswählen

from PIL import Image
class umwandler:
    def __init__(self):
        self.bild=[]
        self.karl=[]
    
    def dat_lesen(self,datei):
        f = file(datei,"r")    
        li = f.readlines()
        f.close()
        return li
    
    def dat_schreiben(self,text,datei):
        f = file(datei,"w")
        f.writelines(text)
        f.close()
    
    def hauptprogramm(self,datei):
        self.bild_2 = Image.open(datei)
        self.bild_2.save('neu_karl.ppm')
        self.bild = self.dat_lesen('neu_karl.ppm')
        print len(self.bild[3])
        vorn = self.bild[:3]
        vorn[1] = vorn[1].split(' ')
        reihen = vorn[1][0]
        spalten = vorn[1][1]
        self.bild = self.bild[3:]

        print len(self.bild[0])
        
        self.bild = self.bild[0].strip()

        print len(self.bild)

        for i in range(0,len(self.bild)):
            self.karl.append(ord(self.bild[i]))
        #print self.karl

        print len(self.karl)

        aufloesung = str(reihen) + (' ') + str(spalten)
        text=''
        c = []
        c.append('P3\n')
        c.append('# Created by IrfanView\n')
        c.append(aufloesung)
        c.append('255\n')
        
        op2 = 1

        for i in range(0,len(self.karl)):
            text += str(self.karl[i])
            if (op2%27)==0:text += '\n'
            text += ' '
            op2 += 1
        #print text
        
        c.append(text)
        self.dat_schreiben(c,'neu.ppm')
        
        print 'fertig'
        
horst = umwandler()
horst.hauptprogramm('test.bmp')

Programmcode den Hinweisen angepasst.
Ergebnis das gleiche. Also lag es nicht daran.
BlackJack

Es steckt immer noch in einer Klasse.

Mit direkt über die Elemente iterieren ist ohne Index gemeint. Eben direkt. ``for element in iterable:``.

Du kannst die PPM-Datei von PIL nicht einfach als Text behandeln. Nur die Kopfzeilen sind "Text", der Rest sind beliebige Bytes. Unter anderem können da auch Bytes vorkommen, die in Texten als Zeilenwechsel dienen.
BlackJack

Direkte Umwandlung in ein "plain" PPM als einfache Funktion:

Code: Alles auswählen

from PIL import Image

def image2ppm(image):
    if image.mode != 'RGB':
        image = image.convert('RGB')
    return (('P3\n%d %d\n%d\n' % (image.size + (255,)))
            + '\n'.join(str(ord(byte)) for byte in image.tostring()))


def main():
    image = Image.open('test.bmp')
    ppm = image2ppm(image)
    ppm_file = open('test.ppm', 'wb')
    ppm_file.write(ppm)
    ppm_file.close()


if __name__ == '__main__':
    main()
IgelaufReisen
User
Beiträge: 49
Registriert: Montag 29. Oktober 2007, 20:10
Wohnort: Berlin
Kontaktdaten:

Das is ja cool.
Danke!
Genau verstehen tue ich den Quelltext zwar noch nicht, aber da werd ich mich heute abend genauer reinlesen.
Jedenfalls nochmals ein ganz großes Danke dafür!
IgelaufReisen
User
Beiträge: 49
Registriert: Montag 29. Oktober 2007, 20:10
Wohnort: Berlin
Kontaktdaten:

Ok,
aber wie geht das ganze in die andere Richtung?
Denn so:

Code: Alles auswählen

from PIL import Image

def image2bmp(image):
    if image.mode != 'RGB':
        image = image.convert('RGB')
    return (('BM\n%d %d\n%d\n' % (image.size + (255,)))
            + '\n'.join(chr(byte) for byte in image.tostring()))


def main():
    image = Image.open('test.ppm')
    ppm = image2ppm(image)
    ppm_file = open('test.bmp', 'wb')
    ppm_file.write(ppm)
    ppm_file.close()


if __name__ == '__main__':
    main()
...geht es ja leider nicht.
Er meckert da rum, dass er irgendetwas nicht kennt.
Aber von bmps verstehe ich noch viel weniger, als von ppms..
:(
BlackJack

So ein PPM sollte man dann wieder in ein `PIL.Image`-Objekt umwandeln. Mit BMPs kann `PIL` ja umgehen.

Code: Alles auswählen

from itertools import imap
from PIL import Image

def p3_ppm2image(ppm):
    values = (value for value in ppm.split() if not value.startswith('#'))
    if values.next() != 'P3':
        raise ValueError('no plain PPM')
    values = imap(int, values)
    size = (values.next(), values.next())
    if values.next() != 255:
        raise ValueError('max value not 255')
    result = Image.new('RGB', size)
    result.fromstring(''.join(imap(chr, values)))
    return result


def main():
    ppm_file = open('test.ppm')
    ppm_data = ppm_file.read()
    ppm_file.close()
    image = p3_ppm2image(ppm_data)
    image.save('test2.bmp')


if __name__ == '__main__':
    main()
IgelaufReisen
User
Beiträge: 49
Registriert: Montag 29. Oktober 2007, 20:10
Wohnort: Berlin
Kontaktdaten:

Alter wie krass.
Wie soll denn nen Neueinsteiger auf sowas kommen?
Also das finde ich wirklich beeindruckend.
Also nochmal nen gaaaaanz großes Dankeschön dafür;)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

IgelaufReisen hat geschrieben:Wie soll denn nen Neueinsteiger auf sowas kommen?
Tut ein Neueinsteiger in der Regel auch nicht. Erstens weil BlackJack gerne Generatoren einsetzt (imap mit int auf die Werte loszulassen ist in der Tat eine nette Lösung) und zweitens weil das erfordert, dass man weiß wie man die Formate ineinander umwandelt.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten