simplist way to read grayscale image data from a file?

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 - http://en.wikipedia.org/wiki/BMP_file_format - 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.
}

it doesn't work

It goes on strike? It decides to translate Chaucer into Romanian?

What does it do?

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?

Output 1 (correct):

233
234
233
234
235
235
234
234
233
234
234
234
234
234
232
234
233
233
234
234
234
234
235
233
233
232
232
232
233
233
233
232
232
233
233
233
232
232
232
231
231
231
232
232
232
232
230
231
230
230
229
230
229
229
230
228
229
229
227
227
227
227
227
227
226
226
226
226
225
225
224
225
224
223
223
224
223
222
222
223
222
221
220
220
220
220
219
220
219
219
219
219
219
218
218
218
217
217
216
215
216
215
215
214
215
215
214
214
214
211
211
211
211
211
210
210
211
209
209
209
208
208
208
206
205
205
203
204
204
204
203
203
203
203
203
202
203
202
202
202
202
201
201
201
201
201
200
200
201
201
200
200
200
200
200
199
199
199
198
199
199
199
198
197
197
197
197
198
197
196
196
196
196
197
197
196
196
196
196
196
195
195
196
195
195
195
195
195
195
194
194
194
194
194
193
194
193
193
192
192
192
192
192
191
191
191
191
190
191
191
191
190
190
190
190
190
190
190
189
189
189
189
189
189
188
188
189
189
188
188
187
187
187
187
187
187
187
187
187
186
186
186
186
186
186
185
185
186
185
185
185
185
185
185
184
184
184
184
184
183
183
183
183
183
183
183
183
183
183
183
183
182
182
182
182
183
183
183
182
181
183
182
182
182
182
182
181
180
181
182
181
181
181
181
181
179
179
179
179
179

Output 2 (incorrect)

0
-5399
-5399
-5141
-5398
-5399
-5398
-5398
-5400
-5655
-5398
-5398
-5653
-5911
-5912
-5655
-5911
-5656
-5655
-5912
-6168
-6169
-5912
-5912
-6170
-6426
-6427
-6683
-6938
-6683
-7197
-7197
-7197
-7454
-7454
-7711
-7712
-8224
-7969
-8481
-8226
-8738
-8996
-8996
-8997
-9253
-9253
-9509
-9510
-9767
-10280
-10280
-10537
-10281
-10538
-11306
-11309
-11309
-11566
-11821
-11823
-12080
-12592
-12851
-13109
-13108
-13365
-13365
-13621
-13621
-13622
-13878
-13879
-13879
-14136
-13879
-14136
-14136
-14392
-14393
-14394
-14393
-14906
-14907
-14651
-15163
-15164
-14908
-15163
-15164
-15164
-15421
-15420
-15421
-15421
-15677
-15678
-15678
-15679
-15935
-16192
-16192
-16448
-16449
-16705
-16449
-16705
-16706
-16706
-16706
-16963
-16963
-16963
-17220
-16963
-17220
-17477
-17477
-17477
-17477
-17733
-17734
-17734
-17990
-17735
-17991
-17991
-17991
-18248
-18248
-18504
-18505
-18505
-18505
-18505
-18505
-18761
-18762
-18506
-18505
-19018
-18761
-18762
-18762
-19275
-18763
-19019
-19019
-19531
-19533
-19533
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
300
int contents[299];           //This will be a data buffer for storing one row of 300 pixels

Wrong. It will be an array holding 299 elements.

Looks like 300 to me.

You need to see an optometrist.

int x[299];

Declares an array of 299 "int"s, with indices in the range 0..298.

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.

hmm. SDFat issue?

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.