Save a portion of the screen
by Dave Young · 04/24/2008 (8:56 am) · 7 comments
In game.cc, after the console screenshot function, add in:
Recompile, and add lemon.
Usage: SaveBitmapXY("newpicture.png","10 10 256 256"); Coordinates are from lower left!
The height and width must be in powers of 2 but don't have to be square.
In the version below, the coordinates are from upper left origin, and it will bump up the allocated bitmap automatically to be pow2.
ConsoleFunction(saveBitmapXY, void, 3, 3, "(string file, coords startx starty extentx extenty)"
"Save a portion of the screen, must be in powers of 2.")
{
Point2I tstart;
Point2I tend;
Point2I extent;
dSscanf(argv[2],"%d %d %d %d",&tstart.x,&tstart.y,&extent.x,&extent.y);
if(isPow2(extent.x)==false || isPow2(extent.y)==false)
{
Con::errorf("Height and width must be power of 2");
return;
}
FileStream fStream;
if(!fStream.open(argv[1], FileStream::Write))
{
Con::printf("Failed to open file '%s'.", argv[1]);
return;
}
glReadBuffer(GL_FRONT);
U8 * pixels = new U8[extent.x * extent.y * 3];
glReadPixels(tstart.x, tstart.y, extent.x, extent.y, GL_RGB, GL_UNSIGNED_BYTE, pixels);
GBitmap * bitmap = new GBitmap;
bitmap->allocateBitmap(U32(extent.x), U32(extent.y),false,GBitmap::RGB);
// flip the rows
for(U32 y = 0; y < extent.y; y++)
dMemcpy(bitmap->getAddress(0, extent.y - y - 1), pixels + y * extent.x * 3, U32(extent.x * 3));
bitmap->writePNG(fStream);
fStream.close();
delete [] pixels;
delete bitmap;
}Recompile, and add lemon.
Usage: SaveBitmapXY("newpicture.png","10 10 256 256"); Coordinates are from lower left!
The height and width must be in powers of 2 but don't have to be square.
In the version below, the coordinates are from upper left origin, and it will bump up the allocated bitmap automatically to be pow2.
ConsoleFunction(saveBitmapXY, void, 3, 3, "(string file, coords startx starty extentx extenty)"
"Save a portion of the screen, from upper left")
{
Point2I tstart;
Point2I extent;
dSscanf(argv[2],"%d %d %d %d",&tstart.x,&tstart.y,&extent.x,&extent.y);
Point2I cextent = Canvas->getExtent();
//Con::errorf("Incoming size %d %d",extent.x, extent.y);
if(isPow2(extent.x)==false || isPow2(extent.y)==false)
{
//Con::errorf("Height and width must be power of 2");
extent.x = getNextPow2(extent.x);
extent.y = getNextPow2(extent.y);
//Con::errorf("Revised size %d %d",extent.x, extent.y);
//return;
}
//Make the starting point relative to lower left corner
tstart.y = cextent.y - extent.y - tstart.y;
FileStream fStream;
if(!fStream.open(argv[1], FileStream::Write))
{
Con::printf("Failed to open file '%s'.", argv[1]);
return;
}
glReadBuffer(GL_FRONT);
U8 * pixels = new U8[extent.x * extent.y * 3];
GBitmap * bitmap = new GBitmap;
bitmap->allocateBitmap(U32(extent.x), U32(extent.y),false,GBitmap::RGB);
glReadPixels(tstart.x, tstart.y, extent.x, extent.y, GL_RGB, GL_UNSIGNED_BYTE, pixels);
// flip the rows
for(U32 y = 0; y < extent.y; y++)
dMemcpy(bitmap->getAddress(0, extent.y - y - 1), pixels + y * extent.x * 3, U32(extent.x * 3));
bitmap->writePNG(fStream);
fStream.close();
delete [] pixels;
delete bitmap;
}About the author
#2
Shouldn't that be game.cc?
04/24/2008 (3:37 pm)
Sounds interesting, one problem thoughQuote:In game.cs
Shouldn't that be game.cc?
#3
04/24/2008 (5:13 pm)
Aye Nathan, it should be ;) Thanks. Good tip Orion. I've expanded my usage for a few specific things, this is one of them :)
#4
05/03/2008 (2:54 pm)
This is great. Thanks!!!
#5
Tnx :)
05/06/2008 (2:46 am)
@Orion: good addiction... since I'm really really a noob... where I have to put those pieces of code?Tnx :)
#6
05/06/2008 (9:12 am)
joz - added some suggested locations to my post, above.
#7
Really I think you are on the top list of the post I looked to... :-D
05/06/2008 (2:25 pm)
Tnx Orion :-)Really I think you are on the top list of the post I looked to... :-D

Associate Orion Elenzil
Real Life Plus
eg
supporting console method:
in GuiControl.cc, somewhere near the ConsoleMethod resize(), add:
ConsoleMethod( GuiControl, getScreenPosition, const char*, 2, 2, "") { char *retBuffer = Con::getReturnBuffer(64); Point2I pos = object->localToGlobalCoord(Point2I(0, 0)); dSprintf(retBuffer, 64, "%d %d", pos.x, pos.y); return retBuffer; }and here's a script wrapper.
this is script, so can go nearly anywhere,
but a reasonable place might be at the bottom of common/client/screenshot.cs:
function GuiControl::SaveBitmap(%this, %filename) { %start = %this.getScreenPosition(); %extent = %this.getExtent(); return saveBitmapXY(%filename, %start SPC %extent); }we use this in vSide to give the user a camera w/ a resizable view-finder to let them take snapshots of various parts of the screen.