如何在 Node.js 中拍摄 window 屏幕截图?
How can I take a window screenshot in Node.js?
我正在研究寻找一种方法来使用 Node.js 截取 window 的屏幕截图,我正在尝试使用 node-ffi 进行此操作,但我没有不知道怎么...一次我被困在这里:
var ffi = require('ffi');
var user32 = new ffi.Library("user32", {
FindWindowA: [ 'uint32' , [ 'string', 'string' ]]
, PrintWindow: [ 'int32' , [ 'int32', 'string', 'int32' ]]
});
var IMG;
var windowHandle = user32.FindWindowA(null, "Calculator");
var printWin = user32.PrintWindow(windowHandle, IMG, 0);
console.log(printWin);
console.log(IMG);
结果:
$ node get-print.js
1
undefined
已编辑
我在 C++ 中找到了以下工作代码
Bitmap bm = new Bitmap(1024, 768);
Graphics g = Graphics.FromImage(bm);
IntPtr hdc = g.GetHdc();
Form1.PrintWindow(this.Handle, hdc, 0);
g.ReleaseHdc(hdc);
g.Flush();
g.Dispose();
this.pictureBox1.Image = bm;
现在我需要在 NodeJs 上执行此操作,
谁能帮帮我?
您可以使用名为“desktop-screenshot”的 NPM 包。使用起来非常简单。
NPM 示例:
var screenshot = require('desktop-screenshot');
screenshot("screenshot.png", function(error, complete) {
if(error)
console.log("Screenshot failed", error);
else
console.log("Screenshot succeeded");
});
虽然我没有完整的代码工作,但理论上如果你能在 C++ 中这样做,那么只需使用 node-gyp 将 C++ 文件编译为 .node 文件,然后包括在你的 nodeJS 文件中。
所以一些示例伪代码,首先在一个新目录中创建一个 binding.gyp 文件,然后将一些代码放入其中:
{
"targets": [
{
"target_name": "addon",
"sources": [
"hi.cc"
]
}
]
}
然后在同一个目录中(暂时)创建另一个名为 hi.cc
的文件,并将您的 C++ 代码放入其中,再加上一些代码以从中创建一个节点模块。所以,根据上面提到的文档,你可以做这样的事情(未经测试):
/*don't know what includes you're using to git the Bitmap
and Graphics functions, but include them here */
/*then to make a node module*/
#include <node.h>
using namespace v8;
void GetImage(const FunctionCallbackInfi<Value>& args) {
Bitmap bm = new Bitmap(1024, 768);
Graphics g = Graphics.FromImage(bm);
IntPtr hdc = g.GetHdc();
Form1.PrintWindow(this.Handle, hdc, 0);
g.ReleaseHdc(hdc);
g.Flush();
/*
this is the key part, although I'm not
100% sure it will work since I don't
know exactly what type Graphics returns,
but basically just convert it somehow into
base64, or a plain old void* value
(as in this following example), then make a new
Local variable of it and set the return type
(or make a function callback). So first get the
Graphics variable into a void* of the data, then
convert it to an ArrayBuffer to use in NodeJS, based on this
answer. Anyway:
*/
Local<
ArrayBuffer
>
v =
ArrayBuffer::New(i, /*some void* value*/ temp, 5000/*or some length*/);
a.GetReturnValue().Set(v);
}
void Initialize(Local<Object> exports) {
NODE_SET_METHOD(exports, "hello", GetImage);
}
NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)
然后确保您确实安装了 node-gyp 和正确的构建工具(请参阅上面的文档,但它几乎 npm i -g node-gyp
),然后转到构建 -> 发布 -> addon.node并将其复制到您的主 nodeJS 目录,然后创建一个新的 nodeJS 文件或在现有文件中包含以下内容:
let addon = require("./addon"),
pictureData = Buffer.from(addon.hello()/* if you choose to return a base64 string instead, then insert: ,"base64"*/);
还有一个替代 Node.js 包目前仍在开发中(最后一次提交是 15 天前;与上面提到的包相比,后者最后一次提交是在 2015 年或 2016 年)。它允许选择它捕获的屏幕,而另一个似乎没有。
https://github.com/bencevans/screenshot-desktop
const screenshot = require('screenshot-desktop');
screenshot.listDisplays().then((displays) => {
// displays: [{ id, name }, { id, name }]
screenshot({ screen: displays[displays.length - 1].id })
.then((img) => {
// img: Buffer of screenshot of the last display
});
})
如果您需要从 NodeJS 逐像素访问屏幕截图数据(并且不想先写入再从磁盘读取),您可以使用我的 CaptureScreenshot
函数 windows-ffi包.
用法:
import {VRect, CaptureScreenshot, GetForegroundWindowHandle} from "windows-ffi";
// First capture a screenshot of a section of the screen.
const screenshot = CaptureScreenshot({
windowHandle: GetForegroundWindowHandle(), // comment to screenshot all windows
rectToCapture: new VRect(0, 0, 800, 600),
});
// The image-data is now stored in the `screenshot.buffer` Buffer object.
// Access it directly (and cheaply) using the helper functions on `screenshot`.
for (let x = 0; x < 800; x++) {
console.log(`Pixel color at [${x}, 0] is:`, screenshot.GetPixel(x, 0).ToHex_RGB());
}
当然,这仅适用于 Windows,因为它使用 Windows API,通过 ffi-napi。
我正在研究寻找一种方法来使用 Node.js 截取 window 的屏幕截图,我正在尝试使用 node-ffi 进行此操作,但我没有不知道怎么...一次我被困在这里:
var ffi = require('ffi');
var user32 = new ffi.Library("user32", {
FindWindowA: [ 'uint32' , [ 'string', 'string' ]]
, PrintWindow: [ 'int32' , [ 'int32', 'string', 'int32' ]]
});
var IMG;
var windowHandle = user32.FindWindowA(null, "Calculator");
var printWin = user32.PrintWindow(windowHandle, IMG, 0);
console.log(printWin);
console.log(IMG);
结果:
$ node get-print.js
1
undefined
已编辑
我在 C++ 中找到了以下工作代码
Bitmap bm = new Bitmap(1024, 768);
Graphics g = Graphics.FromImage(bm);
IntPtr hdc = g.GetHdc();
Form1.PrintWindow(this.Handle, hdc, 0);
g.ReleaseHdc(hdc);
g.Flush();
g.Dispose();
this.pictureBox1.Image = bm;
现在我需要在 NodeJs 上执行此操作,
谁能帮帮我?
您可以使用名为“desktop-screenshot”的 NPM 包。使用起来非常简单。
NPM 示例:
var screenshot = require('desktop-screenshot');
screenshot("screenshot.png", function(error, complete) {
if(error)
console.log("Screenshot failed", error);
else
console.log("Screenshot succeeded");
});
虽然我没有完整的代码工作,但理论上如果你能在 C++ 中这样做,那么只需使用 node-gyp 将 C++ 文件编译为 .node 文件,然后包括在你的 nodeJS 文件中。
所以一些示例伪代码,首先在一个新目录中创建一个 binding.gyp 文件,然后将一些代码放入其中:
{
"targets": [
{
"target_name": "addon",
"sources": [
"hi.cc"
]
}
]
}
然后在同一个目录中(暂时)创建另一个名为 hi.cc
的文件,并将您的 C++ 代码放入其中,再加上一些代码以从中创建一个节点模块。所以,根据上面提到的文档,你可以做这样的事情(未经测试):
/*don't know what includes you're using to git the Bitmap
and Graphics functions, but include them here */
/*then to make a node module*/
#include <node.h>
using namespace v8;
void GetImage(const FunctionCallbackInfi<Value>& args) {
Bitmap bm = new Bitmap(1024, 768);
Graphics g = Graphics.FromImage(bm);
IntPtr hdc = g.GetHdc();
Form1.PrintWindow(this.Handle, hdc, 0);
g.ReleaseHdc(hdc);
g.Flush();
/*
this is the key part, although I'm not
100% sure it will work since I don't
know exactly what type Graphics returns,
but basically just convert it somehow into
base64, or a plain old void* value
(as in this following example), then make a new
Local variable of it and set the return type
(or make a function callback). So first get the
Graphics variable into a void* of the data, then
convert it to an ArrayBuffer to use in NodeJS, based on this
answer. Anyway:
*/
Local<
ArrayBuffer
>
v =
ArrayBuffer::New(i, /*some void* value*/ temp, 5000/*or some length*/);
a.GetReturnValue().Set(v);
}
void Initialize(Local<Object> exports) {
NODE_SET_METHOD(exports, "hello", GetImage);
}
NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)
然后确保您确实安装了 node-gyp 和正确的构建工具(请参阅上面的文档,但它几乎 npm i -g node-gyp
),然后转到构建 -> 发布 -> addon.node并将其复制到您的主 nodeJS 目录,然后创建一个新的 nodeJS 文件或在现有文件中包含以下内容:
let addon = require("./addon"),
pictureData = Buffer.from(addon.hello()/* if you choose to return a base64 string instead, then insert: ,"base64"*/);
还有一个替代 Node.js 包目前仍在开发中(最后一次提交是 15 天前;与上面提到的包相比,后者最后一次提交是在 2015 年或 2016 年)。它允许选择它捕获的屏幕,而另一个似乎没有。
https://github.com/bencevans/screenshot-desktop
const screenshot = require('screenshot-desktop');
screenshot.listDisplays().then((displays) => {
// displays: [{ id, name }, { id, name }]
screenshot({ screen: displays[displays.length - 1].id })
.then((img) => {
// img: Buffer of screenshot of the last display
});
})
如果您需要从 NodeJS 逐像素访问屏幕截图数据(并且不想先写入再从磁盘读取),您可以使用我的 CaptureScreenshot
函数 windows-ffi包.
用法:
import {VRect, CaptureScreenshot, GetForegroundWindowHandle} from "windows-ffi";
// First capture a screenshot of a section of the screen.
const screenshot = CaptureScreenshot({
windowHandle: GetForegroundWindowHandle(), // comment to screenshot all windows
rectToCapture: new VRect(0, 0, 800, 600),
});
// The image-data is now stored in the `screenshot.buffer` Buffer object.
// Access it directly (and cheaply) using the helper functions on `screenshot`.
for (let x = 0; x < 800; x++) {
console.log(`Pixel color at [${x}, 0] is:`, screenshot.GetPixel(x, 0).ToHex_RGB());
}
当然,这仅适用于 Windows,因为它使用 Windows API,通过 ffi-napi。