Trying to extract different types of data from a singe file.

J

JoeC

I am trying to create a windows program that reads binary graphics as
a resource. This has nothing to do with win32 but conversion of data
with memcpy.

graphic::graphic(UINT uiResID, HINSTANCE hinstance){
size = 32;
bitData.clear();
void * p = NULL; // point to the data
int end;
BYTE data;

static HGLOBAL hglob;


HRSRC hRes =
FindResource(hinstance,MAKEINTRESOURCE(uiResID),TEXT("BINARY"));

if(hRes){
hglob = LoadResource(hinstance,hRes);
p = LockResource(hglob);
memcpy((int*) &end, p, sizeof(int)); // puts the first but of
data to int.

for(int lp = 0; lp != end; lp++){
bitData.push_back(0);
}

for(int lp = 0; lp != end; lp++){
memcpy((BYTE*) &bitData[lp], p, sizeof(BYTE)); puts the rest
of the data in BYTE type.
}

}
set();
create();
}

My question is how do I extract each but of data from p first to the
int type with is the number of data bits then each bit of data to put
into my bitData vector. I can't increase the pointer p++ to get to
the next bit of data. This compiles and runs but does not extract the
data for me.
 
J

James Kanze

I am trying to create a windows program that reads binary
graphics as a resource. This has nothing to do with win32 but
conversion of data with memcpy.

memcpy doesn't convert; it just copies bits. If the original
data came from an external source, that's generally not what is
needed.
graphic::graphic(UINT uiResID, HINSTANCE hinstance){
size = 32;
bitData.clear();
void * p = NULL; // point to the data
int end;
BYTE data;
static HGLOBAL hglob;
HRSRC hRes =
FindResource(hinstance,MAKEINTRESOURCE(uiResID),TEXT("BINARY"));

if(hRes){
hglob = LoadResource(hinstance,hRes);
p = LockResource(hglob);
memcpy((int*) &end, p, sizeof(int)); // puts the first but of
data to int.

Note that you've got a reintepret_cast here. That's a sure sign
that something is wrong.

How are the integer values formatted in the file? Until you
know that, you can't do anything reasonable.
for(int lp = 0; lp != end; lp++){
bitData.push_back(0);
}
for(int lp = 0; lp != end; lp++){
memcpy((BYTE*) &bitData[lp], p, sizeof(BYTE)); puts the rest
of the data in BYTE type.

If BYTE is unsigned char, memcpy might just work. But did you
really mean to not increment p in the loop? If so, this is
just:

bitData.insert( bitData.end(), end, *p ) ;

would do the trick (without the previous loop. Otherwise,
you could replace the two loops with:

bitData.resize( end ) ;
memcpy( &bitData[ 0 ], p, end ) ;

(In both cases, of course, only if BYTE is unsigned char, and
bitData is std::vector< BYTE >.)

[...]
My question is how do I extract each but of data from p first
to the int type with is the number of data bits then each bit
of data to put into my bitData vector. I can't increase the
pointer p++ to get to the next bit of data.

What is the format of the input? Until we know that, we can't
really say anything. A lot of formats---almost all, I would
imagine---do pack bitmaps as 8 bits to an unsigned char. If
such is the case, and end gives the number of bits, you'll have
to scale it before using it with memcpy or your loops. On the
other hand, I wouldn't be surprised if some graphic formats have
"bitmaps" that aren't actually bitmaps: bitmaps were the most
basic graphic representation back in the days of black and
white, where a pixel was one bit, but I would imagine that a lot
of graphic formats today would use a string or an array of
pixels, rather than a true bitmap.
 
J

JoeC

I am trying to create a windows program that reads binary
graphics as a resource. This has nothing to do with win32 but
conversion of data with memcpy.

memcpy doesn't convert; it just copies bits. If the original
data came from an external source, that's generally not what is
needed.
graphic::graphic(UINT uiResID, HINSTANCE hinstance){
size = 32;
bitData.clear();
void * p = NULL; // point to the data
int end;
BYTE data;
static HGLOBAL hglob;
HRSRC hRes =
FindResource(hinstance,MAKEINTRESOURCE(uiResID),TEXT("BINARY"));
if(hRes){
hglob = LoadResource(hinstance,hRes);
p = LockResource(hglob);
memcpy((int*) &end, p, sizeof(int)); // puts the first but of
data to int.

Note that you've got a reintepret_cast here. That's a sure sign
that something is wrong.

How are the integer values formatted in the file? Until you
know that, you can't do anything reasonable.
for(int lp = 0; lp != end; lp++){
bitData.push_back(0);
}
for(int lp = 0; lp != end; lp++){
memcpy((BYTE*) &bitData[lp], p, sizeof(BYTE)); puts the rest
of the data in BYTE type.

If BYTE is unsigned char, memcpy might just work. But did you
really mean to not increment p in the loop? If so, this is
just:

bitData.insert( bitData.end(), end, *p ) ;

would do the trick (without the previous loop. Otherwise,
you could replace the two loops with:

bitData.resize( end ) ;
memcpy( &bitData[ 0 ], p, end ) ;

(In both cases, of course, only if BYTE is unsigned char, and
bitData is std::vector< BYTE >.)

[...]
My question is how do I extract each but of data from p first
to the int type with is the number of data bits then each bit
of data to put into my bitData vector. I can't increase the
pointer p++ to get to the next bit of data.

What is the format of the input? Until we know that, we can't
really say anything. A lot of formats---almost all, I would
imagine---do pack bitmaps as 8 bits to an unsigned char. If
such is the case, and end gives the number of bits, you'll have
to scale it before using it with memcpy or your loops. On the
other hand, I wouldn't be surprised if some graphic formats have
"bitmaps" that aren't actually bitmaps: bitmaps were the most
basic graphic representation back in the days of black and
white, where a pixel was one bit, but I would imagine that a lot
of graphic formats today would use a string or an array of
pixels, rather than a true bitmap.

--
James Kanze (GABI Software) email:[email protected]
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

I created the binary files in the object the standard way:

void graphic::save(std::eek:fstream& f){
f.write((char*)&number, sizeof(int));
for(int lp = 0; lp != (size * number); lp++){
f.write((char*)&bitData[lp], sizeof(BYTE));
}
}

void graphic::load(std::ifstream& f){
f.read((char*)&number, sizeof(int));
int end = size * number;

for(int lp = 0; lp != end; lp++){
bitData.push_back(0);
}

for(int lp = 0; lp != end; lp++){
f.read((char*)&bitData[lp], sizeof(BYTE));
}
set();
create();
}

I wrote a binary file.
I can also read the data fine from a file. I am just trying to load
in the binary files as a resource to make my program better so that I
don't have to include graphics they can already be in the complied
code. I hope this helps. I don't have good references for trying to
extract data like this.
 
J

James Kanze

On Aug 1, 4:41 am, James Kanze <[email protected]> wrote:
I created the binary files in the object the standard way:
void graphic::save(std::eek:fstream& f){
f.write((char*)&number, sizeof(int));
for(int lp = 0; lp != (size * number); lp++){
f.write((char*)&bitData[lp], sizeof(BYTE));
}
}

In other words, you have no idea of its format, and you don't
know how to read it.
void graphic::load(std::ifstream& f){
f.read((char*)&number, sizeof(int));
int end = size * number;
for(int lp = 0; lp != end; lp++){
bitData.push_back(0);
}
for(int lp = 0; lp != end; lp++){
f.read((char*)&bitData[lp], sizeof(BYTE));
}
set();
create();
}
I wrote a binary file.

But you don't know what you put into it. That doesn't advance
us very much. (Note that there's a reinterpret_cast here as
well. Bad sign.)
I can also read the data fine from a file.

You can read the bits. You don't know what they mean.
I am just trying to load in the binary files as a resource to
make my program better so that I don't have to include
graphics they can already be in the complied code.

So start by defining the format you want to use. Or use some
pre-established format. (I tend to use XDR by default.)
 
J

JoeC

I created the binary files in the object the standard way:
void graphic::save(std::eek:fstream& f){
f.write((char*)&number, sizeof(int));
for(int lp = 0; lp != (size * number); lp++){
f.write((char*)&bitData[lp], sizeof(BYTE));
}
}

In other words, you have no idea of its format, and you don't
know how to read it.
void graphic::load(std::ifstream& f){
f.read((char*)&number, sizeof(int));
int end = size * number;
for(int lp = 0; lp != end; lp++){
bitData.push_back(0);
}
for(int lp = 0; lp != end; lp++){
f.read((char*)&bitData[lp], sizeof(BYTE));
}
set();
create();
}
I wrote a binary file.

But you don't know what you put into it. That doesn't advance
us very much. (Note that there's a reinterpret_cast here as
well. Bad sign.)
I can also read the data fine from a file.

You can read the bits. You don't know what they mean.
I am just trying to load in the binary files as a resource to
make my program better so that I don't have to include
graphics they can already be in the complied code.

So start by defining the format you want to use. Or use some
pre-established format. (I tend to use XDR by default.)

--
James Kanze (GABI Software) email:[email protected]
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

I didn't realize it was so complicated loading user created files as
resources. That is beyond my skill level or knowledge of the
language. Thanks for the help, I though that loading files was a
standard operation. If not I will not make my graphics a resource.
 
J

James Kanze

On Aug 1, 1:14 pm, James Kanze <[email protected]> wrote:
I didn't realize it was so complicated loading user created
files as resources.

It's not that complicated, but... the language does not define
any binary formats (probably because there are so many to choose
from); when you do binary IO, you have to take charge of the
formatting yourself.

< That is beyond my skill level or knowledge of the
language. Thanks for the help, I though that loading files
was a standard operation.

Reading a file is. But whether text or binary, you really have
to define some sort of format. (Just outputting "file << i << j
<< k", where i, j and k are ints, won't give you something you
are read back in either.)

I might add that this is a basic software engineering problem,
and not particular to C++.

Anyway, your case is particularly simple, because you are
dealing mainly with "bytes", i.e. with raw memory, where each
byte is an element unto itself. Which is the exceptional case
where memcpy works, and istream::read and ostream::write do
everything. So you're only real problem is the initial length.
For that, I'd use an unsigned (rather than signed), although in
practice, unless you later have to port to very exotic machines,
it doesn't matter, and XDR format, which is simply four bytes,
high byte first, IOW:

to write:

void
writeInt(
std::eek:stream& dest,
unsigned value )
{
dest.put( (value >> 24) & 0xFF ) ;
dest.put( (value >> 16) & 0xFF ) ;
dest.put( (value >> 8) & 0xFF ) ;
dest.put( (value ) & 0xFF ) ;
}

to read:

void
readInt(
std::istream& source ;
unsigned& value )
{
unsigned result = 0 ;
result |= dest.get() << 24 ;
result |= dest.get() << 16 ;
result |= dest.get() << 8 ;
result |= dest.get() ;
if ( dest ) {
value = result ;
}
}
If not I will not make my graphics a resource.

Is that portable?

Do you need portability? I'm not too familiar with the Windows
platform. But from what I understand, a resource can be bundled
into the same file as your executable. Which is a definite
advantage when it comes to deployment. (Under Unix, I have my
own programs which serve more or less the same purpose: they
convert the "resource" to C++ data declarations, which I then
compile and link into the program. It's not the same thing, but
it serves the same purpose: to make the entire application a
single file, so you don't end up with a mixture of versions or
something partially installed.)
 
J

JoeC

It's not that complicated, but... the language does not define
any binary formats (probably because there are so many to choose
from); when you do binary IO, you have to take charge of the
formatting yourself.

< That is beyond my skill level or knowledge of the


Reading a file is. But whether text or binary, you really have
to define some sort of format. (Just outputting "file << i << j
<< k", where i, j and k are ints, won't give you something you
are read back in either.)

I might add that this is a basic software engineering problem,
and not particular to C++.

Anyway, your case is particularly simple, because you are
dealing mainly with "bytes", i.e. with raw memory, where each
byte is an element unto itself. Which is the exceptional case
where memcpy works, and istream::read and ostream::write do
everything. So you're only real problem is the initial length.
For that, I'd use an unsigned (rather than signed), although in
practice, unless you later have to port to very exotic machines,
it doesn't matter, and XDR format, which is simply four bytes,
high byte first, IOW:

to write:

void
writeInt(
std::eek:stream& dest,
unsigned value )
{
dest.put( (value >> 24) & 0xFF ) ;
dest.put( (value >> 16) & 0xFF ) ;
dest.put( (value >> 8) & 0xFF ) ;
dest.put( (value ) & 0xFF ) ;
}

to read:

void
readInt(
std::istream& source ;
unsigned& value )
{
unsigned result = 0 ;
result |= dest.get() << 24 ;
result |= dest.get() << 16 ;
result |= dest.get() << 8 ;
result |= dest.get() ;
if ( dest ) {
value = result ;
}
}


Is that portable?

Do you need portability? I'm not too familiar with the Windows
platform. But from what I understand, a resource can be bundled
into the same file as your executable. Which is a definite
advantage when it comes to deployment. (Under Unix, I have my
own programs which serve more or less the same purpose: they
convert the "resource" to C++ data declarations, which I then
compile and link into the program. It's not the same thing, but
it serves the same purpose: to make the entire application a
single file, so you don't end up with a mixture of versions or
something partially installed.)

--
James Kanze (GABI Software) email:[email protected]
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Thanks for the explanation, I will save all of this and try to work
with my program. I can load in the files as binary files but trying
to do it as resources is a but different. I was advised to use strcpy.
 
J

James Kanze

On Aug 2, 2:53 am, James Kanze <[email protected]> wrote:

[...]
Thanks for the explanation, I will save all of this and try to
work with my program. I can load in the files as binary files
but trying to do it as resources is a but different. I was
advised to use strcpy.

If you're working with binary data (i.e. your array really is a
bitmap), strcpy will NOT work. At all. Don't listen to whoever
told you that.
 

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

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top