acid-drop- Hacking the planet from a LilyGo T-Deck using custom firmware |
git clone git://git.acid.vegas/acid-drop.git |
Log | Files | Refs | Archive | README | LICENSE |
bmp2array4bit.py (8335B)
1 ''' 2 3 This script takes in a bitmap and outputs a text file that is a 4 byte array used in Arduino files. 5 6 It is loosely based on Spark Fun's bmp2array script. 7 8 You'll need python 3.6 (the original use Python 2.7) 9 10 usage: python fourbitbmp2array.py [-v] star.bmp [-o myfile.c] 11 12 Create the bmp file in Gimp by : 13 14 . Remove the alpha channel (if it has one) Layer -> Transparency -> Remove Alpha Channel 15 . Set the mode to indexed. Image -> Mode -> Indexed... 16 . Select Generate optimum palette with 16 colors (max) 17 . Export the file with a .bmp extension. Options are: 18 . Run-Length Encoded: not selected 19 . Compatibility Options: "Do not write color space information" not selected 20 . There are no Advanced Options available with these settings 21 22 23 24 25 ''' 26 27 import sys 28 import struct 29 import math 30 import argparse 31 import os 32 33 debug = None 34 35 def debugOut(s): 36 if debug: 37 print(s) 38 39 # look at arguments 40 parser = argparse.ArgumentParser(description="Convert bmp file to C array") 41 parser.add_argument("-v", "--verbose", help="debug output", action="store_true") 42 parser.add_argument("input", help="input file name") 43 parser.add_argument("-o", "--output", help="output file name") 44 args = parser.parse_args() 45 46 if not os.path.exists(args.input): 47 parser.print_help() 48 print("The input file {} does not exist".format(args.input)) 49 sys.exit(1) 50 51 if args.output == None: 52 output = os.path.basename(args.input).replace(".bmp", ".c") 53 else: 54 output = args.output 55 56 debug = args.verbose 57 58 try: 59 #Open our input file which is defined by the first commandline argument 60 #then dump it into a list of bytes 61 infile = open(args.input,"rb") #b is for binary 62 contents = bytearray(infile.read()) 63 infile.close() 64 except: 65 print("could not read input file {}".format(args.input)) 66 sys.exit(1) 67 68 # first two bytes should be "BM" 69 upto = 2 70 #Get the size of this image 71 data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) 72 fileSize = struct.unpack("I", bytearray(data)) 73 74 upto += 4 75 # four bytes are reserved 76 77 upto += 4 78 79 debugOut("Size of file: {}".format(fileSize[0])) 80 81 #Get the header offset amount 82 data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) 83 offset = struct.unpack("I", bytearray(data)) 84 85 debugOut("Offset: {}".format(offset[0])) 86 upto += 4 87 88 data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) 89 headersize = struct.unpack("I", bytearray(data)) 90 headerLength = headersize[0] 91 startOfDefinitions = headerLength + upto 92 debugOut("header size: {}, up to {}, startOfDefinitions {}".format(headersize[0], upto, startOfDefinitions)) 93 upto += 4 94 95 data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) 96 t = struct.unpack("I", bytearray(data)) 97 debugOut("width: {}".format(t[0])) 98 width = t[0] 99 100 upto += 4 101 data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) 102 t = struct.unpack("I", bytearray(data)) 103 debugOut("height: {}".format(t[0])) 104 height = t[0] 105 106 # 26 107 upto += 4 108 109 data = struct.pack("BB", contents[upto], contents[upto+1]) 110 t = struct.unpack("H", bytearray(data)) 111 debugOut("planes: {}".format(t[0])) 112 113 upto = upto + 2 114 data = struct.pack("BB", contents[upto], contents[upto+1]) 115 t = struct.unpack("H", bytearray(data)) 116 debugOut("bits per pixel: {}".format(t[0])) 117 bitsPerPixel = t[0] 118 119 upto = upto + 2 120 data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) 121 t = struct.unpack("I", bytearray(data)) 122 debugOut("biCompression: {}".format(t[0])) 123 124 upto = upto + 4 125 data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) 126 t = struct.unpack("I", bytearray(data)) 127 debugOut("biSizeImage: {}".format(t[0])) 128 129 upto = upto + 4 130 data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) 131 t = struct.unpack("I", bytearray(data)) 132 debugOut("biXPelsPerMeter: {}".format(t[0])) 133 134 upto = upto + 4 135 data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) 136 t = struct.unpack("I", bytearray(data)) 137 debugOut("biYPelsPerMeter: {}".format(t[0])) 138 139 upto = upto + 4 140 data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) 141 t = struct.unpack("I", bytearray(data)) 142 debugOut("biClrUsed: {}".format(t[0])) 143 colorsUsed = t 144 145 upto = upto + 4 146 data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) 147 t = struct.unpack("I", bytearray(data)) 148 debugOut("biClrImportant: {}".format(t[0])) 149 150 upto += 4 151 152 debugOut("Upto: {} Number of colors used: {} definitions start at: {}".format(upto, colorsUsed[0], startOfDefinitions)) 153 154 #Create color definition array and init the array of color values 155 colorIndex = [] #(colorsUsed[0]) 156 for i in range(colorsUsed[0]): 157 colorIndex.append(0) 158 159 #Assign the colors to the array. upto = 54 160 # startOfDefinitions = upto 161 for i in range(colorsUsed[0]): 162 upto = startOfDefinitions + (i * 4) 163 blue = contents[upto] 164 green = contents[upto + 1] 165 red = contents[upto + 2] 166 # ignore the alpha channel. 167 168 # data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3]) 169 # t = struct.unpack("I", bytearray(data)) 170 # colorIndex[i] = t[0] 171 172 colorIndex[i] = (((red & 0xf8)<<8) + ((green & 0xfc)<<3)+(blue>>3)) 173 debugOut("color at index {0} is {1:04x}, (r,g,b,a) = ({2:02x}, {3:02x}, {4:02x}, {5:02x})".format(i, colorIndex[i], red, green, blue, contents[upto+3])) 174 175 #debugOut(the color definitions 176 # for i in range(colorsUsed[0]): 177 # print hex(colorIndex[i]) 178 179 # perfect, except upside down. 180 181 #Make a string to hold the output of our script 182 arraySize = (len(contents) - offset[0]) 183 outputString = "/* This was generated using a script based on the SparkFun BMPtoArray python script" + '\n' 184 outputString += " See https://github.com/sparkfun/BMPtoArray for more info */" + '\n\n' 185 outputString += "static const uint16_t palette[" + str(colorsUsed[0]) + "] = {"; 186 for i in range(colorsUsed[0]): 187 # print hexlify(colorIndex[i]) 188 if i % 4 == 0: 189 outputString += "\n\t" 190 outputString += "0x{:04x}, ".format(colorIndex[i]) 191 192 outputString = outputString[:-2] 193 outputString += "\n};\n\n" 194 outputString += "// width is " + str(width) + ", height is " + str(height) + "\n" 195 outputString += "static const uint8_t myGraphic[" + str(arraySize) + "] PROGMEM = {" + '\n' 196 197 if bitsPerPixel != 4: 198 print("Expected 4 bits per pixel; found {}".format(bitsPerPixel)) 199 sys.exit(1) 200 201 #Start converting spots to values 202 #Start at the offset and go to the end of the file 203 dropLastNumber = True #(width % 4) == 2 or (width % 4) == 1 204 paddedWidth = int(math.ceil(bitsPerPixel * width / 32.0) * 4) 205 debugOut("array range is {} {} len(contents) is {} paddedWidth is {} width is {}".format(offset[0], fileSize[0], len(contents), paddedWidth, width)) 206 207 r = 0 208 width = int(width / 2) 209 #for i in range(offset[0], fileSize[0]): # close but image is upside down. Each row is correct but need to swap columns. 210 #for i in range(fileSize[0], offset[0], -1): 211 212 for col in range(height-1, -1, -1): 213 i = 0 214 for row in range(width): 215 colorCode1 = contents[row + col*paddedWidth + offset[0]] 216 217 if r > 0 and r % width == 0: 218 i = 0 219 outputString += '\n\n' 220 elif (i + 1) % 12 == 0 : 221 outputString += '\n' 222 i = 0 223 224 #debugOut("cell ({0}, {1})".format(row, col) 225 226 r = r + 1 227 i = i + 1 228 outputString += "0x{:02x}, ".format(colorCode1) 229 230 231 232 #Once we've reached the end of our input string, pull the last two 233 #characters off (the last comma and space) since we don't need 234 #them. Top it off with a closing bracket and a semicolon. 235 outputString = outputString[:-2] 236 outputString += "};" 237 238 try: 239 #Write the output string to our output file 240 outfile = open(output, "w") 241 outfile.write(outputString) 242 outfile.close() 243 except: 244 print("could not write output to file {}".format(output)) 245 sys.exit(1) 246 247 debugOut("{} complete".format(output)) 248 debugOut("Copy and paste this array into a image.h or other header file") 249 250 if not debug: 251 print("Completed; the output is in {}".format(output))