Tip: How to Take a Screenshot in Starling

Developers that are used to Flash take it for granted that bitmaps can be accessed since a Bitmap display objects has a bitmapData readily available. In Starling, however, that is not the case. Starling images are using textures to hold the pixel data, and Stage3D textures live exclusively in the GPU memory (or Video RAM) – there is no trivial way for accessing a texture after it has been created and sent to the GPU.

In some occasions it is necessary to get a screenshot of your Starling app from within the app. This can be sometimes useful if you need to upload the screen image to a server, save it to a file or camera roll or pass it to JavaScript (if running in a browser).

I recently had such an occasion, and I ended up doing some digging into the docs and forums. To save you the time, I am posting the code used in the most common cases.

One word of warning: this solution makes use of Context3D.drawToBitmapData, which does a buffer copy from the GPU to system memory –  it is potentially a very slow operation that can take up to a second, although usually it’s much faster so use it with care.

For a screenshot: draw the entire stage into a bitmap with scaling.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Screenshot to BitmapData
public static function takeScreenshot(scl:Number=1.0):BitmapData
{
	var stage:Stage= Starling.current.stage;
	var width:Number = stage.stageWidth;
	var height:Number = stage.stageHeight;
 
	var rs:RenderSupport = new RenderSupport();
 
	rs.clear(stage.color, 1.0);
	rs.scaleMatrix(scl, scl);
	rs.setOrthographicProjection(0, 0, width, height);
 
	stage.render(rs, 1.0);
	rs.finishQuadBatch();
 
	var outBmp:BitmapData = new BitmapData(width*scl, height*scl, true);
	Starling.context.drawToBitmapData(outBmp);
 
	return outBmp;
}

Another scenario we need only part of the screen captured, or an individual display object. The following code copies a [starling] display object into a bitmap.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Any display object to BitmapData
public static function copyToBitmap(disp:DisplayObject, scl:Number=1.0):BitmapData
{
	var rc:Rectangle = new Rectangle();
	disp.getBounds(disp, rc);
 
	var stage:Stage= Starling.current.stage;
	var rs:RenderSupport = new RenderSupport();
 
	rs.clear();
	rs.scaleMatrix(scl, scl);
	rs.setOrthographicProjection(0, 0, stage.stageWidth, stage.stageHeight);
	rs.translateMatrix(-rc.x, -rc.y); // move to 0,0
	disp.render(rs, 1.0);
	rs.finishQuadBatch();
 
	var outBmp:BitmapData = new BitmapData(rc.width*scl, rc.height*scl, true);
	Starling.context.drawToBitmapData(outBmp);
 
	return outBmp;
}

Again, this code should be used for offline operations (outside of the game loop). Let me know if you find any problems with it.

 

 

5 thoughts on “Tip: How to Take a Screenshot in Starling

  1. Hi there,
    I am trying to use some of your code here but it doesn’t seem to render correctly. I am using Starling 1.3 latest revision from GitHub. Any ideas? The screenshot for example only captures a portion of the screen. Perhaps I am doing something wrong using it – do I need to pass in the Starling scaleFactor?

  2. I used the code with Starling 1.3 without any problems.
    You might want to make sure width and height are passed correctly on line 12. I used the starling stage to set width and height, but it’s possible that isn’t working on some scenarios. Just put a trace and print out the width/height and see if these are the values you expect.

  3. Thanks for the code! Just one issue… this appears to fill in black where transparent areas are. Is there a way to render the transparent areas as transparent?

  4. Yes, I noticed that myself. It’s actually not going to support 100% of display object properties. Thanks for the link!

Comments are closed.