Digitaler Bilderrahmen als Uhr (für Malfaule)

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
pytobi
User
Beiträge: 3
Registriert: Freitag 17. April 2009, 10:46

Hi,
nachdem ich auf heise online diesen wunderbaren Artikel http://www.heise.de/foto/artikel/Digita ... 23520.html gelesen hatte, kam mir die Idee, das doch auch mal zu versuchen.

Ich kaufte mir schnell bei Ebay für wenig Geld nen kleinen 7Zoll Intenso Bilderrahmen und fing an mit Gimp zu zeichnen. Nach ner halben Stunde war mein erstes Bild fertig und ich hatte keine Lust mehr. Und fing an zu programmieren.

Jetzt ist der Bildergenerator fertig und ich will ihn euch nicht vorenthalten. Ist mehr schnell als elegant programmiert ;). 720 Bilder in 13 Sekunden hört sich viel besser an.

Kurze Beschreibung der Möglichkeiten:
Displaygröße, alle Farben, Schriftart und -größe, Anzeigedauer des Bilderrahmens und natürlich der Text können verändert werden.

Was noch fehlt:
Startzeitwahl für automatisches Einschalten des Rahmens

Wie sieht das aus:
Bild

Und jetzt der Code:

Code: Alles auswählen

# -*- coding: iso-8859-1 -*-
import sys, random
import Image, ImageDraw, ImageFont

class PictureFrameClock:
    #version 0.1
    #author pytobi
    def __init__(self, args):
        #display size
        self.size=(480, 234)
        #display text
        self.text=[[('es ist', '1'), ('wir haben', '2'), ('jetzt ist es', '3')], [('zehn', '10'), ('fünf', '5'), ('zwanzig', '20'), ('viertel', '15')], [('nach', 'n1'), ('vor', 'n2'), ('halb', 'x1')], [('drei', '3'), ('vier', '4'), ('neun', '9'), ('zwölf', '12'), ('eins', '1'), ('zehn', '10')], [('sieben', '7'), ('zwei', '2'), ('acht', '8'), ('sechs', '6'), ('fünf', '5'), ('elf', '11')], [('uhr', '1')]]
        #backgroud color
        self.bg='#000000'
        #active text color
        self.on='#FFFF10'
        #inactive text color
        self.off='#616161'
        #font size
        fsize=30
        #font
        self.myfont=ImageFont.truetype('dejavusans.ttf', fsize)
        #display time
        self.displaytime=1
        #gap between lines
        self.gap=(self.size[1]-len(self.text)*fsize)/(len(self.text)+1)
        #vertical pitch
        self.pitch=self.gap+fsize
        #self.createPic('test')
        self.createClock()
        sys.exit(0)
        
    def createPic(self, fname, minute=0, n=0, x=0, hour=0, u=0, rnum=0):
        #create image
        self.im = Image.new('RGB', self.size, self.bg)
        draw = ImageDraw.Draw(self.im)
        ypos=self.gap
        #create text lines
        for i in range (len(self.text)):
            #compute horizontal gap between words
            str=''
            for entry in self.text[i]:
                str+=entry[0]
            s=draw.textsize(str, font=self.myfont)[0]
            linegap=(self.size[0]-s)/(len(self.text[i])+1)
            xpos=linegap
            #create words
            for j in range(len(self.text[i])):
                #check if word needs to be active or inactive
                if i==0:
                    if self.text[i][j][1]=='%s' % rnum:
                        color=self.on
                    else:
                        color=self.off
                if i==1:
                    if self.text[i][j][1]=='%s' % minute:
                        color=self.on
                    else:
                        color=self.off
                if i==2:
                    if self.text[i][j][1]=='n%s' % n:
                        color=self.on
                    elif self.text[i][j][1]=='x%s' % x:
                        color=self.on
                    else:
                        color=self.off
                if i==3 or i==4:
                    if self.text[i][j][1]=='%s' % hour:
                        color=self.on
                    else:
                        color=self.off
                if i==5:
                    if self.text[i][j][1]=='%s' % u:
                        color=self.on
                    else:
                        color=self.off
                draw.text((xpos, ypos), self.text[i][j][0], font=self.myfont, fill=color)
                xpos+=draw.textsize(self.text[i][j][0], font=self.myfont)[0]+linegap
            ypos+=self.pitch
        #save image
        self.im.save(fname+'.jpg', "JPEG")
        
    def createClock(self):
        #translate clock time into spoken time
        for i in range(12):
            if i==0:
                hour=12
            else:
                hour=i
            for j in range(60):
                if j==0:
                    minute=0
                    n=0
                    x=0
                    if hour==1:
                        u=0
                    else:
                        u=1
                elif j==5:
                    u=0
                    minute=5
                    n=1
                elif j==10:
                    minute=10
                elif j==15:
                    minute=15
                elif j==20:
                    minute=20
                elif j==25:
                    minute=5
                    n=2
                    x=1
                    if hour==12:
                        hour=1
                    else:
                        hour=i+1
                elif j==30:
                    minute=0
                    n=0
                elif j==35:
                    minute=5
                    n=1
                elif j==40:
                    minute=20
                    n=2
                    x=0
                elif j==45:
                    minute=15
                elif j==50:
                    minute=10
                elif j==55:
                    minute=5
                #only needed because displaytime can be smaller than minimum clock time (5 mins)
                if j%5==0:
                    rnum=random.randint(1,3)
                #create new pic
                if j%self.displaytime==0:
                    self.createPic('%02d_%02d' %(i, j), minute, n, x, hour, u, rnum)
                
args = sys.argv[1:]
if __name__ == '__main__': PictureFrameClock(args)
Hoffe es gibt noch mehr irre Bastler!
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Also diese ganzen `if...elif...else`-Kaskaden solltest Du doch mal überarbeiten. Bis auf wenige Ausnahmen sieht das doch alles nach Copy&Paste-Programmierung aus.

Und `for i in range (len(self.text)):` ist der typische Anti-Pattern des Listeniterierens... wieso benutzt Du da kein `enumerate()`?

Ansonsten ist die Idee ziemlich kurios und das Ergebnis recht stylisch :-) Wobei ich solchen Bilderrahmen an sich nix abgewinnen kann :-D
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Mach ich da was falsch? Unter Windows bekomme ich folgenden Fehler zu sehen:
Traceback (most recent call last):
File "pictureframeclock.py", line 141, in <module>
if __name__ == '__main__': PictureFrameClock(args)
File "pictureframeclock.py", line 22, in __init__
self.myfont=ImageFont.truetype('dejavusans.ttf', fsize)
File "C:\python27\lib\site-packages\PIL\ImageFont.py", line 218, in truetype
return FreeTypeFont(filename, size, index, encoding)
File "C:\python27\lib\site-packages\PIL\ImageFont.py", line 134, in __init__
self.font = core.getfont(file, size, index, encoding)
File "C:\python27\lib\site-packages\PIL\ImageFont.py", line 34, in __getattr__
raise ImportError("The _imagingft C module is not installed")
ImportError: The _imagingft C module is not installed
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
pytobi
User
Beiträge: 3
Registriert: Freitag 17. April 2009, 10:46

@darktrym
Ja, es wird eine PIL-Version kompiliert mit libfreetype benötigt. Die gibts zum Beispiel hier: http://www.lfd.uci.edu/~gohlke/pythonlibs/
Die wird benötigt, weil ich sonst keine Truetype Schriften verwenden kann, und die anderen sind nicht skalierbar.

@Hyperion
Du hast recht, besonders schön ist das ganze nicht. Vielleicht komm ich nochmal dazu ein bisschen zu cleanen.
Die enumerate-Funktion kannte ich noch gar nicht, muss ich mir mal anschauen.
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Nur kurz Feedback für die Nachwelt. Diese PIL Versionen sind allesamt ziemlich broken, keine Ahnung was der Typ damit macht.
Ergebnis: Kein Fenster, aber auch kein Werfen einer Exception dafür erfolgreiches Beenden mit Rückgabewert 0.
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
BlackJack

@darktrym: Was meinst Du mit „kein Fenster”? Das Programm erzeugt einen Haufen Bilddateien. Es hat keine GUI. Und es gibt auch keinen Text auf der Konsole aus. Das heisst ein Rückgabewert von 0 ist das einzige was Du neben den Bilddateien erwarten solltest.
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Gut, dann funktioniert das Programm. Ich bin vom Beschreibung ausgegangen, also das ein Viewer integriert ist.
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
Antworten