在线抠图网站速抠图sukoutu.com全面技术解析之canvas应用
- 技术关键词
Canvas应用,泛洪算法(Flood Fill),图片缩放,相对位置等比缩放,判断一个点是否在一个平面闭合多边形,nginx代理
- 业务关键词
在线抠图,智能抠图,一键抠图,钢笔抠图,矩阵抠图,图片处理,图片压缩,图片尺寸,图片格式,图片透明度,图片下载
- 引用组件(前端)
Jquery,Canvas,Jcrop, Layer,MiniColors
- 技术解析背景
发表这篇随笔,一方面帮助前端的同学认识Canvas的实际应用场景和了解相关技术点,另一方面让sukoutu.com能够帮助更多的人去快速高效的完成抠图。
作为一名后端研发去开发一套纯前端的在线抠图工具实际上看起来有些疑惑和怪异,或许是因为 14年5月发表的一个随笔 html5 canvas+js实现ps钢笔抠图 的延续。
发表在知乎上的一篇文章 能让你知道sukoutu.com上线的原由、目的以及相关功能简介。

- 速抠图网站实现原理
网站几乎没有和后端服务做交互。后端用nginx作为server,另外代理了三方房展的图片访问(解决前端跨域访问网络图片跨域禁止canvas渲染的问题,通过nginx代理访问规避这个问题)。图片上传及图片操作等均在客户端浏览器上完成(图片操作流畅的很),因为有Canvas,所以整个工具网站的核心都在于js的交互及canvas的应用。
- 智能抠图(仿PS魔法棒效果)
这里参考了一些开源项目和泛洪算法(Flood Fill)的实现案例。对于一次纯色或者背景色差比较大的图片抠图,基本都能实现一键抠图的效果,通过点击滑选闭合色区来实现抠图,但是对于背景色差复杂的图片就很难实现自己想要的抠图了。
算法参考:图像分割经典算法--《泛洪算法》(Flood Fill)
实现原理:底层放图片,顶层放canvas,将图片按照对等尺寸渲染至到画布上得到ImageData,鼠标点击获取ImageData RGB 色值,用floodfill算法得到闭合外围坐标,在顶层canvas渲染边线(ctx.putImageData)
init: function (img) {
this.data.img = img;
this.data.tempCanvas = document.createElement('canvas');
var tempCtx = this.data.tempCanvas.getContext('2d');
//切记,原始图像大小
tempCtx.canvas.width = panel.data.targetImgWidth;
tempCtx.canvas.height = panel.data.targetImgHeight;
tempCtx.drawImage(img, 0, 0, panel.data.targetImgWidth, panel.data.targetImgHeight);
this.data.imgData = tempCtx.getImageData(0, 0, panel.data.targetImgWidth, panel.data.targetImgHeight);
},
- 钢笔抠图
钢笔抠图参考 html5 canvas+js实现ps钢笔抠图
实现原理:底层放图片,顶层放canvas,鼠标点击坐标存放到array中,canvas根据坐标list画线画点,canvas的 globalCompositeOperation = "destination-out" 属性可以实现通过由多个点构成的闭合区间设置成透明色穿透画布背景色或是背景图片。
- 矩阵抠图
这里用的是非常实用的Jcrop插件,参考Jcrop官网 ,提供了丰富的api,比如等比、移动等实用的功能。
- 图片等比缩放(很实用)
解决图片加载要等比缩放到画布中,并且居中显示。
function imgScale(src, w, h, fun) {
var img = new Image();
img.src = src;
img.onload = function () {
var wi = img.width;
var he = img.height;
var toHe = he * w / wi;
var toWi = 0;
if (toHe > h) {
toWi = wi * h / he;
toHe = h;
} else {
toWi = w;
}
fun(toWi, toHe);
};
}
- 相对位置等比缩放
在实现钢笔抠图或矩阵抠图需要放大,并且钢笔及矩阵坐标list也要等比缩放,需要用到如下算法来实现。
_scale = function (c, a, f) {
x1 *= c.x;
y1 *= c.y;
x2 *= c.x;
y2 *= c.y;
if (a) {
_values = [1.0000000000000002, -0, -0, 1.0000000000000002];
var b = transform(a.x - translationStart.x, a.y - translationStart.y);
var d = transform(c.x * -b.x, c.y * -b.y);
translation.x = d.x + a.x;
translation.y = d.y + a.y
}
};
transform = function (b, d, a) {//两中心x差,两中心y差
var c = new Point(_values[0] * b + _values[1] * d, _values[2] * b + _values[3] * d);
return c
};
- Canvas应用
图片压缩、图片尺寸调整、图片背景色、图片透明度实际均可通过canvas属性来操作
//透明度
ctx.globalAlpha = imgCreate.cutObj.alpha;
//背景色
ctx.fillStyle = imgCreate.cutObj.color;
//根据坐标list裁剪图片
var ctx = $("#createCanvas")[0].getContext('2d');
ctx.beginPath();
ctx.moveTo(0, 0);
for (var i = 0; i < proxy.cutObj.pointArray.length; i++) {
ctx.lineTo(proxy.cutObj.pointArray[i].pointx, proxy.cutObj.pointArray[i].pointy);
}
ctx.lineTo(proxy.cutObj.pointArray[0].pointx, proxy.cutObj.pointArray[0].pointy);
ctx.clip();
ctx.drawImage(proxy.cutObj.imgObj, tempPointArray[0].pointx * -1, tempPointArray[0].pointy * -1, proxy.cutObj.width, proxy.cutObj.height);
//生成及下载图片兼容(ie\谷歌\火狐)
var fileName = proxy.cutObj.name + "." + proxy.cutObj.suffix.replace("e", "");
if (window.navigator.msSaveOrOpenBlob) {
var imgData = $("#createCanvas")[0].msToBlob();
var blobObj = new Blob([imgData]);
window.navigator.msSaveOrOpenBlob(blobObj, fileName);
} else {
var imgData = $("#createCanvas")[0].toDataURL("image/" + imgCreate.cutObj.suffix, parseFloat(imgCreate.cutObj.quality));
imgData = imgData.replace("image/" + imgCreate.cutObj.suffix, 'image/octet-stream');
var a = document.createElement('a');
var event = new MouseEvent('click');
a.download = fileName;
a.href = URL.createObjectURL(dataURIToBlob(imgData));
a.dispatchEvent(event);
}
在线抠图网站速抠图sukoutu.com全面技术解析之canvas应用的更多相关文章
- html5 canvas+js实现ps钢笔抠图(速抠图 www.sukoutu.com)
html5 canvas+js实现ps钢笔抠图(速抠图 www.sukoutu.com) 根据html5 canvas+js实现ps钢笔抠图的实现,aiaito 开发者开发了一套在线抠图工具,速抠 ...
- 收集各种在线HTTP网站载入速度(响应时间)站长测试(检测)工具
收集各种在线HTTP网站载入速度(响应时间)站长测试(检测)工具 名称\详情 简单功能描述 推荐星级 演示/示例 监控宝 从中国多地对你提交的URL进行载入速度(响应时间)测试 ★★★★★ 17C ...
- IT在线学习网站总结
以下是我自己做软件过程中发现的一些不错的IT学习网站,个人感觉比较受用,故总结出来以供IT爱好者一起学习: www.maiziedu.com 麦子学院 www.jikexueyuan.com 极客学 ...
- 在线音乐网站【04】Part two 功能实现
上一篇博客里面已近总结了三个功能的具体实现,今天把剩余功能的具体实现补充总结,如果你想对整个小项目有清楚的了解,建议去看下前几篇博客. 1.在线音乐网站(1)需求和功能结构 2.在线音乐网站(2 ...
- 在线音乐网站【03】Part one 功能实现
今天打算把网站功能的具体实现给总结一下,如果你想了解整个小项目,建议你先看看前面2篇博客. 1.在线音乐网站(1)需求和功能结构 2.在线音乐网站(2)数据库和开发环境 7.网站主要模块实现 a.在线 ...
- 我是怎么开发一个小型java在线学习网站的
2016/1/27 11:55:14 我是怎么开发一个小型java在线学习网站的 一直想做一个自己的网站(非博客),但是又不知道做什么内容的好,又一次看到了w3schools,就萌发了开发一个在线ja ...
- HTML5初学者福利!11个在线学习网站推荐
HTML5初学者福利!11个在线学习网站推荐 HTML5的强大及流行趋势,让更多的人想要系统的对它进行学习.而大多数人获取HTML5知识的重要途径都是网络,不过面对五花八门的搜索结果,是不是觉得摸不着 ...
- 六:在线工具网站,让你PC上要装的软件少一半!
记住这几个在线工具网站,让你PC上要装的软件少一半! 一.uzer.me——丰富的云端应用聚合 这个云平台将我们常用的Office系列软件.Adobe家族的系列软件……乃至CAD制图都整合在了云端,随 ...
- 初学者福音——10个最佳APP开发入门在线学习网站
根据Payscale的调查显示,现在的APP开发人员的年薪达到:$66,851.这也是为什么那么多初学的开发都想跻身到APP开发这行业的主要原因之一.每当你打开App Store时候,看着琳琅满目的A ...
随机推荐
- validation set以及cross validation的常见做法
如果给定的样本充足,进行模型选择的一种简单方法是随机地将数据集切分成三部分,分为训练集(training set).验证集(validation set)和测试集(testing set).训练集用来 ...
- BUPT复试专题—最长连续等差子数列(2014软院)
题目描述 给定-个长度为N的整数数列,你需要在其中找到最长的连续子数列的长度, 并满足这个子数列是等差的.注意公差小于或等于0的情况也是允许的. 输入 第一行为数据组数T(1~100),表示测试数 ...
- [Oracle] 获取运行计划的各方法总结
总的结论: 一.获取运行计划的6种方法(具体步骤已经在每一个样例的开头凝视部分说明了): 1. explain plan for获取: 2. set autotrace on . 3. stati ...
- electron 开发拆坑总结
electron 总结 前言 有一个web项目需要用客户端来包装一下 项目的主要业务都在服务器上 所以项目的大多数功能都用url 地址来访问: 客户端登陆界面在本地 打包客户端的本地登陆界面 做为登陆 ...
- C++ 学习总结 复习篇
友元的使用 分为友元类和友元函数 //友元类与友元函数的共同点:都可以让某一个类作为另一个类或者函数的参数. //友元类:它让当前类成为另一个类的友元,然后,另一个类 ...
- Object类及其常用方法简介
https://www.cnblogs.com/wxywxy/p/6740277.html Object类是一个特殊的类,是所有类的父类,如果一个类没有用extends明确指出继承于某个类,那么它默认 ...
- linux 输入子系统(3) button platform driver
button platform driver 一般位于driver/input/keyboard/gpio_keys.c /*用于按键事件的上报,它将在按键的中断发生后被调用.其中逻辑就是获取到按键类 ...
- Spring Boot 动态数据源(多数据源自己主动切换)
本文实现案例场景: 某系统除了须要从自己的主要数据库上读取和管理数据外.另一部分业务涉及到其它多个数据库,要求能够在不论什么方法上能够灵活指定详细要操作的数据库. 为了在开发中以最简单的方法使用,本文 ...
- python day - 09 函数
函数 1.函数的定义,引用. 定义:函数是对功能和代码块的封装和定义. 函数用 def关键字来表示. 格式: def 函数名(): 函数体 eg: return(返回值) 在函数中遇到return ...
- cat /proc/cpuinfo | awk -F: '/name/{print $2}' | uniq -c
cat /proc/cpuinfo | awk -F: '/name/{print $2}' | uniq -c