PhotoShop图层混合模式的Canvas实现
来源:互联网 发布:阿里云vpn搭建openvpn 编辑:程序博客网 时间:2024/04/29 15:34
前端开发人员可能会遇到这样一个问题。
当设计人员给到一个PSD以后,会发现其中有些图层是有图层混合效果的。
这样会产生一个情况就是,我们为了这个效果而不得不将背景+带混合的图层切到一起。
当这样的元素多了以后,我们所切出的图片就会越来越大并且难以修改。
那么,本章我们将讲解如何使用Canvas元素来实现混合模式。
以达到减少图片体量和数量的效果。
首先,我们来讲一下基本实现原理。
大家可能都知道,Canvas是位图处理,Svg是矢量处理。那么什么是位图,什么是矢量图呢?
请看以下图片进行对比:
图像引用自互联网,原文地址:http://jingyan.baidu.com/album/54b6b9c0dbef682d583b4722.html?picindex=2
从上图可知,100%大小的矢量图在缩放到800%的时候并没有出现失真的情况,即:没有马赛克。
而位图则出现了万恶的马赛克,图像已经变得模糊不清了。
那么,为什么我们要使用Canvas呢?
因为网上太多类似的文章了,所以这里直接外链。
就本章节的内容来说,我们使用Canvas是为了使用像素处理。
为了方便读者实践,这里给出两张实验图片。(图片取自网络,请勿用于商业用途,如有侵犯请联系本人进行处理,感激不尽)
实现效果的前置代码:
// 指定要使用的处理器,这里暂时不指定var processor = "";// 所有的处理器都在这个对象下var pixProcessor = {};var imgBackground = new Image();var imgButterfly = new Image();imgBackground.onload = imgButterfly.onload = function () { this.loaded = true; if (imgBackground.loaded && imgButterfly.loaded) { process(); }};imgBackground.src = "background.jpg";imgButterfly.src = "butterfly.png";var canvas = document.createElement("canvas");canvas.width = 610;canvas.height = 502;var context = canvas.getContext("2d");以上代码十分好理解。
1.将两张图片加载进来。
2.创建一个canvas元素并获取其context。
3.图片加载完成后触发名为process的函数。
好的,现在我们来仔细看看process函数里都做了什么操作。
function process() { // 计算蝴蝶图片相对背景图片的中心位置 var centerX = (imgBackground.width - imgButterfly.width) / 2; var centerY = (imgBackground.height - imgButterfly.height) / 2; // 绘制背景图 context.drawImage(imgBackground, 0, 0); // 通过getImageData函数获取背景图片中,蝴蝶图片所应该在的区域的像素数据 var backgroundData = context.getImageData(centerX, centerY, imgButterfly.width, imgButterfly.height); // 缓存ImageData中的data数组,这才是我们要操作的东西 var backgroundPixs = backgroundData.data; // 清空一次画布 context.clearRect(0, 0, canvas.width, canvas.height); // 绘制蝴蝶图 context.drawImage(imgButterfly, centerX, centerY); // 不解释 var butterflyData = context.getImageData(centerX, centerY, imgButterfly.width, imgButterfly.height); // 不解释 var butterflyPixs = butterflyData.data; // 再次绘制背景图 context.drawImage(imgBackground, 0, 0); // 再次绘制蝴蝶图(反正这句话也没什么卵用,忘了当时为啥要写这句话了) context.drawImage(imgButterfly, centerX, centerY); // 若没有定义处理器则不进行处理 if (typeof processor != "undefined") { var newPix; for (var i = 0; i < backgroundPixs.length; i += 4) { // 跳过全透明像素 if (butterflyPixs[i + 3] == 0) continue; // 传入两个图像对应的像素进行处理 newPix = pixProcesser[processor]({ red: backgroundPixs[i], green: backgroundPixs[i + 1], blue: backgroundPixs[i + 2], alpha: backgroundPixs[i + 3] }, { red: butterflyPixs[i], green: butterflyPixs[i + 1], blue: butterflyPixs[i + 2], alpha: butterflyPixs[i + 3] }); if (newPix) { // 将处理好的像素赋值给背景图ImageData(实际上你传给蝴蝶图也没问题,只是下面putImageData的时候需要指向蝴蝶图罢了) backgroundPixs[i] = newPix.red; backgroundPixs[i + 1] = newPix.green; backgroundPixs[i + 2] = newPix.blue; } } // 好的,将处理结果交给浏览器 context.putImageData(backgroundData, centerX, centerY); } if (document.body) { document.appendChild(canvas); } else { window.addEventListener("load", function () { document.appendChild(canvas); }, false); }}
好的,现在我们进入华丽时间!~
1.正常模式,processor需要指定为 normal
pixProcesser.normal = function (background, butterfly) { /// <summary>正常模式</summary> var alpha = butterfly.alpha; return { red: butterfly.red * alpha + background.red * (1 - alpha), green: butterfly.green * alpha + background.green * (1 - alpha), blue: butterfly.blue * alpha + background.blue * (1 - alpha), alpha: butterfly.alpha * alpha + background.alpha * (1 - alpha) } };
2.溶解,processor需要指定为 dissolve
pixProcesser.dissolve: function (background, butterfly) { /// <summary>溶解</summary> // 正式用判断条件 //if (Math.floor(Math.random() * 100) > (butterfly.alpha / 255 * 100)) { // 测试用判断条件 if (Math.floor(Math.random() * 100) > 50) { return background; } else { return butterfly; } };
3.变暗,processor需要指定为 darken
pixProcesser.darken: function (background, butterfly) { /// <summary>变暗</summary> return { red: Math.min(background.red, butterfly.red), green: Math.min(background.green, butterfly.green), blue: Math.min(background.blue, butterfly.blue), alpha: Math.min(background.alpha, butterfly.alpha) }; };
4.正片叠底,processor需要指定为 multiply
pixProcesser.multiply: function (background, butterfly) { /// <summary>正片叠底</summary> return { red: butterfly.red * background.red / 255, green: butterfly.green * background.green / 255, blue: butterfly.blue * background.blue / 255, alpha: butterfly.alpha * background.alpha / 255 }; };
5.颜色加深,processor需要指定为 colorBurn
pixProcesser.colorBurn: function (background, butterfly) { /// <summary>颜色加深</summary> return { red: Math.max(0, background.red + butterfly.red - 255) * 255 / butterfly.red, green: Math.max(0, background.green + butterfly.green - 255) * 255 / butterfly.green, blue: Math.max(0, background.blue + butterfly.blue - 255) * 255 / butterfly.blue, alpha: Math.max(0, background.alpha + butterfly.alpha - 255) * 255 / butterfly.alpha }; };
6.线性加深,processor需要指定为 linearBurn
pixProcesser.linearBurn: function (background, butterfly) { /// <summary>线性加深</summary> return { red: Math.max(0, background.red + butterfly.red - 255), green: Math.max(0, background.green + butterfly.green - 255), blue: Math.max(0, background.blue + butterfly.blue - 255), alpha: Math.max(0, background.alpha + butterfly.alpha - 255) }; };
7.深色,processor需要指定为 darkerColor
pixProcesser.darkerColor: function (background, butterfly) { /// <summary>深色</summary> if ((background.red + background.green + background.blue + background.alpha) < (butterfly.red + butterfly.green + butterfly.blue + butterfly.alpha)) { return background; } else { return butterfly; } };
8.变亮,processor需要指定为 lighten
pixProcesser.lighten: function (background, butterfly) { /// <summary>变亮</summary> return { red: Math.max(background.red, butterfly.red), green: Math.max(background.green, butterfly.green), blue: Math.max(background.blue, butterfly.blue), alpha: Math.max(background.alpha, butterfly.alpha) }; };
9.滤色,processor需要指定为 screen
pixProcesser.screen: function (background, butterfly) { /// <summary>滤色</summary> return { red: 255 - (255 - butterfly.red) * (255 - background.red) / 255, green: 255 - (255 - butterfly.green) * (255 - background.green) / 255, blue: 255 - (255 - butterfly.blue) * (255 - background.blue) / 255, alpha: 255 - (255 - butterfly.alpha) * (255 - background.alpha) / 255 }; };
10.颜色减淡,processor需要指定为 colorDodge
pixProcesser.colorDodge: function (background, butterfly) { /// <summary>颜色减淡</summary> return { red: background.red + butterfly.red * background.red / (255 - butterfly.red), green: background.green + butterfly.green * background.green / (255 - butterfly.green), blue: background.blue + butterfly.blue * background.blue / (255 - butterfly.blue), alpha: background.alpha + butterfly.alpha * background.alpha / (255 - butterfly.alpha) }; };
11.线性减淡,processor需要指定为 linearDodge
pixProcesser.linearDodge: function (background, butterfly) { /// <summary>线性减淡</summary> return { red: Math.min(background.red + butterfly.red, 255), green: Math.min(background.green + butterfly.green, 255), blue: Math.min(background.blue + butterfly.blue, 255), alpha: Math.min(background.alpha + butterfly.alpha, 255) }; };
12.浅色,processor需要指定为 lighterColor
pixProcesser.lighterColor: function (background, butterfly) { /// <summary>浅色</summary> if ((background.red + background.green + background.blue + background.alpha) > (butterfly.red + butterfly.green + butterfly.blue + butterfly.alpha)) { return background; } else { return butterfly; } };
13.叠加,processor需要指定为 overlay
pixProcesser.overlay: function (background, butterfly) { /// <summary>叠加</summary> return { red: 255 - (255 - butterfly.red) * (255 - background.red) / 128, green: 255 - (255 - butterfly.green) * (255 - background.green) / 128, blue: 255 - (255 - butterfly.blue) * (255 - background.blue) / 128, alpha: 255 - (255 - butterfly.alpha) * (255 - background.alpha) / 128 }; };
14.柔光,processor需要指定为 softLight
pixProcesser.softLight: function (background, butterfly) { /// <summary>柔光</summary> return { red: background.red + (2 * butterfly.red - 255) * (Math.sqrt(background.red / 255) * 255 - background.red) / 255, green: background.green + (2 * butterfly.green - 255) * (Math.sqrt(background.green / 255) * 255 - background.green) / 255, blue: background.blue + (2 * butterfly.blue - 255) * (Math.sqrt(background.blue / 255) * 255 - background.blue) / 255, alpha: background.alpha + (2 * butterfly.alpha - 255) * (Math.sqrt(background.alpha / 255) * 255 - background.alpha) / 255 }; };
15.强光,processor需要指定为 hardLight
pixProcesser.hardLight: function (background, butterfly) { /// <summary>强光</summary> return { red: butterfly.red > 128 ? 255 - (255 - butterfly.red) * (255 - background.red) / 128 : butterfly.red * background.red / 128, green: butterfly.green > 128 ? 255 - (255 - butterfly.green) * (255 - background.green) / 128 : butterfly.green * background.green / 128, blue: butterfly.blue > 128 ? 255 - (255 - butterfly.blue) * (255 - background.blue) / 128 : butterfly.blue * background.blue / 128, alpha: butterfly.alpha > 128 ? 255 - (255 - butterfly.alpha) * (255 - background.alpha) / 128 : butterfly.alpha * background.alpha / 128 }; };
16.亮光,processor需要指定为 vividLight
pixProcesser.vividLight: function (background, butterfly) { /// <summary>亮光</summary> return { red: butterfly.red <= 128 ? 255 - (255 - background.red) / (2 * butterfly.red) * 255 : background.red / (2 * (255 - butterfly.red)) * 255, green: butterfly.green <= 128 ? 255 - (255 - background.green) / (2 * butterfly.green) * 255 : background.green / (2 * (255 - butterfly.green)) * 255, blue: butterfly.blue <= 128 ? 255 - (255 - background.blue) / (2 * butterfly.blue) * 255 : background.blue / (2 * (255 - butterfly.blue)) * 255, alpha: butterfly.alpha <= 128 ? 255 - (255 - background.alpha) / (2 * butterfly.alpha) * 255 : background.alpha / (2 * (255 - butterfly.alpha)) * 255 }; };
17.线性光,processor需要指定为 linearLight
pixProcesser.linearLight: function (background, butterfly) { /// <summary>线性光</summary> return { red: Math.min(2 * butterfly.red + background.red - 255, 255), green: Math.min(2 * butterfly.green + background.green - 255, 255), blue: Math.min(2 * butterfly.blue + background.blue - 255, 255), alpha: Math.min(2 * butterfly.alpha + background.alpha - 255, 255) }; };
18.点光,processor需要指定为 pinLight
pixProcesser.pinLight: function (background, butterfly) { /// <summary>点光</summary> if (typeof pixProcesser.pinLightProcess == "undefined") { pixProcesser.pinLightProcess = function (sourceColor, blendColor) { return blendColor <= 128 ? Math.min(sourceColor, 2 * blendColor) : Math.max(sourceColor, 2 * blendColor - 255); }; } return { red: pixProcesser.pinLightProcess(background.red, butterfly.red), green: pixProcesser.pinLightProcess(background.green, butterfly.green), blue: pixProcesser.pinLightProcess(background.blue, butterfly.blue), alpha: pixProcesser.pinLightProcess(background.alpha, butterfly.alpha) }; };
19.实色混合,processor需要指定为 hardMix
pixProcesser.hardMix: function (background, butterfly) { /// <summary>实色混合</summary> return { red: (background.red + butterfly.red) < 255 ? 0 : 255, green: (background.green + butterfly.green) < 255 ? 0 : 255, blue: (background.blue + butterfly.blue) < 255 ? 0 : 255, alpha: (background.alpha + butterfly.alpha) < 255 ? 0 : 255 }; };
20.差值,processor需要指定为 difference
pixProcesser.difference: function (background, butterfly) { /// <summary>差值</summary> return { red: Math.abs(butterfly.red - background.red), green: Math.abs(butterfly.green - background.green), blue: Math.abs(butterfly.blue - background.blue), alpha: Math.abs(butterfly.alpha - background.alpha), }; };
21.排除,processor需要指定为 exclusion
pixProcesser.exclusion: function (background, butterfly) { /// <summary>排除</summary> return { red: (butterfly.red + background.red) - butterfly.red * background.red / 128, green: (butterfly.green + background.green) - butterfly.green * background.green / 128, blue: (butterfly.blue + background.blue) - butterfly.blue * background.blue / 128, alpha: (butterfly.alpha + background.alpha) - butterfly.alpha * background.alpha / 128 }; };
22.减去,processor需要指定为 subtract
pixProcesser.subtract: function (background, butterfly) { /// <summary>减去</summary> return { red: Math.max(0, background.red - butterfly.red), green: Math.max(0, background.green - butterfly.green), blue: Math.max(0, background.blue - butterfly.blue), alpha: Math.max(0, background.alpha - butterfly.alpha) }; };
23.划分,processor需要指定为 divide
pixProcesser.divide: function (background, butterfly) { /// <summary>划分</summary> return { red: (background.red / butterfly.red) * 255, green: (background.green / butterfly.green) * 255, blue: (background.blue / butterfly.blue) * 255, alpha: (background.alpha / butterfly.alpha) * 255, }; };
至此完成。您可以自己动手实验啦~~~
非常感谢您的阅读!您的支持是我的动力!
- PhotoShop图层混合模式的Canvas实现
- Photoshop图层混合(Layer Blending)模式的算法实现
- Photoshop图层混合(Layer Blending)模式的算法实现
- photoshop 图层混合模式
- 【叠加模式】PHOTOSHOP图层混合模式的计算公式
- Photoshop图层混合模式的计算公式
- Photoshop----色彩原理和图层的混合模式
- PHOTOSHOP图层混合模式的计算公式
- Photoshop图层混合模式的计算公式
- Photoshop PS图层混合模式详解
- Photoshop图层混合模式计算公式
- Photoshop----图层混合模式详解
- OpenCV简单实现PhotoShop图层混合
- Photoshop图层混合模式及中英文名称对照
- Photoshop图层混合模式计算公式大全
- Photoshop 色彩模式及图层混合样式
- Photoshop图层混合模式计算公式大全
- 关于photoshop图层混合
- oracle锁概念,阻塞
- Don't use dynamic versions for your dependencies
- jquery获取滚动条高度和位置,JQuery获取元素文档大小、偏移和位置和滚动条位置的方法集合
- 支持向量机通俗导论
- 【刷机】小米降级刷机 线刷 图解 MIUI降级刷机
- PhotoShop图层混合模式的Canvas实现
- gcc命令的使用
- 英伟达硬件加速解码器在 FFMPEG 中的使用
- 【STL学习】容器篇-线性容器
- iOS判断机型
- 转自 http://aikilis.tk/:0x3f3f3f3f作无穷大的精妙
- 网桥的搭建
- css中单位px和em,rem的区别
- ftp用户权限设置