The source code for Running Marisa can be found here.

Included with the Arduino GLCD library is a Processing program by Michael Margolis that converts an image into a header file that you can include in your Arduino sketch to display bitmaps using GLCD.DrawBitmap(). It’s pretty convenient, but what if I wanted to include lots of bitmaps, to be used as frames of an animation? I’d have to generate the header files one by one and include all of them, then define some arrays to point to the different frames.

I decided to modify the program to accept a folder as an input, and the output would be a single file containing the headers for all of the files in the array. In addition, at the very end of the file, a pointer array is declared, with each entry in the array pointing to the address of each image. The length of the array is also stored as a variable.

Bitmap header file

The lines appended to the end of the file.

You can download the Processing file and java applet here.

So for example, if I had a folder named “mari_run” and each image in that folder was a different frame of an animation, I’d run the program and choose that folder. A header file named “mari_run.h” would be placed in the folder, and I’d simply include that file in my Arduino sketch. In the sketch, I can use GLCD.DrawBitmap(mari_run[5],0,0); to draw the 5th frame of the animation. The length of the array would be defined by an integer mari_run_length.

[sourcecode]/*
* glcdBitmapFolder.
*
* Creates a bitmap definition file that can be included in an Arduino sketch
* to display bitmap images on a graphics LCD using the Arduino GLCD library.
*
* Created 6 Nov 2008 Copyright Michael Margolis 2008
*
* (Modified 1 Dec 2010 by Walfas, folder input enabled)
*/

String sourceFolderPath;
String sourceFolderName;
String[] imageNames;

PrintWriter output;
String outFileName;

String allFiles = "static uint8_t *";
int numFiles = 0;

PImage img;
int[] imgPixels;

void setup() {
sourceFolderPath = selectFolder();

// Determine the name of the selected folder
String[] f = split(sourceFolderPath, "\\");
if (f.length > 0) {
sourceFolderName = f[f.length-1];
println("Folder selected: " + sourceFolderName);
}

// Filter out the bmp files in the folder
imageNames = getImgList(sourceFolderPath);
println(imageNames);

// The output file will be based on the name of the folder
outFileName = sourceFolderPath + "\\\\" + sourceFolderName + ".h";
output = createWriter(outFileName);
allFiles += sourceFolderName + "[] = {";

// Print information and includes at the top of the file
printHeader();

// Load the images
for (int i=0; i<imageNames.length; i++) {
img = loadImage(sourceFolderPath+"\\\\"+imageNames[i]);
if(img != null){
imgPixels = new int[img.width*img.height];
for(int j=0; j<img.width*img.height; j++) {
imgPixels[j] = img.pixels[j];
}

appendFile(imageNames[i]);
println("Appended "+imageNames[i]+" to header file");
}
}

size(img.width, img.height);
// Display the image
loadPixels();
for (int j=0; j<width*height; j++)
pixels[j] = imgPixels[j];
updatePixels();

allFiles += "};";

output.println("#ifndef " + sourceFolderName + "_H");
output.println("#define " + sourceFolderName + "_H");
output.println(allFiles);
output.println("#endif\n");

output.println("#ifndef " + sourceFolderName + "_length_H");
output.println("#define " + sourceFolderName + "_length_H");
output.print("static int " + sourceFolderName + "_length = ");
output.println(numFiles + ";");
output.println("#endif");

output.flush(); // Write the remaining data
output.close(); // Finish the file
}

void draw()
{

}

void printHeader() {
output.println("// " + sourceFolderName + ".h bitmap file for GLCD library");
output.print("// Generated from: ");
for (int i=0; i<imageNames.length; i++) {
output.print(imageNames[i]+" ");
}
output.println();
String[] monthName = {"","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
output.println("// Date: " + day() + " " + monthName[month()] + " " + year());
output.println();

output.println("#include <inttypes.h>");
output.println("#include <avr/pgmspace.h>");
output.println();
}

String[] getImgList(String folderPath) {
String[] fileNames;
String[] fileParts;
String[] bmpNames = new String[0];

fileNames = listFiles(folderPath);

for (int i=0; i<fileNames.length; i++) {
fileParts = split(fileNames[i], ".");

if (fileParts.length > 0) {
if (fileParts[fileParts.length-1].equals("bmp")) {
bmpNames = append(bmpNames, fileNames[i]);
}
}
}
return bmpNames;
}

String[] listFiles(String folder) {
File file = new File(folder);
String fileNames[] = file.list();
return fileNames;
}

void appendFile(String inFileName){
String[] f = split(inFileName, ‘.’);
String baseName = inFileName.substring(0,inFileName.lastIndexOf(‘.’));

baseName = baseName.replace(‘.’,’_’);

output.println("#ifndef " + baseName + "_H");
output.println("#define " + baseName + "_H");

output.println();
output.print("static uint8_t ");
output.print(baseName);
output.println("[] PROGMEM = {");

output.print(" ");
output.print(img.width); // note width and height are bytes so 256 will be 0
output.println(", // width");
output.print(" ");
output.print(img.height);
output.println(", // height");
for(int page=0; page < (img.height + 7)/8; page++) {
output.println("\n /* page " + page + " (lines " + page*8 + "-" + (page*8+7) + ") */");
output.print(" ");
for(int x=0; x < img.width; x++){
output.print( "0x" + Integer.toHexString(getValue(x,page))) ;
if( (x == (img.width-1)) &amp;&amp; (page == (((img.height +7)/8)-1)) )
output.println(); // this is the last element so print a newline
else {
output.print(","); // comma on all but last entry
if( x % 16 == 15)
output.print("\n ");
}
}
}
output.print("\n};\n");
output.println("#endif\n");

numFiles ++;
allFiles += baseName+", ";
}
int getValue( int x, int page){
int val = 0;
for( byte b=0; b < 8; b++){
int y = page * 8 + b;
int pos = y * img.width + x;
if( imgPixels[pos] != 0xffffffff ){
val |= (1 << b); // here if color is not black
}
}
return val;
}
[/sourcecode]

Tagged with:
 

Comments are closed.