3

我目前正在使用画布使用 JavaScript 创建屏幕截图并将它们编码为 base64。

但是,我目前的截图只包括实际的网页,没有其他内容(没有地址栏等),我想知道是否可以实现全屏截图(任务栏和整个浏览器窗口,等)以编程方式。

4

3 回答 3

4

Firefox 没有此功能。您可以做的最好的事情是通过js-ctypes使用操作系统功能。然而,这并不简单。无论如何,我需要 Windows API 的这段代码,所以它来了。首先,您需要设置库、函数和数据类型:

Components.utils.import("resource://gre/modules/ctypes.jsm");

var userlib = ctypes.open("user32");
var gdilib = ctypes.open("gdi32");

var HWND = ctypes.voidptr_t;
var HGDIOBJ = ctypes.voidptr_t;
var HDC = HGDIOBJ;
var HBITMAP = HGDIOBJ;
var LPCTSTR = ctypes.unsigned_char.ptr;
var WORD = ctypes.uint16_t;
var DWORD = ctypes.uint32_t;

var SRCCOPY = 0xCC0020;

var BITMAPCOREHEADER = ctypes.StructType("BITMAPCOREHEADER", [
  {bcSize: DWORD},
  {bcWidth: WORD},
  {bcHeight: WORD},
  {bcPlanes: WORD},
  {bcBitCount: WORD}
]);

var GetDC = userlib.declare(
  "GetDC", ctypes.winapi_abi,
  HDC,
  HWND
);

var ReleaseDC = userlib.declare(
  "ReleaseDC", ctypes.winapi_abi,
  ctypes.int,
  HWND, HDC
);

var CreateCompatibleDC = gdilib.declare(
  "CreateCompatibleDC", ctypes.winapi_abi,
  HDC,
  HDC
);

var CreateCompatibleBitmap = gdilib.declare(
  "CreateCompatibleBitmap", ctypes.winapi_abi,
  HBITMAP,
  HDC, ctypes.int, ctypes.int
);

var DeleteObject = gdilib.declare(
  "DeleteObject", ctypes.winapi_abi,
  ctypes.bool,
  HGDIOBJ
);

var SelectObject = gdilib.declare(
  "SelectObject", ctypes.winapi_abi,
  HGDIOBJ,
  HDC, HGDIOBJ
);

var BitBlt = gdilib.declare(
  "BitBlt", ctypes.winapi_abi,
  ctypes.bool,
  HDC, ctypes.int, ctypes.int, ctypes.int, ctypes.int,
  HDC, ctypes.int, ctypes.int, DWORD
);

var GetDIBits = gdilib.declare(
  "GetDIBits", ctypes.winapi_abi,
  ctypes.int,
  HDC, HBITMAP, ctypes.unsigned_int, ctypes.unsigned_int,
  ctypes.unsigned_char.ptr, BITMAPCOREHEADER.ptr, ctypes.unsigned_int
);

现在有趣的部分:

// The screen part we want to copy
var x = 0;
var y = 0;
var width = screen.width;
var height = screen.height;

// Create a bitmap/device context for the data
var screenDC = GetDC(null);
var dc = CreateCompatibleDC(screenDC);
var bitmap = CreateCompatibleBitmap(screenDC, width, height);

// Copy screen contents to bitmap
SelectObject(dc, bitmap);
BitBlt(dc, 0, 0, width, height, screenDC, x, y, SRCCOPY);

// Extract bitmap data
var bitmapHeader = new BITMAPCOREHEADER();
bitmapHeader.bcSize = BITMAPCOREHEADER.size;
bitmapHeader.bcWidth = width;
bitmapHeader.bcHeight = height;
bitmapHeader.bcPlanes = 1;
bitmapHeader.bcBitCount = 32;

var dataSize = width * height * 4;
var buffer = new ctypes.ArrayType(ctypes.unsigned_char, dataSize)();
GetDIBits(dc, bitmap, 0, height, buffer, bitmapHeader.address(), 0);

// Clean up
ReleaseDC(null, screenDC);
DeleteObject(dc);
DeleteObject(bitmap);

userlib.close();
gdilib.close();

// Draw data to the canvas
var canvas = document.getElementById("canvas");
canvas.setAttribute("width", width);
canvas.setAttribute("height", height);

var context = canvas.getContext("2d");
var imageData = context.createImageData(width, height);
for (var i = 0; i < height; i++)
{
  // Windows bitmaps are stored bottom-to-top, they are also using BGR0
  // byte order instead of RGBA. The data needs to be corrected here.
  var offset1 = i * width * 4;
  var offset2 = (height - 1 - i) * width * 4;
  for (var j = 0; j < width; j++)
  {
    imageData.data[offset1 + j * 4 + 0] = buffer[offset2 + j * 4 + 2];
    imageData.data[offset1 + j * 4 + 1] = buffer[offset2 + j * 4 + 1];
    imageData.data[offset1 + j * 4 + 2] = buffer[offset2 + j * 4 + 0];
    imageData.data[offset1 + j * 4 + 3] = 255;
  }
}
context.putImageData(imageData, 0, 0);

对于其他操作系统,您当然需要完全不同的代码。另一种方法是用你的扩展打包一个专门的 DLL 并通过 js-ctypes 使用它——这将允许用 C++ 编写相同的东西,这会稍微简单一些。

于 2012-04-18T17:01:54.713 回答
0

否 - 如评论所述的安全性。

您唯一能做的就是从文档信息(如 location.href)中获取您需要/可以获取的内容。将其作为可见信息添加到底部/顶部 => grap => 再次隐藏(如果用户应该继续工作)。

于 2012-04-18T13:28:07.177 回答
-1

首先按下shift+F2 它打开Firefox控制台..给出命令screenshot --fullpage并按Enter(对于整页)

screenshot(仅适用于可见部分)

您也可以通过转到工具-> Web 开发人员-> 开发人员工具栏来执行此操作

值得一试..最好没有扩展

于 2013-07-12T09:34:47.317 回答