zoukankan      html  css  js  c++  java
  • 基于Canvas 实现图片转点阵图

    要实现什么##

    同事想做一张世界地图的背景图,但是网上找的图片都太low了。他想用那种密集的点阵组成的世界地图。作为程序员,想法当然是通过图片处理,识别像素点,然后生成新的图片。

    目标是这样的:

    实现思路##

    其实稍微想一下就很容易想明白:
    1. 获取图片数据
    2. 分析像素点,判断是不是空白 (每个像素点的rgb色值不是255或某个阈值: r<255 || g<255 || b<255),就替换成指定颜色像素点
    3. 把图片划分成像素块, 某一个像素块里空白面积小于 50%(看需求设定阈值),判断为填充点,否则变为透明。
    4. 重新绘制图片。

    不拘泥于语言,基本思路都是这样。下面是一个Canvas版本:

    <!DOCTYPE html>
    <html lang="zh-CN" class=" no-touch"><head>
    <head><title>Canvas 转点阵</title></head>
    <body>
    <img src="./timg.jpg" id='img' style="display:none;"  />
    <div id="container" style="1200px;height:1038px">
    <canvas id="cvs" width="1200" height="1038"></canvas>
    </div>
    <script type="text/javascript">
        // 判断像素块是否空白or像素覆盖
        function isCover(imgdata, width, x, y) {
            var covered = 0;
            // 像素快为 8*8 
            for (var i=x; i<x+8; i++) {
                for (var j=y; j<y+8; j++) {
                    var idx = i*4*width + 4*j;
                    // 阈值设为192
                    if (imgdata[idx]<192 || imgdata[idx+1]<192 || imgdata[idx+2]<192 ) {
                        covered++;
                    }
                    // 覆盖面积超过 45/64
                    if (covered > 45) {
                        return true;
                    }
                }
            }
            return false;
        }
    
        // 填充像素块
        function drawPoints(imgdata, width, x, y, clear=false) {
            for (var i=x; i<x+8; i++) {
                for (var j=y; j<y+8; j++) {
                    var idx = i*4*width + 4*j;
                    if (i >=x+2 && i<x+6 && j>=y+2 && j<y+6 && !clear) {
                        // 画小方块
                        imgdata[idx] = 168;
                        imgdata[idx+1] = 168;
                        imgdata[idx+2] = 168;
                        imgdata[idx+3] = 192;
                    } else {
                        // 置为空白
                        imgdata[idx] = 255;
                        imgdata[idx+1] = 255;
                        imgdata[idx+2] = 255;
                        imgdata[idx+3] = 0;
                    }
                }
            }
            return imgdata;
        }
        
        // 点阵转换
        function convertPointArray(img) {
            for (var i=0; i<img.height; i=i+8) {
                for (var j=0; j<img.width; j=j+8) {
                    var isCovered = isCover(img.data, img.width, i, j);
                    if (isCovered) {
                        img.data = drawPoints(img.data, img.width, i, j);
                    } else {
                        // 其他区域直接清空
                        img.data = drawPoints(img.data, img.width, i, j, true);
                    }
                }
            }
            return img;
        }
        
        function _init() {
            var cvs = document.getElementById('cvs'),
                ctx = cvs.getContext('2d'),
                img = new Image();
            img = document.getElementById('img');
            img.crossOrigin = "*";
            img.onload = function() {
                // 把图片放到canvas 画布上
                ctx.drawImage(img, 0, 0, cvs.width, cvs.height);
                // 获取像素数据
                var imageData = ctx.getImageData(0, 0, cvs.width, cvs.height);
                // 转换
                imageData = convertPointArray(imageData);
                // 擦除原来的图片
                ctx.clearRect(0, 0, cvs.width, cvs.height);
                // 重新绘图
                ctx.putImageData(imageData, 0, 0);
            }
        }
        
        _init();
    </script>
    </body>
    </html>
  • 相关阅读:
    roughViz 一个可重用,功能强大的手绘图表组件
    sqlg rdbms 上实现的Apache TinkerPop
    golang 几个好用的cli package
    ent 基本使用十九 事务处理
    oracle查看表空间和物理文件大小
    Oracle备份的几种方式
    Oracle导出/导入数据库的三种模式
    Oracle 11g 数据库 expdp/impdp 全量导入导出
    Oracle查询数据库中所有表的记录数
    oracle 如何查看当前用户的表空间名称
  • 原文地址:https://www.cnblogs.com/dapianzi/p/7505275.html
Copyright © 2011-2022 走看看