失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > java 生成纯色图片_canvas简单实现纯色背景图片抠图(示例代码)

java 生成纯色图片_canvas简单实现纯色背景图片抠图(示例代码)

时间:2019-06-16 15:10:29

相关推荐

java 生成纯色图片_canvas简单实现纯色背景图片抠图(示例代码)

最近在研究html5 canvas的过程中,发现,canvas为前端对图像的处理开辟了一条新的道路,canvas可以做到很多事情,甚至可以做个类似于PhotoShop的东西,曾经本人在一家软件工作就做类似的工作,可以看一下我之前开发的软件:

这个就是canvas实现的类似于Adobe Photoshop,足以见得canvas的强大之处!

本文就是抽出其中一个小的功能点,来简单聊聊canvas强大之处:我们来一步步实现一个简单的智能抠图功能:(具体的代码见我的github:monkeyWangs/Matting)

1.环境准备

本人采用ES6语法作为开发环境,选用webpack作为构建工具,于是乎,我们有了webpack.config.js

/**

* @author monkeyWang

*

*/

/* 引入操作路径模块和webpack */

var path = require(‘path‘);

var webpack = require(‘webpack‘);

module.exports = {

/* 输入文件 */

entry: ‘./src/index.js‘,

output: {

/* 输出目录,没有则新建 */

path: path.resolve(__dirname, ‘./dist‘),

/* 静态目录,可以直接从这里取文件 */

publicPath: ‘/dist/‘,

/* 文件名 */

filename: ‘matting.js‘

},

module: {

rules: [

/* 用babel来解析js文件并把es6的语法转换成浏览器认识的语法 */

{

test: /.js$/,

loader: ‘babel-loader‘,

/* 排除模块安装目录的文件 */

exclude: /node_modules/

}

]

}

}

这样变准备好了开发用的基本环境,接下来我们来实现具体的核心代码,为了方便起见,我的代码全写在了inde.js

2.代码实现

首选我们需要新建一个对象:

/**

* @author monkeywang

* Date: 17/3/30

*/

class Matting {

}

然后我们需要接受用户上传的图片文件:

class Matting {

/**

* 构造函数

* @param file

*/

constructor(file) {

this.file = file

}

}

再接着把图片文件转成base64格式,所以我们在类中建了一个createStream方法:

createStream() {

let reader = new FileReader()

let ext = this.file.name.substring(this.file.name.lastIndexOf(".") + 1).toLowerCase()

if (ext != ‘png‘ && ext != ‘jpg‘ && ext != ‘jpeg‘) {

alert("图片的格式必须为png或者jpg或者jpeg格式!")

return

}

reader.onload = (e) => {

let src = e.target.result

let img = new Image()

img.src = src

let w = img.width

let h = img.height

this.fitch(w, h, img)

}

reader.readAsDataURL(this.file)

}

然后,开始我们的抠图逻辑代码之前,先描述一下我的思想:颜色属性其实是由RGBA四个元素组成的,RGB,代表三基色,A代表透明度,当A的值为0,则表示这个颜色是纯透明的,所以我们的主要逻辑就是把背景色设置为透明就好了。

创建一个canvas画布,然后把图片放到这个画布中,接着取这个图片上下左右四个点的像素,接下来要扣除这个图片的背景,那么,就需要去对整个图片的像素点颜色和背景色之前的区别,如果颜色相同,则把这个颜色的透明度设置成0

fitch(width, height, img) {

let dataUrl

let c = document.createElement("canvas")

c.width = width

c.height = height

let ctx = c.getContext("2d")

ctx.drawImage(img, 0, 0)

/**

* 取图片四个脚边的像素点rgba

* @type {*}

*/

let tl = Array.prototype.slice.call(ctx.getImageData(0, 0, 1, 1).data).join(‘,‘)

let tr = Array.prototype.slice.call(ctx.getImageData(width - 1, 0, 1, 1).data).join(‘,‘)

let br = Array.prototype.slice.call(ctx.getImageData(width - 1, height - 1, 1, 1).data).join(‘,‘)

let bl = Array.prototype.slice.call(ctx.getImageData(0, height - 1, 1, 1).data).join(‘,‘)

let imgdata = [tl, tr, bl, br] // 四个取色点

let selfImageData = [] // 当前rgba

imgdata.sort()

// 目前只支持纯色背景抠图,简单的判断是否为纯色

let deferNum = this.unique(imgdata).length

if (deferNum <= 1) {

{

selfImageData = imgdata[1].split(",") // 设置要扣除的主题色

let isPNG = true // 判断是否已经扣过

let imgDataUrl = ctx.getImageData(0, 0, width, height) //获取像素点

let data = imgDataUrl.data

for (let i = 0; i < data.length; i += 4) {

// 得到 RGBA 通道的值

let r = data[i]

let g = data[i + 1]

let b = data[i + 2]

/**

* function 判断颜色是不是属于背景色

* @param numerical

* @param index

* @returns {boolean}

*/

let isIn = (numerical, index) => {

if (selfImageData[3] == 0) {

isPNG = false

return false

}

return numerical > parseInt(selfImageData[index]) && numerical < parseInt(selfImageData[index])// 去掉边缘色

}

if ([r, g, b].every(isIn)) {

data[i + 3] = 0 // 设置背景透明

}

}

// 将修改后的代码复制回画布中

ctx.putImageData(imgDataUrl, 0, 0)

dataUrl = c.toDataURL("image/png")

if (isPNG) {

/**

* 创建下载链接 进行图片下载

* @type {Element}

*/

let a = document.createElement(‘a‘)

a.href = dataUrl //下载图片

a.download = ‘未命名.png‘

a.click()

}

else {

alert(‘背景已抠除!‘)

}

}

}

else {

alert(‘只支持纯色背景抠图!‘)

}

}

然后我们测试一下效果:创建index.html

Title

开始抠图

function matting() {

var file = document.getElementById(‘file‘).files[0];

var mat = new Matting(file);

mat.createStream();

}

然后我们选择一个纯色背景图

抠图后,我们看看:

确实完成了抠图。

当然实现算法还不是很完善,主要是为了给大家展示canvas的无限可能,当然我也在逐步优化算法中,使得图片抠图更加完美,更加智能,也欢迎大家的star, pullrequest

如果觉得《java 生成纯色图片_canvas简单实现纯色背景图片抠图(示例代码)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。