Seite 1 von 1

Einfachste Möglichkeit ein pixelweise ein Bild zu erstellen?

Verfasst: Mittwoch 16. Februar 2005, 16:58
von sonium
Hi, was ist die einfachste möglichkeit in Python pixelweise ein Bild (egal ob in Datei oder auf Bildschirm) zu erzeugen?

Code wäre nett :)

Verfasst: Mittwoch 16. Februar 2005, 17:11
von Leonidas
Nutzen der PIL?
Was anderes fällt mir jetzt nicht direkt ein, du kannst auch versuchen pygame oder gtk.DrawingArea zu nutzen, das sollte auch ok gehen nur wie es mit dem speichern aussieht..

Verfasst: Mittwoch 16. Februar 2005, 20:32
von jens
Hier gab es mal ein Mandelbrot Skript, welches mit TK pixelweise das Bild aufbaute... wobei es aber nicht wirklich Grafikpixel war, sondern Textpunkte, glaube ich...

Verfasst: Mittwoch 16. Februar 2005, 23:48
von BlackJack
Hi sonium,

Was möchtest Du denn mit dem Bild machen? Das am einfachsten zu erzeugende Format in irgendeiner beliebigen Programmiersprache, die Text in Dateien ausgeben kann, sind wohl die Netpbm Formate pbm (Schwarzweiss), pgm (Graustufen (auch mehr als 256)) und ppm (RGB).

Die Bilder lassen sich dann zum Beispiel mit den Netpbm Programmen, ImageMagick oder Gimp weiterverarbeiten.

Verfasst: Donnerstag 17. Februar 2005, 13:41
von Leonidas
Also ich finde XBM (X11 Bitmap) und XPM (X11 Pixmap) besser, finde ich von der Struktur einfacher.

Verfasst: Donnerstag 17. Februar 2005, 15:33
von BlackJack
Dann hast Du Dir nicht angeschaut, wie die NetPBM Formate aussehen. Was kann man denn an der Struktur noch einfacher machen? Es wird das Format, Höhe und Breite, eventuell noch die Anzahl der Graustufen als Text in eine Datei geschrieben und dann folgen die Bilddaten, entweder als Höhe*Breite Bytes/Words bei den "Raw" Formaten oder als Zahlen als Text durch Whitespace getrennt.

Verfasst: Donnerstag 17. Februar 2005, 15:55
von Leonidas
BlackJack hat geschrieben:Dann hast Du Dir nicht angeschaut, wie die NetPBM Formate aussehen. Was kann man denn an der Struktur noch einfacher machen? Es wird das Format, Höhe und Breite, eventuell noch die Anzahl der Graustufen als Text in eine Datei geschrieben und dann folgen die Bilddaten, entweder als Höhe*Breite Bytes/Words bei den "Raw" Formaten oder als Zahlen als Text durch Whitespace getrennt.
Doch das habe ich:
PPM:

Code: Alles auswählen

P3
# feep.ppm
4 4
15
 0  0  0    0  0  0    0  0  0   15  0 15
 0  0  0    0 15  7    0  0  0    0  0  0
 0  0  0    0  0  0    0 15  7    0  0  0
15  0 15    0  0  0    0  0  0    0  0  0
gegen XPM. Da finde ich XPM irgendwie übersichtlicher. Also ein bild einfacher als das Bild mit buchstaben zu malen kann ich mir wirklich nicht einfacher vorstellen.

Verfasst: Donnerstag 17. Februar 2005, 17:14
von BlackJack
Das malen mit Buchstaben ist doch gar nicht das Problem, es ging darum ein Bild von einem Programm erzeugen zu lassen. Ich würde beides nicht per Hand erstellen wollen. Mit mehr als 4-5 Farben wird's auch ziemlich unübersichtlich bei XPM. Schau Dir mal das hier an: http://strony.ac-net.pl/magdah/jxpm/kod ... odim03.xpm

Die NetPBM Formate sind von der Struktur her einfacher aufgebaut und einfacher von einem Programm zu erzeugen. Vom einlesen mal ganz zu schweigen. Man muss jedenfalls kein C-Programm scannen.

Verfasst: Freitag 18. Februar 2005, 23:23
von BlackJack
Eine kleine Klasse mit der man ein PGM (Graustufen) erstellen und speichern kann:

Code: Alles auswählen

import struct

class PGM:
    def __init__(self, width, height, maxval=None, comment='producer: pnm.py'):
        if width <= 0 or height <= 0:
            raise ValueError("Dimensions must be > 0")
        
        self.width = width
        self.height = height
        self.maxval = maxval
        self.comment = comment
        
        #
        # Create empty image.
        #
        self.data = list()
        for dummy in xrange(self.height):
            self.data.append([0] * self.width)
    
    def __getitem__(self, coordinate_or_row):
        try:
            x, y = coordinate_or_row
            return self.data[y][x]
        except TypeError:
            return self.data[coordinate_or_row]
    
    def __setitem__(self, coordinate_or_row, pixel_or_row):
        try:
            x, y = coordinate_or_row
            self.data[y][x] = pixel_or_row
        except TypeError:
            self.data[coordinate_or_row] = pixel_or_row

    def write(self, fileobj):
        #
        # Write header.
        #
        fileobj.write('P5\n')
        if self.comment:
            fileobj.write('# %s\n' % self.comment)
        fileobj.write('%s %s\n' % (self.width, self.height))
        if self.maxval is None:
            self.maxval = max(map(max, self.data))
        fileobj.write('%s\n' % self.maxval)
        
        #
        # Write image data.
        #
        row_format = '>%d%s' % (self.width, 'BH'[int(self.maxval > 255)])
        for row in self.data:
            fileobj.write(struct.pack(row_format, *row))

    def save(self, filename):
        image_file = open(filename, 'wb')
        self.write(image_file)
        image_file.close()
So zu benutzen:

Code: Alles auswählen

from __future__ import division
import math

image = PGM(320, 240)
for y in xrange(image.height):
    for x in xrange(image.width):
        image[x, y] = int(abs((math.sin(x / 23)
                               + math.sin(y / 42)
                               + math.sin(x / 6.4)
                               + math.sin(y / 3.2))) * (255 / (2*math.pi)))
image.save('sin.pgm')

image = PGM(320, 240)
for row_nr in xrange(image.height):
    image[row_nr] = [row_nr] * image.width

image.save('gradient_h.pgm')
Die Klasse auf TrueColor Bilder (PPM) umzustellen sollte nicht weiter schwer sein. Es fehlt natürlich auch ein wenig Dokumentation und ein paar Überprüfungen von Paramtern.

Verfasst: Samstag 19. Februar 2005, 07:23
von mawe
Hi!

Sehr nett. Im Beispiel sollte man aber auch PGM importieren, sonst bleibts ziemlich finster :wink:

Gruß, mawe

Verfasst: Samstag 19. Februar 2005, 19:12
von sonium
mitlerweile hab bin ich auf pygame.surfarray gekommen. Hier eine Fläche pixelweise Blau anmalen:

Code: Alles auswählen

try:
    import pygame
    import Numeric as N
    from pygame.locals import *
    surfarray = pygame.surfarray
    if not surfarray: raise ImportError
except:
    raise ImportError, 'Error Importing Pygame/surfarray or Numeric'
    
pygame.init()
    

def show(img):
    screen = pygame.display.set_mode(img.shape[:2], 0, 32)
    surfarray.blit_array(screen, img)
    pygame.display.flip()
    pygame.display.set_caption("Simple GFX Output")
    while 1:
        e = pygame.event.wait()
        if e.type == QUIT: raise SystemExit
            
img = N.zeros((320, 240, 3))

for x in range(img.shape[0]):
    for y in range(img.shape[1]):
        img[x,y,:] = [100,155,255]

show(img)