Picking out integers from a binary character string

R

rusttree

I'm working on a program that manipulates bmp files. I know the offset
location of each piece of relevent data within the bmp file. For
example, I know the 18th through 21st byte is an integer value
representing the width of the bmp image. So far, I have been able to
use fstream's seek, write, and read to pull out chucks of bytes and
convert them to usable integers straight out of the binary file. It
works well, but over the course of my program there are thousands of
writes and reads, which I imagine is not the most efficient way of
processing the data.

Instead, I want to read in the entire bmp binary data into one
character string, say "buffer". I want to then pick out 4-byte chunks
of buffer and convert them to usable integers, do all of the necessary
processing, then write the whole buffer back to a new bmp file. This
would require only one write and one read. My experience with binary
character manipulation is, however, very limited and I have not yet
been able to pick out the individual bytes from buffer that I want.
Here's an example of how I'm trying it:

<******>
char buffer[25000000]; //buffer can handle a bmp up to 25MB
int fileSize;
int width;

ifstream bmp ("image.bmp", ios::binary); //open bmp for binary input
bmp.seekg(0, ios::end); //put cursor at end of file
fileSize = bmp.tellg(); //offset of last byte = size of file
bmp.seekg (0, ios::beg); //put cursor at beginning of file
bmp.read (buffer, fileSize); //read entire bmp into char string buffer

width = (int)buffer[18];
cout << width << endl;
<******>

Instead of setting the 18th, 19th, 20th, and 21st byte into "width", it
just sets the 18th byte by itself. I was hoping c++ would be smart
enough to realize that since "int width" was 4 bytes by definition, it
would know to fill in the other 3 appropriately. So my question is how
would I get all 4 bytes into "width" as an integer value.
 
L

Larry I Smith

I'm working on a program that manipulates bmp files. I know the offset
location of each piece of relevent data within the bmp file. For
example, I know the 18th through 21st byte is an integer value
representing the width of the bmp image. So far, I have been able to
use fstream's seek, write, and read to pull out chucks of bytes and
convert them to usable integers straight out of the binary file. It
works well, but over the course of my program there are thousands of
writes and reads, which I imagine is not the most efficient way of
processing the data.

Instead, I want to read in the entire bmp binary data into one
character string, say "buffer". I want to then pick out 4-byte chunks
of buffer and convert them to usable integers, do all of the necessary
processing, then write the whole buffer back to a new bmp file. This
would require only one write and one read. My experience with binary
character manipulation is, however, very limited and I have not yet
been able to pick out the individual bytes from buffer that I want.
Here's an example of how I'm trying it:

<******>
char buffer[25000000]; //buffer can handle a bmp up to 25MB
int fileSize;
int width;

ifstream bmp ("image.bmp", ios::binary); //open bmp for binary input
bmp.seekg(0, ios::end); //put cursor at end of file
fileSize = bmp.tellg(); //offset of last byte = size of file
bmp.seekg (0, ios::beg); //put cursor at beginning of file
bmp.read (buffer, fileSize); //read entire bmp into char string buffer

width = (int)buffer[18];
cout << width << endl;
<******>

Instead of setting the 18th, 19th, 20th, and 21st byte into "width", it
just sets the 18th byte by itself. I was hoping c++ would be smart
enough to realize that since "int width" was 4 bytes by definition, it
would know to fill in the other 3 appropriately. So my question is how
would I get all 4 bytes into "width" as an integer value.

Hmm, well an int MAY be 4 bytes, and it may not. It all depends
on the machine's architecture (16/32/64 bit). The 'int' at
'buffer[18]' may, or may not, be in the correct format for your
hardware (big-endian, little-endian). You may, or may not, be
able to read/write an 'int' at a particular memory address - it
all depends on whether or not your hardware requires a particular
address alignment for 'int'. Now, having considered all of this,
you could do:

int width;
width = *((int *)(buffer + 18));

- 'buffer' is a char pointer
- So, 'buffer + 18' is a char pointer to the
19th char (remember, the subscripts start at zero).
- You want an 'int', so cast 'buffer + 18' to an
int pointer.
- Assign what-the-pointer-points-to (i.e. *thePointer)
to 'width'.

Using C++ static-cast would be better than using the
C-style '(int *)' cast.

Regards,
Larry
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,021
Latest member
AkilahJaim

Latest Threads

Top