Forked from Noitidart/_ff-addon-snippet-gtkScreenshot.js
Created
May 31, 2016 08:10
-
-
Save Happy-Ferret/d6ae1535548d102e993b6f6887e49402 to your computer and use it in GitHub Desktop.
_ff-addon-snippet-gtkScreenshot - Takes screenshot of all monitors on on GTK systems. [jsctypes] [gtk] [gdk]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Cu.import('resource://gre/modules/ctypes.jsm'); | |
var gdk2 = ctypes.open('libgdk-x11-2.0.so.0'); | |
var _void = ctypes.void_t; | |
var gint = ctypes.int; | |
var GdkPixbuf = ctypes.StructType('GdkPixbuf'); | |
var GdkDrawable = ctypes.StructType('GdkDrawable'); | |
var GdkColormap = ctypes.StructType('GdkColormap'); | |
var GdkWindow = ctypes.StructType('GdkWindow'); | |
var guchar = ctypes.unsigned_char; | |
var guint = ctypes.unsigned_int; | |
var int = ctypes.int; | |
var gint = ctypes.int; | |
var gboolean = gint; | |
// https://developer.gnome.org/gdk3/stable/gdk3-Windows.html#gdk-get-default-root-window | |
var gdk_get_default_root_window = gdk2.declare('gdk_get_default_root_window', ctypes.default_abi, GdkWindow.ptr); | |
// https://developer.gnome.org/gdk3/stable/gdk3-Windows.html#gdk-window-get-origin | |
var gdk_drawable_get_size = gdk2.declare('gdk_drawable_get_size', ctypes.default_abi, | |
gint, // return | |
GdkWindow.ptr, // *window | |
gint.ptr, // *x | |
gint.ptr // *y | |
); | |
// https://developer.gnome.org/gdk3/stable/gdk3-Windows.html#gdk-window-get-origin | |
var gdk_window_get_origin = gdk2.declare('gdk_window_get_origin', ctypes.default_abi, | |
gint, // return | |
GdkWindow.ptr, // *window | |
gint.ptr, // *x | |
gint.ptr // *y | |
); | |
// https://developer.gnome.org/gdk2/stable/gdk2-Pixbufs.html#gdk-pixbuf-get-from-drawable | |
var gdk_pixbuf_get_from_drawable = gdk2.declare('gdk_pixbuf_get_from_drawable', ctypes.default_abi, | |
GdkPixbuf.ptr, // return | |
GdkPixbuf.ptr, // *dest | |
GdkDrawable.ptr, // *src | |
GdkColormap.ptr, // *cmap | |
int, // src_x | |
int, // src_y | |
int, // dest_x | |
int, // dest_y | |
int, // width | |
int // height | |
); | |
// https://developer.gnome.org/gdk-pixbuf/unstable/gdk-pixbuf-The-GdkPixbuf-Structure.html#gdk-pixbuf-get-pixels | |
var gdk_pixbuf_get_pixels = gdk2.declare('gdk_pixbuf_get_pixels', ctypes.default_abi, | |
guchar.ptr, // return | |
GdkPixbuf.ptr // *pixbuf | |
); | |
// https://developer.gnome.org/gdk-pixbuf/stable/gdk-pixbuf-Utilities.html#gdk-pixbuf-add-alpha | |
var gdk_pixbuf_add_alpha = gdk2.declare('gdk_pixbuf_add_alpha', ctypes.default_abi, | |
GdkPixbuf.ptr, // return | |
GdkPixbuf.ptr, // *pixbuf | |
gboolean, // substitute_color | |
guchar, // r | |
guchar, // g | |
guchar // b | |
); | |
// | |
var libc = ctypes.open('libc.so.6'); | |
var memcpy = libc.declare('memcpy', OS.Constants.Sys.Name.toLowerCase().indexOf('win') == 0 ? ctypes.winapi_abi : ctypes.default_abi, | |
ctypes.void_t, // return | |
ctypes.void_t.ptr, // *dest | |
ctypes.void_t.ptr, // *src | |
ctypes.size_t // count | |
); | |
var rootGdkWin = gdk_get_default_root_window(); | |
console.info('rootGdkWin:', rootGdkWin.toString()); | |
var x_orig = gint(); | |
var y_orig = gint(); | |
var width = gint(); | |
var height = gint(); | |
var rez_gdkDrawGetSiz = gdk_drawable_get_size(rootGdkWin, width.address(), height.address()); | |
console.info('width:', width.value, 'height:', height.value); | |
var rez_gdkWinGetOrg = gdk_window_get_origin(rootGdkWin, x_orig.address(), y_orig.address()); | |
console.info('x:', x_orig.value, 'y:', y_orig.value); | |
var rootGdkDrawable = ctypes.cast(rootGdkWin, GdkDrawable.ptr); | |
console.time('gdk_pixbuf'); | |
var screenshot = gdk_pixbuf_get_from_drawable(null, rootGdkDrawable, null, x_orig.value, y_orig.value, 0, 0, width.value, height.value); | |
console.timeEnd('gdk_pixbuf'); | |
console.info('screenshot:', screenshot.toString()); | |
/* METHOD 2 - use c to add alpha | |
console.time('gdk_rgba'); | |
var screenshot_with_a = gdk_pixbuf_add_alpha(screenshot, false, 0, 0, 0); | |
console.timeEnd('gdk_rgba'); | |
console.time('gdk_pixels'); | |
var rgba = gdk_pixbuf_get_pixels(screenshot_with_a); | |
console.timeEnd('gdk_pixels'); | |
var n_channels = 4; | |
var pixbuf_len = width.value * height.value * n_channels; | |
// console.time('cast pixels'); | |
// var casted_rgba = ctypes.cast(rgba, guchar.array(pixbuf_len).ptr).contents; | |
// console.timeEnd('cast pixels'); | |
// console.info('casted_rgba:', casted_rgba, casted_rgba[0], casted_rgba[1], casted_rgba[2], casted_rgba[3]); | |
console.time('init imagedata'); | |
var imagedata = new ImageData(width.value, height.value); | |
console.timeEnd('init imagedata'); | |
console.time('memcpy'); | |
memcpy(imagedata.data, rgba, pixbuf_len); | |
console.timeEnd('memcpy'); | |
//*/ | |
///* METHOD 1 - use js to add alpha | |
console.time('gdk_pixels'); | |
var rgb = gdk_pixbuf_get_pixels(screenshot); | |
console.timeEnd('gdk_pixels'); | |
var n_channels = 3; | |
var pixbuf_len = width.value * height.value * n_channels; | |
// console.time('cast pixels'); | |
// var casted_rgb = ctypes.cast(rgba, guchar.array(pixbuf_len).ptr).contents; | |
// console.timeEnd('cast pixels'); | |
// console.info('casted_rgb:', casted_rgb, casted_rgb[0], casted_rgb[1], casted_rgb[2], casted_rgb[3]); | |
console.time('init imagedata'); | |
var imagedata = new ImageData(width.value, height.value); | |
console.timeEnd('init imagedata'); | |
console.time('memcpy'); | |
memcpy(imagedata.data, rgb, pixbuf_len); | |
console.timeEnd('memcpy'); | |
var pixbuf_pos = pixbuf_len - 1; | |
var dataRef = imagedata.data; | |
var dataRef_pos = parseInt(imagedata.data.length)- 1; | |
console.time('js_rgba'); | |
while (dataRef_pos > -1) { | |
dataRef[dataRef_pos-3] = dataRef[pixbuf_pos-2]; | |
dataRef[dataRef_pos-2] = dataRef[pixbuf_pos-1]; | |
dataRef[dataRef_pos-1] = dataRef[pixbuf_pos]; | |
dataRef[dataRef_pos] = 255; | |
pixbuf_pos -= 3; | |
dataRef_pos -= 4; | |
} | |
console.timeEnd('js_rgba'); | |
console.info('ok rgba done, pixbuf_pos:', pixbuf_pos, 'dataRef_pos:', dataRef_pos); | |
//*/ | |
var idat = imagedata; | |
var NS_HTML = 'http://www.w3.org/1999/xhtml'; | |
var can = document.createElementNS(NS_HTML, 'canvas'); | |
can.width = width.value; | |
can.height = height.value; | |
var ctx = can.getContext('2d'); | |
ctx.putImageData(idat, 0, 0); | |
gBrowser.contentDocument.documentElement.appendChild(can); | |
gdk2.close(); | |
libc.close(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment