Thanks for your speedy reply Samith, lots of good info.
Typically, when you need to deal with unknown endianness you would write a byte order marking at the top of the file, which when read back by another machine can indicate if the content of the file needs to be endian swapped. A common byte order marking is the 16 bit integer 0xfeff. If you read a byte order mark from a file and it comes out as 0xfffe, then you have to reverse the endianness of the contents of that file. If it gets read in as 0xfeff, then you won't need to perform any endian swapping.
This in particular was very enlightening. I'll use a byte order marking to check weather to swap all other numbers read.
You don't need to worry about endian-ness unless you are switching machine families or using Java.
It's nice to know that pretty much all conventional PCs use little endain. But I did a bit of searching and found that vc++ has some built in functions for swapping byte order (I think they're quite well optimised as well). With all this info I found that it really wasn't much effort to support big and little endian (unless I've overlooked something) even if it's not likely to be necessary. Good practice I guess.
This is what I managed to come up with so far:
It still needs to be cleaned up, but I think I've not overlooked anything important (other than a load function..)
bool save_as_image( std::string argFilename, std::vector<ggCell>& argCells )
{
// saves a vector of cells as an image.
// could pack more into each pixel but it's not necessary
// calculate the image size needed
unsigned int dimWidth = 128;
unsigned int hlpBytesNeeded = GG_BYTES_PER_CELL*argCells.size();
unsigned int dimHeight = 17 + (hlpBytesNeeded/4)/128;
out("height is " + uint_to_string(dimHeight));
// load template header
sf::Image imgHeader;
if ( !imgHeader.loadFromFile("data/pattern_header.png") ) {
return false;
}
// create new image with header
sf::Image imgPattern;
imgPattern.create( dimWidth, dimHeight, sf::Color(0,0,0));
imgPattern.copy( imgHeader, 0, 0 );
// write all pixels
unsigned int x = 0;
unsigned int y = 16;
for ( unsigned int index=0; index<argCells.size(); ++index ) {
// gen colours
sf::Color colX, colY, colType;
colX = int_to_pixel( argCells[index].x );
colY = int_to_pixel( argCells[index].y );
colType = int_to_pixel( argCells[index].type );
// write to image
imgPattern.setPixel( x, y, colX );
increment(x,y);
imgPattern.setPixel( x, y, colY );
increment(x,y);
imgPattern.setPixel( x, y, colType );
increment(x,y);
// output colours used
out("[" + std::to_string(index) + "] ");
out("X: ( " + std::to_string(colX.r) + ", " + std::to_string(colX.g) + ", " + std::to_string(colX.b) + ", " + std::to_string(colX.a) + " )\n");
out("[" + std::to_string(index) + "] ");
out("X: ( " + std::to_string(colY.r) + ", " + std::to_string(colY.g) + ", " + std::to_string(colY.b) + ", " + std::to_string(colY.a) + " )\n");
out("[" + std::to_string(index) + "] ");
out("X: ( " + std::to_string(colType.r) + ", " + std::to_string(colType.g) + ", " + std::to_string(colType.b) + ", " + std::to_string(colType.a) + " )\n");
}
// save image
imgPattern.saveToFile( argFilename );
return true;
}
sf::Color int_to_pixel( int number ) {
// code number to look better as an image
number += GG_INT_CODE;
// convert to pixel
int r_single = number & 0xff000000;
int g_single = number & 0x00ff0000;
int b_single = number & 0x0000ff00;
int a_single = number & 0x000000ff;
int r = r_single >> 24;
int g = g_single >> 16;
int b = b_single >> 8;
int a = a_single;
sf::Color colour((unsigned char)r,(unsigned char)g,(unsigned char)b,(unsigned char)a);
return colour;
}
int pixel_to_int( sf::Color colour, bool swap ) {
int r = (int) colour.r;
int g = (int) colour.g;
int b = (int) colour.b;
int a = (int) colour.a;
int number = r << 24;
number = number | g << 16;
number = number | b << 8;
number = number | a;
if ( swap ) {
number = (int)_byteswap_ulong( number );
}
// decode
number -= GG_INT_CODE;
return number;
}
void increment( unsigned int& x, unsigned int& y ) {
++x;
if ( x >= 128 ) {
x = 0;
++y;
}
}