js:破解/生成验证码基础--2d二维码点生成/处理

来源:互联网 发布:php 反射机制 编辑:程序博客网 时间:2024/05/24 05:25

js:破解/生成验证码基础--2d二维码点生成/处理 - qidizi - qidizi 的博客

----------------------------分析----------

对于黑白图片(去噪点,多色二色转换),可以通过xy坐标点获取像素二值化(黑0白1)组成二维点;比较即可判别字

预先生成的二维点码可以规则变动生成2d变形,3d图片(1点凸起)

 

-------------- 制作字码的页面代码---------


<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
.tab {
    border-collapse:collapse  ;
    border-spacing:0px;
    background-color:black;
}
.tab tr div{
    width:7px;
    height:7px;
    display:block;
    background-color:buttonface;
}
.tab tr, .tab tr td {
    padding:0px;
    margin:0px;
}
.tab tr div.pain {
    background-color:red;
}
.num3 {
    width:30px;
}
#showFontDiv{
    padding-top:100px;
}
</style>
</head>
<body>
<div>字元描绘板<br/>
    点粒度<a href="#1" onclick="chTdPx(-1);">-</a><input value="10" id="tdPx" class="num3" /><a href="#1" onclick="chTdPx(+1);">+</a>
    <a href="#1" onclick="clearTable();">清空</a>
</div>
<div id="fontTableDiv"></div>
    
    <input type="checkbox" id="cutLeftOn" />切左边
    <input type="checkbox" id="cutTopOn" />切上边
    <input type="checkbox" id="cutRightOn" />切右边
    <input type="checkbox" id="cutBottomOn" />切下边
    
    <br/>
    <input type="checkbox" id="widthOn" />拉宽倍数
    <a href="#1" onclick="chNum(-1, 'widths', 1);">-</a>
    <input value="2" id="widths"  class="num3" />
    <a href="#1" onclick="chNum(+1, 'widths', 1);">+</a>
    
    <br/>
    <input type="checkbox" id="heightOn" />拉高倍数
    <a href="#1" onclick="chNum(-1, 'heights', 1);">-</a>
    <input value="2" id="heights"  class="num3" />
    <a href="#1" onclick="chNum(+1, 'heights', 1);">+</a>
    
    <br/>
    <input type="checkbox" id="phpOn" />输出php数组代码
    <br/>
    <a href="#1" onclick="showFont()">应用效果并显示字符</a>
<div id="showFontDiv"></div>
<script>
showTable(24);

/*
 * 改变字表点大小
 */
function chTdPx(how) {
    getObj('tdPx').value = getObj('tdPx').value * 1 + how * 1;
    
    if (getObj('tdPx').value < 1) {
        getObj('tdPx').value = 1;
    }
    
    var px = getObj('tdPx').value;
    forTd(
        function(td) {
            td.firstChild.style.width = px + 'px';
            td.firstChild.style.height = px + 'px';
        }
    );
}

/*
 * 改变数字大小
 */
function chNum(how, id, min, max) {
    getObj(id).value = getObj(id).value * 1 + how * 1;
    
    if (getObj(id).value < min) {
        getObj(id).value = min;
    } else if (getObj(id).value > max) {
        getObj(id).value = max;
    }
    
}

/*
 * 循环所有的td回调某个方法
 */
function forTd(func) {
    var rows = getObj('fontTable').rows;
    var rl = rows.length;
    var cl = rows[0].cells.length;

    for (var r = 0; r < rl; r++) {
        for (var c = 0; c < cl; c++) {
            func(rows[r].cells[c], r, c);
        }
    }
}

/*
 * 清空字点
 */
function clearTable() {
    forTd(
        function(td, r, c) {
            td.firstChild.className = '';
            window.font2d[r][c] = 0;
        }
    );
}

function showTable(count) {    
    getObj('fontTableDiv').innerHTML = tableHtml(count);
}

/*
 * 画像素正方形表
 */
function tableHtml(count) {
    var tab = '<table class="tab" title="点击反选,再次点击还原" id="fontTable">';
    window.font2d = [];
    
    for (var r = 0; r < count; r++) {//行
        tab += '<tr>';
        var tmp = [];
        
        for (var c = 0; c < count; c++) {//列
            tab += '<td><div onclick="divPain(this, ' + r + ', ' + c + ');"></div></td>';
            tmp.push(0);
        }
        
        window.font2d.push(tmp);
        tab += '</tr>';
    }
    
    tab += '</table>';
    return tab;
}

/*
 * 画中的方块
 */
function divPain(obj, row, cell) {    
    if (obj.className == 'pain') {
        obj.className = '';
        window.font2d[row][cell] = 0;
    } else {
        obj.className = 'pain';
        window.font2d[row][cell] = 1;
    }
}

/*
 * 记忆点阵非空点
 * 非空点可以不记忆,自动补充成方块
 * 且切割只保留最小的高宽
 */
function showFont() {
    if (fontEmpty()) {
        return alert('字元为空');
    }
    
    var font2dTmp = doCut(window.font2d);
    font2dTmp = doWidths(font2dTmp);
    font2dTmp = doHeights(font2dTmp);
    getObj('showFontDiv').innerHTML = num2Div(font2dTmp);
}

/*
 * 检测字元二维数组是否为空
 */
function fontEmpty() {
    if (! window.font2d) {
        return true;
    }
    
    var rl = window.font2d.length;
    var cl = window.font2d[0].length;
    
    for (var r = 0; r < rl; r++) {
        for (var c = 0; c < cl; c++) {
            if (window.font2d[r][c]) {
                return false;
            }
        }
    }
    
    return true;
}

/*
 * 数字转成二色块
 */
function num2Div(font) {

    var php = '';
    var div = [];
    
    for (var r = 0; r < font.length; r++) {
        var tmp = [];
        
        for (var c = 0; c < font[0].length; c++) {
            var ch = font[r][c];
            php += ch;
            tmp.push(ch ? '<span style="color:red;">' + ch + '</span>' : ch);
        }
        
        div.push(tmp.join(''));
    }
        
    if (getObj('phpOn').checked) {        
        prompt('复制使用', "'' => array(" + font[0].length + ", '" + php + "')");//把01串转成数字,为了保持位数,必须在前面加1,使用时记得去1
    }
    
    return div.join('<br/>');
}

/*
 * 处理切边
 */
function doCut(font) {
    if (! getObj('cutTopOn').checked && ! getObj('cutLeftOn').checked && ! getObj('cutBottomOn').checked && ! getObj('cutRightOn').checked) {
        return font;
    }
    
    var top = getObj('cutTopOn').checked ? getTop(font) : 0;
    var left = getObj('cutLeftOn').checked ? getLeft(font) : 0;
    var bottom = getObj('cutBottomOn').checked ? getBottom(font) : font.length - 1;
    var right = getObj('cutRightOn').checked ? getRight(font) : font[0].length - 1;
    
    var tmp = [];
    
    for (var r = top; r <= bottom; r++) {//只取非空的左到右列
        var tmpC = [];
        
        for(var c = left; c <= right; c++) {//只保留从上到下的非空行
            tmpC.push(font[r][c]);
        }
        
        tmp.push(tmpC);
    }
    
    return tmp;
}

/*
 * 移除上边空白
 * 全空,返回false,使用===检测
 */
function getTop(font) {
    for (var r = 0; r < font.length; r++) {//上切
        for (var c = 0; c < font[0].length; c++) {//检查是否整行都空,就切除
            if (font[r][c]) return r;//返回非空首行
        }
    }
    
    return false;
}

/*
 * 移除左边空白
 * 全空,返回false,使用===检测
 */
function getLeft(font) {
    for (var c = 0; c < font[0].length; c++) {//左切
        for (var r = 0; r < font.length; r++) {//检查是否整行都空,就切除
            if (font[r][c]) return c;//返回非空首列
        }
    }
    
    return false;
}

/*
 * 移除下边空白
 * 全空,返回false,使用===检测
 */
function getBottom(font) {
    for (var r = font.length - 1; r >= 0 ; r--) {//下切
        for (var c = 0; c < font[0].length; c++) {//检查是否整行都空,就切除
            if (font[r][c]) return r;//返回非空尾列
        }
    }
    
    return false;
}

/*
 * 移除右边空白
 * 全空,返回false,使用===检测
 */
function getRight(font) {
    for (var c = font[0].length - 1; c >= 0 ; c--) {//右切
        for (var r = 0; r < font.length; r++) {//检查是否整列都空,就切除
            if (font[r][c]) return c;//返回非空右列
        }
    }
    
    return false;
}

/*
 * 插算拉宽
 */
function doWidths(font) {
    if (! getObj('widthOn').checked || (getObj('widths').value < 1) ) {
        return font;
    }
    
    var times = getObj('widths').value * 1;
    var tmp = [];
    
    for (var r = 0; r < font.length; r++) {
        var tmpC = [];
        
        for (var c = 0; c < font[0].length; c++) {
            for (var l = 0; l < times; l++) {
                tmpC.push(font[r][c]);//复制多次
            }
        }
        
        tmp.push(tmpC);
    }
    
    return tmp;
}

/*
 * 插算拉高
 */
function doHeights(font) {
    var times = getObj('heights').value * 1;
    
    if (! getObj('heightOn').checked || (times < 1) ) {
        return font;
    }
    
    var tmp = [];
    
    for (var r = 0; r < font.length; r++) {
        for (var l = 0; l < times; l++) {//行复制n次
            var tmpC = [];
            
            for (var c = 0; c < font[0].length; c++) {
                    tmpC.push(font[r][c]);//复制多次
            }
            
            tmp.push(tmpC);
        }
    }
    
    return tmp;
}

function getObj(id) {
    return document.getElementById(id);
}
</script>
</body>
</html>

原创粉丝点击