Quantcast
Channel: CNode:Node.js专业中文社区
Viewing all articles
Browse latest Browse all 14821

彻底跨平台,Node.js高效生成验证码,我自己用纯js实现了一个图形模块

$
0
0

都说用Nodejs来生成验证码效率很低下,但有时候你仍然想用node来生成验证码

百度搜索.jpg点开百度搜索结果的第一条,找到三个模块: 1.node-canvas 2.node-gyp 3.ccap 看描述,这些无一例外需要安装其它支持库(C或C++编写,平台兼容性极差) 我个人认为一切需要安装额外支持库的模块都是耍流氓!搜索结果比较多的是CCAP, 而ccap的介绍: https://cnodejs.org/topic/50f90d8edf9e9fcc58a5ee0b在提到性能时,是这样写的: 在2cpu的linux 64位服务器上生成验证码速度可以达到1200次/秒,测试生成的图片是BMP的,jpeg的图片验证码生成速度大约在600次/秒。 也仅仅达到1200次/秒

为什么需要完全用js来实现图形模块?在node本身没有提供图形库的情况下,只有完全用js编写的图形库能做到在任何平台上运行的效果一致,实测,我的模块可以在openwrt路由器上完美运行!我测试了另外一款全js实现的验证码生成模块(图形操作很有限,没有画点、线等一些基本功能,甚至颜色设置也很差) captchapng 在我的电脑上测试:(node版本4.4.4,32位CPU双核2.0G主频) 按照所给的demo,生成的是80x30的验证码,900张/秒 而我的生成的是100x40的验证码,可以达到2400张/秒 captchapng测试.jpg在openwrt路由器上测试:(只有完全用js编写的模块可以在路由器上运行!ccap之类的是绝对无法运行的) 同样的代码 captchapng是7张/秒 我的模块也是7张/秒 路由器的型号是TP-WR841N V10,硬改内存64M,CPU超频到850M,node版本4.4.5 之所以说ccap之类的是绝对无法运行,因为路由器的node运行环境非常极端!内存极少,CPU指令与电脑是完全不同的 所以依赖C/C++支持的模块是无法运行的!甚至代码量过大的js程序也无法运行,例如使用npm安装express,由于express需要依赖太多其它模块,导致npm的运行没有足够的内存

以下是我对captchapng的测试代码 png.js

var http = require('http');
var captchapng = require('captchapng');
//captchapng版本 0.0.1

function getImg(){
	    var p = new captchapng(80,30,parseInt(Math.random()*9000+1000)); // width,height,numeric captcha
        p.color(0, 0, 0, 0);  // First color: background (red, green, blue, alpha)
        p.color(80, 80, 80, 255); // Second color: paint (red, green, blue, alpha)

        var img = p.getBase64();
        var imgbase64 = new Buffer(img,'base64');
		return imgbase64;
}

var start = new Date().getTime();
var i = 0;
while((new Date().getTime() - start) < 1000){
    var img = getImg();
    i++;
}
console.log("1秒钟生成:" + i);


http.createServer(function (request, response) {
        response.writeHead(200, {
            'Content-Type': 'image/png'
        });
		var img = getImg();
        response.end(img);

}).listen(8080);

console.log('Web server started.');

好了,现在来介绍一下我花了两天时间编写的“图形库”

字符图形测试: 字符测试.jpg验证码: 验证码1.jpg验证码2.jpg匆忙做出来的,样子很难看,图片大小和百度云网盘登录的验证码是一样的,都是100x40 其实我编写的是一个只能操作24位bmp图片的“图形库”,大家都知道bmp图片是没有压缩的, 所以文件大小必定会比jpg,gif,png之类的大,但是,对于验证码仅仅100x40的图片来说仅仅11.7K,微不足道! 况且,用Js来编写操作这些格式的程序太过复杂。 实测在我的电脑上可以达到2400张/秒的优秀成绩(我的电脑是32位 CPU双核2G主频) 假如去除上面验证码中的正弦曲线,可以达到6500张/秒! 假如同时去除字符和正弦曲线只保留画圆、画线、画空心矩形和实心矩形,可以达到12000张/秒!

安装

npm install zengming 我个人的测试模块,呵呵,有时间再把这个"图形库"拆分出来

测试代码 bmp.js

var http = require('http');
var fs = require('fs');
var z = require('zengming');
var BMP24 = z.BMP24;
var font = z.Font;

/*
 用PCtoLCD2002取字模
 行列式扫描,正向取模(高位在前)
 */
var cnfonts = {//自定义字模
    w : 16,
    h : 16,
    fonts: "中国",
    data : [
        [0x01,0x01,0x01,0x01,0x3F,0x21,0x21,0x21,0x21,0x21,0x3F,0x21,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0xF8,0x08,0x08,0x08,0x08,0x08,0xF8,0x08,0x00,0x00,0x00,0x00],/*"中",0*/
        [0x00,0x7F,0x40,0x40,0x5F,0x41,0x41,0x4F,0x41,0x41,0x41,0x5F,0x40,0x40,0x7F,0x40,0x00,0xFC,0x04,0x04,0xF4,0x04,0x04,0xE4,0x04,0x44,0x24,0xF4,0x04,0x04,0xFC,0x04],/*"国",1*/
        ]
};

function makeImg2() {
    var img = new BMP24(300,140);
    img.drawString('helloworld', 20,10, font.font8x16, 0xff0000);
    img.drawString('helloworld', 20,25, font.font12x24, 0x00ff00);
    img.drawString('helloworld', 20,50, font.font16x32, 0x0000ff);
    img.drawString('中国', 20,85, cnfonts, 0xffffff);
    return img;
}

function makeCapcha() {
    var img = new BMP24(100, 40);
    img.drawCircle(11, 11, 10, z.rand(0, 0xffffff));
    img.drawRect(0, 0, img.w-1, img.h-1, z.rand(0, 0xffffff));
    img.fillRect(53, 15, 88, 35, z.rand(0, 0xffffff));
    img.drawLine(50, 6, 3, 60, z.rand(0, 0xffffff));
    //return img;

    //画曲线
    var w=img.w/2;
    var h=img.h;
    var color = z.rand(0, 0xffffff);
    var y1=z.rand(-5,5); //Y轴位置调整
    var w2=z.rand(10,15); //数值越小频率越高
    var h3=z.rand(4,6); //数值越小幅度越大
    var bl = z.rand(1,5);
    for(var i=-w; i<w; i+=0.1) {
        var y = Math.floor(h/h3*Math.sin(i/w2)+h/2+y1);
        var x = Math.floor(i+w);
        for(var j=0; j<bl; j++){
            img.drawPoint(x, y+j, color);
        }
    }

    var p = "ABCDEFGHIJKLMNOPQRSTUVWXYZ3456789";
    var str = '';
    for(var i=0; i<5; i++){
        str += p.charAt(Math.random() * p.length |0);
    }

    var fonts = [font.font8x16, font.font12x24, font.font16x32];
    var x = 15, y=8;
    for(var i=0; i<str.length; i++){
        var f = fonts[Math.random() * fonts.length |0];
        y = 8 + z.rand(-10, 10);
        img.drawChar(str[i], x, y, f, z.rand(0, 0xffffff));
        x += f.w + z.rand(2, 8);
    }
    return img;
}



var start = new Date().getTime();
var i = 0;
while((new Date().getTime() - start) < 1000){
    //var img = makeCapcha();
    var img = makeImg2();
    i++;
}
console.log("1秒钟生成:" + i);


var src = "C:/Users/Administrator/Desktop/Camera/1121.bmp";
var dst = "C:/Users/Administrator/Desktop/Camera/test.bmp";

http.createServer(function (req,res) {
    console.time("bmp24");
    var img = makeCapcha();
    console.timeEnd("bmp24");

    res.setHeader('Content-Type', 'image/bmp');
    res.end(img.getFileData());

}).listen(8080);

以上的代码集成了此模块的所有功能,特别说明一下,字符的显示借鉴了单片机的字符显示程序 所以字符是完全可以自定义的,你可以用取字模的软件自己生成字库, 我用的是PCtoLCD2002取字模, 行列式扫描,正向取模(高位在前) 程序已经内置了三种规格的字体,仅包含大小写字母和数字

API,非常简洁、强大、优雅、风骚、时尚、前无古人后无来者

//获得对象的两种方式: //构造函数,创建指定宽高的图片对象(初始化为一张全黑的图片) new BMP24(w, h)

从文件加载bmp 注意!必需确保文件是24位bmp 参数:文件路径 , cb(err, BMP24) BMP24.loadFromFile(filename, cb)


//获取BMP整个文件数据 obj.getFileData()

//画点, RGB颜色值(例如红色0xff0000) obj.drawPoint(x, y, rgb)

//画线 obj.drawLine(x1, y1, x2, y2, rgb)

//画矩形&实心矩形 obj.drawRect(x1, y1, x2, y2, rgb) obj.fillRect(x1, y1, x2, y2, rgb)

//画圆 obj.drawCircle(x, y, r, rgb)

//画字符&字符串,font参数为字库,color为RGB颜色值(例如红色0xff0000) obj.drawChar(ch, x, y, font, color) obj.drawString(str, x, y, font, color)


Viewing all articles
Browse latest Browse all 14821

Trending Articles