pov.py 3.19 KB
Newer Older
Julian's avatar
Julian committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#this script reads a BMP file and displays it as POV. For optimal results use a BMP that is 11 pixels wide.

import leds,utime
#default filename. Depending on how you want to run this, change it
FILENAME = "Smiley.bmp"
#Determines the Frame Rate, currently not used.
DELAY = 0
#Determine Brightness Level. You might not wanna use the full values from the BMP
BRIGHTNESS = 1.0



class BMPError(Exception):
    pass

Rahix's avatar
Rahix committed
16
class POV:
Julian's avatar
Julian committed
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
    def __init__(self, filename=FILENAME):
        self.filename = filename
        f = open("/" + self.filename, "rb")
        if f.read(2) != b'BM':  # check signature
            raise BMPError("Not BitMap file")
        #turn into int.from_bytes
        bmpFileSize = int.from_bytes(f.read(4), 'little')
        f.read(4)  # Read & ignore creator bytes

        self.bmpImageOffset = self.read_le(f.read(4))  # Start of image data
        headerSize = self.read_le(f.read(4))
        self.bmpWidth = self.read_le(f.read(4))
        self.bmpHeight = self.read_le(f.read(4))
        flip = False

        print("Size: %d\nImage offset: %d\nHeader size: %d" %
              (bmpFileSize, self.bmpImageOffset, headerSize))
        print("Width: %d\nHeight: %d" % (self.bmpWidth, self.bmpHeight))

        if self.read_le(f.read(2)) != 1:
            raise BMPError("Not singleplane")
        bmpDepth = self.read_le(f.read(2))  # bits per pixel
        print("Bit depth: %d" % (bmpDepth))
        if bmpDepth != 24:
            raise BMPError("Not 24-bit")
        if self.read_le(f.read(2)) != 0:
            raise BMPError("Compressed file")

        print("Image OK!")
        self.rowSize = (self.bmpWidth * 3 + 3) & ~3  # 32-bit line boundary
        self.fileOffset = f.tell()
        print("File Offset"+str(self.fileOffset))
        f.close()
        self.read_image()


    def correct_brightness(self, color):
        return int(pow((color * BRIGHTNESS) / 255, 2.7) * 255 + 0.5)
    def getWidth(self):
        return self.bmpWidth
    def setFileOffset(self, fileOffset):
        self.fileOffset = fileOffset
    def getFileOffset(self):
        return self.fileOffset
    def read_le(self, bytes):
        return int.from_bytes(bytes, 'little')
Rahix's avatar
Rahix committed
63
    def read_image(self):
Julian's avatar
Julian committed
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
        self.imageArray = []
        flip = True
        rowSize = (self.bmpWidth * 3 + 3) & ~3
        f = open("/" + self.filename, "rb")
        for row in range(self.bmpHeight):
            rowArray = []
            if flip:  # Bitmap is stored bottom-to-top order (normal BMP)
                pos = self.bmpImageOffset + (self.bmpHeight - 1 - row) * rowSize
            else:  # Bitmap is stored top-to-bottom
                pos = self.bmpImageOffset + row * rowSize
            f.seek(pos)
            for col in range(self.bmpWidth):
                rgb = [f.read(1), f.read(1), f.read(1)]
                rgb = [int.from_bytes(x, "little") for x in rgb]
                #rgb = [self.correct_brightness(x) for x in rgb]
                rowArray += [rgb]
            self.imageArray += [rowArray]

    def getImageArray(self):
        return self.imageArray
Rahix's avatar
Rahix committed
84

Julian's avatar
Julian committed
85
86
87
88
89
90
91
92
93
94
95
    def playMe(self):
        for i in self.imageArray:
            leds.set_all(i)

def play(imagename):
    myPov = POV(imagename)
    while True:
        myPov.playMe()


play("Smiley.bmp")