交互式弯曲图像

Posted

技术标签:

【中文标题】交互式弯曲图像【英文标题】:Interactive bend image 【发布时间】:2015-08-24 17:15:00 【问题描述】:

我想用这种方式在网络浏览器中转换图像

->

更准确地说,应该是3D效果(就像把图像包裹起来一样)。我正在考虑以下选项:

CSS3 变换(matrix3d 是否有可能?) html5 画布(我还没有任何经验) applet 或 flash(这是最不受欢迎的)

我希望有一些简单聪明的方法来实现这一点,但是一些 3rd 方重型库也可以完成这项工作。有什么建议吗?

【问题讨论】:

为什么不将其发送到后端进行图像处理?我没有使用任何与图像处理相关的东西,但我认为会有一些选项可以实现你想要的。上传图片,将其发送到脚本以获取data URL 或其他内容的响应。 应该是交互式的,我想打开放图片的罐子。 我所知道的最接近romancortes.com/blog/pure-css-coke-can的想法 尝试查看Ezimba 上的代码。它们在翘曲类别下具有弯曲特征。 【参考方案1】:

您可以将图像切成 1 个像素的切片,然后偏移这些切片以在视觉上环绕您的杯子:

左:图像环绕在杯子顶部,右:图像环绕在杯子中心。

这是示例代码和演示:

var faceCanvas=document.getElementById('face');
var faceCtx=faceCanvas.getContext('2d');

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw,ch;


$myslider=$('#myslider');
$myslider.val(50);

var PI=Math.PI;
var cupTop=78;
var cupBottom=295;
var dxx=19;
var dyy=34;
var l=x0:41,y0:cupTop,x1:74,y1:cupBottom;
var r=x0:249,y0:cupTop,x1:218,y1:cupBottom;
var t=
  x0:l.x0,
  y0:l.y0,
  x1:l.x0+dxx,
  y1:r.y0+dyy,
  x2:r.x0-dxx,
  y2:r.y0+dyy,
  x3:r.x0,
  y3:r.y0
;
var b=
  x0:l.x1,
  y0:l.y1,
  x1:l.x1+dxx,
  y1:r.y1+dyy,
  x2:r.x1-dxx,
  y2:r.y1+dyy,
  x3:r.x1,
  y3:r.y1
;
var topOffset=40;

var imgCount=2;
var cup=new Image();
cup.crossOrigin='anonymous';
cup.onload=start;
var pic=new Image();
pic.crossOrigin='anonymous';
pic.onload=start;
cup.src="https://dl.dropboxusercontent.com/u/139992952/multple/PaperCup.png";
//pic.src='https://dl.dropboxusercontent.com/u/139992952/multple/avatars1.jpg';
pic.src='https://dl.dropboxusercontent.com/u/139992952/multple/google.png'
function start()
  if(--imgCount>0)return;

  cw=canvas.width=faceCanvas.width=cup.width;
  ch=canvas.height=faceCanvas.height=cup.height;

  draw();

  face();

  $myslider.change(function()
    var value=parseInt($(this).val())/100;
    topOffset=(l.y1-l.y0-pic.height)*value;
    draw();
    face();
  );




function face()

  //
  var lm=(l.y1-l.y0)/(l.x1-l.x0);
  var lb=l.y1-(lm*l.x1);
  //
  var rm=(r.y1-r.y0)/(r.x1-r.x0);
  var rb=r.y1-(rm*r.x1);

  faceCtx.clearRect(0,0,faceCanvas.width,faceCanvas.height);

  for(var y=0;y<pic.height;y++)

    var yy=cupTop+topOffset+y;
    var leftX=(yy-lb)/lm;
    var rightX=(yy-rb)/rm;
    var width=rightX-leftX;

    faceCtx.drawImage(
      pic,
      0,y,pic.width,1,
      leftX,yy,width,1
    );  

  

  var yy=cupTop+topOffset;
  var p0=x:(yy-lb)/lm,y:cupTop+topOffset;
  var p3=x:(yy-rb)/rm,y:cupTop+topOffset;
  var p1=x:p0.x+dxx,y:p0.y+dyy;
  var p2=x:p3.x-dxx,y:p3.y+dyy;
  var points=calcPointsOnBezier(p0,p1,p2,p3);

  ctx.save();
  setClip();
  ctx.clip();

  for(var x in points)
    var y=points[x];
    ctx.drawImage(faceCanvas,  x,0,1,ch,  x,y-yy,1,ch );
    ctx.drawImage(faceCanvas,  x,0,1,ch,  x,y-yy,1,ch );
   
  ctx.restore();


function setClip()
  ctx.beginPath();
  ctx.moveTo(t.x0,t.y0)
  ctx.bezierCurveTo(t.x1,t.y1,t.x2,t.y2,t.x3,t.y3);
  ctx.lineTo(r.x1,r.y1);
  ctx.bezierCurveTo(b.x2,b.y2,b.x1,b.y1,b.x0,b.y0);
  ctx.lineTo(t.x0,t.y0);


function calcPointsOnBezier(p0,p1,p2,p3)
  var points=;
  for(var x=parseInt(p0.x);x<parseInt(p3.x+1);x++)
    points[x]=p0.y;
  
  for(var i=0;i<1000;i++)
    var t=i/1000;
    var pt=getCubicBezierXYatT(p0,p1,p2,p3,t);
    points[parseInt(pt.x)]=parseInt(pt.y);
  
  return(points);


function draw()
  ctx.strokeStyle='gold';
  ctx.clearRect(0,0,cw,ch);
  ctx.drawImage(cup,0,0);


function getCubicBezierXYatT(startPt,controlPt1,controlPt2,endPt,T)
  var x=CubicN(T,startPt.x,controlPt1.x,controlPt2.x,endPt.x);
  var y=CubicN(T,startPt.y,controlPt1.y,controlPt2.y,endPt.y);
  return(x:x,y:y);


// cubic helper formula at T distance
function CubicN(T, a,b,c,d) 
  var t2 = T * T;
  var t3 = t2 * T;
  return a + (-a * 3 + T * (3 * a - a * T)) * T
  + (3 * b + T * (-6 * b + b * 3 * T)) * T
  + (c * 3 - c * 3 * T) * t2
  + d * t3;
body background-color: ivory; 
canvasborder:1px solid red;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
Vertical Position:<input id=myslider type=range min=0 max=100 value=50><br>
<canvas id="canvas" width=300 height=300></canvas>
<canvas id="face" width=300 height=300 hidden></canvas>

【讨论】:

这是我从我的存档项目中提取的部分代码。 ;-)

以上是关于交互式弯曲图像的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV中的图像处理 —— 霍夫线 / 圈变换 + 图像分割(分水岭算法) + 交互式前景提取(GrabCut算法)

交互式图像 - 反应

css 交互式图像比较 - 范围输入版本

使用 epub 查看交互式地图

如何在 Google Colab 中使用 matplotlib 绘制交互式可绘制图像?

如何获取要显示在 Oracle APEX 交互式报告中的图像或链接?