Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

Win Elchtest

Saving screenshot to disk?

This topic is 5564 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

Hello, i''m looking for a function to save the actual rendered screen to an image file. even better would be something where i could set some parameters, like i only want the part saved from screen coordiantes e.g. (200,300) to (328, 428) or something like this. thanx a lot!

Share this post


Link to post
Share on other sites
Advertisement
Look into glReadPixels(); it allows you specify a section of the screen to be saved into a buffer. However, you'll need to provide code to write that buffer into a valid image file. Since BMP has an easily implementable file structure, you might also want to see this topic on openglforums for sample code.

RapscallionGL - arriving soon.

[edited by - johnnie2 on February 8, 2003 2:31:54 PM]

Share this post


Link to post
Share on other sites
Got bored.




bool SaveGLScreenshot(RECT &Region, char *FileName)
{
// extract the height and width from the rectangle
unsigned long Width = Region.right-Region.left,
Height= Region.bottom-Region.top;

long ImageSize = Width*Height*3; // width*height*(bitdepth/bitsperbyte)

unsigned char *Data = new unsigned char[ImageSize]; // allocate some space

// read the data in RGB format from the color buffer
glReadPixels(Region.left, Region.top, Width, Height, GL_RGB, GL_UNSIGNED_BYTE, Data);

FILE *Bitmap = fopen(FileName, "wb"); // open up a file to write

if(!Bitmap) // bail if we couldn''t open the file (shouldn''t happen)
{
delete [] Data;
return false;
}

unsigned char temp;
// reorder RGB to standard bitmap ordering of BGR
for(int index = 0; index < ImageSize; index+=3)
{
temp = Data[index];
Data[index] = Data[index+2]; // swap reds
Data[index+2] = temp; // with blues
}

// prepare the file header
BITMAPFILEHEADER FileHeader;
// clear everything out so we can fill arbitrarily
memset(&FileHeader, 0, sizeof(BITMAPFILEHEADER));
// filetype is always "BM"
FileHeader.bfType = MAKEWORD(''B'',''M'');
// total size of our bitmap file
FileHeader.bfSize = sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER) + ImageSize;
// offset from start of file to bitmap data
// NOTE: this is misdocumented in the MSDN
FileHeader.bfOffBits = sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER);

// prepare the info header
BITMAPINFOHEADER InfoHeader;
// clear stuff
memset(&InfoHeader, 0, sizeof(BITMAPINFOHEADER));
// size of this structure
InfoHeader.biSize = sizeof(BITMAPINFOHEADER);
// width and height
InfoHeader.biWidth = Width;
InfoHeader.biHeight = Height;
// number of image planes - must be 1 in Windows
InfoHeader.biPlanes = 1;
// bitdepth is 24-bit (3 byte-sized components per pixel)
InfoHeader.biBitCount = 24;
// no compression - outut raw RGB data
InfoHeader.biCompression = BI_RGB;

// write to the file - yay.
fwrite(&FileHeader, sizeof(BITMAPFILEHEADER), 1, Bitmap);
fwrite(&InfoHeader, sizeof(BITMAPINFOHEADER), 1, Bitmap);
fwrite(Data, sizeof(unsigned char), ImageSize, Bitmap);

// perform some clean up
fclose(Bitmap);

delete [] Data;

// it''s all good.
return true;
}


As in,
// RECT coord order: left, top, right, bottom
RECT Area = {0, 0, 640, 480};
SaveGLScreenshot(Area, "scr.bmp");


Later,
ZE.

//email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links

Share this post


Link to post
Share on other sites
Why not try it with DevIL?

may be a bit of an overkill but its veeeerryyy handy!
(also for textures )

mfg Phreak
--
"Input... need input!" - Johnny Five, Short Circuit.

Share this post


Link to post
Share on other sites
I think that with the JPEG library comes an example of how so save JPEGs on your disk.Just do this:

GLint v[4];

glGetIntegerv(GL_VIEWPORT,v);

GLubyte *data = (GLubyte*)malloc(v[2] * v[3] * 3);

glReadPixels(0,0,v[2],v[3],GL_RGB,GL_UNSIGNED_BYTE,data);

//WRITE THE DATA TO A FILE


The PAIN is coming...this summer!!!In cinemas everywhere.

Share this post


Link to post
Share on other sites
quote:
Original post by LousyPhreak
Why not try it with DevIL?

may be a bit of an overkill but its veeeerryyy handy!
(also for textures )



Because someone who has no clue how to get image data into an image file has no business using an all-powerful library that shelters them from all the guts. I''m not a sadist, but the trend, especially among indies, of taking middleware as a godsend that prevents one from actually tackling problems is a dangerous one.

Later,
ZE.

//email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links

Share this post


Link to post
Share on other sites
thanx at all for the help. finally i got enough time yesterday to implement the stuff.

@ZealousElixir: your function seems to crash in some cases, like if the rectangle starts with x < 60. i don''t know why. one thing i thought it may be hasn''t changed that error.

i replaced:
fwrite(&FileHeader, sizeof(BITMAPFILEHEADER), 1, Bitmap);
in:
fwrite(&FileHeader, 1, sizeof(BITMAPFILEHEADER, Bitmap);

so i mixed around all of the functions i''ve found, and i''m now finally using this one, which hasn''t made any error (yet):



int SaveBMP (char *filename, int width, int height, unsigned char *BMP_Data) {
FILE *file_ptr;
BITMAPINFOHEADER bmp_infoh;
BITMAPFILEHEADER bmp_fileh;
unsigned int counter;
unsigned char tempRGB;

file_ptr = fopen (filename, "wb");
if (!file_ptr) {
return 0;
}

bmp_fileh.bfOffBits = sizeof (BITMAPFILEHEADER) + sizeof (BITMAPINFOHEADER);
bmp_fileh.bfReserved1 = 0;
bmp_fileh.bfReserved2 = 0;
bmp_fileh.bfSize = sizeof (BITMAPFILEHEADER);
bmp_fileh.bfType = 0x4D42;

bmp_infoh.biBitCount = 24;
bmp_infoh.biClrImportant = 0;
bmp_infoh.biClrUsed = 0;
bmp_infoh.biCompression = BI_RGB;
bmp_infoh.biHeight = height;
bmp_infoh.biPlanes = 1;
bmp_infoh.biSize = sizeof (BITMAPINFOHEADER);
bmp_infoh.biSizeImage = width * abs (height) * 3;
bmp_infoh.biWidth = width;
bmp_infoh.biXPelsPerMeter = 0;
bmp_infoh.biYPelsPerMeter = 0;

for (counter = 0; counter < bmp_infoh.biSizeImage; counter += 3) {
tempRGB = BMP_Data [counter];
BMP_Data [counter] = BMP_Data [counter + 2];
BMP_Data [counter + 2] = tempRGB;
}

fwrite (&bmp_fileh, 1, sizeof (BITMAPFILEHEADER), file_ptr);
fwrite (&bmp_infoh, 1, sizeof (BITMAPINFOHEADER), file_ptr);
fwrite (BMP_Data, 1, bmp_infoh.biSizeImage, file_ptr);

fclose (file_ptr);
return 1;
}

//this function make screenshot with previsius function for save BMP


void *BMPw_Data;
void SaveScreenshot (int startx, int starty, int width, int height, char *dateiname) {
BMPw_Data = malloc (width * height * 3);
memset (BMPw_Data, 0, width * height * 3);

glReadPixels (startx, starty, width, height, GL_RGB, GL_UNSIGNED_BYTE, BMPw_Data);
SaveBMP (dateiname, width, height, (unsigned char*)BMPw_Data);

free (BMPw_Data);
}


calling with this:
SaveScreenshot (0, 0, 1024, 768, "bla.bmp");

Share this post


Link to post
Share on other sites
woa! Found the perfect article! And that method is soooo much faster than those posted here

Instead of reading what has been rendered, you render DIRECTLY to the texture! :D

http://www.nvidia.com/dev_content/gdc2002/opengl_rendertexture_files/frame.htm

"No lies of sugar can sweeten the sournes of reality"

}+TITANIUM+{ A.K.A. DXnewbie[onMIRC]

Share this post


Link to post
Share on other sites
Seriema: What does that do? Render to a texture, then you STILL have to read the data back anyways... so I don''t understand what the point was.

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

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

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!