|
| 1 | +import os, sys |
| 2 | +from PIL import Image |
| 3 | + |
| 4 | +class RLEBitmap: |
| 5 | + width = 0 |
| 6 | + height = 0 |
| 7 | + pixels = None |
| 8 | + image = None |
| 9 | + |
| 10 | + #basic constructor |
| 11 | + def __init__(self): |
| 12 | + self.image = None |
| 13 | + self.pixels = None |
| 14 | + self.height = 0 |
| 15 | + self.width = 0 |
| 16 | + |
| 17 | + def open_png(self, filename): |
| 18 | + #open up the image |
| 19 | + self.image = Image.open(filename) |
| 20 | + #get the pixel data |
| 21 | + self.pixels = self.image.load() |
| 22 | + #get the width and height |
| 23 | + self.width, self.height = self.image.size |
| 24 | + print ("width=",self.width) |
| 25 | + print ("height=",self.height) |
| 26 | + |
| 27 | + def get_color_atpoint(self, point): |
| 28 | + #return the pixel color as a tuple, at the given point |
| 29 | + return (self.pixels[point[0], point[1]]) |
| 30 | + |
| 31 | + #read an image from a file stream |
| 32 | + def read_rle_fromstream(self, stream): |
| 33 | + #colors used within the image, this can be a list and not a dictionary |
| 34 | + colors = [] |
| 35 | + colorCount = 0 |
| 36 | + colorIndex = 0 |
| 37 | + |
| 38 | + #iterator data |
| 39 | + i = 0 |
| 40 | + x = 0 |
| 41 | + y = 0 |
| 42 | + |
| 43 | + #reset bitmap data |
| 44 | + self.image = None |
| 45 | + self.pixels = None |
| 46 | + |
| 47 | + #read in and skip the first line, it's the header description |
| 48 | + |
| 49 | + self.line1 = stream.readline() |
| 50 | + print("line1=", self.line1) |
| 51 | + #get the image width and height |
| 52 | + self.line2 = stream.readline() |
| 53 | + print("line2=", self.line2) |
| 54 | + self.width = int(self.line2.split(':')[1]) |
| 55 | + self.height = int(stream.readline().split(':')[1]) |
| 56 | + #skip the new line |
| 57 | + stream.readline() |
| 58 | + |
| 59 | + #set up our bitmap in memory |
| 60 | + self.image = Image.new("RGB", (self.width, self.height)) |
| 61 | + |
| 62 | + #read in the image palette, and skip the first line as it's the palette description |
| 63 | + stream.readline() |
| 64 | + |
| 65 | + #interate through until we hit whitespace |
| 66 | + sI = stream.readline() |
| 67 | + while not sI.isspace(): |
| 68 | + #split the line into rgb components |
| 69 | + sISplit = sI.split(',') |
| 70 | + #read in the values as an RGB tuple |
| 71 | + colors.append((int(sISplit[0]), int(sISplit[1]), int(sISplit[2]))) |
| 72 | + #read in the next new line |
| 73 | + sI = stream.readline() |
| 74 | + |
| 75 | + #now we read in the pixel count, and skip the first line as it's the header description |
| 76 | + stream.readline() |
| 77 | + |
| 78 | + #iterate through until we hit whitespae |
| 79 | + #first line |
| 80 | + sI = stream.readline() |
| 81 | + while not sI.isspace(): |
| 82 | + #split the line into index/count components |
| 83 | + sISplit = sI.split(':') |
| 84 | + #get the RGB index value that we need based on index |
| 85 | + colorIndex = int(sISplit[0]) |
| 86 | + #get the count of how many times we need to loop through this color |
| 87 | + colorCount = int(sISplit[1]) |
| 88 | + |
| 89 | + i = 0 |
| 90 | + for i in range(0, colorCount): |
| 91 | + self.image.putpixel((x, y), colors[colorIndex]) |
| 92 | + x += 1 |
| 93 | + |
| 94 | + if (x == (self.width)): |
| 95 | + x = 0 |
| 96 | + y += 1 |
| 97 | + |
| 98 | + #read in the next new line |
| 99 | + sI = stream.readline() |
| 100 | + |
| 101 | + #once the image has been constructed in memory, dump the pixel data into a table |
| 102 | + self.pixels = self.image.load() |
| 103 | + |
| 104 | + #print rle conversion |
| 105 | + def write_rle_tostream(self): |
| 106 | + #colors used within the image |
| 107 | + colors = {} |
| 108 | + #store the RLE data |
| 109 | + pixels = [] |
| 110 | + pixelsTFE = [] # this is the format required by TFTe_SPI |
| 111 | + #store the color in use |
| 112 | + currentColor = None |
| 113 | + currentColorCount = 0 |
| 114 | + |
| 115 | + #iterator data |
| 116 | + x = 0 |
| 117 | + y = 0 |
| 118 | + |
| 119 | + #iterate through image |
| 120 | + #row by row |
| 121 | + for y in range(0, self.height): |
| 122 | + #column by column |
| 123 | + for x in range(0, self.width): |
| 124 | + #get the current pixel |
| 125 | + newColor = self.pixels[x, y] |
| 126 | + |
| 127 | + #compare new color versus existing color |
| 128 | + if newColor != currentColor: |
| 129 | + #we don't want to do this if currentColor is nothing |
| 130 | + if currentColor != None: |
| 131 | + #add current (existing) color to our dictionary |
| 132 | + #and give it an index value (lookup value) |
| 133 | + #this is rudimentary lookup table for both saving the color data below and for saving/reading the file later |
| 134 | + colors.setdefault(currentColor, len(colors.keys())) |
| 135 | + #return the index value |
| 136 | + colorIndex = colors[currentColor] |
| 137 | + #add the color and pixel count to our list |
| 138 | + pixels.append((colorIndex, currentColorCount)) |
| 139 | + while currentColorCount > 128: |
| 140 | + if currentColor == 0: |
| 141 | + pixelsTFE.append(127) |
| 142 | + else : |
| 143 | + pixelsTFE.append(255) |
| 144 | + currentColorCount = currentColorCount - 128 |
| 145 | + if currentColor != 0: |
| 146 | + currentColorCount = currentColorCount+128 |
| 147 | + pixelsTFE.append(currentColorCount-1) |
| 148 | + #set the new color to our currentcolor |
| 149 | + currentColor = newColor |
| 150 | + #set the count equal to 1, as we need to count it as part of the new run |
| 151 | + currentColorCount = 1 |
| 152 | + else: |
| 153 | + currentColor = newColor |
| 154 | + currentColorCount = 1 |
| 155 | + else: |
| 156 | + currentColorCount += 1 |
| 157 | + |
| 158 | + #flush out the last of the colors we were working on, into the array |
| 159 | + colors.setdefault(currentColor, len(colors.keys())) |
| 160 | + colorIndex = colors[currentColor] |
| 161 | + pixels.append((colorIndex, currentColorCount)) |
| 162 | + while currentColorCount > 128: |
| 163 | + if currentColor == 0: |
| 164 | + pixelsTFE.append(127) |
| 165 | + else : |
| 166 | + pixelsTFE.append(255) |
| 167 | + currentColorCount = currentColorCount - 128 |
| 168 | + if currentColor != 0: |
| 169 | + currentColorCount = currentColorCount+128 |
| 170 | + pixelsTFE.append(currentColorCount-1) |
| 171 | + |
| 172 | + print("colors =", colors) |
| 173 | + print("pixels (on/off , amount) =" , pixels) |
| 174 | + print("rle = " ,pixelsTFE) |
| 175 | + |
| 176 | +#some tests |
| 177 | +#open up a PNG and write it to a RLE document |
| 178 | +rb = RLEBitmap() |
| 179 | +#rb.open_png('input\golfcourse.png') |
| 180 | +rb.open_png('more1_button.png') |
| 181 | +#fs = open('output\more1_button.rle','w') |
| 182 | +#fs = open('output\golfcourse.rle','w') |
| 183 | +rb.write_rle_tostream() |
| 184 | +#fs.close() |
0 commit comments