In [11]:
import png
import math
import glob
import os
import numpy as np;
from IPython.display import Image
In [12]:
#returns the width and height (respectively) of the given img
def getPngDimensions(filename):
img = png.Reader(filename).asDirect()
vals = []
vals.append(img[0])
vals.append(img[1])
return vals
In [17]:
def getPixels(filename):
pic1 = png.Reader(filename).asRGBA()
rows = pic1[2]
pixels = []
pixelcount = 0
for row in rows:
count = 0
pixel = []
for entry in row:
pixel.append(entry)
count = count + 1
if (count == 4):
pixels.append(pixel)
pixel = []
pixelcount = pixelcount + 1
count = 0;
return pixels
def reencodeImageWithGivenBpp(pixels, inRbpp, inGbpp, inBbpp, outRbpp, outGbpp, outBbpp):
outpixels = []
for pixel in pixels:
outpixel = []
channelCount = 0
for channel in pixel:
numIn = -1
numOut = -1
colorchar = "?"
if channelCount == 0:
numIn = inRbpp
numOut = outRbpp
colorchar = "R"
elif channelCount == 1:
numIn = inGbpp
numOut = outGbpp
colorchar = "G"
elif channelCount == 2:
numIn = inBbpp
numOut = outBbpp
colorchar = "B"
elif channelCount == 3:
outpixel.append(channel)
break
channelCount = channelCount + 1
#find if we're upscaling or downscaling
#for downscaling, we need to divide our value by 2^(difference in powers)
#for upscaling, we need to multiply by the same value. We don't apply any dithering.
outval = 0;
if (numIn > numOut):
dif = numIn - numOut
outval = channel >> dif
else:
dif = numOut - numIn
outval = channel << dif
outpixel.append(outval)
#print(colorchar + ": " + str(channel) + " --> " + str(outval))
outpixels.append(outpixel)
return outpixels
In [18]:
def ConvertPixelsToPngWriteable(pixels, width):
resultArray1 = []
resultArray2 = []
count = 0;
for pixel in pixels:
count = count + 1
resultArray2.append(pixel[0])
resultArray2.append(pixel[1])
resultArray2.append(pixel[2])
if (count == width):
count = 0
resultArray1.append(resultArray2)
resultArray2 = []
return resultArray1
In [74]:
def MakeDir(path):
#ignore exception saying it already exists
try:
os.makedirs(path)
except OSError:
if not os.path.isdir(path):
raise
def ProcessFolder(outputImages=False):
curDir = os.getcwd()
sizeTotal = 0
with open(curDir + "\\output.txt", 'w') as outFile:
outFile.write("#ifndef SPRITE_DEFINITIONS_H\r\n#define SPRITE_DEFINITIONS_H\r\n\r\n")
sizeTotal = ProcessFolderRec(os.getcwd(), outFile, sizeTotal, outputImages)
outFile.write("//" + str(sizeTotal) + " bytes used (estimated)\r\n")
outFile.write("#endif")
outFile.close()
print (str(sizeTotal) + " bytes used (estimate)")
def ProcessFolderRec(folderPath, outFile, sizeTotal, outputImages=False):
print("Processing folder: " + folderPath)
os.chdir(folderPath)
for directory in (d for d in glob.glob('*/') if d != '/out'):
sizeTotal = sizeTotal + ProcessFolderRec(folderPath + '/' + directory, outFile, outputImages)
#make sure we're in the right working dir
os.chdir(folderPath)
for filename in glob.glob('*.png'):
print("Processing file: " + filename)
imgdimensions = getPngDimensions(filename)
imgwidth = imgdimensions[0]
imgheight = imgdimensions[1]
inpixels = getPixels(filename)
outpixels = reencodeImageWithGivenBpp(inpixels, 8,8,8, 5,6,5)
if(outputImages):
altPixels = reencodeImageWithGivenBpp(outpixels, 5,6,5, 8,8,8)
altPixels = ConvertPixelsToPngWriteable(altPixels, imgwidth)
#try making the output directory
MakeDir("out/")
alteredOutFile = open("out/" + filename[:-4] + "_out.png", 'wb')
writer = png.Writer(size = imgdimensions)
writer.write(alteredOutFile, altPixels)
alteredOutFile.close()
##########################################
#write the entry
#get rid of the extension, uppercase everything, and replace spaces with underscores
spriteName = filename[:-4].upper().replace(" ", "_")
#start defining the array
outFile.write("const PROGMEM uint16_t ")
outFile.write(spriteName)
outFile.write("[] = {")
#define the width
outFile.write(str(imgwidth))
outFile.write(", ")
#define the height
outFile.write(str(imgheight))
outFile.write(", ")
totNumPixels = imgheight * imgwidth
curpixel = 0
#go through each pixel and calculate the integer representation
for pixel in outpixels:
outValue = 0;
channelCount = 0
curpixel = curpixel + 1
for channel in pixel:
if channelCount == 3:
#check for transparency. If we're transparent then
#ignore what we recorded for the other pixels and
#save magenta in our outvalue
if channel == 0:
outValue = 0xF81F
break
outValue = outValue | channel
#red has 5 bits, green has 6, and blue has 5
if channelCount == 0:
outValue = outValue << 6
elif channelCount == 1:
outValue = outValue << 5
#don't shift for the last 5 bits
channelCount = channelCount + 1
#write this vlue to our list of pixels
outFile.write(str(outValue))
#don't put a comma after the last value
if(curpixel != totNumPixels):
outFile.write(",")
outFile.write("};\r\n\r\n")
sizeTotal = sizeTotal + (imgwidth * imgheight * 2) + 4
print("Finished processing entry: " + filename)
print ("Current size: " + str(sizeTotal))
return sizeTotal
In [75]:
ProcessFolder()
In [ ]:
In [ ]: