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>
  • 相关阅读:
    PAT 甲级 1027 Colors in Mars
    PAT 甲级 1026 Table Tennis(模拟)
    PAT 甲级 1025 PAT Ranking
    PAT 甲级 1024 Palindromic Number
    PAT 甲级 1023 Have Fun with Numbers
    PAT 甲级 1021 Deepest Root (并查集,树的遍历)
    Java实现 蓝桥杯VIP 算法训练 无权最长链
    Java实现 蓝桥杯VIP 算法训练 无权最长链
    Java实现 蓝桥杯 算法提高 抽卡游戏
    Java实现 蓝桥杯 算法提高 抽卡游戏
  • 原文地址:https://www.cnblogs.com/dapianzi/p/7505275.html
Copyright © 2011-2022 走看看