I'm working on a project where an arduino will sort through grayscale values of each pixel in a previously stored image (presumably on an SD card, saved from photoshop)
All images will be a fixed size. The basic process will be:
start in one corner
control lights and servos based on 0-255 value of pixel
move to next pixel
repeat through the whole image.
I'm getting a little lost figuring out what image file format will work best (.raw?) and how to read the file. I've found some examples where people are reading values based on camera stream outputs but trying to sort out what parts have to do with the image and what parts have to do with the camera interface is leaving me pretty confused.
given that my programming knowledge is somewhat limited (I had one C++ course in college), what's the simplest way to approach this?
I've loosely looked through the SD card stuff...I don't get it yet but I think I can get a handle on it once I decide which SD shield to buy (every one I look at seems to come with cautions and warnings about problems) and get it to play with.
I'm mainly concerned with the second part - parsing graphics files. How to read a pixel value and then use it to do stuff. I'm just not familiar with conventions for that kind of thing.
maybe I just need to start with the SD stuff and work up from there.
How to read a pixel value and then use it to do stuff
Depending on the file format, the file will contain information (metadata) about the organisation of the data (sample size, endianess, samples per row, number of rows).
Reading a pixel value is easy.
Finding the pixel in the first place is the tricky bit.
You may want to start with bitmaps. Using MS paint, make a very small .bmp of something greyscale and then study the .bmp file with a hex editor to see what is there to work with.
What Zoomkat said - try to make your image some odd size like 37 pixels by 23.
Make the top row all white, then the next line all black, then all grey.
Linux sources are also good for finding out image file formats, as is Google.
Check - BMP file format - Wikipedia - for a description of the BMP. By reading byte for byte you should be able to recognize the header fields and then of course the pixels.
so I had to shelve this for a bit while waiting on my microSD reader from sparkfun. Got it and have been through the initial tests, seems to be working fine.
I've decided on just using photoshop .raw files. no headers, doesn't even look like there are any EOL characters. Should be pretty easy to just go row by row in image width increments.
I've been looking at the page here http://www.sparkfun.com/tutorials/172 and making sure the files are reading correctly and the data is doing what I think it is. I've run into something that puzzles me, I'm hoping someone can point out whatever I've over looked. I'm probably just not remembering the details of working with arrays.
The following code (based on the sparkfun "how do I read a file" first example) works and outputs expected results:
//Add the SdFat Libraries
#include <SdFat.h>
#include <SdFatUtil.h>
#include <ctype.h>
//Create the variables to be used by SdFat Library
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;
char name[] = "G.raw"; //Create an array that contains the name of our file.
int contents[299]; //This will be a data buffer for writing contents to the file.
int in_int=0; // change back to char and add conversion
int index =0;
void setup(void)
{
Serial.begin(9600); //Start a serial connection.
pinMode(10, OUTPUT); //Pin 10 must be set as an output for the SD communication to work.
card.init(); //Initialize the SD card and configure the I/O pins.
volume.init(card); //Initialize a volume on the SD card.
root.openRoot(volume); //Open the root directory in the volume.
}
void loop(void){
file.open(root, name, O_READ); //Open the file in read mode.
in_int=file.read(); //Get the first byte in the file.
//Keep reading from the file to get the first row
while(in_int >=0 && index <= 299){ //If the value is less than 0 we've reached the end of the file.
Serial.println(in_int); //Print current
in_int=file.read(); //Get next
index++;
}
file.close(); //Close the file
delay(100000); //Wait before repeating the process.
}
but when I try to switch to reading 300 values into an array, it doesn't work. I think the array isn't being filled properly, but it looks to me exactly like they do it in the second sparkfun "how do I read.." example:
//Add the SdFat Libraries
#include <SdFat.h>
#include <SdFatUtil.h>
#include <ctype.h>
//Create the variables to be used by SdFat Library
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;
char name[] = "G.raw"; //Create an array that contains the name of our file.
int contents[299]; //This will be a data buffer for storing one row of 300 pixels
int contentsSize = 300; //This variable sets the number of bytes to read from the file.
int index = 0;
void setup(void)
{
Serial.begin(9600); //Start a serial connection.
pinMode(10, OUTPUT); //Pin 10 must be set as an output for the SD communication to work.
card.init(); //Initialize the SD card and configure the I/O pins.
volume.init(card); //Initialize a volume on the SD card.
root.openRoot(volume); //Open the root directory in the volume.
}
void loop(void){
file.open(root, name, O_READ); //Open the file in read mode.
index=file.read(contents, contentsSize); //contents is the data buffer for storing data. size is a variable set to the amount of data to read.
file.close(); //Close the file
for (int i = 0; i < contentsSize; i++) {
Serial.println(contents[i]);
}
delay(100000); //Wait before repeating the process.
}
to be honest I'm not quite sure. Like I said I think the array isn't being filled properly, so maybe the second output is just whatever junk is in that memory?
Alright. even with the fix for my own vision based issues, it's still doing something odd.
output starts at -5399 and continues as previously posted, ending with a bunch of 0s.
if I change to only get two values:
int contents[2];
int contentsSize = 2;
I get:
-5399
0
int contents[10];
int contentsSize = 9;
gives:
-5399
-5399
-5141
-5398
233
0
0
0
0
also - noticed that when I first open the serial monitor it's sometimes outputting something else. mostly 0s it looks like. hitting reset once or twice brings it back and the output is consistent with the two value and 9 value examples above.
Interestingly, it probably isn't a bug in SdFat, but a bug in your code. The read() function that takes an array to store data in expects that the array will be byte sized. Your array is not.
You might change your array to be a byte or char array, or try printing the MSB (highByte()) and LSB (lowByte()) of the integer array you are using.
that makes sense, thanks. using a byte array and just calling ((int) (contents [xx])) gives the correct results.
last obstacle - clearing the array and reading in the next line. Is there an easy way to tell file.read to start at the 301st byte? my google-fu is failing me.
thanks again.
edit - nevermind. as long as I don't close the file it stays on the same byte it left off at. easy peasy.