惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Azure Blog
Microsoft Azure Blog
V
V2EX
博客园 - 【当耐特】
WordPress大学
WordPress大学
爱范儿
爱范儿
美团技术团队
宝玉的分享
宝玉的分享
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
小众软件
小众软件
量子位
Hugging Face - Blog
Hugging Face - Blog
B
Blog RSS Feed
Recorded Future
Recorded Future
Engineering at Meta
Engineering at Meta
雷峰网
雷峰网
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
M
MIT News - Artificial intelligence
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 聂微东
H
Hackread – Cybersecurity News, Data Breaches, AI and More
腾讯CDC
大猫的无限游戏
大猫的无限游戏
Jina AI
Jina AI
博客园 - 叶小钗
GbyAI
GbyAI
Y
Y Combinator Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
F
Full Disclosure
G
Google Developers Blog
D
Docker
T
Tailwind CSS Blog
C
Check Point Blog
Last Week in AI
Last Week in AI
人人都是产品经理
人人都是产品经理
T
The Blog of Author Tim Ferriss
B
Blog
博客园 - 三生石上(FineUI控件)
博客园 - Franky
H
Help Net Security
MyScale Blog
MyScale Blog
U
Unit 42
D
DataBreaches.Net
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
I
InfoQ
阮一峰的网络日志
阮一峰的网络日志
The GitHub Blog
The GitHub Blog
L
LangChain Blog
有赞技术团队
有赞技术团队
Martin Fowler
Martin Fowler
Microsoft Security Blog
Microsoft Security Blog

张鑫旭-鑫空间-鑫生活

1分钟速度了解text-align match-parent声明 « 张鑫旭-鑫空间-鑫生活 光标的形状也能设置了,就是CSS caret-shape属性 « 张鑫旭-鑫空间-鑫生活 pretext与文字四面环绕效果的实现 « 张鑫旭-鑫空间-鑫生活 JSON.rawJSON方法的作用是什么? « 张鑫旭-鑫空间-鑫生活 如何使用CSS判断鼠标从哪个方向进入元素? « 张鑫旭-鑫空间-鑫生活 借助mediabunny纯JS实现视频水印、剪裁、合成等功能 « 张鑫旭-鑫空间-鑫生活 务必谨慎使用JS WeakRef弱引用 « 张鑫旭-鑫空间-鑫生活 CSS六边形头像的实现与蜂巢布局 « 张鑫旭-鑫空间-鑫生活 CSS corner-shape与背景底纹技术 « 张鑫旭-鑫空间-鑫生活 浅学WebTransport API:下一代Web双向通信技术 « 张鑫旭-鑫空间-鑫生活 HTML dialog元素新支持了closedBy属性 « 张鑫旭-鑫空间-鑫生活 HTML interestfor属性与悬停popover交互效果 « 张鑫旭-鑫空间-鑫生活 CSS3模拟window7炫酷界面效果展示 « 张鑫旭-鑫空间-鑫生活 图片旋转+剪裁js插件(兼容各浏览器) « 张鑫旭-鑫空间-鑫生活 纯js无图片无外链CSS图片幻灯片播放插件 « 张鑫旭-鑫空间-鑫生活 CSS border三角、圆角图形生成技术简介 « 张鑫旭-鑫空间-鑫生活 CSS “渐进增强”在web制作中常见应用举例 « 张鑫旭-鑫空间-鑫生活 让IE6/IE7/IE8浏览器支持CSS3属性 « 张鑫旭-鑫空间-鑫生活 jQuery – 高亮动态显示页面HTML代码插件 « 张鑫旭-鑫空间-鑫生活 翻译 – 逐渐消失的Flash网站 « 张鑫旭-鑫空间-鑫生活 CSS reset的重新审视 – 避免样式重置 « 张鑫旭-鑫空间-鑫生活 新浪微博插入话题后部分文字选中的js实现 « 张鑫旭-鑫空间-鑫生活 JavaScript实现http地址自动检测并添加URL链接 « 张鑫旭-鑫空间-鑫生活 CSS实现兼容性的渐变背景(gradient)效果 « 张鑫旭-鑫空间-鑫生活 CSS content内容生成技术以及应用 « 张鑫旭-鑫空间-鑫生活 CSS gradient渐变之webkit核心浏览器下的使用 « 张鑫旭-鑫空间-鑫生活 CSS渐变之CSS3 gradient在Firefox3.6下的使用 « 张鑫旭-鑫空间-鑫生活 区分IE8/IE7/IE6及其他浏览器-CSS “\9″hack « 张鑫旭-鑫空间-鑫生活 CSS实现跨浏览器兼容性的盒阴影效果 « 张鑫旭-鑫空间-鑫生活 CSS3&HTML5各浏览器支持情况一览表 « 张鑫旭-鑫空间-鑫生活 翻译 – CSS Sprites:实用技术还是生厌之物? « 张鑫旭-鑫空间-鑫生活 纯CSS实现易拉罐3D滚动效果 « 张鑫旭-鑫空间-鑫生活 纯CSS实现侧边栏/分栏高度自动相等 « 张鑫旭-鑫空间-鑫生活 CSS+JavaScript实现页面不同布局的切换 « 张鑫旭-鑫空间-鑫生活 JavaScript实现最简单的拖拽效果 « 张鑫旭-鑫空间-鑫生活 自己写的无图片版jQuery zxxbox弹出框插件 « 张鑫旭-鑫空间-鑫生活 中国古代道家思想与网页重构的思考 « 张鑫旭-鑫空间-鑫生活 让所有浏览器支持HTML5 video视频标签 « 张鑫旭-鑫空间-鑫生活 纯CSS实现各类气球泡泡对话框效果 « 张鑫旭-鑫空间-鑫生活 JS HEX十六进制与RGB, HSL颜色的相互转换 « 张鑫旭-鑫空间-鑫生活 CSS实现兼容性的渐变、高光等文字效果 « 张鑫旭-鑫空间-鑫生活 去除冗余 – 精简您的CSS样式代码 « 张鑫旭-鑫空间-鑫生活 对overflow与zoom”清除浮动”的一些认识 « 张鑫旭-鑫空间-鑫生活 jQuery Pagination Ajax分页插件中文详解 « 张鑫旭-鑫空间-鑫生活 absolute绝对定位的非绝对定位用法 « 张鑫旭-鑫空间-鑫生活 网页布局思想浅议-淘宝新版首页为实例 « 张鑫旭-鑫空间-鑫生活 回流与重绘:CSS性能让JavaScript变慢? « 张鑫旭-鑫空间-鑫生活 CSS float浮动的深入研究、详解及拓展(二) « 张鑫旭-鑫空间-鑫生活 CSS float浮动的深入研究、详解及拓展(一) « 张鑫旭-鑫空间-鑫生活 60个极富创造性的震撼的电影海报设计 « 张鑫旭-鑫空间-鑫生活 jQuery Lightbox(balupton版)图片展示插件讲解 « 张鑫旭-鑫空间-鑫生活 博客内嵌flash音乐播放器代码、下载与使用 « 张鑫旭-鑫空间-鑫生活 CSS3 animate实现图片墙3D翻转效果 « 张鑫旭-鑫空间-鑫生活 图片旋转效果的一些研究、jQuery插件及实例 « 张鑫旭-鑫空间-鑫生活 CSS3 border-image详解、应用及jQuery插件 « 张鑫旭-鑫空间-鑫生活 jQuery-两款不同原理的圆角插件讲解 « 张鑫旭-鑫空间-鑫生活 页面可用性之outline轮廓外框的一些研究 « 张鑫旭-鑫空间-鑫生活 CSS3 transition实现超酷图片墙动画效果 « 张鑫旭-鑫空间-鑫生活 HTML CSS列表元素ul,ol,dl的研究与应用 « 张鑫旭-鑫空间-鑫生活 jQuery图片文本滚动切换插件jCarousel中文翻译与详解 « 张鑫旭-鑫空间-鑫生活 酷酷的jQuery鼠标悬停图片放大切换显示效果 « 张鑫旭-鑫空间-鑫生活 IE6下z-index犯癫不起作用bug的初步研究 « 张鑫旭-鑫空间-鑫生活 checkbox复选框的一些深入研究与理解 « 张鑫旭-鑫空间-鑫生活 jQuery之使用slideToggle实现垂直下拉菜单 « 张鑫旭-鑫空间-鑫生活 jQuery-innerfade内部列表自动淡入淡出插件 « 张鑫旭-鑫空间-鑫生活 jQuery-火焰灯效果导航菜单 « 张鑫旭-鑫空间-鑫生活 IE下css bug集合-翻译自haslayout.net « 张鑫旭-鑫空间-鑫生活 翻译-IE7/8@font-face嵌入字体与文字平滑 « 张鑫旭-鑫空间-鑫生活 jQuery-马化腾产品设计与用户体验的一些技术实现 « 张鑫旭-鑫空间-鑫生活 像素的世界及其在web开发制作中的应用 « 张鑫旭-鑫空间-鑫生活 css行高line-height的一些深入理解及应用 « 张鑫旭-鑫空间-鑫生活 CSS实现圆角六色渐变自适应按钮详解 « 张鑫旭-鑫空间-鑫生活 我熟知的三种三栏网页宽度自适应布局方法 « 张鑫旭-鑫空间-鑫生活 jQuery照片图像剪裁插件Jcrop中文翻译详解 « 张鑫旭-鑫空间-鑫生活 Ajax Upload多文件上传插件翻译及中文演示 « 张鑫旭-鑫空间-鑫生活 告别图片—使用字符实现兼容性的圆角尖角效果beta版 « 张鑫旭-鑫空间-鑫生活 大小不固定的图片、多行文字的水平垂直居中 « 张鑫旭-鑫空间-鑫生活 jQuery boxy弹出层对话框插件中文演示及讲解 « 张鑫旭-鑫空间-鑫生活 JavaScript实现新浪微博文字放大显示动画效果 « 张鑫旭-鑫空间-鑫生活 翻译:让网络更快一些——最小化浏览器中的回流(reflow) « 张鑫旭-鑫空间-鑫生活 jQuery之addClasas与removeClass使用实例 « 张鑫旭-鑫空间-鑫生活 关于Google圆角高光高宽自适应按钮及其拓展 « 张鑫旭-鑫空间-鑫生活 JavaScript实现图片幻灯片滚动播放动画效果 « 张鑫旭-鑫空间-鑫生活 jQuery-鼠标经过显示大图并跟随鼠标效果插件 « 张鑫旭-鑫空间-鑫生活 关于gif图片(或png8)杂边锯齿的问题 « 张鑫旭-鑫空间-鑫生活 对html与body的一些研究与理解 « 张鑫旭-鑫空间-鑫生活 鲜为人知的一个解决兼容性问题的利器——小数 « 张鑫旭-鑫空间-鑫生活 搜狐白社会似iphone短信对话框效果的优化 « 张鑫旭-鑫空间-鑫生活 关于文字内容溢出用点点点(…)省略号表示 « 张鑫旭-鑫空间-鑫生活 jquery之append与insertBefore使用实例 « 张鑫旭-鑫空间-鑫生活 jQuery之图片关联伸缩效果 « 张鑫旭-鑫空间-鑫生活 jquery之图片左右切换动画效果 « 张鑫旭-鑫空间-鑫生活 jQuery之replace字符串替换实现不同尺寸图片切换 « 张鑫旭-鑫空间-鑫生活 jQuery-实现图片的放大镜显示效果 « 张鑫旭-鑫空间-鑫生活 jQuery-单击文字或图片内容放大显示效果插件 « 张鑫旭-鑫空间-鑫生活 reflection.js-实现图片投影倒影效果js插件 « 张鑫旭-鑫空间-鑫生活 jQuery-很酷的弹出层效果js插件 « 张鑫旭-鑫空间-鑫生活 复选框单选框与文字对齐问题的研究与解决 « 张鑫旭-鑫空间-鑫生活 css margin的相关属性,问题及应用 « 张鑫旭-鑫空间-鑫生活 IE6下png背景不透明问题的综合拓展 « 张鑫旭-鑫空间-鑫生活
JS检测PNG图片是否有透明背景、抠图等相关处理 « 张鑫旭-鑫空间-鑫生活
张鑫旭,zhangxinxu · 2018-05-01 · via 张鑫旭-鑫空间-鑫生活

by zhangxinxu from http://www.zhangxinxu.com/wordpress/?p=7510
本文可全文转载,但需要保留原作者和出处,摘要引流则随意。

一、JS检测PNG图片是否有透明背景

用户上传图片,如果是PNG图片,有时候我们希望这张PNG图片背景不要是透明的,例如:

  1. 后端保存图片时候常常会转成JPG格式的,此时,如果后端同学不加以判断和处理,则透明区域会变成黑色,影响体验;

    例如,下面canvas将PNG图强制转换成JPG后的对比效果:

    透明背景转jpg格式后变黑

    您可以狠狠地点击这里:PNG透明背景转JPG后变黑demo

  2. 轮播广告的后台,为了显示质量,后台往往是直接存图,保留原格式。这样就有这样一个问题,如果广告图是上下层叠定位的,此时如果某个广告图编辑传的是部分区域透明度的图,前端又没有考虑到这种场景则显示就会出现问题,透出了下面一张图糟糕的体验问题;

有时候,我们又希望上传的PNG图片带透明的,例如:

  1. 某平台可以自定义菜单,允许用户编辑文字和上传图标,很显然,这个图标需要是透明背景的,否则可能UI会很糟糕;
  2. QQ邮箱域名邮箱可以自定义logo和主题,如果上传的域名logo图片背景不是透明的,主题背景颜色也不一样,同样会出现比较糟糕的UI,如下截图:

    自定义logo和背景不相符合

以上这些场景的处理通常这样的:

  • PNG背景透明区域变黑色 -> 后端黑色用白色代替;
  • 广告图镂空 -> CSS给<img>元素设置个背景色:
    img { background-color: #fff; }

    但,如果图片源用在多个地方,则此方法很难罩住所有场景。

  • 上传图标需透明 -> 忽略,交给用户
  • 上传logo需透明 -> 忽略,交给用户

实际上,以上所有的处理都可以在上传图片的时候由前端一次性解决。

分两步:

  • 前端获取上传图片信息(包括图片类型,图片数据),IE10+
  • JS检测图片是否有透明背景,IE9+

我们先看demo,您可以狠狠地点击这里:png图片是否含有透明像素JS检测demo

如果是不含透明色的PNG图片,则会提示不含透明;如果是,则提示含透明,如下截图:

是否背景透明的检测

检测原理是借助canvas的getImageData()方法,关于此方法具体API和使用,可以参见“canvas getImageData与任意字符图形点、线动效”这篇文章“像素点信息获取”这里的详细介绍。

一句话概括就是getImageData()方法可以获取canvas画布上每一个像素点的颜色信息,于是,我们只要把上传的图片绘制在canvas上,然后检测有没有透明的像素点信息即可。

相关检测JS代码如下(完整代码参见demo页面):

// 图片绘制在画布上
context.drawImage(img, 0, 0);
// 获取图片像素信息
var imageData = context.getImageData(0, 0, width, height).data;
// 检测有没有透明数据
var isAlphaBackground = false;
for (var index = 3; index &lt; imageData.length; index += 4) {
    if (imageData[index] != 255) {
        isAlphaBackground = true;
        break;    
    }
}
// isAlphaBackground就是最后石头有透明或半透明背景色的结果

上面imageData就是我们获取的图片像素信息数组,是个一维数组,类型为Uint8ClampedArray,也就是数组中所有的值范围都是0~255,数组信息这样:

[R,G,B,A,R,G,B,A,R,G,B,A,R,G,B,A,R,G,B,A,R,G,B,A,...]

因此,我们只要判断数组中的A是否全部都是255就可以判断有没有透明信息了,一个for循环就搞定了。

如果图片尺寸很大
demo页面旨在演示,如果图片尺寸很大,按照demo页面的处理,可能会比较耗时间,我们可以在把canvas画布进行尺寸限制,也就是图片尺寸压缩,这个不会影响对是否有透明背景的判断,具体操作和代码可以参见这篇文章:“canvas实现图片前端JS压缩并上传”。

背景透明与否的实际处理

如果站在解决实际问题的角度,判断是否背景透明并不一定要得到。

  1. 对于不需要透明背景的处理,我们可以直接使用canvas补一个背景色,无论图片是不是透明的都不需要判断。操作如下:
    1. canvas绘制一个底色,通常是白色:
      context.fillStyle = '#ffffff';
      context.fillRect(0, 0, canvas.width, canvas.height);
    2. 绘制图片:
      context.drawImage(img, 0, 0);
    3. 上传canvas图片(转换成base64后者blob数据都可以),canvas.toDataURL(file.type)或者canvas.toBlob(callback, file.type)
  • 如果是需要PNG背景图片,则我们就可以先进行前端检测,然后:
    • 简单的处理是直接提示用户,“您上传图片为实色背景,最终效果可能不好看,确认继续?”
    • 更好的处理则是发现用户上传图片不是透明PNG图,则立即弹出个小窗口,在线背景去色就好了!于是自然引出了下一部分内容,如何实现图片的简易抠图(背景透明)效果?
  • 二、实现一个简易的图片背景去色效果

    图片去色网上很多在线的工具,有些还很厉害,例如clippingmagic,但,这东西是别人的,且我们不需要这么复杂交互,就算代码爬过来也没什么用,还是自己写写功能更实在。

    好在,如果只是想实现一个不太复杂的图片背景色去色效果,还是挺容易的。

    实现的关键依然是getImageData()方法,去色,然后把相似颜色变成透明颜色就可以了。

    您可以狠狠地点击这里:借助canvas实现图片背景色去色demo

    例如,我们点击左边图片的白色区域,然后设置容差值是20,点击“执行去色”按钮,结果如下截图:

    图片背景去色变透明效果截图

    如果我们选择紫色,则效果是:

    紫色去色后的效果截图

    实现原理

    关键2个步骤,一是取色,二是去色。

    1. 取色的实现

    根据点击坐标,取当前点击位置像素点颜色值信息即可,代码如下:

    canvas.addEventListener('click', function (event) {
        var rect = this.getBoundingClientRect();
        var x = event.clientX - rect.left;
        var y = event.clientY - rect.top;
        // rgbaPicker就是点击像素点的颜色信息
        rgbaPicker = context.getImageData(x, y, 1, 1).data;
    });

    2. 去色的实现

    去色则是替换getImageData()的一些像素点色值为透明即可,这个不难,难的是如何判别两种色值是相似的呢?

    这里有个简易的颜色色值相似度计算算法:

    similar = Math.sqrt((r2 - r1) * (r2 - r1) + (g2 - g1) * (g2 - g1) + (b2 - b1) * (b2 - b1))

    其中,r2,r1表示RGB中的红色red,g2,g1表示RGB中的绿色green,b2,b1表示RGB中的蓝色blue。

    OK,有了相似度算法,下面就是简单的色值替换处理了:

    // 像素点色值
    var rgba = rgbaPicker;
    // 容差大小
    var tolerance = eleTolerance.value;
    // 基于原始图片数据处理,
    // 其中:
    // imgData是左图像素信息,
    // imgDataResult是右图处理后的像素信息
    for (var index = 0; index &lt; imgData.data.length; index += 4) {
        var r = imgData.data[index];
        var g = imgData.data[index + 1];
        var b = imgData.data[index + 2];
        
        if (Math.sqrt(
            (r - rgba[0]) * (r - rgba[0]) + 
            (g - rgba[1]) * (g - rgba[1]) + 
            (b - rgba[2]) * (b - rgba[2])) <= tolerance
        ) {
            imgDataResult.data[index] = 0;
            imgDataResult.data[index + 1] = 0;
            imgDataResult.data[index + 2] = 0;
            imgDataResult.data[index + 3] = 0;
        } else {
            imgDataResult.data[index] = r;
            imgDataResult.data[index + 1] = g;
            imgDataResult.data[index + 2] = b;
            imgDataResult.data[index + 3] = imgData.data[index + 3];
        }
    }
    // put数据
    contextResult.putImageData(imgDataResult, 0, 0);

    点睛代码就是最后的putImageData(),可以让画布使用新数据进行图像呈现,就可以看到去色后的效果了。

    以上JS为片段截取,如果看不透彻,可以前往demo页面查看完整的源代码,未压缩,就在页面上,简洁明了无干扰,非常适合学习。

    代码采用MIT协议,可以随意复制,商业亦可,但需要保留代码顶部的作者和原出处版权说明。所有代码都是自己键盘一个一个敲出来的,尊重辛勤劳动,尊重代码使用授权协议,共建和谐社会。如果发现都是删掉协议说明的拿来主义,我想我会考虑使用付费。

    其他说明

    这里的去色效果是最简单的去色效果了,其实标准的去色功能,还需要一个“连续”还是“不连续”的勾选功能。

    但是,对于图标和logo这些去色需求,当前的整体去色应该足够,“连续”功能有兴趣的小伙伴可以自己尝试实现下,考验连续区域算法。

    三、结束语

    本文第一段“检测透明”,和第二段“去色变透明”本来计划是两篇文章的,因为以前很多文章好多好东西都整在一个文章里,结果很容易就湮没了,无人问津,甚是可惜;加上文章篇幅变得很长,大家又都很忙,没有那么多耐心通读长文,也很容易错过稀缺优质内容。

    但是写着写着还是控制不住自己的手,还是合在了一起,其实我也不明白我的执念在哪里!虽然分开总体阅读类肯定比一篇要多,搜索效果也更好,PV数据也会好看些,这个月发文文章数量也会上去,但是,一想到要分开变成两篇也不错的文章,我就心里难受,难道是跟洁癖一样的心理疾病——“文章大而全合体综合征”,无法放弃去完美品质文章的追求。

    忽略眼前利益的极致追求,或许是自己印刻在骨子里的特质吧,也是自己能够成长到现在这个样子的原因所在。

    感谢阅读,欢迎交流!

    本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
    本文地址:http://www.zhangxinxu.com/wordpress/?p=7510

    (本篇完)