Seite 1 von 1

bmp nach ppm

Verfasst: Mittwoch 5. Dezember 2007, 21:34
von IgelaufReisen
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

Verfasst: Mittwoch 5. Dezember 2007, 21:40
von 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')

Verfasst: Mittwoch 5. Dezember 2007, 22:03
von IgelaufReisen
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.

Verfasst: Mittwoch 5. Dezember 2007, 22:26
von BlackJack
PIL unterstützt nur die "raw"-Formate und nicht die "plain"-Formate von PPM/PGM/PBM.

Verfasst: Donnerstag 6. Dezember 2007, 20:47
von IgelaufReisen
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?

Verfasst: Montag 10. Dezember 2007, 20:50
von IgelaufReisen
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')

Verfasst: Montag 10. Dezember 2007, 21:13
von 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.

Verfasst: Montag 10. Dezember 2007, 21:20
von IgelaufReisen
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?

Verfasst: Montag 10. Dezember 2007, 21:30
von IgelaufReisen

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.

Verfasst: Montag 10. Dezember 2007, 22:05
von 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.

Verfasst: Mittwoch 12. Dezember 2007, 11:23
von 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()

Verfasst: Mittwoch 12. Dezember 2007, 17:58
von IgelaufReisen
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!

ppm nach bmp

Verfasst: Mittwoch 12. Dezember 2007, 18:26
von IgelaufReisen
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..
:(

Verfasst: Mittwoch 12. Dezember 2007, 20:12
von 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()

Verfasst: Mittwoch 12. Dezember 2007, 20:56
von IgelaufReisen
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;)

Verfasst: Mittwoch 12. Dezember 2007, 22:09
von Leonidas
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.