<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>FlashFuck.it &#187; webcam</title>
	<atom:link href="http://www.flashfuck.it/tag/webcam/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.flashfuck.it</link>
	<description>flash platform, gaming and 3D</description>
	<lastBuildDate>Mon, 23 Jan 2012 18:11:43 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>The Burning Man &#8211; bitmapData fire effect</title>
		<link>http://www.flashfuck.it/2009/07/16/the-burning-man-bitmapdata-fire-effect/</link>
		<comments>http://www.flashfuck.it/2009/07/16/the-burning-man-bitmapdata-fire-effect/#comments</comments>
		<pubDate>Thu, 16 Jul 2009 14:17:10 +0000</pubDate>
		<dc:creator>pigiuz</dc:creator>
				<category><![CDATA[ActionScript 3]]></category>
		<category><![CDATA[BitmapData]]></category>
		<category><![CDATA[effects]]></category>
		<category><![CDATA[experiments]]></category>
		<category><![CDATA[webcam]]></category>

		<guid isPermaLink="false">http://www.flashfuck.it/?p=149</guid>
		<description><![CDATA[Yesterday night it was too warm to sleep and I have no air conditioning at home, so I thought it was a good opportunity to make some experiments related to the high temperature&#8230; &#8220;the burning man&#8221; Here&#8217;s the algorithm in human language: - pick up the image from the webcam - perform a threshold on [...]]]></description>
			<content:encoded><![CDATA[<p>Yesterday night it was too warm to sleep and I have no air conditioning at home, so I thought it was a good opportunity to make some experiments related to the high temperature&#8230; &#8220;the burning man&#8221; <img src='http://www.flashfuck.it/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p>Here&#8217;s the algorithm in human language:<br />
- pick up the image from the webcam<br />
- perform a threshold on it to exclude (alpha 0) every pixel below the average skin amount of red (between 44 and 90 depending on the light)<br />
- perform a second threshold to exclude (alpha 0) every pixel above the average skin amount of green and blue (between 3344 and 6677 depending on the light)<br />
- draw the result onto a new bitmapdata with the ADD blendmode<br />
- apply blur to the bitmapdata<br />
- generate a perlin noise of one channel (i chose red)<br />
- displace the bitmapdata towards -y<br />
- apply again a displacement map filter to displace horizontally (i used a cos function to make the x displacement a little likely)<br />
- apply a displacement map towards +y with just a bit less strenght than the previous &#8220;-y&#8221; one (this is to make the fire propagation much more likely)<br />
- then merge the original webcam output with the displaced one&#8230;and you&#8217;ve the burning man! <img src='http://www.flashfuck.it/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>here the actionscript implementation</p>
<pre lang="actionscript">
package
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.BitmapDataChannel;
	import flash.display.BlendMode;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.filters.BlurFilter;
	import flash.filters.DisplacementMapFilter;
	import flash.filters.DisplacementMapFilterMode;
	import flash.geom.ColorTransform;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.media.Camera;
	import flash.media.Video;

	[SWF(width="320",height="240",frameRate="31",backgroundColor="0x000000")]
	public class BurningMan extends Sprite
	{

		private var _cam:Camera;
		private var _vid:Video;

		private var _fireThreshold:BitmapData;
		private var _firePerlin:BitmapData;
		private var _fireOffset:Point;
		private var _fireSpeed:int = 20;
		private var _fireDisplaceUP:DisplacementMapFilter;
		private var _fireDisplaceDWN:DisplacementMapFilter;
		private var _fireDisplaceSrc:BitmapData;
		private var _fireBlur:BlurFilter;
		private var _fireColorTransform:ColorTransform;

		private var _fireMerge:BitmapData;

		private var _camBd:BitmapData;
		private var _b:Bitmap;

		private static const WIDTH:Number = 320;
		private static const HEIGHT:Number = 240;
		private static const ORIGIN:Point = new Point();
		private static const REFLECT:Matrix = new Matrix(-1,0,0,1,WIDTH,0);
		private static const RESIZE_2X:Matrix = new Matrix(2,0,0,2);

		private var _rect:Rectangle;

		public function BurningMan()
		{
			super();
			init();
		}

		private function init():void
		{
			_cam = Camera.getCamera();
			_cam.setMode(WIDTH,HEIGHT,31);
			_vid = new Video(WIDTH,HEIGHT);
			_vid.attachCamera(_cam);

			_fireOffset = new Point();
			_fireThreshold = new BitmapData(WIDTH,HEIGHT,true,0x00000000);
			_fireMerge = new BitmapData(WIDTH,HEIGHT,true,0x00000000);

			_firePerlin = new BitmapData(WIDTH*.5,HEIGHT*.5,false,0x000000);
			_fireDisplaceSrc = new BitmapData(WIDTH,HEIGHT,false,0x000000);
			_fireDisplaceUP = new DisplacementMapFilter(_fireDisplaceSrc,ORIGIN,BitmapDataChannel.RED,BitmapDataChannel.RED,0,-15,DisplacementMapFilterMode.CLAMP);
			_fireDisplaceDWN = new DisplacementMapFilter(_fireDisplaceSrc,ORIGIN,BitmapDataChannel.RED,BitmapDataChannel.RED,0,9,DisplacementMapFilterMode.CLAMP);
			_fireBlur = new BlurFilter(2,2,4);
			_fireColorTransform = new ColorTransform(1.3,1.1,1,.7);

			_camBd = new BitmapData(WIDTH,HEIGHT,true,0x00000000);
			_rect = _camBd.rect;
			_b = new Bitmap(_camBd);
			_firePerlin.lock();
			_fireMerge.lock();
			addChild(_b);

			addEventListener(Event.ENTER_FRAME,update);
		}

		private function update(e:Event=null):void
		{
			//locks
			_camBd.lock();

			_fireOffset.y+=_fireSpeed;
			_firePerlin.perlinNoise(_firePerlin.width*.125,_firePerlin.height*.125,1,0,true,false,BitmapDataChannel.RED,false,[_fireOffset])
			_fireDisplaceSrc.draw(_firePerlin,RESIZE_2X);

			_camBd.draw(_vid,REFLECT);
			_fireThreshold.setVector(_rect,_camBd.getVector(_rect));
			_fireThreshold.threshold(_fireThreshold,_rect,ORIGIN,"<",0xFF440000,0x00000000,0xFF0000,true);
			_fireThreshold.threshold(_fireThreshold,_rect,ORIGIN,">",0xFF003344,0x00000000,0x00FFFF,true);
			_fireMerge.draw(_fireThreshold,null,_fireColorTransform,BlendMode.ADD,_rect);

			_fireDisplaceUP.scaleX = Math.cos(((_fireOffset.y/(2<<3))%360)*180/Math.PI)*2;
			_fireDisplaceDWN.scaleX = -_fireDisplaceUP.scaleX;
			_fireMerge.applyFilter(_fireMerge,_fireMerge.rect,ORIGIN,_fireBlur);
			_fireMerge.applyFilter(_fireMerge,_rect,ORIGIN,_fireDisplaceUP);
			_fireMerge.applyFilter(_fireMerge,_rect,ORIGIN,_fireDisplaceDWN);
			_camBd.draw(_fireMerge,null,_fireColorTransform,BlendMode.HARDLIGHT,_rect);

			//unlocks
			_camBd.unlock();
		}
	}
}
</pre>
<p>here's a preview of myself empowered by the force of the fire!:D<br />
<a href="http://www.flashfuck.it/test/burning_man/index.html" title="burning man" class="flickr-image alignnone"><img src="http://farm3.static.flickr.com/2517/3726036339_476f627507_o.jpg" alt="burning man" class=""  /></a><br />
click the photo to see the demo in action</p>
]]></content:encoded>
			<wfw:commentRss>http://www.flashfuck.it/2009/07/16/the-burning-man-bitmapdata-fire-effect/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

