Defold Screenshot - Capture the moment!

No, but it could probably be added.

1 Like

Thank you for making this extension. Basically it works, but Iā€™m still struggling with some things, that donā€™t really have to do with the screensaver itself.

Iā€™m implementing the screensaver in an application where I want the user to actually find the picture on their system. Iā€™m working on a Mac. The standard location is the user/library/application Support folder. Thatā€™s a hidden folder so surely the safest place where nobody outside of tech will ever find a saved file.

How could I save the screenshot in a place that is more accessible to users? I understand that this could be different for each device.

1 Like

If you wish your user to choose the folder himself then use DefDiags:

Or:

1 Like

Got it.
Thanks!

1 Like

Iā€™d like to take a screenshot and share it as a .png in HTML.

Iā€™m using the code from the screenshot extension, but when the screenshot has been captured, this happens in vanilla Chrome v88:

The code:

local function download_base64_image(base64_image)
	local img_for_download = string.gsub(base64_image, "image/png", "image/octet-stream")
	html5.run("window.location.href='"..img_for_download.."';")
end

local function html5_screenshot_callback(self, base64_img)
	download_base64_image(base64_img)
end

function init(self)
	screenshot.png(html5_screenshot_callback)
end

Has anyone seen this behaviour before? There seem to be some security stuff going on.

Do you have any extensions enabled which may be interfering? / Are you testing on a remote server?

Nope.

Yes, although the same result happens when using ā€œBuild HTML5ā€.

I donā€™t know if you can trigger a cross-origin location change without user interaction. Iā€™d take a different approach:

defos.on_interaction(function ()
  html5.run([[
    const element = document.createElement('a')
    element.setAttribute('href', ']] .. base64_image .. [[')
    element.setAttribute('download', 'screenshot.png')

    element.style.display = 'none'
    document.body && document.body.appendChild(element)

    element.click()

    document.body && document.body.removeChild(element)
  ]])
end)

(but I may be wrong)

Another thing to be careful about is to make sure the canvas isnā€™t tainted by rendering cross-origin textures into it, but Iā€™m not sure how that could happen in Defold.

6 Likes

This worked straight up. Incredible. Thanks so much!

4 Likes

Iā€™m using the latest Screenshot library 1.8.0.
Defold 1.2.180.
Getting black screenshot on Android 9

screenshot.png(function(self, image, w, h)
					local path = sys.get_save_file(sys.get_config("project.title"), "screenshot1_cb.png")
					local f = io.open(path, "wb")
					f:write(image)
					f:flush()
					f:close()
					print(path)
					share.file(path, "Check my score !!")
				end)

Anyone else having the same issue?

This is very likely caused by the upgrade to Open GL 3. Iā€™m happily accepting pull requests!

Iā€™m not familiar with the inner workings of OpenGL. Iā€™ll try to make it work once I have time, but itā€™s low in my priority list at the moment. If anyone else is already familiar with OpenGL, help is welcome :grin: Lots of Defold game could use the screenshot extension to gain some virality.

The extension doesnā€™t seem to work anymore with Defold 1.2.191 on Mac. I popped an issue on the repo: https://github.com/britzl/defold-screenshot/issues/19

Iā€™ve pushed a fix to the repo. Please try the master branch and let me know if it solves the problem for you as well.

4 Likes

Yes, all fixed. Brilliant.

3 Likes

How would I go about creating a box node from the screenshot? This seems the most obvious way:

local buffer, w, h = screenshot.buffer()
gui.new_texture("test", w, h, "rgba", buffer)

But it throws an error:

ERROR:SCRIPT: /main/main.gui_script:5: bad argument #5 to 'new_texture' (string expected, got userdata)
stack traceback:
  [C]:-1: in function new_texture
  /main/main.gui_script:5: in function </main/main.gui_script:1>

ERROR:GAMESYS: Error when initializing gui component: -2.

Edit: There seems to be something strange going on. With a callback there are different results:

screenshot.buffer(function(self, buffer, w, h)
	gui.new_texture("test", w, h, "rgba", buffer) -- ERROR:GUI: Invalid image buffer size. Expected 9830400, got 2457600
end)

screenshot.buffer(function(self, buffer, w, h)
	gui.new_texture("test", w, h, "rgb", buffer) -- ERROR:GUI: Invalid image buffer size. Expected 7372800, got 2457600
end)

screenshot.buffer(function(self, buffer, w, h)
	gui.new_texture("test", w, h, "l", buffer) -- No error, but the image comes out as a red raster.
end)
local buffer, w, h = screenshot.buffer()

This will not return a string with binary image data. It returns a buffer user data object. This type is accepted by resource.set_texture() but gui.new_texture() expected a string (yes, this is not super logical and perhaps something we should change (gui.new_texture() should accept both a string and a buffer).

What you can do is to get the bytes from the buffer using buffer.get_bytes(buffer) and then call gui.new_texture().

OR (and I just realized this) you can use screenshot.get_pixels() which will give you the pixels as a string.

5 Likes

Thanks so much! This is really helpful.

Hi all, Iā€™m new to Defold and enjoying the experience so far! Is it possible that the extension doesnā€™t consider the resolution of the monitor when saving a region of the app window? The same build correctly saves the screen region to a PNG file on a standard monitor (1920x1080p), but the result is significantly less on a MacBook Air (2560 x 1664p). The same behavior occurs on my phone. Full screen capture works flawlessly, generating a PNG file with different resolutions depending on the monitorā€™s screen resolution. Could it be that when passing a region w,h, the extension cuts the region from the fullscreen pass without taking into consideration the source resolution? Does that make sense?

It could be DPI issue somehow?