本文介绍了有没有一种可能的方式来创建一个firefox扩展的整个屏幕截图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



然而,我目前的屏幕截图只包含实际的网页,没有其他的东西(没有地址栏等),我想知道是否有可能通过编程实现整个屏幕(任务栏和整个浏览器窗口等)的屏幕截图。

解决方案

Firefox没有这个功能。您可以通过使用操作系统功能。但是,这并不简单。无论如何,我需要这个代码的Windows API,所以它来了。首先,您需要设置库,函数和数据类型:
$ b

Components.utils.import ( 资源://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}
]);
$ b $ var GetDC = userlib.declare(
GetDC,ctypes.winapi_abi,
HDC,
HWND
);

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

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

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
);

现在有趣的部分:

  //我们要复制的屏幕部分
var x = 0;
var y = 0;
var width = screen.width;
var height = screen.height;

//为数据创建位图/设备上下文
var screenDC = GetDC(null);
var dc = CreateCompatibleDC(screenDC);
var bitmap = CreateCompatibleBitmap(screenDC,width,height);

//将屏幕内容复制到位图
SelectObject(dc,bitmap);
BitBlt(dc,0,0,width,height,screenDC,x,y,SRCCOPY);

//提取位图数据
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);

//清理
ReleaseDC(null,screenDC);
DeleteObject(dc);
DeleteObject(bitmap);

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

//将数据绘制到画布
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 {
// Windows位图从下到上存储,它们也使用BGR0
//而不是RGBA。数据需要在这里纠正。
var offset1 = i * width * 4;
var offset2 =(height - 1 - i)* width * 4; (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 ++中编写相同的东西,这会稍微简单一些。


I'm currently creating screenshots with JavaScript using canvas and encoding them in base64.

However, my current screenshots only include the actual web page and nothing else (no address bar, etc.) and I'd like to know if it is possible to achieve a screenshot of the whole screen (taskbar, and the whole browser window, etc.) programmatically.

解决方案

Firefox doesn't have this functionality. The best you can do is using operating system functions via js-ctypes. However, it isn't quite simple. I needed this code for the Windows API anyway so here it comes. First you need to set up the libraries, functions and data types:

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
);

And now the interesting part:

// 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);

For other operating systems you would need entirely different code of course. The alternative would be packaging a specialized DLL with your extension and using it via js-ctypes - this would allow writing the same thing in C++, that would be slightly simpler.

这篇关于有没有一种可能的方式来创建一个firefox扩展的整个屏幕截图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-14 17:27