最近在工作遇到一个问题,在将png图片转jpeg时,透明区域被填充成黑色,通过网上的介绍找到了解决的方法,现在总结下分享给同样遇到这个问题的朋友们,感兴趣的可以通过本文详细学习下。

在用canvas将png图片转jpeg时,发现透明区域被填充成黑色。

代码如下:

XML/HTML Code复制内容到剪贴板
  1. <p>Canvas:</p>
  2. <canvas id="canvas" style="border: 1px solid #ccc;"></canvas>
  3. <br>
  4. <p>Base64转码后的图片:</p>
  5. <div id="base64Img"></div>
  6. <script type="text/javascript">
  7. var base64Img = document.getElementById("base64Img"),
  8. canvas = document.getElementById("canvas"),
  9. context = canvas.getContext("2d");
  10. // 创建新图片
  11. var img = new Image();
  12. img.src = "1.png";
  13. img.addEventListener("load", function() {
  14. // 绘制图片到canvas上
  15. canvas.width = img.width;
  16. canvas.height = img.height;
  17. context.drawImage(img, 0, 0);
  18. getBase64(canvas, function(dataUrl) {
  19. // 展示base64位的图片
  20. var newImg = document.createElement("img");
  21. newImg.src = dataUrl;
  22. base64Img.appendChild(newImg);
  23. });
  24. }, false);
  25. // 获取canvas的base64图片的dataURL(图片格式为image/jpeg)
  26. function getBase64(canvas, callback) {
  27. var dataURL = canvas.toDataURL("image/jpeg");
  28. if(typeof callback !== undefined) {
  29. callback(dataURL);
  30. }
  31. }
  32. </script>

效果如下:

为什么canvas会png的透明区域转成黑色呢?

canvas转换成jpeg之前移除alpha通道,所以透明区域被填充成了黑色。

但是,我们希望的是,canvas可以将png的透明区域填充成白色。

那么怎么将canvas中的透明区域填充成白色呢?

以下是我实践过的两种解决方案,希望对你有帮助。

解决方案一:将透明的pixel设成白色

因为png图片的背景都是透明的,所以我们可以寻找透明的pixel,然后将其全部设置成白色,核心代码如下:

JavaScript Code复制内容到剪贴板
  1. // 将canvas的透明背景设置成白色
  2. var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
  3. for(var i = 0; i < imageData.data.length; i += 4) {
  4. // 当该像素是透明的,则设置成白色
  5. if(imageData.data[i + 3] == 0) {
  6. imageData.data[i] = 255;
  7. imageData.data[i + 1] = 255;
  8. imageData.data[i + 2] = 255;
  9. imageData.data[i + 3] = 255;
  10. }
  11. }
  12. context.putImageData(imageData, 0, 0);

完整代码如下:

XML/HTML Code复制内容到剪贴板
  1. <p>Canvas:</p>
  2. <canvas id="canvas" style="border: 1px solid #ccc;"></canvas>
  3. <br>
  4. <p>Base64转码后的图片:</p>
  5. <div id="base64Img"></div>
  6. <script type="text/javascript">
  7. var base64Img = document.getElementById("base64Img"),
  8. canvas = document.getElementById("canvas"),
  9. context = canvas.getContext("2d");
  10. // 创建新图片
  11. var img = new Image();
  12. img.src = "1.png";
  13. img.addEventListener("load", function() {
  14. // 绘制图片到canvas上
  15. canvas.width = img.width;
  16. canvas.height = img.height;
  17. context.drawImage(img, 0, 0);
  18. // 将canvas的透明背景设置成白色
  19. var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
  20. for(var i = 0; i < imageData.data.length; i += 4) {
  21. // 当该像素是透明的,则设置成白色
  22. if(imageData.data[i + 3] == 0) {
  23. imageData.data[i] = 255;
  24. imageData.data[i + 1] = 255;
  25. imageData.data[i + 2] = 255;
  26. imageData.data[i + 3] = 255;
  27. }
  28. }
  29. context.putImageData(imageData, 0, 0);
  30. // 展示base64位的图片
  31. getBase64(canvas, function(dataUrl) {
  32. var newImg = document.createElement("img");
  33. newImg.src = dataUrl;
  34. base64Img.appendChild(newImg);
  35. });
  36. }, false);
  37. // 获取canvas的base64图片的dataURL(图片格式为image/jpeg)
  38. function getBase64(canvas, callback) {
  39. var dataURL = canvas.toDataURL("image/jpeg");
  40. if(typeof callback !== undefined) {
  41. callback(dataURL);
  42. }
  43. }
  44. </script>

效果如下:

缺点显而易见。当png图片上存在半透明区域时,会将其填充为黑色。这是我们不希望的。

解决方案二:在canvas绘制前填充白色背景

核心代码如下:

JavaScript Code复制内容到剪贴板
  1. // 在canvas绘制前填充白色背景
  2. context.fillStyle = "#fff";
  3. context.fillRect(0, 0, canvas.width, canvas.height);

完整代码如下:

XML/HTML Code复制内容到剪贴板
  1. <p>Canvas:</p>
  2. <canvas id="canvas" style="border: 1px solid #ccc;"></canvas>
  3. <br>
  4. <p>Base64转码后的图片:</p>
  5. <div id="base64Img"></div>
  6. <script type="text/javascript">
  7. var base64Img = document.getElementById("base64Img"),
  8. canvas = document.getElementById("canvas"),
  9. context = canvas.getContext("2d");
  10. // 创建新图片
  11. var img = new Image();
  12. img.src = "1.png";
  13. img.addEventListener("load", function() {
  14. // 绘制图片到canvas上
  15. canvas.width = img.width;
  16. canvas.height = img.height;
  17. // 在canvas绘制前填充白色背景
  18. context.fillStyle = "#fff";
  19. context.fillRect(0, 0, canvas.width, canvas.height);
  20. context.drawImage(img, 0, 0);
  21. // 展示base64位的图片
  22. getBase64(canvas, function(dataUrl) {
  23. var newImg = document.createElement("img");
  24. newImg.src = dataUrl;
  25. base64Img.appendChild(newImg);
  26. });
  27. }, false);
  28. // 获取canvas的base64图片的dataURL(图片格式为image/jpeg)
  29. function getBase64(canvas, callback) {
  30. var dataURL = canvas.toDataURL("image/jpeg");
  31. if(typeof callback !== undefined) {
  32. callback(dataURL);
  33. }
  34. }
  35. </script>

效果如下:

Perfect!

显然,在canvas绘制前填充白色背景这种方法,不仅简单,而且对png图片的半透明区域填充难看的黑色块。推荐这种解决方案。

另:canvas.toDataURL()方法不允许处理跨域图片。否则会报错。

转载地址:http://www.jb51.net/html5/503985.html

解决canvas转base64/jpeg时透明区域变成黑色背景的方法的更多相关文章

  1. 一键切换皮肤的解决思想及iframe嵌套时寻找下级iframe的方法

    项目中有个一键切换皮肤的功能,感觉还不错,记录下,就是各颜色样式设置起来太复杂了,不知道有没有更简便的方法: 1.切换皮肤结构层 <li title="<s:text name= ...

  2. 解决pycharm运行py文件时只有unittest选项的方法

    有时候在编完脚本开始运行时,发现某个py脚本右键运行的选项不是run,二是run in unittest,试过很多方法都不能很好的去除,主要是因为脚本中含有test字符串,一种解决方法是将脚本中所有的 ...

  3. 解决 canvas 将图片转为base64报错: Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasEleme...

    问题描述 当用户点击分享按钮时,生成一张海报,可以保存图片分享到朋友圈,用户的图片是存储在阿里云的OSS,当海报完成后,执行.canvas.toDataURL("image/png" ...

  4. 解决 canvas 绘图在高清屏中的模糊问题

    解决 canvas 绘图在高清屏中的模糊问题 为什么模糊 CSS 像素是一个抽象单位(1 px),浏览器根据某种规则将 css 像素转化为屏幕需要的实际像素值. 在高清屏之前,屏幕上显示一个像素点需要 ...

  5. 小程序canvas转base64方法 使用upng库 亲测没问题

    普通字符串base64编码转化可以使用原生的atob和btoa方法 图片转码:传统的图片转base64的方法可以采用FileReader的readAsDataURL()或canvas.toDataUR ...

  6. 基于vue上传base64图片,通过canvas压缩base64

    其实和vue关系不大,和我们之前做上传压缩性质是一样的 当然下面的代码是没有处理ios横屏拍照的bug的 有兴趣的可以多搜一下  网上都有相应的解答 .. var that = this if (e. ...

  7. 解决SQLSERVER在还原数据时出现的“FILESTREAM功能被禁用”问题

    解决SQLSERVER在还原数据时出现的“FILESTREAM功能被禁用”问题 今天由于测试需要,在网上下载了Adventureworks2008实例数据库的BAK文件,进行还原时出现了这样的错误“F ...

  8. 解决iphone填写表单时,表单项获取焦点时往下拉屏,导致顶部标题栏下滑错位

    $(function () { //解决iphone填写表单时,表单项获取焦点时往下拉屏,导致顶部标题栏下滑错位 var u = navigator.userAgent; var isiOS = !! ...

  9. 图片_ _Android有效解决加载大图片时内存溢出的问题 2

    Android有效解决加载大图片时内存溢出的问题 博客分类: Android Android游戏虚拟机算法JNI 尽量不要使用setImageBitmap或 setImageResource或 Bit ...

随机推荐

  1. VB调用存储过程 - CreateParameter 方法

    这次又转为VB6了.......  (┬_┬) ---------------------------------------------------------------------------- ...

  2. VC++ 在使用 CImage 的Draw 输入一个图像时,有时候会造成图像失真严重,解决的方法如下

    VC++  在使用 CImage 的Draw 输入一个图像时,有时候会造成图像失真严重,解决的方法如下 失真主要是由于变形造成的.只要设置一下变形的模式就可以了 ::SetStretchBltMode ...

  3. 一步一步学WebSocket(二) 使用SuperWebSocket实现自己的服务端

    上一篇文章,我们了解了客户端如何与服务器创建WebSocket连接.但是一个巴掌拍不响,既然是通信,就必然最少要有两个端.今天我们来看看c#如何用已有的框架实现一个WebSocket服务端. 在.Ne ...

  4. JavaScript DOM编程艺术读书笔记(四)

    第十章 实现动画效果 var repeat = "moveElement('"+elementID+"',"+final_x+","+fin ...

  5. VS使用过程中,编写JS没有智能提示解决方法

    问题:编写基本Script代码没有问题,但是在编写DOM代码时候没有智能提示.也就是在编写一般javascript代码时候没有问题,但是要写DOM代码的时候发现没有智能提示,如document等都需要 ...

  6. 使用MLeaksFinder检测项目中的内存泄露

    github地址:https://github.com/Zepo/MLeaksFinder MLeaksFinder使用简单方便,可以帮助你在开发时发现内存泄露你的iOS应用.它可以自动发现和UIVi ...

  7. DIOCP之编写第一个应用程序(一)

    Server 设计功能如下: 1.支持客户端登录 2.连接数据库进行操作 3.推送信息 4.限制文件上传大小 第一步:创建一个VCL-Forms Application(创建一个标准VCL程序) 第二 ...

  8. centos如何卸载软件

    需要看你的软件包格式: 如果你带有yum,可以直接yum remove xxx如果是rpm包,rpm -e xxxtar包的话需要你直接删除该文件或者make uninstall xxx常见的就这三种

  9. [Docker] docker 基础学习笔记4(共6篇)

    离线安装nginx   apache 如何启动war包   linux 离线升级内核   nginx和Apache的使用   nginx 的负载均衡配置 是如此的简单,比weblogic的要简单100 ...

  10. css总结

    1. css中的role属性 html 里面的 role 本质上是增强语义性,当现有的HTML标签不能充分表达语义性的时候,就可以借助role来说明.通常这种情况出现在一些自定义的组件上,这样可增强组 ...