使用 Canvas 获取照片上的红色印章

3,533 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

本文同时参与 「掘力星计划」  ,赢取创作大礼包,挑战创作激励金

前段时间整理了一下 Canvas 的方法和属性的使用现在项目中有个扣红色印章的需求于是写了一个小demo

实现抠取纸张上盖的红色印章,这个函数很简单,传入url,返回一个base64格式的印章图片,代码直接粘贴复制就 OK。

GTRS.convertToTransparent(url,callback);
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" id="viewportid" content="width=750,user-scalable=no" />
        <title></title>
    </head>
    <body style="background: aliceblue;font-size: 24px;">
        <h1>自动扣取图章</h1>
            <input type="file" id="upload" />
        </p>
        <div id="myCanvas">
            <img width="300" src="" id="show" />
        </div>
        <script>
            // 获取图片中的红色印章Get the Red Seal
            var GTRS = {
                // 预处理画布
                canvas: null,
                context: null,
                // 切割点位数组,顺序为开始和结束,
                cuttingPoint: [{x:0,y:0},{x:0,y:0}],
                // 设置范围判定值
                colorRange: 0,
                // 临时图片
                myImage: null,
                // 获取红色印章(只保留红色区间色彩)
                // 接受URL
                convertToTransparent: function(URL,callback) {
                    // 初始化画布
                    this.canvas = document.createElement("canvas");
                    this.context = this.canvas.getContext("2d");
                    let that=this;
                    this.myImage= new Image();
                    this.myImage.onload = function() {
                        that.canvas.width = that.myImage.width;
                        that.canvas.height = that.myImage.height;
                        that.context.drawImage(that.myImage, 0, 0);
                        that.setColorData();
                        that.exportSeal(callback);
                    }
                    this.myImage.src = URL;
                },
                // 输出处理后的图片到画布
                setColorData: function() {
                    // 像素点
                    let length = this.canvas.width * this.canvas.height;
                    // 获取所有色值,每个像素数4个值,R、G、B、A
                    this.myImage = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height);
                    for (let i = 0; i < length * 4; i += 4) {
                        let myRed = this.myImage.data[i];
                        let myGreen = this.myImage.data[i + 1];
                        let myBlue = this.myImage.data[i + 2];
                        if (!this.colorInRange(myRed, myGreen, myBlue)) {
                            this.myImage.data[i + 3] = 0;
                        }
                        if (this.myImage.data[i] > 70) {
                            this.myImage.data[i] = 230;
                        }
                    }
                    this.context.putImageData(this.myImage, 0, 0);
                },
                // *判断是否为红色,方法的核心部分,但是就这2行,还可能有点bug -_-
                colorInRange: function(red, green, blue) {
                    if (red >= this.colorRange && green >= this.colorRange && blue >= this.colorRange && ((red - green) > 20)) {
                        return true;
                    };
                    return false;
                },
                exportSeal: function(callback) {
                    // 获取所有像素
                    let length = this.canvas.width * this.canvas.height;
                    this.myImage = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height);
                    this.cuttingPoint[0].y = this.leftPoint(length, this.myImage);
                    this.cuttingPoint[0].x = this.topPoint(length, this.myImage);
                    this.cuttingPoint[1].y = this.bootomPoint(length, this.myImage);
                    this.cuttingPoint[1].x = this.rightPoint(length, this.myImage);
                    let image = new Image();
                    let that = this;
                    image.src = this.canvas.toDataURL("image/png");
                    image.onload = function() {
                        let canvas = document.createElement("canvas");
                        canvas.width = that.cuttingPoint[1].x - that.cuttingPoint[0].x;
                        canvas.height = that.cuttingPoint[1].y - that.cuttingPoint[0].y;
                        let context = canvas.getContext("2d");
                        context.drawImage(image, that.cuttingPoint[0].x, that.cuttingPoint[0].y, canvas.width, canvas.height, 0, 0,
                            canvas
                            .width, canvas.height);
                            if(callback){
                                callback(canvas.toDataURL());
                            }
                         
                    }
                },
                download: function(url) {
                    let a = document.createElement("a");
                    a.download = '';
                    a.href = url;
                    document.body.appendChild(a);
                    a.click();
                    a.remove();
                },
                // 切割开始点Y
                topPoint: function(length, myImage) {
                    for (let i = 0; i < this.canvas.width; i += 1) {
                        for (let j = 0; j < this.canvas.height; j++) {
                            let myRed = this.myImage.data[j * this.canvas.width * 4 + i * 4]
                            if (myRed >= 10) {
                                return i;
                            }
                        }
                    }
                },
                // 切割开始点X
                leftPoint: function(length, myImage) {
 
                    for (let i = 0; i < length * 4; i += 4) {
                        // 获取起点x
                        let myRed = this.myImage.data[i];
                        if (myRed >= 10) {
                            return Math.ceil(i / 4 / this.canvas.width);
                        }
                    }
                },
                // 切割结束点Y                  
                bootomPoint: function(length, myImage) {
                    for (let i = length * 4 - 4; i >= 4; i -= 4) {
                        let myRed = this.myImage.data[i];
                        if (myRed >= 10) {
                            return Math.ceil(i / 4 / this.canvas.width);
                        }
                    }
                },
                // 切割结束点X
                rightPoint: function(length, myImage) {
                    for (let i = this.canvas.width - 1; i > 0; i--) {
                        for (let j = this.canvas.height; j > 0; j--) {
                            let myRed = this.myImage.data[(this.canvas.height - j) * this.canvas.width * 4 + i * 4]
                            if (myRed >= 10) {
                                return i;
                            }
                        }
                    }
                }
            }
            document.getElementById('upload').addEventListener('change', function(event) {
                var reads = new FileReader();
                f = document.getElementById('upload').files[0];
                reads.readAsDataURL(f);
                reads.onload = function(e) {
                    GTRS.convertToTransparent(this.result,function(url){
                        document.getElementById('show').src=url;
                    });
                };
             
            });
        </script>
    </body>
</html>

点赞支持、手留余香、与有荣焉,动动你发财的小手哟,感谢各位大佬能留下您的足迹。

11.png

往期精彩推荐

前端常用的几种加密方法

canvas 爬坑路【方法篇】

不懂 seo 优化?一篇文章帮你了解如何去做 seo 优化

canvas 爬坑路【属性篇】

【实战篇】微信小程序开发指南和优化实践

聊一聊移动端适配

前端性能优化实战

聊聊让人头疼的正则表达式

获取文件blob流地址实现下载功能

Vue 虚拟 DOM 搞不懂?这篇文章帮你彻底搞定虚拟 DOM

Git 相关推荐

通俗易懂的 Git 入门

git 实现自动推送

面试相关推荐

前端万字面经——基础篇

前端万字面积——进阶篇

更多精彩详见:个人主页