Quick question (hopefully), how do I save an SDL_Surface image to a file?

Unfortunately I am having trouble using that forum. Is there any way that I could get one of you to post my question there for me? (I have tried to register 3 times to no avail)

Quick question (hopefully), how do I save an SDL_Surface image to a file?

It shouldn't be too hard. I never used SDL_surface, but it looks pretty straight forward.

...//this would be for a standard 24 bit bitmap
...//suppose you have an SDL_surface called surface
//Before we begin, we need to calculate the actual file size and some width alignment issues...
//Bitmaps are width WORD aligned.  That is, their width must be divisible by 4.
//That means that there may be some extra zeroes at the end of each row to pad it.
//So multiply "surface.w" by 3, since each pixel is 3 chars "RGB", and mod it by 4.
//So let's say you have something that's 9 characters long.  9%4 is 1.  Which means it's
//1 character past what we need to be.. so we have to add 3 zeroes (AKA 4-1)
//Okay let's start getting the numbers together for the bitmap header.
int padding = 4 - ((surface.w * 3) % 4);
int total_width = 3*surface.w + padding;
int num_pixels = surface.w * surface.h;
int file_size = total_width * surface.h + 54;
int header_size = 54;
int offset_until_data = 40;

//We're ready to build the header
//You can only write or put characters.
//So you have to convert the ints to a char array or several char variables.
//You need to put the least significant byte first.
//If you don't know how, you can use this method... but there may be an easier way.
/*  
void write_long(long data, ofstream& fout)
//I actually found this bit on the internet awhile back.  rgb_image.cpp
//This works by AND'ing the data with all zeroes except 11111111 at the end...
//to get the least significant byte only and zero-ing the rest.
//Then it right shifts by 8, 16, 24, and does the same thing to get the next bytes. 
	unsigned char byte[4];
	byte[0] = (unsigned char)(data&0x000000ff); 		
	byte[1] = (unsigned char)((data>>8)&0x000000ff);
	byte[2] = (unsigned char)((data>>16)&0x000000ff);
	byte[3] = (unsigned char)((data>>24)&0x000000ff);

	fout.put(byte[0]);
	fout.put(byte[1]);
	fout.put(byte[2]);
	fout.put(byte[3]); 
*/
//At times you will need to write a short.  It's done the same way except with just 2 bytes.


std::ofstream fout;
fout.open("output.bmp", std::ofstream::binary);
fout.put('B');
fout.put('M');//all bitmap files start with "BM"

write_long(fout, (40+14+numRows*width));
write_short(fout, 0);//reserved
write_short(fout, 0);//reserved
write_long(fout, file_size);
write_long(fout, offset_until_data);
write_long(fout, surface.h); 
write_long(fout, surface.w);
write_short(fout, 1); //number of planes I think. just put 1 here.
write_short(fout, 24); //number of bits.  Must be 24 for this example.
write_long(fout, 0); //Put zeroes for the rest.. You can look up what they do if  
write_long(fout, 0); //you need to change this.
write_long(fout, 0);
write_long(fout, 0);
write_long(fout, 0);
write_long(fout, 0);
//Header done.  Now we have to write the pixel data.
//Unfortunately since we have to put the padding at the end of each row, we have to write
//the file line by line and fill in zeroes each time.
//I haven't tested the rest of this... if this doesn't work, let me know.

char* pixel_position = (char*)surface.pixels;  //Make a cursor to move through the array
for (unsigned int i = 0; i < surface.h; ++i){
  fout.write((char*)pixel_position, surface.w*3);  //Write one line
  for (int j = 0; j < padding; ++j) fout.put(0);   //Put in the zeroes
  pixel_position += surface.w*3;  //On to the next line....
}
fout.close();

-Greywolf

oops put this line between 10 and 11
if (padding == 4) padding = 0;

Been away on vacation w/o internet. Anyways, that is a great solution and more than less exactly what I was looking for. The only issue is that upon investigation through the header file source code itself I found a function called Save_BMP. As it turns out it does exactly what it says. I guess I went on a wild goose chase for nothing. Your code has not gone to waste however, I am implementing it for saving other file formats. (Although writing those files so dang precisely is annoying!) THANKS FOR YOUR HELP!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.