本书的第2章介绍了在将数据移动到C++插件时使用典型的JavaScript数据类型。Node.js 引入了一种新的数据类型, `Buffer`,这在标准JavaScript中是找不到的(尽管新版本的JavaScript现在已经有了类型化数组,它们提供了许多相同的功能)。 Node.js缓冲区对象用来表示原始的二进制数据,类似于C++数组(在本例中是整数数组)。当你使用 Node.js输入/输出或TCP的时候,您可能会使用 `Buffer` 对象。虽然将 `Buffer` 对象转换成JavaScript字符串是很常见的(通过指定整数数据的编码),但通常情况下,您可能希望直接在二进制数据上操作。
Buffer
对象是C++addon开发的一个有趣的方面,首先因为它们实际上不是V8的一部分,而是node.js的一部分。其次, Buffer
对象数据是惟一的,因为它没有在V8堆中分配——这一属性可以让我们在处理C++插件和工作线程时避开一些数据复制(下面将对此进行讨论)。
在本节中,我们将讨论如何使用NAN将 Buffer
对象传递给C++插件。之所以使用NAN,是因为Buffer
对象API最近发生了一些重大变化,而NAN将保护我们免受这些问题的影响。我们将通过图像转换器来观察 Buffer
o对象——特别是将二进制png图像数据转换成位图格式的二进制数据。
这一节的所有代码都可以在”Buffers” 部分下的 nodecpp-demo
存储库中完整地提供。在https://github.com/freezer333/nodecpp-demo中。
例子:PNG and BMP 转换
图像处理,一般来说,是任何操纵/转换图像的东西。当然,图像是二进制数据的一大块——在它最基本的状态中,一个整数(或3或4)可以用来表示图像中的每个像素,这些整数可以存储在一个文件中,或者保存在一个连续分配的数组中。通常,图像数据不是以原始数据形式保存的,而是将其压缩/编码成图像格式标准,如png、gif、bmp、jpeg等。
图像处理是C++插件的一个很好的候选,因为图像处理通常是耗时的,CPU密集型的,并且一些处理技术具有C++可以利用的并行性。对于我们现在要看的例子,我们将简单地将png格式的数据转换成bmp格式的数据。有很多现成的、开放源码的C++库可以帮助我们完成这项任务,我将使用 LodePNG
,因为它是免费的,而且非常简单易用。 LodePNG
可以在http://lodev.org/lodepng/中找到,它的源代码在https://github.com/lvande/LodePNG。非常感谢开发者,Lode Vandevenne提供了这样一个易于使用的库!
[1] 从png转换成bmp并不特别费时,对于addon来说可能有点太过了,但它对于演示来说是很好的。如果您正在寻找图像处理的纯JavaScript实现(包括远多于png到bmp转换),请查看JIMP https://www.npmjs.com/package/jimphttps://www.npmjs.com/package/jimp 。
addon
对于这个addon,我们将创建以下目录结构,其中包括从https://github.com/lvande/lodepng下载的源代码,也就是lodepng.h
和 lodepng.cpp
。
/png2bmp
|
|--- binding.gyp
|--- package.json
|--- png2bmp.cpp # the addon
|--- index.js # program to test the addon
|--- sample.png # input (will be converted to bmp)
|--- lodepng.h # from lodepng distribution
|--- lodepng.cpp # From loadpng distribution
要下载完整的addon,请转到https://github.com/freezer333/nodecpp-demo,这个特殊的例子在 buffers
目录中。
lodepng.cpp
包含了进行图像处理的所有必要代码,我将不讨论它的细节。此外,lodepng发行版包含了一些示例代码,允许您在png和bmp之间进行特定的转换——我已经稍微修改了它,并将其放入addon源代码文件 png2bmp.cpp
,我们很快就会看一看。让我们首先看看实际的JavaScript程序是什么样子的——在深入研究addon代码之前:
'use strict';
const fs = require('fs');
const path = require('path');
const png2bmp = require('./build/Release/png2bmp');
var png_file = process.argv[2];
var bmp_file = path.basename(png_file, '.png') + ".bmp";
var png_buffer = fs.readFileSync(png_file);
png2bmp.saveBMP(bmp_file, png_buffer, png_buffer.length);
这个程序只需要fs
、path
和addon,它将位于 ./build/Releast/png2bmp
。程序从命令行参数中获取一个输入(png)文件名,并将png读取到Buffer中。然后,它将 Buffer
送入addon,它将转换后的BMP保存到指定的文件名中。因此,addon将png转换为BMP,并将结果保存到一个文件中——不返回任何东西。
package.json
,它设置npm start调用 index.js
程序带有一个命令行参数的 sample.png
.。这是一个很普通的图片:
{
"name": "png2bmp",
"version": "0.0.1",
"private": true,
"gypfile": true,
"scripts": {
"start": "node index.js sample.png"
},
"dependencies": {
"nan": "*"
}
}
最后,让我们看一看 binding.gyp
文件——这是相当标准的