前几天由于团队需要,折腾了一下图像液化的处理过程。

现在来整理一下思路,做个记录。

用到公式如下,网上拿来的

话不多说,上代码

本来想尽量写出点逼格。。。后来发现怎么写也还是几个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);

使用它

  1. 先用canvas的

    getImageData();

    方法获取到要处理图片的imageData

  2. 全局作用域下调用

    LiquifyFilter.liquify( imageData, 圆心X, 圆心Y, 目标点X, 目标点Y, 作用半径, [力度百分比] );

    完成转换。

  3. 然后再用canvas的

    puImageData();

    把转换后的imageData输出到canvas中

效果图如下

最新文章

  1. C#利用微软库完成设备网络定位(经纬度-地址)
  2. ReportingService报表入门
  3. 同时运行多个scrapy爬虫的几种方法(自定义scrapy项目命令)
  4. Android Toolbar样式定制详解
  5. 用PDB库调试Python程序
  6. django-url调度器-高级篇
  7. Android ViewPager 应该及技巧
  8. Xcode代码格式化教程,可自定义样式
  9. chrome扩展——Postman
  10. 关于fork有意思的两道题目
  11. JavaScript 获取当月天数
  12. 使用多线程完成Socket
  13. cpppp
  14. vi所有特殊字符
  15. jQuery推断复选框是否勾选
  16. 后端list集合中的数据传递到前台HTML中显示(表格形式)
  17. 年关将至业内警示P2P跑路风险
  18. VBA 高级筛选
  19. mysql reset password重置密码
  20. c++builder 代码模板 code templates

热门文章

  1. 穿透、击穿、雪崩…Redis这么多问题,如何解决?
  2. 如何在矩池云上运行FinRL-Libray股票交易策略框架
  3. linux Wireshark图解TCP三次握手与四次挥手
  4. TP5框架中实现多条件登录(自写代码,密码未md5()加密)
  5. nginx 如何访问php文件
  6. kali换源及安装docker
  7. SpringBoot——两种传参方式
  8. IDEA版部署离线ArcGIS api for JavaScript
  9. Cobalt Strike的安装
  10. bat加mimikatz一键获取密码