使用canvas去除图片透明部分

Posted sohu前端

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用canvas去除图片透明部分相关的知识,希望对你有一定的参考价值。

接上篇


上篇使用canvas将一张大图切割成了多个异形小图片,但遗留了一个问题: 虽然图片看起来只剩一个小图了,但其实四周遗留了大量透明部分。


如下面这个大图为420*320像素

我们采用上篇那种方式自动截取中间一小段106*163像素的小图,得到下面这样一个图,中间那个小图其实才是需要的(为了看起来更清晰,我给页面加了个背景),所以其实得到的图片还是420*320像素,只是在小图位置透明度不为0,其他地方都为0,接下来要作的就是剪裁掉透明部分,真正变成一个小图。

使用canvas去除图片透明部分

熟悉图像或者颜色的人应该都知道,从rgb角度来看,png图片的每个像素点都是由4部分:red、green、blue、alpha,alpha就是透明度,完全透明为0,完全不透明为255,半透明介于二者之间的一个值。如果一个图像是10*10像素,那其实就是100组rgba的值。

使用canvas去除图片透明部分

这样就很容易想到,判断每一行的所有像素点是不是透明的,如果都透明那就把这一行删掉,直到有一行哪怕有一个点不透明,我们就知道是时候该结束了。从上下左右四个方便分别做这样一个处理,那透明部分就全部被去掉留下一个真正的小图。

把上面的思路优化一下,就是找到4个边界:上、下、左,右,以这四个点为边界取出其中所有像素点重新做一张图就可以了。

使用canvas去除图片透明部分

思路清晰了,下面进行具体的实践,canvas的getImageData方法可以得到图像的所有像素点,但它是一个一维的,即下图所示,也就是数组每4项组成一个像素点。看起来很容易蒙,虽然不影响裁剪的进行,但演示起来可能不太容易懂。

使用canvas去除图片透明部分

为了演示方便,我们首先把它转为每个像素点是一个数组项的一维数组,这样数组的总长度为原来的4分之1。然后把它转化为二维的,二维数组的每一项的值为那一行所有的像素点,转化之后为

使用canvas去除图片透明部分

下面为具体实现方法

使用canvas去除图片透明部分

转化为二维数组之后就简单了,分别从数组第1项和最后1项分别查找上边界和下边界,即只要alpha不为0就马上终止,说明这行是有图像的。上面的方法是查找上下边界,查找左右边界的方法略有不同,即二维数组length为图像宽,每一项的length为图像高,且数组项值的为列的索引*宽,如二维数组第一项为[0*420, 1*420, 2*420..........320*420 ],具体实现这里就不再多说。


下面为如何查找非透明像素行的实现

使用canvas去除图片透明部分

得到了四个边界之后,要做的就简单了,就是通过这些边界过滤出真正是图像的像素点,实现策略为使用上、下边界取出所有有不透明点的行,然后再从这些行中使用左右边界取出所有不透明点的列。

使用canvas去除图片透明部分

接下里得到就是一个真正的需要的小图的点了,把他重新绘制到canvas,改变canvas的宽高即可。具体实现为首先使用createImageData创建一个宽为rightBoundary - leftBoundary高为bottomBoundary-topBoundary的像素对象,然后把刚才得到那些值设置给它,然后再使用putImageData绘制即可。

好了,下面就是最终得到的小图,程序总算完美了。图像的处理非常的有意思,后续的篇章会讲一些自动提取图像主题色同样拥有实用价值的内容,欢迎继续关注。


以上是关于使用canvas去除图片透明部分的主要内容,如果未能解决你的问题,请参考以下文章

canvas将图片转成base64格式 以及 验证图片是否透明

图片处理(缩放去除)

HTML5中如何设置画布canvas中用drawImage画出来的每个图片不同的透明度?

为啥用ps 做的透明画布的图片 一打开就白底了 ? 跟格式有关吗

[读码时间] 图片列表:鼠标移入/移出改变图片透明度

ps怎么保存透明图片