I loaded another test image and quickly noticed that my problem with the colors where worse than I initially tought.
The culprit seems to be my adaption of the bit manipulation routines found in Adafruit's drawPixel function in the RGBMatrixPanel.cpp file. I believe it can be related to the way the original code uses pointers/references and the way I have converted the code to Processing and/or the way I handle binary data.
Here is the current Processing code:
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) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}