Skip to content

Commit

Permalink
png to rle conversion in pynthon + Test touch screen
Browse files Browse the repository at this point in the history
  • Loading branch information
mstrens committed Mar 12, 2021
1 parent f278434 commit 88cfc3a
Show file tree
Hide file tree
Showing 5 changed files with 317 additions and 0 deletions.
58 changes: 58 additions & 0 deletions python-png_to_rle/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# python-rle
Convert a PNG file into a human-readable RLE format by using Python 3 and Pillow.

<h3>If you don't have Pillow installed</h3>
Run the following command from the command prompt:
<pre>pip install pillow</pre>

<h3>What is RLE</h3>
According to Wikipedia, RLE stands for "Run-length encoding (RLE)". <br/><br/>
Run-length encoding is a very simple form of lossless data compression in which runs of data (that is, sequences in which the same data value occurs in many consecutive data elements) are stored as a single data value and count, rather than as the original run.
<br/><br/>
<i>For example, this string:</i><br/>
WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW<br/><br/>
<i>...becomes this after using RLE:</i><br/>
12W1B12W3B24W1B14W<br/><br/>
This script simply converts a binary PNG image into an RLE-type file format.
<h3>Example</h3>
<i>Original image</i><br/>
<img src="https://github.com/anwserman/python-rle/blob/master/input/golfcourse.png">
<i>Sample output</i><br/>
<pre>
#Image Dimensions
Width: 683
Height: 384


#Image Palette
255, 0, 128
0, 102, 0
0, 255, 0
66, 255, 66
0, 0, 255
255, 255, 0
128, 128, 128
0, 0, 0

#Pixel Count
0: 42670
1: 48
0: 631
1: 53
0: 627
1: 61
0: 55
2: 55
0: 509
1: 67
0: 48
2: 63

... truncated for brevity
</pre>
<h3>Included commands</h3>
<b>open_png(filename):</b> Open up a PNG file by file path, and read it into memory<br/>
<b>get_color_atpoint(point):</b> Get a tuple with RGB values at a given point in an image, by passing in a tuple with X,Y coordinates<br/>
<b>read_rle_fromstream(stream):</b> Read in RLE information from a file, by passing in a file stream <br/>
<b>write_memory_tofile(filename):</b> Write out the image in memory as a binary file <br/>
<b>write_rle_tostream(filename):</b> Write out RLE information to a file, by passing in a file stream<br/>
Binary file added python-png_to_rle/more1_button_48pixels.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added python-png_to_rle/more1_button_96pixels.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
184 changes: 184 additions & 0 deletions python-png_to_rle/png_to_rle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
import os, sys
from PIL import Image

class RLEBitmap:
width = 0
height = 0
pixels = None
image = None

#basic constructor
def __init__(self):
self.image = None
self.pixels = None
self.height = 0
self.width = 0

def open_png(self, filename):
#open up the image
self.image = Image.open(filename)
#get the pixel data
self.pixels = self.image.load()
#get the width and height
self.width, self.height = self.image.size
print ("width=",self.width)
print ("height=",self.height)

def get_color_atpoint(self, point):
#return the pixel color as a tuple, at the given point
return (self.pixels[point[0], point[1]])

#read an image from a file stream
def read_rle_fromstream(self, stream):
#colors used within the image, this can be a list and not a dictionary
colors = []
colorCount = 0
colorIndex = 0

#iterator data
i = 0
x = 0
y = 0

#reset bitmap data
self.image = None
self.pixels = None

#read in and skip the first line, it's the header description

self.line1 = stream.readline()
print("line1=", self.line1)
#get the image width and height
self.line2 = stream.readline()
print("line2=", self.line2)
self.width = int(self.line2.split(':')[1])
self.height = int(stream.readline().split(':')[1])
#skip the new line
stream.readline()

#set up our bitmap in memory
self.image = Image.new("RGB", (self.width, self.height))

#read in the image palette, and skip the first line as it's the palette description
stream.readline()

#interate through until we hit whitespace
sI = stream.readline()
while not sI.isspace():
#split the line into rgb components
sISplit = sI.split(',')
#read in the values as an RGB tuple
colors.append((int(sISplit[0]), int(sISplit[1]), int(sISplit[2])))
#read in the next new line
sI = stream.readline()

#now we read in the pixel count, and skip the first line as it's the header description
stream.readline()

#iterate through until we hit whitespae
#first line
sI = stream.readline()
while not sI.isspace():
#split the line into index/count components
sISplit = sI.split(':')
#get the RGB index value that we need based on index
colorIndex = int(sISplit[0])
#get the count of how many times we need to loop through this color
colorCount = int(sISplit[1])

i = 0
for i in range(0, colorCount):
self.image.putpixel((x, y), colors[colorIndex])
x += 1

if (x == (self.width)):
x = 0
y += 1

#read in the next new line
sI = stream.readline()

#once the image has been constructed in memory, dump the pixel data into a table
self.pixels = self.image.load()

#print rle conversion
def write_rle_tostream(self):
#colors used within the image
colors = {}
#store the RLE data
pixels = []
pixelsTFE = [] # this is the format required by TFTe_SPI
#store the color in use
currentColor = None
currentColorCount = 0

#iterator data
x = 0
y = 0

#iterate through image
#row by row
for y in range(0, self.height):
#column by column
for x in range(0, self.width):
#get the current pixel
newColor = self.pixels[x, y]

#compare new color versus existing color
if newColor != currentColor:
#we don't want to do this if currentColor is nothing
if currentColor != None:
#add current (existing) color to our dictionary
#and give it an index value (lookup value)
#this is rudimentary lookup table for both saving the color data below and for saving/reading the file later
colors.setdefault(currentColor, len(colors.keys()))
#return the index value
colorIndex = colors[currentColor]
#add the color and pixel count to our list
pixels.append((colorIndex, currentColorCount))
while currentColorCount > 128:
if currentColor == 0:
pixelsTFE.append(127)
else :
pixelsTFE.append(255)
currentColorCount = currentColorCount - 128
if currentColor != 0:
currentColorCount = currentColorCount+128
pixelsTFE.append(currentColorCount-1)
#set the new color to our currentcolor
currentColor = newColor
#set the count equal to 1, as we need to count it as part of the new run
currentColorCount = 1
else:
currentColor = newColor
currentColorCount = 1
else:
currentColorCount += 1

#flush out the last of the colors we were working on, into the array
colors.setdefault(currentColor, len(colors.keys()))
colorIndex = colors[currentColor]
pixels.append((colorIndex, currentColorCount))
while currentColorCount > 128:
if currentColor == 0:
pixelsTFE.append(127)
else :
pixelsTFE.append(255)
currentColorCount = currentColorCount - 128
if currentColor != 0:
currentColorCount = currentColorCount+128
pixelsTFE.append(currentColorCount-1)

print("colors =", colors)
print("pixels (on/off , amount) =" , pixels)
print("rle = " ,pixelsTFE)

#some tests
#open up a PNG and write it to a RLE document
rb = RLEBitmap()
#rb.open_png('input\golfcourse.png')
rb.open_png('more1_button.png')
#fs = open('output\more1_button.rle','w')
#fs = open('output\golfcourse.rle','w')
rb.write_rle_tostream()
#fs.close()
75 changes: 75 additions & 0 deletions test touch screen/test_touchscreen/test_touchscreen.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@

#include "SPI.h"

#define TFT_MISO 19
#define TFT_MOSI 23
#define TFT_SCLK 18
#define TFT_CS 13 //15 // Chip select control pin
#define TFT_DC 14// 2 // Data Command control pin

#define TFT_RST 12// 4 // Reset pin (could connect to RST pin)

//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST
#define TOUCH_CS 27 //21 // Chip select pin (T_CS) of touch screen

#define TFT_LED_PIN 25



void setup() {
Serial.begin(115200);
Serial.println("\n\nStarting...");


pinMode(TFT_DC, OUTPUT);
digitalWrite(TFT_DC, HIGH); // Data/Command high = data mode

pinMode(TFT_RST, OUTPUT);
digitalWrite(TFT_RST, HIGH); // Set high, do not share pin with another SPI device

pinMode(TFT_LED_PIN , OUTPUT) ;
digitalWrite(TFT_LED_PIN , HIGH) ;


SPI.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1);
Serial.println("\n\nEnd of setup...");
//SPI.endTransaction();

tft.begin();

tft.setRotation(1);
tft.fillScreen(TFT_NAVY); // Clear screen to navy background

}

void readOneAxis(uint8_t axis){
uint16_t data ;
//Serial.print("1");
SPI.endTransaction();
SPI.beginTransaction(SPISettings(2500000, MSBFIRST, SPI_MODE0));
//Serial.print("2");
digitalWrite( TOUCH_CS, LOW) ; // select the device
//pinMode(TFT_RST, INPUT );
SPI.transfer(axis);
//Serial.print("3");
data = SPI.transfer16(axis) ;
//Serial.print("4");
Serial.print(" "); Serial.print(data);
digitalWrite( TOUCH_CS, HIGH) ; // select the device
SPI.endTransaction();
//Serial.print("5");

}
#define X_AXIS 0xD3
#define Y_AXIS 0x93
#define Z_AXIS 0xB1


void loop() {
// put your main code here, to run repeatedly:
readOneAxis(X_AXIS);
readOneAxis(Y_AXIS);
readOneAxis(Z_AXIS);
Serial.println("");
//delay(500);
}

0 comments on commit 88cfc3a

Please sign in to comment.