【问题标题】:How can I take a window screenshot in Node.js?如何在 Node.js 中截取窗口截图?
【发布时间】:2017-08-19 13:32:23
【问题描述】:

我正在研究寻找一种使用 Node.js 截取窗口屏幕截图的方法,并且我正在尝试使用 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 上执行此操作,

谁能帮帮我?

【问题讨论】:

标签: javascript node.js npm user32 node-ffi


【解决方案1】:

您可以使用名为“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");
});

https://www.npmjs.com/package/desktop-screenshot

【讨论】:

  • 但我需要一个窗口而不是整个桌面的屏幕截图。
  • 使用 desktop-screenshot 截取桌面,然后使用 node-easyimage 裁剪图像 github.com/hacksparrow/node-easyimage>,或者,由于 easyimage 需要 imagemagick,所以直接使用 child_process 调用 imagemagick:它已经内置了截图在。
  • 我想创建一个特定窗口区域的屏幕截图,该区域不在前台。任何可以做到这一点的nodejs包?
  • 没有。没有。没有。
  • 是的,但是没有这个模块,他的问题是什么。
【解决方案2】:

虽然我没有完整的代码工作,但理论上如果你能够在 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"*/);

【讨论】:

  • 评论稍后参考这个,关于如何将简单的 C 实用程序移植到节点的非常好的答案。
【解决方案3】:

还有一个替代的 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
    });
})

【讨论】:

    【解决方案4】:

    如果您需要从 NodeJS 逐像素访问屏幕截图数据(并且不想先写入然后从磁盘读取),您可以使用我的 windows-ffi 包的 CaptureScreenshot 函数。

    用法:

    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,因为它通过 ffi-napi 使用 Windows API。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多