小记-用canvas完成图像液化(向前变形)过程
前几天由于团队需要,折腾了一下图像液化的处理过程。
现在来整理一下思路,做个记录。
用到公式如下,网上拿来的
话不多说,上代码
本来想尽量写出点逼格。。。后来发现怎么写也还是几个function搞定,就那样了。
(function(global) {
// 计算两点距离平方
function distanceSqr( x1, y1, x2, y2 ) { return sqr(x1-x2) + sqr(y1-y2); }
// 计算平方
function sqr(x) { return x*x; }
// 遍历一个指定圆内的所有点
// 通过callback传入回调方法,回调传出每一个点的相关信息
function eachCircleDot( imageData, ox, oy, r, callback ) {
var imgWidth = imageData.width,
imgHeight = imageData.height,
data = imageData.data,
left = ox-r,
right = ox+r,
top = oy-r,
bottom = oy+r,
dotRedOffset,dotGreenOffset,dotBlueOffset,alphaOffset;
for( var x = left; x < right; x++ )
for( var y = top; y < bottom; y++ )
if( distanceSqr( x, y, ox, oy ) <= sqr(r) ) {
dotRedOffset = y*imgWidth*4+x*4;
dotGreenOffset = dotRedOffset + 1;
dotBlueOffset = dotGreenOffset + 1;
alphaOffset = dotBlueOffset + 1;
callback(
// 当前点的坐标
{ x:x, y:y },
// 点的RGBA四个分量对应字节的下标
{
r: dotRedOffset,
g: dotGreenOffset,
b: dotBlueOffset,
a: alphaOffset,
},
// 传进来的ImageData的data部分
data
);
}
}
// 复制一个imageData的data到一个buff里
function copyImageDataBuff( imgData ) {
var data = imgData.data,
imgDataBuff = [];
for( var i in data )
imgDataBuff[i] = data[i];
return imgDataBuff;
}
// 从buff按照指定坐标复制像素点数据到目标imageData里
function moveDot( imgData, dataBuff, x, y, srcX, srcY ) {
var imgWidth = imgData.width,
imgHeight = imgData.height,
data = imgData.data;
x = Math.floor(x);
y = Math.floor(y);
srcX = Math.floor(srcX);
srcY = Math.floor(srcY);
var targetStartOffset = y*imgHeight*4 + x*4,
srcStartOffset = srcY*imgHeight*4 + srcX*4;
for( var i = 0; i < 4; i++ )
data[ targetStartOffset + i ] = dataBuff[ srcStartOffset + i ];
}
// 执行液化过程
// imgData 通过canvas的getImageData方法得到的数据对象
// cx,cy 圆心坐标
// mx,my 移动目标坐标
// r 作用半径
// strength 力度百分比(1-100)
function liquify( imgData, cx, cy, mx, my, r, strenth ) {
var imgDataBuff = copyImageDataBuff(imgData);
eachCircleDot( imgData, cx, cy, r, function( posi ) {
var tx = posi.x,
ty = posi.y;
var u = transFormula( cx, cy, mx, my, tx, ty, r, strenth );
moveDot( imgData, imgDataBuff, tx, ty, u.x, u.y );
function transFormula( cx, cy, mx, my, tx, ty, r, strenth ) {
strenth = strenth || 100;
var relativity = sqr(r) - distanceSqr( tx, ty, cx, cy );
var distanceMovedSqr = distanceSqr( mx, my, cx, cy );
var rate = sqr( relativity / ( relativity + distanceMovedSqr*(100/strenth) ) );
var ux = tx - rate * (mx-cx),
uy = ty - rate * (my-cy);
return { x:ux, y:uy };
}
});
}
// 挂到全局对象
global.LiquifyFilter = {
liquify: liquify
};
})(window);
使用它
先用canvas的
getImageData();
方法获取到要处理图片的imageData
全局作用域下调用
LiquifyFilter.liquify( imageData, 圆心X, 圆心Y, 目标点X, 目标点Y, 作用半径, [力度百分比] );
完成转换。
然后再用canvas的
puImageData();
把转换后的imageData输出到canvas中
效果图如下
小记-用canvas完成图像液化(向前变形)过程的更多相关文章
- html5 Canvas处理图像 实例讲解
最近在学习canvas,canvas有很强大的图像处理功能,下面写一个我的学习总结: canvas常用功能: 1. 绘制矩形.圆形.曲线.组合图形 2. 绘制文本 3.绘制渐变.变形的图形 4. 图片 ...
- [转载] DSP6000图像位移与变形典型算法
原文地址:转载:DSP6000图像位移与变形典型算法作者:Jane 李现路:DSP6000图像位移与变形典型算法 一.图像的平移算法 图像平移的数学表达式原理: 初始坐标为(x0,y0)的点经过平移( ...
- 用纯Python实现循环神经网络RNN向前传播过程(吴恩达DeepLearning.ai作业)
Google TensorFlow程序员点赞的文章! 前言 目录: - 向量表示以及它的维度 - rnn cell - rnn 向前传播 重点关注: - 如何把数据向量化的,它们的维度是怎么来的 ...
- canvas学习笔记(下篇) -- canvas入门教程--保存状态/变形/旋转/缩放/矩阵变换/综合案例(星空/时钟/小球)
[下篇] -- 建议学习时间4小时 课程共(上中下)三篇 此笔记是我初次接触canvas的时候的学习笔记,这次特意整理为博客供大家入门学习,几乎涵盖了canvas所有的基础知识,并且有众多练习案例, ...
- canvas 绘制图像
结果: 代码: <!DOCTYPE html> <html> <head lang="en"> <meta charset="U ...
- canvas绘制图像轮廓效果
在2d图形可视化开发中,经常要绘制对象的选中效果. 一般来说,表达对象选中可以使用边框,轮廓或者发光的效果. 发光的效果,可以使用canvas的阴影功能,比较容易实现,此处不在赘述. 绘制边框 绘制 ...
- html5新特性canvas绘制图像
在前端页面开发过程中偶尔会有需要对数据进行相应的数学模型展示,或者地理位置的动态展示,可能就会想到用canvas,网上有很多已经集成好的,比如说类似echarts,确实功能非常强大,而且用到了canv ...
- H5中标签Canvas实现图像动画
一:主题部分 1.介绍 canvas可以实现画图功能,所以只要通过js的控制,就可以实现简单的动画效果. 这里主要是两个程序,一个小球来回上下弹跳,一个是吹气球. 2.弹跳程序 <!DOCTYP ...
- 【canvas】高级功能一 变形
[canvas]Demo1 scale缩放 <!DOCTYPE html> <html lang="en"> <head> <meta c ...
随机推荐
- Python字典的创建与复制
Python 字典练习题 1.字典的创建 1.1 普通创建 d={'name':'Allen','age':21,'gender':'male'} print(d) # {'name': 'Allen ...
- python如何data格式和时间戳的转换
Python 获取几天前的时间 计算几天前并转换为指定格式. import time import datetime # 先获得时间数组格式的日期 threeDayAgo = (datetime.da ...
- LeetCode-096-不同的二叉搜索树
不同的二叉搜索树 题目描述:给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数. 二叉搜索树(Binary Search ...
- centeros7 定时任务
crond是什么? crond 和crontab是不可分割的.crontab是一个命令,常见于Unix和类Unix的操作系统之中,用于设置周期性被执行的指令.该命令从标准输入设备读取指令,并将其存放于 ...
- LGP1397题解
并不是那么的有意思呢 首先,我们可以将题目给出的地推式看做一个一次函数 \(k * x+b\),来思考一个问题,如果给出两个一次函数 \(F(x)\) 和 \(G(x)\),那么 \(F(G(x))\ ...
- InnoDB 锁的类型
一.全局锁 mysql> flush table with read lock; FTWRL 会对整个实例加只读锁.会阻塞所有线程读以外的所有操作.查看线程状态 State: Waiting f ...
- 7. 堪比JMeter的.Net压测工具 - Crank 总结篇 - crank带来了什么
目录 堪比JMeter的.Net压测工具 - Crank 入门篇 堪比JMeter的.Net压测工具 - Crank 进阶篇 - 认识yml 堪比JMeter的.Net压测工具 - Crank 进阶篇 ...
- jdk配置完成tomcat无法启动问题解决
今天在进行struts2练习之前,准备为电脑配置tomcat容器,发现jdk的java指令可以正确运行,而tomcat启动时控制台弹出后立即消失.查资料显示jdk为正确配置,但是自己的java指令都能 ...
- ArcGIS Server 禁用/rest/services路径(禁用服务目录)
ArcGIS Server服务目录(路径如:http://<hostname>:6080/arcgis/rest/services)默认可以不需要登陆直接打开.效果如下图. ArcGIS服 ...
- 嵌入式无操作系统下管理内存和队列(类UCOS II思想)
例子:存储日志,最多存128条,每条最大1MB. 内存方面 因为嵌入式不适合用动态内存,会产生碎片.这里我们用 u8 data[LOG_SIZE];开辟固定128MB的内存区,再对其分为128个1MB ...