Jump to content
  • Advertisement
Sign in to follow this  
Cypher777

Binary string streams...

This topic is 5413 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm currently writing a resource TGA loader. In order to do this, I should have to use the standard Lock/Load/Find resource commands, and then extract the data from the buffer, right? I'm trying to use stringstreams to do this, but I'm having problems extracting data greater than 1 byte (shorts - 2 bytes) since stringstream can only put data in character variables with get/read/readsome. Is there some other way of reading in these values with string stream? I tried using a typecast to a char, but that doesn't seem to work. Thanks for any assistance.
// Init Code
char* buffer = (char*)LockResource( LoadResource(NULL, FindResource(NULL, MAKEINTRESOURCE(IDR_TGA1), "TGA" )));

stringstream *resourceStream = new stringstream(buffer, ios::in || ios::binary );

LoadTGA(resstream,resourceName);


// Load Code
bool LoadTGA(stringstream *resstream, unsigned int id )
{
   _TARGA* tga = new _TARGA;

   // code snippets of stream extraction
   tga->datatypecode = resstream->get();  //datatypecode is an unsigned char, works ??

   resstream->readsome((char*)tga->colourmaporigin , 2); //colourmaporigin is a short int, conversion doesn't work, colourmaporigin retains default value


Share this post


Link to post
Share on other sites
Advertisement
Using std::stringstream::read() would be the preferred way to do that kind of things, I believe.

resstream->read((char*)tga->colourmaporigin , 2); should work.

edit: resstream->read((char*) &tga->colourmaporigin , 2); should work.

As a side note, why are you using new to create the stringstream?

[Edited by - Fruny on September 26, 2004 5:19:25 PM]

Share this post


Link to post
Share on other sites
Thanks for the help, still doesn't seem to work though. I used to new to declare the stringstream just because I was in a playful mood, does it make a difference? Here is my TGA loading code, using Fruny's suggestion, can anyone point out why it's not working? I've also included my TGA structure.


struct PIXEL
{
unsigned char red;
unsigned char green;
unsigned char blue;
unsigned char alpha;

PIXEL( unsigned char _red = 0, unsigned char _green = 0, unsigned char _blue = 0, unsigned
char _alpha = 0 ) : red(_red), green(_green), blue(_blue), alpha(_alpha)
{
// Nothing else to do
}
};

#pragma pack(push,1)
struct _TARGA
{
unsigned char idlength;
unsigned char colourmaptype;
unsigned char datatypecode;
short int colourmaporigin;
short int colourmaplength;
unsigned char colourmapdepth;
short int x_origin;
short int y_origin;
short width;
short height;
unsigned char bitsperpixel;
unsigned char imagedescriptor;
PIXEL* data;
};
#pragma pack(pop,1)





bool LoadTGA(stringstream *resstream, unsigned int id )
{
_TARGA* tga = new _TARGA; // Targa Image
unsigned int imageSize; // Size of actual image data
unsigned int skip; // Offset from beginning of file to image data

if ( ! resstream )
{
return false;
}

tga->idlength = resstream->get();
tga->colourmaptype = resstream->get();
tga->datatypecode = resstream->get();

resstream->read((char*)tga->colourmaporigin , 2);
resstream->read((char*)tga->colourmaplength , 2);

tga->colourmapdepth = resstream->get();

resstream->read((char*) tga->x_origin , 2);
resstream->read((char*) tga->y_origin , 2);
resstream->read((char*) tga->width , 2);
resstream->read((char*) tga->height , 2);

tga->bitsperpixel = resstream->get();
tga->imagedescriptor = resstream->get();


imageSize = tga->width * tga->height * sizeof(PIXEL) ;

tga->data = (PIXEL*)malloc(imageSize);

if ( ! tga->data )
{
return false;
}

// Find offset of image data
skip = tga->idlength + (tga->colourmaptype * tga->colourmaplength);

// Move to image data
resstream->seekg(skip, ios_base::beg);

// Read image data
if ( resstream->readsome((char*)tga->data, imageSize)!= imageSize)
{
if(tga->data!=NULL)
{
free(tga->data);
}

return false;
}

PIXEL* pixels = new PIXEL[ tga->width*tga->height]; // Used to flip image and swap red/blue values

for ( int height = 0; height < tga->height; ++height )
{
for ( int width = 0; width < tga->width; ++width )
{
pixels[(tga->height - height - 1) * tga->width + width].blue = tga->data->red;
pixels[(tga->height - height - 1) * tga->width + width].green = tga->data->green;
pixels[(tga->height - height - 1) * tga->width + width].red = tga->data->blue;
pixels[(tga->height - height - 1) * tga->width + width].alpha = tga->data->alpha;

tga->data++;
}
}


glBindTexture(GL_TEXTURE_2D, id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tga->width, tga->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

delete [] pixels;
delete tga;

return true;
}

Share this post


Link to post
Share on other sites
Watch out, names starting with an underscore and a capital letter are reserved for the library implementors. You shouldn't name your structure _TARGA.

And I messed up, I forgot a critical ampersand.

resstream->read((char*) &tga->colourmaporigin , 2);

i.e. cast the address of tga->colourmaporigin to a char*, not the variable itself.

Share this post


Link to post
Share on other sites
What about the



tga->colourmaptype = resstream->get();
tga->datatypecode = resstream->get();




for reading in one byte to an unsigned character? Is that the correct syntax? Whenever I run it through a debugger, it assigns them an incorrect value of 255.

Share this post


Link to post
Share on other sites
Quote:
Original post by Cypher777
Whenever I run it through a debugger, it assigns them an incorrect value of 255.


get() returns an int, not a char. It will return EOF (generally -1) if the end of the stream is reached. If you try and assign that to a char variable, you'll get 255.

Share this post


Link to post
Share on other sites
So instead, I should read in the unsigned char's with the std::stringstream::read() function?


resstream->read((char*) &tga->idlength, 1);
resstream->read((char*) &tga->colourmaptype, 1 );
resstream->read((char*) &tga->datatypecode, 1 );




Or do I also need to change my TARGA struct variables to regular char's instead of unsigned char's? (Cannot typecast to unsigned char from char, and char values can be negative so an underflow error may occur) Sorry for the questions, this is just new to me and I'm getting frustrated.

[Edited by - Cypher777 on September 26, 2004 9:08:17 PM]

Share this post


Link to post
Share on other sites
Yeah, use read. No you don't need to change to unsigned - that only affects how the type is used in arithmetic operations (including bitshifts), but now how it is represented internally, which is what is relevant to binary IO - otherwise you wouldn't be casting to char* when reading other data types either.

Share this post


Link to post
Share on other sites
(Thanks for your help Fruny)
Ok, converted any get()'s to read()'s so that the majority of the reading looks like this...


TARGA* tga = new TARGA; // Targa Image
unsigned int imageSize; // Size of actual image data
unsigned int skip; // Offset from beginning of file to image data

if ( ! resstream )
{
return false;
}

resstream->read((char*) &tga->idlength, 1);
resstream->read((char*) &tga->colourmaptype, 1 );
resstream->read((char*) &tga->datatypecode, 1 );

resstream->read((char*) &tga->colourmaporigin , 2);
resstream->read((char*) &tga->colourmaplength , 2);
resstream->read((char*) &tga->colourmapdepth, 1);


resstream->read((char*) &tga->x_origin , 2);
resstream->read((char*) &tga->y_origin , 2);
resstream->read((char*) &tga->width , 2);
resstream->read((char*) &tga->height , 2);

resstream->read((char*) tga->bitsperpixel, 1 );
resstream->read((char*) tga->imagedescriptor, 1 );


imageSize = tga->width * tga->height * sizeof(PIXEL) ;

tga->data = (PIXEL*)malloc(imageSize);




But the only value being changed is the tga->idlength to a value of 1. Otherwise, any unsigned char's have a value of 205 and any short int's have a value of -12851, even after "reading" from the input stream.

[Edited by - Cypher777 on September 26, 2004 9:28:38 PM]

Share this post


Link to post
Share on other sites
Check for IO failures (e.g. with resstream->fail(), resstream->eof()) in between operations, and print a debugging statement if anything bad happened.

You shouldn't use malloc() in there (come on, you're already using new TARGA), instead use:

tga->data = new PIXEL[tga->width * tga->height];

and clean up with delete[] tga->data; (array new -> array delete)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!