Defold Screenshot - Capture the moment!


I created a screenshot extension a while back but never got it working on iOS (captured images were completely black). I took another look at the code today, did some searches on Stack Overflow, added one line of code and lo and behold, the darn thing is working on iOS! I thought I had tried this solution already, but apparently not :slight_smile:

Anyway, if you want to capture screenshots then this extension is for you! You can capture the entire screen or a region and you can get the screenshot as a png, buffer or as raw pixels:

-- Take screenshot and encode to a PNG
-- Write it to foo.png
local png, w, h = screenshot.png()
local f ="screenshot1.png", "wb")

-- Take screenshot and return it as a Defold buffer
-- Set buffer as texture on a model
local buffer, w, h = screenshot.buffer()
local url = go.get("cube#model", "texture0")
resource.set_texture(url, { type = resource.TEXTURE_TYPE_2D, width = w, height = h, format = resource.TEXTURE_FORMAT_RGBA }, buffer)

-- Take screenshot and return pixels as a Lua string
local pixels, w, h = screenshot.pixels()

-- Capture screenshots of a portion of the screen
screenshot.png(x, y, w, h)
screenshot.buffer(x, y, w, h)
screenshot.pixels(x, y, w, h)

Taking Screenshot in Defold

Sweet this may play well with the cucumber library, bundling screens in the response


Very useful thing! But one problem - build failed: 86896d19-8027-43a5-aef0-1682719cec2d.lib(screenshot.cpp_0.o) : error LNK2019: unresolved external symbol __imp_glBindRenderbuffer referenced in function “unsigned char * __ptr64 __cdecl ReadPixels(unsigned int,unsigned int,unsigned int,unsigned int)” (?ReadPixels@@YAPEAEIIII@Z)
build/dmengine.exe : fatal error LNK1120: 1 unresolved externals


Hmm, works for me on OSX. You’re on Windows right?


Yes. Maybe libs required?


I mean what package include only GLES headers, nor source, nor precompiled libs. Sorry for my bad English.


@britzl Maybe if you bundle for windows, you’ll get a similar build issue?


Yup, will try tomorrow when I have access to a Windows machine.


Guys, I think the problem is not in the OS. Just the dev environment of the britzl includes GL SDK, and mine - no. And at build process linker searches for gl2.lib or gl2.obj, which is not in the package, but installed on the computer britzl and registered in the path.
And how do you insert usernames as a link in your posts? :slight_smile:


Nope, the extension is built on our server in a fixed build environment. The whole OpenGL package is included in the engine and I leverage that fact. All I include are the headers. BUT I haven’t tested on Windows and for one reason or another the glBindRenderbuffer() doesn’t exist on Windows.

Prefix with an @ symbol.


You don’t need a windows computer to bundle for windows (not even with native extensions)
Perhaps I misunderstand, but what he got was a build error, not a runtime error.


Umm, you’re right, how silly of me.

Please take a moment to picture me with a jesters hat bouncing around the office looking like a fool…


@xndr: The extension should work for windows now.


Yes! It’s work. Very-very much thanks!


Got the next error on MacOS (editor 2, screenshot v1.5). Build && run from editor:

Undefined symbols for architecture x86_64
"__ZSt20__throw_length_errorPKc", referenced from:
      __ZNSt6vectorIhSaIhEE14_M_fill_insertEN9__gnu_cxx17__normal_iteratorIPhS1_EEmRKh in lib126eb502-6aef-474a-b00b-61d59df86846.a(lodepng.c_0.o)
      __ZNSt6vectorIhSaIhEE15_M_range_insertIPhEEvN9__gnu_cxx17__normal_iteratorIS3_S1_EET_S7_St20forward_iterator_tag in lib126eb502-6aef-474a-b00b-61d59df86846.a(lodepng.c_0.o)

On android build extension runs well.

edit: conflicted with (game analytics extension)
try to understand, how to fix it
temporary fixed by copy ext.manifest settings from GA to screenshot


It’s been a while. Think you could do the same for HTML5? :wink:
I think you can, and I really hope so! (when you have time to look again, ofc)

I spent a few days on Stack Overflow already. Maybe I can at least save you some time there. Pretty sure I’ve figured out why screenshots are all black, and a solution to make it work. I am struggling to implement it though, and hoping you or some other experienced folks here might be able to spot an obvious way to do this.

The official source (bottom half of section 2.2 WebGL specs) says:
“By default, after compositing the contents of the drawing buffer shall be cleared to their default values”

Then it goes on to say: “attempting to perform operations using this context as a source image after the rendering function has returned can lead to undefined behavior. This includes readPixels or toDataURL calls, using this context as the source image of another context’s texImage2D or drawImage call, or creating an ImageBitmap [HTML] from this context’s canvas.”

The Solution may be: “Techniques like synchronous drawing buffer access (e.g., calling readPixels or toDataURL in the same function that renders to the drawing buffer) can be used to get the contents of the drawing buffer.”

I was trying to do that on my own, so not to bother you with it, but I feel like I am in way over my head at this point. All I’ve manage to do, is possibly confirm that we are in fact getting the cleared buffer, and not the drawing buffer.
Adding glClear(GL_COLOR_BUFFER_BIT) to this code in the Screenshot extension:

static GLubyte* ReadPixels(unsigned int x, unsigned int y, unsigned int w, unsigned int h) {
#if ...
#elif defined (__EMSCRIPTEN__)
	glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, data);
	return data;

Gives screenshot like this (orange instead of black):

I tried doing a bunch of other stuff, but that’s all I got.

Sorry I couldn’t help more! :persevere: (if this even helps at all)


Hi guys, I’m looking to send a screenshot to Facebook Instant API. If this plugin can’t do it, is there an alternative way to capture a bitmap in Defold and send it on to the Facebook Instant API to be shared in a post?


I struggled with this problem while developing the Instant Games extension but didn’t find a working solution at the time. The issue is reported here: