Topic: Tilt-Shift photo effect in Canvas Pages that link to <a href="https://ozoneasylum.com/backlink?for=30755" title="Pages that link to Topic: Tilt-Shift photo effect in Canvas" rel="nofollow" >Topic: Tilt-Shift photo effect in Canvas\

 
Author Thread
poi
Paranoid (IV) Inmate

From: Norway
Insane since: Jun 2002

IP logged posted posted 01-10-2009 12:54 Edit Quote

Oy! Turns out I opened my mouth when we were talking about Tilt-Shift photo effect at work and my fellow WebApp team devs challenged me to implement such effect in Canvas.

So here comes a Tilt-Shift photo effect in Canvas.

It was straight forward to code and the results are really neat. Hope you like it.
I'll try to elaborate a bit on the techinque later.



(Edited by poi on 01-10-2009 13:06)

reisio
Paranoid (IV) Inmate

From: Florida
Insane since: Mar 2005

IP logged posted posted 01-10-2009 23:03 Edit Quote

Take that, unbelievers!

racerX
Nervous Wreck (II) Inmate

From: Portland Oregon
Insane since: Jun 2006

IP logged posted posted 01-10-2009 23:22 Edit Quote

Very nice.
Maybe you can help me quicken up a script I'm working on. It takes 4 points and draws an image in a perspective view. It looks great but it takes 30 seconds to finish.

The technique is lifted from Ben Joffe's canvas skew, which is no longer on the internet. I saved it a couple years ago and found it was the only example i could find to create a billboard type effect.

The only other example I've found is at this link.
http://wd-testnet.world-direct.at/mozilla/dhtml/funo/fish2.htm
Maybe you know who the author of this script is. I've been playing with it and have all four sides working but the clipping is messed up. I would love to ask them how to make it work. The server doesn't lead anywhere so I have no clue who's site it is.

Here's the Canvas Skew examples
source pic haha guy
http://www.hetemeel.com/archive/haha%20Im%20creating%20dynamic%20IMAGES!!1!.jpg


I can't post the script until I hear back from Mr. Joffe, whom I've emailed for permission. He might refuse to allow me to use it so I don't want be responsible for any damages, plus, he's a great scripter and I respect his intellectual property. I assume he posted the test so people could learn from it and he asks to be informed if the script is reused. I'm fairly certain I'll be able to share the script soon.


Your script would be an awesome addition to this for making convincing perspective.
May I use some of your techniques?

poi
Paranoid (IV) Inmate

From: Norway
Insane since: Jun 2002

IP logged posted posted 01-11-2009 21:35 Edit Quote

racerX: Ben, "Mr. Joffe", is a cool guy. I've worked, and partied, with him. I really doubt he'd have any problem as your code is not a total ripoff of his.

What are you doing for it to take 30 seconds ? Computing the pesrpective and doing 600-1200 drawImage of a 1pixel slice shouldn't take so long.

Feel free to use some of the techniques from my tilt-shift experiment. But bare in mind that's it's not optimized for speed.

racerX
Nervous Wreck (II) Inmate

From: Portland Oregon
Insane since: Jun 2006

IP logged posted posted 01-11-2009 23:45 Edit Quote

OK here's the code. I picked out the parts of his script that deal with the image and the points.
I might have it looping too many times or have something in the wrong order. It would be awesome if you could see what I'm doing wrong.

Here's the script

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<HTML lang="en">
<HEAD>
<TITLE>HTML</title>
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<META name="Content-Script-Type" content="text/javascript">
<META name="Content-Style-Type" content="text/css">
<STYLE type="text/css">
<!--
BODY {margin: 0;padding: 0;background-color: #000;color: #FFF;font-family: arial;font-size: 10pt;line-height: 200%;}
CANVAS {background-color: #FFF;}
-->
</STYLE>
<SCRIPT type="text/javascript">
<!--

const Refinement=1//sets size of slices less for better refinement
const x=100
const y=200
var pic=new Image();
pic.src="http://www.ozoneasylum.com/images/layouts/ozoneasylum/logos/default.jpg"

CanvasRenderingContext2D.prototype.skew=function(src, co){
this.save();var height=src.height;var width=src.width;var cr8ctx=document.createElement('CANVAS').getContext('2d');
var leftSpace=Math.min(co[0][0], conumber2[0]);//topleftX or bottmleftX return smallest
var totalWidth=Math.max(cont[0], coStrezz[0])-leftSpace;// top right or bottom right return biggest - smallest
cr8ctx.canvas.setAttribute('width', totalWidth);//biggest-smallest
cr8ctx.canvas.setAttribute('height', height);// actual image height
if (conumber2[0]<co[0][0]) cr8ctx.translate(co[0][0]-conumber2[0], 0);// if BL<TL translate(TL-BL,0)
var topWidth=cont[0]-co[0][0];//TR-TL
var botWidth=coStrezz[0]-conumber2[0];//BR-BL
var leftChange=conumber2[0]-co[0][0];//BL-TL
for (var i=0; i<height; i+=Refinement)
cr8ctx.drawImage(src, 0, i, width, Refinement, leftChange*i/height, i, Math.abs((topWidth*(height-i)+botWidth*i)/height), Refinement);
var leftTop=co[0]nt-(contnt-co[0]nt)*(co[0][0]-leftSpace)/(cont[0]-co[0][0]);
var rightTop=contnt+(contnt-co[0]nt)*(leftSpace+totalWidth-cont[0])/(cont[0]-co[0][0]);
var leftBot=conumber2nt-(coStrezznt-conumber2nt)*(conumber2[0]-leftSpace)/(coStrezz[0]-conumber2[0])-leftTop;
var rightBot=coStrezznt+(coStrezznt-conumber2nt)*(leftSpace+totalWidth-coStrezz[0])/(coStrezz[0]-conumber2[0])-rightTop;
for (var i=0; i<totalWidth; i+=Refinement)
this.drawImage(cr8ctx.canvas, i, 0, Refinement, height, leftSpace+i, (leftTop*(totalWidth-i)+rightTop*i)/totalWidth, Refinement, (leftBot*(totalWidth-i)+rightBot*i)/totalWidth);
this.restore(); }
function skewpic(dot){
var canvas=document.getElementById('canvas').getContext('2d');
for (var i=0; i<4; i++) {canvas.skew(pic, dot);} }
//
//Number.prototype.sqr=function(){return this*this}; |0 [0][0]=p0x 1 nt[0]=p1x
// topleft topright bottomleft bottomright | [0]nt=p0y ntnt=p1y
//THIS SCRIPT ADAPTED FROM BEN JOFFES'S CANVAS SKEW. PLEASE RETAIN THIS NOTICE. THANK(YOU)
//var dot=[[30,30],[380,100],[130,280],[180,80]]; |2 number2[0]=p2x 3 Strezz[0]=p3x
// | number2nt=p2x Strezznt=p3x
//-->
</SCRIPT>
</HEAD>
<BODY onload="skewpic([[30,240],[440,180],[200,460],[540,260]])">

<CANVAS id="canvas" width="800" height="500"></CANVAS><BR>
<B>Canvas Skew</B>
<a href="javascript:skewpic([[30,70],[380,10],[200,460],[280,180]])">hey</a>
</BODY>
</HTML>

I was hoping you could help me figure out how to straighten the lines. Although I really like how it looks curled like this and I want to be able to do this when I need to, I want to figure out how make the lines straight

Here's a clip of what you should see.
Probably only works in mozilla.
I haven't gotten around to playing with opera lately.

racerX
Nervous Wreck (II) Inmate

From: Portland Oregon
Insane since: Jun 2006

IP logged posted posted 01-11-2009 23:48 Edit Quote



woopsie! forgot the pic

racerX
Nervous Wreck (II) Inmate

From: Portland Oregon
Insane since: Jun 2006

IP logged posted posted 01-11-2009 23:52 Edit Quote

uh oh, the script got screwed up above

it's calling [numbers] some other name.

I'll wrap it in code tags. sorry.

code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<HTML lang="en">
<HEAD>
<TITLE>HTML</title>
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<META name="Content-Script-Type" content="text/javascript">
<META name="Content-Style-Type" content="text/css">
<STYLE type="text/css">
<!--
BODY {margin: 0;padding: 0;background-color: #000;color: #FFF;font-family: arial;font-size: 10pt;line-height: 200%;}
CANVAS {background-color: #FFF;}
-->
</STYLE>
<SCRIPT type="text/javascript">
<!--

const Refinement=1//sets size of slices less for better refinement
const x=100
const y=200
var pic=new Image();
pic.src="http://www.ozoneasylum.com/images/layouts/ozoneasylum/logos/default.jpg"

CanvasRenderingContext2D.prototype.skew=function(src, co){
this.save();var height=src.height;var width=src.width;var cr8ctx=document.createElement('CANVAS').getContext('2d');
var leftSpace=Math.min(co[0][0], co[2][0]);//topleftX or bottmleftX return smallest
var totalWidth=Math.max(co[1][0], co[3][0])-leftSpace;// top right or bottom right return biggest - smallest
cr8ctx.canvas.setAttribute('width', totalWidth);//biggest-smallest
cr8ctx.canvas.setAttribute('height', height);// actual image height
if (co[2][0]<co[0][0]) cr8ctx.translate(co[0][0]-co[2][0], 0);// if BL<TL  translate(TL-BL,0)
var topWidth=co[1][0]-co[0][0];//TR-TL
var botWidth=co[3][0]-co[2][0];//BR-BL
var leftChange=co[2][0]-co[0][0];//BL-TL
for (var i=0; i<height; i+=Refinement)
cr8ctx.drawImage(src, 0, i, width, Refinement, leftChange*i/height, i, Math.abs((topWidth*(height-i)+botWidth*i)/height), Refinement);
var leftTop=co[0][1]-(co[1][1]-co[0][1])*(co[0][0]-leftSpace)/(co[1][0]-co[0][0]);
var rightTop=co[1][1]+(co[1][1]-co[0][1])*(leftSpace+totalWidth-co[1][0])/(co[1][0]-co[0][0]);
var leftBot=co[2][1]-(co[3][1]-co[2][1])*(co[2][0]-leftSpace)/(co[3][0]-co[2][0])-leftTop;
var rightBot=co[3][1]+(co[3][1]-co[2][1])*(leftSpace+totalWidth-co[3][0])/(co[3][0]-co[2][0])-rightTop;
for (var i=0; i<totalWidth; i+=Refinement) 
this.drawImage(cr8ctx.canvas, i, 0, Refinement, height, leftSpace+i, (leftTop*(totalWidth-i)+rightTop*i)/totalWidth, Refinement, (leftBot*(totalWidth-i)+rightBot*i)/totalWidth);
this.restore();		}
function skewpic(dot){
var canvas=document.getElementById('canvas').getContext('2d');
for (var i=0; i<4; i++) {canvas.skew(pic, dot);}	}
//
//Number.prototype.sqr=function(){return this*this};  |0 [0][0]=p0x  1 [1][0]=p1x    
//       topleft topright bottomleft bottomright      |  [0][1]=p0y    [1][1]=p1y
//THIS SCRIPT ADAPTED FROM BEN JOFFES'S CANVAS SKEW. PLEASE RETAIN THIS NOTICE. THANK(YOU)
//var dot=[[30,30],[380,100],[130,280],[180,80]];	      |2 [2][0]=p2x  3 [3][0]=p3x
//                                                                                             |  [2][1]=p2x     [3][1]=p3x
//-->
</SCRIPT>
</HEAD>
<BODY onload="skewpic([[30,240],[440,180],[200,460],[540,260]])">

<CANVAS id="canvas" width="800" height="500"></CANVAS><BR>
<B>Canvas Skew</B> 
<a href="javascript:skewpic([[30,70],[380,10],[200,460],[280,180]])">hey</a>
</BODY>
</HTML>

racerX
Nervous Wreck (II) Inmate

From: Portland Oregon
Insane since: Jun 2006

IP logged posted posted 01-12-2009 21:31 Edit Quote

hehe figured it out. There's no reason to be looping canvas.skew(pic,dot). Duhhh.
it only needs to be called once. The loop was left over from the older script.
Now it only take a few seconds to draw the images really big. under 300px and it loads in about 1 second.

Thanks poi, I'm going to try to use the tilt-shift now. Wish me luck hahah

poi
Paranoid (IV) Inmate

From: Norway
Insane since: Jun 2002

IP logged posted posted 01-12-2009 21:46 Edit Quote

I just optimized the Tilt-Shift a little. Now I only generate the most blurry image and combine it with the original, thus saving in memory and dividing the number of drawImage for the actual render by 2

racerX: Sorry I haven't had time to check the source codes you pasted above.
Good luck with the code.

benjoffe
Neurotic (0) Inmate
Newly admitted

From:
Insane since: Feb 2009

IP logged posted posted 02-18-2009 14:07 Edit Quote

Hey poi,
I've thought of an optimisation for the tilt-shift, instead of using 240 drawImage calls you could draw a gradient over 'dof' from transparent to white and back with globalCompositionOperation set to destination-out. Then the temporary canvas could be pasted to the output with just one drawImage.

@racerX
FWIW I put that skew function back online: http://www.benjoffe.com/code/dev/canvas_skew/
I also came across a similar script somebody has written which uses some very clever tricks to simulate a perspective for a texture (it seems to be an approximation hack but it looks quite seamless): http://acko.net/blog/projective-texturing-with-canvas

poi
Paranoid (IV) Inmate

From: Norway
Insane since: Jun 2002

IP logged posted posted 02-18-2009 16:39 Edit Quote

benjoffe: mmh ... good point about the gradient + globalCompositeOperation. There's got to be a way to use them and update the output in real time.

Alas in the last link you pasted they do every thing with quads, which is completely retarded in an affine world. Using quads creates lots of approximations and thus requires much higher subdivision level to get a decent result than when dealing with triangles.

andyhu
Neurotic (0) Inmate
Newly admitted

From:
Insane since: Jul 2010

IP logged posted posted 07-30-2010 11:03 Edit Quote

Hi racerx,
Thanks for sharing your code. I need exactly same functionality to be done. However is there anyway we can implement it with excanvas so it can be rendered by IE? I have tried to use excanvas togheter with your script but it doesn't work.

Thanks

coach
Nervous Wreck (II) Inmate

From:
Insane since: May 2011

IP logged posted posted 05-31-2011 11:03 Edit Quote
Edit TP: spam removed
quakingbog
Obsessive-Compulsive (I) Inmate

From:
Insane since: Mar 2012

IP logged posted posted 03-12-2012 14:31 Edit Quote

I want to do something using some of the methods above, but much simpler I beliew... I simply want to take an image and skew it so that it looks like it has 3-dimensional perspective to it. You can see an example here of what I am trying to accomplish here:

http://www.world.org/skew

Any ideas? Is there something similar to what is presented above, but in much simpler form, to accomplish what I am trying to do?

Thanks!

- Jeff



Post Reply
 
Your User Name:
Your Password:
Login Options:
 
Your Text:
Loading...
Options:


« BackwardsOnwards »

Show Forum Drop Down Menu