Image Reading Help

Reading BMPs in C++
And Hints on Reading them using the Arduino
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Reading/Writing In C++
• Use fstream – File Stream
• Input File stream – ifstream
• Output File stream – ofstream
• Functions:
•
•
•
•
•
•
open(filename) – open particular file
is_open() – check if the file is open
close() – close the file
eof() – reached the end of file
write(char array, num_char) – ofstream , write a chunk of data to file
read(char array/buffer, num_char) – ifstream, read a chunk of data from file
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Writing
ofstream myfile("example.bin",ios::binary);
unsigned char abyte = 'T';
unsigned char byteArray[] = "A byte array";
if (myfile.is_open())
{
myfile << "This is a line.\n";
myfile << abyte;
myfile << byteArray;
myfile.write((char*)byteArray, sizeof(byteArray));
myfile.close();
}
else cout << "Unable to open file";
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Reading
unsigned char byte;
if (byte == '\n')
unsigned char byteArray[17] = {};
{myfile.read((char*)byteArray, 17);
ifstream
myfile("example.bin",ios::binary);
for (int i = 0; i < 17; i++)
if (myfile.is_open())
}}
{ myfile >> noskipws;//do not skip
whitespace
myfile.close();}
while (!myfile.eof())
{myfile >> byte;
cout << byteArray[i];
else cout << "Unable to open file";
cout << byte;
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Reading/Writing a BMP Image
• Open it in binary mode:
ifstream
in("grayimage.bmp",
ios::binary);
• Check if its open in.is_open()
• Read one character:
• somechar= in.get()
• Close: in.close()
• Open it in binary mode:
ofstream
out("myimage1.bmp",
ios::binary);
• Check if its open out.is_open()
• Write one character:
• out.put(somechar);
• Close: out.close()
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Source: Dr. Javaid Iqbal’s slides
Reading/Writing a BMP Image
#include <iostream>
#include <fstream>
if (in.is_open() &&
out.is_open())
int main(){
{
//Open an input and output stream while (!in.eof())
in binary mode
{ out.put(in.get());} }
ifstream in("grayimage.bmp",
ios::binary);
//Close both files
ofstream out("myimage1.jpg",
ios::binary);
out.close();
in.close();
return 0; }
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Source: Dr. Javaid Iqbal’s slides
Reading the Header
• Header Size = 54 bytes (generally)
• Create a structure/class to store the information
• Read byte by byte and convert into numbers
BYTEs
FUNCTION
CALCULATION
REMARKS
Byte0
Byte1
Indicates validity of a
BMP file
X=Byte0+Byte1*256
If X=19778(decimal) then it a valid BMP file
(byte0=66;byte1=77)
0x42 0x4D (Hex code for B and M)
Byte2
Byte3
Byte4
Byte5
Indicate file size
SIZE=Byte2+Byte3*256
+Byte4*256*256+Byte5*256*256*256
SIZE indicates file size in bytes
Byte6
Byte7
Byte8
Byte9
Reserved
Byte10
Byte11
Byte12
Byte13
Image offset or start of
Data
SOD=Byte10+Byte11*
SOD indicates the byte from where the actual
256+Byte11*256*256+Byte13*256*256*2
data of image started
56
Fatma Faruq,Department of Mechatronics, College of Electrical
Source: Dr.
and Mechanical Engineering , NUST
Javaid Iqbal’s slides
Header File - BMP
BYTEs
FUNCTION
CALCULATION
REMARKS
Byte14
Byte15
Byte16
Byte17
Header Size from this
point
H=Byte14+Byte15*256
+Byte16*256*256+Byte17*256*256*256
H indicates the Total size of the header in Bytes in the
BMP file from this point. Usually it is 40.
Byte18
Byte19
Byte20
Byte21
Image Width
WIDTH=Byte18+Byte19*256+Byte20*256*256+
Byte21*256*256*256
WIDTH indicates width of image in pixels
Byte22
Byte23
Byte24
Byte25
Image Height
HEIGHT=Byte22+Byte23*256+Byte24*256*256
+Byte25*256*256*256
HEIGHT indicates Width of image in pixels
Byte26
Byte27
Color plane
CP=Byte26+Byte27*256
No of color planes being used
Byte28
Byte29
Bits per Pixel
BPP=Byte28 + Byte29*256
if BPP=1then image is monochrome,
if BPP=4 then image is 16 color,
if BPP=8 then image is 256 color,
if BPP=16 then image is 64K color,
if BPP=24 then image is 16 million color,
Fatma Faruq,Department of Mechatronics, College of Electrical
Source: Dr.
and Mechanical Engineering , NUST
Javaid Iqbal’s slides
Header File - BMP
Byte30
Byte31
Byte32
Byte33
Compression method
CM=Byte30+Byte31*
256+Byte32*256*256+Byte33*256*256*
256
Byte34
Byte35
Byte36
Byte37
Size of Image
S=Byte34+Byte35*256
+Byte36*256*256+Byte37*256*256*256
Specifies size of image (excluding header)
in bytes or it can be calculated (width x
height) of image.
Byte38
Byte39
Byte40
Byte41
Horizontal Pixels per meter
HPM=Byte38+Byte39*256+Byte40*256
*256+Byte41*256*256*256
Specifies the horizontal resolution, in
Pixels per meter.
Byte42
Byte43
Byte44
Byte45
Vertical Pixels per meter
VPM=Byte42+Byte43*256+Byte44*256
*256+Byte45*256*256*256
Specifies the vertical resolution, in Pixels
per meter.
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Source: Dr. Javaid Iqbal’s slides
Header File - BMP
Byte46
Byte47
Byte48
Byte49
No of colors used by color pallet
CU=Byte46+Byte47*256+Byte48*256*256+Byt
e49*256*256*256
If this value is zero, the bitmap uses the maximum
number of colors corresponding to the value of the
byte28,29
Byte50
Byte51
Byte52
Byte53
No of important colors
ICU=Byte50+Byte51*
256+Byte52*256*256+Byte53*256*256*256
If ICU=0 then all color are important, generally
ignored.
Byte54
Byte55
Byte56
Byte57
*Palette
Byte54 = Blue
Byte55 = Green
Byte56 =Red
Byte 57 = Reserve
If SOD (start of data) is not equal to 54then it is
the start of Palette till 1078th byte (Byte 1078)
If SOD is 54 then it is the start of data
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Source: Dr. Javaid Iqbal’s slides
Reading the header
• Open the file in binary mode for reading
• Two options:
• Read byte by byte – create an unsigned char , read upto 54
• Read an entire chunk – create an unsigned char array of size 54, read entire
chunk
• Convert to information
• You can also create a structure and read the entire structure using
read – you may end up with garbage due to difference in compilers,
padding etc.
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Reading the header in a char array
int headerSizeF = 54;
unsigned char* data = new unsigned char[headerSizeF];
ifstream file1;
file1.open(fileName.c_str());
cout << "Reading header info" << endl;
cout << "Hex Header" << endl;
for (int i = 0; i<headerSizeF; i++)
{
file1 >> data[i];
// write the data at the screen.
cout << hex << (int)data[i] << " ";
}
file1.close();
cout << endl;
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Converting parts of that char array
//header information
int var = 0;
imHeaderInfo *imheader = new imHeaderInfo;
imheader->isValid = convertToDword(data[var + 1], data[var]);
var += 2;
imheader->fileSizeBytes = convertToDDword(data[var + 3], data[var + 2], data[var + 1], data[var]);
var += 4;
imheader->reserved = convertToDDword(data[var + 3], data[var + 2], data[var + 1], data[var]);
var += 4;
imheader->offset = convertToDDword(data[var + 3], data[var + 2], data[var + 1], data[var]);
var += 4;
imheader->headerSize = convertToDDword(data[var + 3], data[var + 2], data[var + 1], data[var]);
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Converting to Dword or Double Dword
int convertToDword(int high, int low)
{return (high * 256 + low);}
int convertToDDword(int highhigh, int high, int low,
int lowlow)
{
return (highhigh * 256 * 256 * 256 + high * 256 *
256 + low * 256 + lowlow);}
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Reading a File From an SD card
Please note that the pin numbers may be different for your hardware.
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Source:http://arduino.cc/en/Tutorial/ReadWrite
Arduino SD Card Library
• SD Card Library has two classes
• SD Card Class
• used to acces card and manipulate files and directories
• File Class
• used to read, write files
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Programming using the SD Card Library
• Include
• #include <SD.h>
• Checking for an SD Card
• SD.begin(CSPIN)
• returns true or false
• Opening a file
• SD.open(filename)
• returns a File object
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Reading a File
• Declare File object
• File myfile
• Get object using SD.open
• Check if the file has something to read
• myfile.available()
• Read file byte by byte
• myfile.read()
• returns byte read
• Close File object
• myfile.close()
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Putting it all together
#include <SD.h>
File myFile;
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
Serial.print("Initializing SD card...");
// On the Ethernet Shield, CS is pin 4. It's set as an output by default.
// Note that even if it's not used as the CS pin, the hardware SS pin
// (10 on most Arduino boards, 53 on the Mega) must be left as an output
// or the SD library functions will not work.
pinMode(10, OUTPUT);
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Source:http://arduino.cc/en/Tutorial/ReadWrite
Putting it all together
if (!SD.begin(4)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
myFile = SD.open("test.txt", FILE_WRITE);
// if the file opened okay, write to it:
if (myFile) {
Serial.print("Writing to test.txt...");
myFile.println("testing 1, 2, 3.");
// close the file:
myFile.close();
Serial.println("done.");
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Source:http://arduino.cc/en/Tutorial/ReadWrite
Putting it all together
// re-open the file for reading:
myFile = SD.open("test.txt");
if (myFile) {
Serial.println("test.txt:");
}
// read from the file until there's nothing else in it:
while (myFile.available()) {
Serial.write(myFile.read());
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
void loop()
{
// nothing happens after setup
}
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Source:http://arduino.cc/en/Tutorial/ReadWrite
Functions in the File Class
•
•
•
•
•
•
•
•
•
•
•
•
•
•
available()
close()
flush()
peek()
position()
print()
println()
seek()
size()
read()
write()
isDirectory()
openNextFile()
rewindDirectory()
Note: A directory is also a File class object
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Functions in the SD Class
• begin()
• exists()
• mkdir()
• open()
• remove()
• rmdir()
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Reading an Image - Hints
• What is an image?
• An image is a series of bytes
• It has a header that you can use to get information: height, width, start of the
pixel data
• What is a monochrome image?
• Pixels have values 0 or 1
• Important:
• Consider alignment and padding
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Hints - Reading a bitmap
•
•
•
•
char *filename = "pic_mc.bmp";
Open the file: File photoFile = SD.open(filename);
Check to see if its open: if (photoFile) {
Go to an address and read a byte:
• photoFile.seek(0xa);
• offset = photoFile.read();
//go to location for offset
• Read more than a byte and convert to suitable number:
• photoFile.seek(0x12);
• width = 0;
• for (i = 0; i<4; i++)
• {width += (photoFile.read() << (8*i)); } // or width+= photoFile.read()*(pow(256,i));
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Hints - Reading a bitmap
• After reading the width and height, skip to the pixel array and read
the entire array in a char array
• Display this array in binary.
• Remember image data is stored upside down.
• These are just hints, there could be many ways to achieve the same
purpose (better or worse)
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
About the NERC Map
• Open it up in paint – size 56 by 96
• Match the pixels to the arena
•
•
•
•
Identify the walls of the arena
Identify the obstacles
Identify the free path
Map the image to the actual arena
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST
Debugging and other tips
•
•
•
•
•
•
•
Use the serial monitor extensively
Maybe code in c++ first to understand
Think about the space you need to allocate
Try to use as little space as possible
Remember padding!!
You can use the new and delete operators
Make sure you read the bmp correctly
•
•
•
•
Open up a hex editor
Load your bmp file in the hex editor
Examine the contents to get a better understanding
Match the output of your code
Fatma Faruq,Department of Mechatronics, College of Electrical
and Mechanical Engineering , NUST