I have created a bitmap converter in Processing 2.0 that takes a 32x32 PNG/GIF/JPG and converts it to a 32x32 matrix buffer compatible image.h file.
The script is based on the drawPixel function in the Adafruit RGB matrix panel library.
I have it up and running, but with some color problems, most likely due to some of the bits being manipulated incorrectly.
It would be great if better coders than me could have a look at the script, to see where I get it wrong. If needed I can also upload test files and photos for further diagnostics.
As a backup plan I intend to make a Arduino sketch that accepts the image in 5/6/5 format without any bit manipulation, sends it to the buffer/panel through drawPixel calls and then dumps the buffer through a serial connection. This will be enough for my immediate needs, but I want to be able to share the Processing script with you guys for easy conversion.PImage image;
String imageName = "test.gif";
String saveDir = "./imageFiles/";
PrintWriter outputMatrix;
int [][] matrixbuff= new int [3][32];
void setup() {
selectInput("Select a file to process:", "imageName");
}
void imageName(File selection) {
if (selection == null) {
println("Window was closed or the user hit cancel.");
}
else {
println("User selected " + selection.getAbsolutePath());
// Do note that the file used is from the hardcoded reference in the top of this file and not the file selection dialog - need more code to handle it correctly
image = loadImage(imageName);
size(image.width, image.height);
outputMatrix = createWriter(saveDir + "image.h");
// outputMatrix = createWriter(saveDir + imageName.substring(0, (imageName.length()-4)) + ".h");
background(0, 0, 0);
image(image, 0, 0);
outputMatrix.println("// Generated by Processing script");
outputMatrix.println("// Original file: " + imageName);
outputMatrix.println("// Size: " + image.width + "x" + image.height + "px");
outputMatrix.println("#include <avr/pgmspace.h>");
outputMatrix.println("static const uint8_t PROGMEM image[] = {");
//Convert all pixels from original color > 5/6/5 > 4/4/4 > matrix buffer format and save to file
//Can be done much more elegantly but I'm to rusty/lazy to do it properly at the moment
for (int y = 0; y < 16; y++) {
println("y:" + y);
for (int x = 0; x < 32; x++) {
print("x:" + x + " y:");
int limit;
int nPlanes = 4;
int c;
int r;
int g;
int b;
int c16;
int r16;
int g16;
int b16;
// Convert original color to 5/6/5 format
color tempColor = image.get(x, y);
int red = tempColor >> 16 & 0xFF;
int green = tempColor >> 8 & 0xFF;
int blue = tempColor & 0xFF;
float alpha = alpha(tempColor);
if (alpha == 255) {
c = Color565(red, green, blue);
}
else {
c = Color565(0, 0, 0);
}
tempColor = image.get(x, y+16);
red = tempColor >> 16 & 0xFF;
green = tempColor >> 8 & 0xFF;
blue = tempColor & 0xFF;
alpha = alpha(tempColor);
if (alpha == 255) {
c16 = Color565(red, green, blue);
}
else {
c16 = Color565(0, 0, 0);
}
// Matrix needs 4/4/4. Pluck out relevant bits from 5/6/5 while separating into R,G,B:
// Upper half
r = c >> 12; // RRRRrggggggbbbbb
g = (c >> 7) & 0xF; // rrrrrGGGGggbbbbb
b = (c >> 1) & 0xF; // rrrrrggggggBBBBb
//quick and dirty graytone gradient hack to figure out whats wrong with my adaption of the bit manipulation routines
//r = g = b = y;
println(y + " Color:" + c + ",B" + binary(r, 4) + binary(g, 4) + binary(b, 4) + ",0x" + hex(r, 1) + ",0x" + hex(g, 1) + ",0x" + hex(b, 1) + ",");
// Matrix needs 4/4/4. Pluck out relevant bits from 5/6/5 while separating into R,G,B:
// Lower half
r16 = c16 >> 12; // RRRRrggggggbbbbb
g16 = (c16 >> 7) & 0xF; // rrrrrGGGGggbbbbb
b16 = (c16 >> 1) & 0xF; // rrrrrggggggBBBBb
println(" y:" + (y + 16) + " Color:" + c16 + ",B" + binary(r16, 4) + binary(g16, 4) + binary(b16, 4) + ",0x" + hex(r16, 1) + ",0x" + hex(g16, 1) + ",0x" + hex(b16, 1) + ",");
// Data for the upper half of the display is stored in the lower bits of each byte.
// Plane 0 is a tricky case -- its data is spread about, stored in least two bits not used by the other planes.
matrixbuff[2][x] &= ~unbinary("00000011"); // Plane 0 R,G mask out in one op
if (boolean(r & 1)) matrixbuff[2][x] |= unbinary("00000001"); // Plane 0 R: 64 bytes ahead, bit 0
if (boolean(g & 1)) matrixbuff[2][x] |= unbinary("00000010"); // Plane 0 G: 64 bytes ahead, bit 1
if (boolean(b & 1)) {
matrixbuff[1][x] |= unbinary("00000001"); // Plane 0 B: 32 bytes ahead, bit 0
}
else {
matrixbuff[1][x] &= ~unbinary("00000001"); // Plane 0 B unset; mask out
}
// The remaining three image planes are more normal-ish.
// Data is stored in the high 6 bits so it can be quickly
// copied to the DATAPORT register w/6 output lines.
// Loop counter stuff
limit = 1 << nPlanes;
for (int bit = 2; bit < limit; bit <<= 1) {
matrixbuff[0][x] &= ~unbinary("00011100"); // Mask out R,G,B in one op
if (boolean(r & bit)) matrixbuff[0][x] |= unbinary("00000100"); // Plane N R: bit 2
if (boolean(g & bit)) matrixbuff[0][x] |= unbinary("00001000"); // Plane N G: bit 3
if (boolean(b & bit)) matrixbuff[0][x] |= unbinary("00010000"); // Plane N B: bit 4
}
// Data for the lower half of the display is stored in the upper
// bits, except for the plane 0 stuff, using 2 least bits.
matrixbuff[0][x] &= ~unbinary("00000011"); // Plane 0 G,B mask out in one op
if (boolean(r16 & 1)) {
matrixbuff[1][x] |= unbinary("00000010"); // Plane 0 R: 32 bytes ahead, bit 1
}
else {
matrixbuff[1][x] &= ~unbinary("00000010"); // Plane 0 R unset; mask out
}
if (boolean(g16 & 1)) matrixbuff[0][x] |= unbinary("00000001"); // Plane 0 G: bit 0
if (boolean(b16 & 1)) matrixbuff[0][x] |= unbinary("00000010"); // Plane 0 B: bit 0
// Loop counter stuff
for (int bit = 2; bit < limit; bit <<= 1) {
matrixbuff[0][x] &= ~unbinary("11100000"); // Mask out R,G,B in one op
if (boolean(r16 & bit)) matrixbuff[0][x] |= unbinary("00100000"); // Plane N R: bit 5
if (boolean(g16 & bit)) matrixbuff[0][x] |= unbinary("01000000"); // Plane N G: bit 6
if (boolean(b16 & bit)) matrixbuff[0][x] |= unbinary("10000000"); // Plane N B: bit 7
}
println(" Buffer0:0x" + hex(matrixbuff[0][x], 2) + " Buffer1:0x" + hex(matrixbuff[1][x], 2) + " Buffer2:0x" + hex(matrixbuff[2][x], 2));
}
for (int x = 0; x < image.width; x++) {
outputMatrix.print("0x" + hex(matrixbuff[0][x], 2) + ",");
}
outputMatrix.println("");
for (int x = 0; x < image.width; x++) {
outputMatrix.print("0x" + hex(matrixbuff[1][x], 2) + ",");
}
outputMatrix.println("");
for (int x = 0; x < image.width; x++) {
outputMatrix.print("0x" + hex(matrixbuff[2][x], 2) + ",");
}
outputMatrix.println("");
}
outputMatrix.println("};");
outputMatrix.flush();
outputMatrix.close();
}
}
int Color565(int r, int g, int b) {
return ((r & 0xF8) << | ((g & 0xFC) << 3) | (b >> 3);
}
Disclaimer: My panel was not bought from Adafruit - I live in Europe and the customs handling fees here would have made an Adafruit bought panel several times more expensive than the one I ended up buying. As such I don't expect support, but since this script is meant for the community and can help all Adafruit RGB matrix panel owners I hope for some leeway