<?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>Stormin&#039; The CastleStormin&#039; The Castle</title> <atom:link href="http://www.storminthecastle.com/feed/" rel="self" type="application/rss+xml" /><link>http://www.storminthecastle.com</link> <description>HTML5 Tips, Tricks and Code</description> <lastBuildDate>Thu, 23 May 2013 18:18:40 +0000</lastBuildDate> <language>en-US</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.5.1</generator> <item><title>Introduction to HTML5 Canvas</title><link>http://www.storminthecastle.com/2013/05/20/introduction-to-html5-canvas/</link> <comments>http://www.storminthecastle.com/2013/05/20/introduction-to-html5-canvas/#comments</comments> <pubDate>Mon, 20 May 2013 03:18:37 +0000</pubDate> <dc:creator>John Robinson</dc:creator> <category><![CDATA[Uncategorized]]></category><guid
isPermaLink="false">http://www.storminthecastle.com/?p=606</guid> <description><![CDATA[Maybe you&#8217;ve heard of the HTML 5 Canvas API, but don&#8217;t know what it&#8217;s good for&#8230;?  Maybe you&#8217;ve heard that it&#8217;s the way to go if you want to code an HTML5 game? Or maybe you&#8217;ve heard that it gives &#8230;<p
class="read-more"><a
href="http://www.storminthecastle.com/2013/05/20/introduction-to-html5-canvas/">Read more &#187;</a></p>]]></description> <content:encoded><![CDATA[<p><a
href="/2013/05/20/introduction-to-html5-canvas/"><img
class="alignleft size-full wp-image-607" style="border: none; background: none;" alt="canvas_sun_orange" src="http://www.storminthecastle.com/wp-content/uploads/2013/05/canvas_sun_orange.png?735384" width="128" height="128" /></a>Maybe you&#8217;ve heard of the HTML 5 Canvas API, but don&#8217;t know what it&#8217;s good for&#8230;?  Maybe you&#8217;ve heard that it&#8217;s the way to go if you want to code an HTML5 game? Or maybe you&#8217;ve heard that it gives you explicit control over drawing in your browser? So what does all that mean?&#8230; Just what is the HTML5 Canvas API?</p><p>Let me pull back the curtain a little for you and give you some insight into what the HTML5 Canvas API is all about and what it can do for you and your web apps.</p><p>In this article, I’m going to give an introductory overview of the HTML5 Canvas API.  The sample application that comes with this article, “<a
href="http://www.storminthecastle.com/projects/canvasintro/canvasplayground.html">Canvas Playground</a>”, gives a number of canvas drawing examples and even lets you interactively play around with the Canvas API. <a
href="http://www.storminthecastle.com/projects/canvasintro/canvasplayground.html">Give it a try</a>.</p><p><span
id="more-606"></span></p><p>The HTML5 Canvas API is a procedural drawing API for JavaScript.  It’s well supported in all major browsers including Internet Explorer (starting with version 9) and is defined by the <a
href="http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas/">HTML5 Canvas W3C specification</a>.  The Canvas API is a vector-based drawing API and should feel pretty familiar to those with exposure to graphics subsystems such as Quartz or GDI+.  But to those folks with less exposure the API may feel a bit overwhelming.  Here are just some of the capabilities at a glance:</p><ul><li>Defining Paths with lines, curves, arcs and more…</li><li>Filling and Stroking Paths</li><li>Clipping to a Path</li><li>Filling and Stroking Text</li><li>Affine Transformation (Translate, Scale, Rotate, Skew)</li><li>Fills using Gradients and Patterns</li><li>Pixel Manipulation</li><li>Offscreen Rendering</li><li>Rendering Blurred Shadows</li><li>Dashed Lines, Line End Caps and Joins</li><li>Exporting Canvas Rendering to a PNG or JPEG</li></ul><p>If all of this sounds a little foreign to you don&#8217;t worry.  Coming up I’ll touch on a few of these capabilities and show some concrete examples to give you a feel for the API and how it works.  First of all the HTML5 Canvas is a browser DOM object and can be added to your webpage either declaratively through the &lt;canvas&gt; tag or programatically through the createElement method.  Once defined it contains a framebuffer bitmap at screen resolution that is the same width and height of the canvas object itself.</p><pre><code>
&lt;canvas width=“640” height=“480”/&gt;
</code></pre><p>Adding this tag to your HTML page will create a canvas object on your page that is 640 pixels wide by 480 pixels high and will be transparent.  The DOM object associated with the canvas object doesn&#8217;t directly have any drawing methods.  In order to actually draw on the canvas, you have to obtain a drawing context object by calling the canvas’s getContext method with a string parameter of “2d”.</p><pre><code>
context = canvas.getContext("2d");
</code></pre><p>The context object returned contains the actual drawing APIs that allow us to draw on our canvas object.  Let&#8217;s give it a try.  The following code snippet shows how to get a reference to a canvas object on a page, get a reference to it’s 2d context and draw a red filled rectangle on the canvas.</p><pre><code>
// Get a reference to the canvas object
canvas = document.querySelector("canvas");
// Get a reference to it’s 2d drawing context
context = canvas.getContext("2d");

// Displays a filled red rectangle on the screen
context.fillStyle="#FF0000";
context.fillRect(50,50,100,150);
</code></pre><p>Next lets look at drawing some more interesting shapes.  Outside of a few convenience methods for rectangles almost all shape drawing is done through the use of Paths.  So you might be asking yourself… What the Heck is a Path? A Path is a collection of lines or shapes (possibly disconnected) that once defined can be either filled or stroked.  Let&#8217;s look at a quick illustrative example.</p><pre><code>
// Define a path in the shape of a triangle with the moveTo and lineTo methods
context.beginPath();
context.moveTo(400,50);
context.lineTo(50,400);
context.lineTo(400,400);
context.closePath();

// Fill the path
context.fillStyle="purple";
context.fill();

// Stroke the path
context.strokeStyle="blue";
context.lineWidth=7;
context.stroke();
</code></pre><p>This code defines a path in the shape of a triangle and then goes on to fill the path and then to stroke that same path.  Let&#8217;s walk through this line by line.  The graphics context maintains a current path as a part of its state and calls to certain methods will accumulate either lines or shapes into the current path.  in the first line of code, a call to beginPath clears the current path from the context so that we start with a clean slate.  The context object also maintains a current “pen” position that is used to help define a path. This pen position can be changed with the moveTo method which simply sets the current positon of the “pen” to the provided x and y coordinates.  The lineTo method uses the current pen position as a starting point and the provided x and y coordinates to add a line to the current path.  The current pen position will be updated to the point at the end of the line. The next lineTo method call uses the current pen position and the provided x and y position to add another line to the current path. The next call to closePath will close the path by adding a line from the current pen position to the point that started the current path.  We have now defined a path that is in the shape of a triangle.  But it&#8217;s important to note that even though we have defined a path, nothing has been drawn to the canvas.  A path really just describes a set of lines and shapes.  Now that we have defined path, the path can be either filled or stroked to actually do the drawing.  The fill method will fill the interior of the path with the current fill style. By default the fill color or style is set to black. To specify a different style we can use any CSS color value. A few examples of valid color values: “red”, “purple”, rgb(255,255,0), rgba(255,255,0,128), #ff00ff. In addition to filling a path, you can also stroke the path which will outline the shapes defined in the path with the current stroke style which can also take any valid CSS color value. To change the width of the stroke, you can specify a pixel width for the stroked lines with the lineWidth property.  You can play around with these values in the <a
title="Canvas Playground App" href="http://www.storminthecastle.com/projects/canvasintro/canvasplayground.html">Canvas Playground App</a> by loading the &#8220;polygon sample&#8221;.  Next lets look at the &#8220;circle&#8221; example.</p><pre><code>
// Define a path in the shape of a circle with the arc method
context.beginPath();
context.arc(320, 240, 150, 0, 2*Math.PI);

// Fill the Path
context.fillStyle="orange";
context.fill();

// Stroke the Path
context.strokeStyle="green";
context.lineWidth=15;
context.stroke();
</code></pre><p>This example demonstates that paths aren’t limited to lines or polygonal shapes, but can also include arcs or circles.  My <a
title="Canvas Playground App" href="http://www.storminthecastle.com/projects/canvasintro/canvasplayground.html">sample application</a> goes on to show a few more slightly advanced examples and lets you interactively tweak the code.  Take a look at the <a
title="W3C Canvas Specification" href="http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas/">full canvas specification</a> and experiment.  If you liked learning a few basics about the HTML5 Canvas API but are hungry for more&#8230; This<em> really is just the tip of the iceberg&#8230;  </em> My upcoming ebook, “Essential Canvas for HTML5” will cover the subject in depth.  Just drop your email into the form below so that I can let you know when it&#8217;s available.</p><div
id="mc_signup"><form
method="post" action="#mc_signup" id="mc_signup_form"> <input
type="hidden" id="mc_submit_type" name="mc_submit_type" value="html" /> <input
type="hidden" name="mcsf_action" value="mc_submit_signup_form" /> <input
type="hidden" id="_mc_submit_signup_form_nonce" name="_mc_submit_signup_form_nonce" value="daa8e9abab" /><div
class="mc_form_inside"><div
class="updated" id="mc_message"></div><div
class="mc_merge_var"> <label
for="mc_mv_EMAIL" class="mc_var_label">Email Address</label> <input
type="text" size="18" value="" name="mc_mv_EMAIL" id="mc_mv_EMAIL" class="mc_input"/></div><div
class="mergeRow"> <label>Preferred Format</label><div
class="field-group groups"><ul
class="mc_list"><li><input
type="radio" name="email_type" id="email_type_html" value="html" checked="checked"><label
for="email_type_html">HTML</label></li><li><input
type="radio" name="email_type" id="email_type_text" value="text"><label
for="email_type_text">Text</label></li><li><input
type="radio" name="email_type" id="email_type_mobile" value="mobile"><label
for="email_type_mobile">Mobile</label></li></ul></div></div><div
class="mc_signup_submit"> <input
type="submit" name="mc_signup_submit" id="mc_signup_submit" value="Subscribe" class="button" /></div></div></form></div><p>&nbsp;</p><p>Take a look at my <a
title="Sample Application" href="http://www.storminthecastle.com/projects/canvasintro/canvasintro.html">sample application</a> as it provides a <a
title="Live Demonstration" href="http://www.storminthecastle.com/projects/canvasintro/canvasintro.html">live demonstration</a> of all the examples shown in this article as well as a few more slightly advanced ones. The <a
title="Full Source Code" href="http://www.storminthecastle.com/projects/canvasintro/code.zip?735384">full source code for the article can be downloaded here</a>.</p><p>&nbsp;</p> ]]></content:encoded> <wfw:commentRss>http://www.storminthecastle.com/2013/05/20/introduction-to-html5-canvas/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Complex Animations Using HTML5 Canvas</title><link>http://www.storminthecastle.com/2013/05/13/complex-animations-using-html5-canvas/</link> <comments>http://www.storminthecastle.com/2013/05/13/complex-animations-using-html5-canvas/#comments</comments> <pubDate>Mon, 13 May 2013 00:55:01 +0000</pubDate> <dc:creator>John Robinson</dc:creator> <category><![CDATA[Uncategorized]]></category><guid
isPermaLink="false">http://www.storminthecastle.com/?p=595</guid> <description><![CDATA[In my upcoming ebook, &#8220;Essential Canvas for HTML5&#8220;, you&#8217;ll not only learn the basics of animation but you&#8217;ll also learn how to do complex Flash-like animations using HTML5 and Javascript that impart dynamics through tweening and other advanced techniques. I&#8217;ll &#8230;<p
class="read-more"><a
href="http://www.storminthecastle.com/2013/05/13/complex-animations-using-html5-canvas/">Read more &#187;</a></p>]]></description> <content:encoded><![CDATA[<p>In my upcoming ebook, &#8220;<a
title="Essential Canvas for HTML5" href="/book-essential-canvas-for-html5/">Essential Canvas for HTML5</a>&#8220;, you&#8217;ll not only learn the basics of animation but you&#8217;ll also learn how to do complex Flash-like animations using HTML5 and Javascript that impart dynamics through tweening and other advanced techniques. I&#8217;ll break it all down for you and walk you through the source code. Here is just one of the samples that come with the book.</p><iframe
width="640px" height="480px" src="/projects/book/fancyanimation.html" scrolling="no" class="iframe-class" frameborder="0"></iframe><p><span
id="more-595"></span></p><p><b>Learn the ins and outs of animation using the HTML5 Canvas API&#8230;</b> Join my mailing list now so that find out when &#8220;<a
title="Essential Canvas for HTML5" href="/book-essential-canvas-for-html5/">Essential Canvas for HTML5</a>&#8221; becomes available. Just drop your email into the form below!</p><div
id="mc_signup"><form
method="post" action="#mc_signup" id="mc_signup_form"> <input
type="hidden" id="mc_submit_type" name="mc_submit_type" value="html" /> <input
type="hidden" name="mcsf_action" value="mc_submit_signup_form" /> <input
type="hidden" id="_mc_submit_signup_form_nonce" name="_mc_submit_signup_form_nonce" value="daa8e9abab" /><div
class="mc_form_inside"><div
class="updated" id="mc_message"></div><div
class="mc_merge_var"> <label
for="mc_mv_EMAIL" class="mc_var_label">Email Address</label> <input
type="text" size="18" value="" name="mc_mv_EMAIL" id="mc_mv_EMAIL" class="mc_input"/></div><div
class="mergeRow"> <label>Preferred Format</label><div
class="field-group groups"><ul
class="mc_list"><li><input
type="radio" name="email_type" id="email_type_html" value="html" checked="checked"><label
for="email_type_html">HTML</label></li><li><input
type="radio" name="email_type" id="email_type_text" value="text"><label
for="email_type_text">Text</label></li><li><input
type="radio" name="email_type" id="email_type_mobile" value="mobile"><label
for="email_type_mobile">Mobile</label></li></ul></div></div><div
class="mc_signup_submit"> <input
type="submit" name="mc_signup_submit" id="mc_signup_submit" value="Subscribe" class="button" /></div></div></form></div><p><a
title="Essential Canvas for HTML5" href="/book-essential-canvas-for-html5/"><br
/><h2>Click here if you&#8217;d like to know more!</h2><p></a></p> ]]></content:encoded> <wfw:commentRss>http://www.storminthecastle.com/2013/05/13/complex-animations-using-html5-canvas/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>How You Can Build an HTML5 Photobooth App</title><link>http://www.storminthecastle.com/2013/05/07/how-you-can-build-an-html5-photobooth-app/</link> <comments>http://www.storminthecastle.com/2013/05/07/how-you-can-build-an-html5-photobooth-app/#comments</comments> <pubDate>Tue, 07 May 2013 02:17:49 +0000</pubDate> <dc:creator>John Robinson</dc:creator> <category><![CDATA[Uncategorized]]></category> <category><![CDATA[Canvas]]></category> <category><![CDATA[Graphics]]></category> <category><![CDATA[HTML5]]></category> <category><![CDATA[WebRTC]]></category><guid
isPermaLink="false">http://www.storminthecastle.com/?p=537</guid> <description><![CDATA[You want the users of your web app to be able to use their webcam to take their own profile shots and you&#8217;d like them to be able to personalize or stylize the picture before uploading it your weberver. Or &#8230;<p
class="read-more"><a
href="http://www.storminthecastle.com/2013/05/07/how-you-can-build-an-html5-photobooth-app/">Read more &#187;</a></p>]]></description> <content:encoded><![CDATA[<p><a
href="http://www.storminthecastle.com/wp-content/uploads/2013/05/photo-booth.png?735384"><img
class="alignleft size-full wp-image-538" style="border: none; background: none;" alt="photo-booth" src="http://www.storminthecastle.com/wp-content/uploads/2013/05/photo-booth.png?735384" width="128" height="128" /></a></p><p>You want the users of your web app to be able to use their webcam to take their own profile shots and you&#8217;d like them to be able to personalize or stylize the picture before uploading it your weberver. Or maybe you’ve seen one of those fun photobooth-type apps that takes photos, applies cool image effects to them and lets you share them&#8230; wondering how they worked.</p><p>Imagine if your HTML5 app could programmatically access your webcam, take snapshots and modify the image data procedurally. You could then let your user’s upload or share their self portraits.</p><p>In this article, I’m going to teach you how to do that and more. Building on some articles that I&#8217;ve shared in the past, I’ll walk you through a sample application that displays the video from your webcam, applies image processing effects to that video, lets you take still snapshots of the filtered video and lets you serialize the snapshots so that they can be uploaded to a web server.</p><p><span
id="more-537"></span></p><p>In one of my earlier articles, “<a
href="http://www.storminthecastle.com/2013/03/23/lights-camera-action/">Lights, Camera, Action!</a>” I showed you the minimal amount of code needed to access you webcam and display the video into an HTML5 video object.  In this sample, we use the same code which lets us display the original video from the webcam.  But in order to do something more interesting with the video, we need to get the image data into a canvas object so that our Javascript code can manipulate it.  In fact in the sample app, we actually hide the HTML5 video object itself by setting it&#8217;s display style to none and the filtered video is actually rendered by a canvas object.  As it turns out a HTML5 video object can be used in place of a source image in a drawImage call to a 2d canvas context. Unfortunately the HTML5 video object doesn’t provide a frame accurate way of accessing the image data for a given frame. So in order to acquire the frame data we’ll leverage the requestAnimationFrame method to execute our callback on a recurring basis so that it can repeatedly acquire video frames. The following code is used to alias the vendor prefixed variants of requestAnimationFrame in order to make the code more portable across a range of browsers.  <em>Credit: This requestAnimation polyfill was written by <a
title="Paul Irish's requestAnimationFrame polyfill" href="http://paulirish.com/2011/requestanimationframe-for-smart-animating/">Paul Irish</a>.</em></p><pre><code>// Alias the vendor prefixed variants of requestAnimationFrame so that 
// we can access them via window.requestAnimationFrame fallback to 
// setTimeout at 60hz if not supported.
window.requestAnimationFrame = (function(){
  return  window.requestAnimationFrame       || 
          window.webkitRequestAnimationFrame || 
          window.mozRequestAnimationFrame    || 
          window.oRequestAnimationFrame      || 
          window.msRequestAnimationFrame     || 
          function( callback ){
            window.setTimeout(callback, 1000 / 60);
          };
})();
</code></pre><p>When requestAnimationFrame is invoked it will invoke the provided callback in approximately 1/60th of a second.  We could have also just used the setTimeout method.  But there are several advantages to using requestAnimationFrame over setTimeout.  The primary advantage is that if the browser tab is not currently visible or if our browser is minimized then requestAnimationFrame (unlike setTimeout) will not invoke the callback, thereby saving cpu cycles when our page is not visible.  Our requestAnimationFrame callback function is called update and is shown below:</p><pre><code>function update(){  
  //...
  processVideoFrame();
  requestAnimationFrame(update); 
};
</code></pre><p>In the update function, processVideoFrame is called to acquire a single frame of video from the video object and process it.  A call to requestAnimationFrame is then made to queue our update function to be called again approximately 1/60th of a second later (Assuming that rate can be maintained by the CPU).  This function serves as the &#8220;pump&#8221; that will continually capture video frames and process them with any selected image filters.</p><pre><code>function processVideoFrame() {
  // We have to check for the video dimensions here.
  // Dimensions will be zero until they can be determined from
  // the stream.
  if (context &amp;&amp; video.videoWidth &gt; 0 &amp;&amp; video.videoHeight &gt; 0) {
    // Resize the canvas to match the current video dimensions
    if (canvas.width != video.videoWidth) 
      canvas.width = video.videoWidth;
    if (canvas.height != video.videoHeight) 
      canvas.height = video.videoHeight;

    // Copy the current video frame by drawing it onto the 
    // canvas's context
    context.drawImage(video, 0, 0, canvas.width, canvas.height);
    processImage(canvas);
  }
}
</code></pre><p>In the processVideoFrame function, the canvas object is sized to match the dimensions of the video object. A call to the drawImage method will copy the pixel data from the current frame within the video object onto the canvas&#8217;s context.  A subsequent call to processImage is made to apply an image filter if one is currently selected.</p><pre><code>function processImage() {
  if (canvas.width &gt; 0 &amp;&amp; canvas.height &gt; 0) {
    if (imageFilter) {      
      context.putImageData(imageFilter.apply(null, [context.getImageData(0, 0, 
        canvas.width, canvas.height)]), 0, 0);
    }
  }
}
</code></pre><p>In another one of my articles, “<a
href="http://www.storminthecastle.com/2013/04/06/how-you-can-do-cool-image-effects-using-html5-canvas/">How You Can Do Cool Image Effects Using HTML5 Canvas</a>”, I demonstrated how to apply image filters to the pixel data contained within a canvas object. We’ll be doing the same thing here on each frame of captured video.  In the sample app, the following image filters can be applied to the video: grayscale, sepia, red, brighter, darker.  <em>Please refer to my earlier article for more detail on image filters.</em></p><p>The next thing I want to cover is how you can take a snapshot of the image currently in our canvas, so that it can be uploaded or shared. The following function is used to take a snapshot.</p><pre><code>function takeSnapshot() {
  var url = canvas.toDataURL();
  console.log(url);
  // Set the src of the image url to the data url
  document.querySelector("#snapshot").src = url;
  // Display the DOM elements that contain the snapshot
  document.querySelector("#snapshotdiv").style.display="inline-block";
}
</code></pre><p>The real work is done by the canvas’s toDataURL method.  This method takes the image data currently contained within the canvas, copies it, compresses it and returns a data URL of this image. So just what is a data URL?  A data URL (or more correctly&#8230; a data URI) is a way to represent a serialized chunk of data as a <em>&#8220;stringified&#8221;</em> URL.  An example is shown here:</p><pre style="white-space: pre-wrap;"><code>data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==
</code></pre><p>This example data URL encodes a PNG image of a red dot. To try this out for yourself, you can take this example and paste it into the URL bar of your browser and you’ll see a small red dot rendered. If you’d like to learn more about data urls, check out the <a
href="http://en.wikipedia.org/wiki/Data_URI_scheme">wikipedia article</a>.  Since this URL is a base64 encoded version of the image file itself. This string can be uploaded to your webserver and saved. It will just take a bit of string manipulation and a base64 decoder in your backend code to convert it back to a binary image file. Turning our attention back the takeSnapshot function, once we’ve obtained the data url for our image it can be assigned the src property of an image object to display the snapshot.</p><p><strong>Get My Free Bonus Article on Color Matrix Filters!</strong>  I&#8217;ll send you a link to a bonus article for my data-driven Color Matrix Filter and sample application when you join my mailing list.  A Color Matrix Filter can do almost an infinite number of different color filter effects.  You won&#8217;t want to miss adding this to your toolchest!  Just drop your email in the form below:</p><div
id="mc_signup"><form
method="post" action="#mc_signup" id="mc_signup_form"> <input
type="hidden" id="mc_submit_type" name="mc_submit_type" value="html" /> <input
type="hidden" name="mcsf_action" value="mc_submit_signup_form" /> <input
type="hidden" id="_mc_submit_signup_form_nonce" name="_mc_submit_signup_form_nonce" value="daa8e9abab" /><div
class="mc_form_inside"><div
class="updated" id="mc_message"></div><div
class="mc_merge_var"> <label
for="mc_mv_EMAIL" class="mc_var_label">Email Address</label> <input
type="text" size="18" value="" name="mc_mv_EMAIL" id="mc_mv_EMAIL" class="mc_input"/></div><div
class="mergeRow"> <label>Preferred Format</label><div
class="field-group groups"><ul
class="mc_list"><li><input
type="radio" name="email_type" id="email_type_html" value="html" checked="checked"><label
for="email_type_html">HTML</label></li><li><input
type="radio" name="email_type" id="email_type_text" value="text"><label
for="email_type_text">Text</label></li><li><input
type="radio" name="email_type" id="email_type_mobile" value="mobile"><label
for="email_type_mobile">Mobile</label></li></ul></div></div><div
class="mc_signup_submit"> <input
type="submit" name="mc_signup_submit" id="mc_signup_submit" value="Subscribe" class="button" /></div></div></form></div><p>&nbsp;</p><p>That’s all for this go ‘round. Hope you’ve learned a few things and enjoyed the article. You can <a
href="http://www.storminthecastle.com/projects/photobooth/photoboothlite.html">try out the sample app here</a> and <a
href="http://www.storminthecastle.com/projects/photobooth/photoboothlite.zip?735384">get the full source code here</a>.</p> ]]></content:encoded> <wfw:commentRss>http://www.storminthecastle.com/2013/05/07/how-you-can-build-an-html5-photobooth-app/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Make Your UI More Responsive with HTML5 Web Workers</title><link>http://www.storminthecastle.com/2013/04/19/make-your-ui-more-responsive-with-html5-web-workers/</link> <comments>http://www.storminthecastle.com/2013/04/19/make-your-ui-more-responsive-with-html5-web-workers/#comments</comments> <pubDate>Fri, 19 Apr 2013 22:44:09 +0000</pubDate> <dc:creator>John Robinson</dc:creator> <category><![CDATA[Uncategorized]]></category> <category><![CDATA[HTML5]]></category> <category><![CDATA[Javascript]]></category><guid
isPermaLink="false">http://www.storminthecastle.com/?p=401</guid> <description><![CDATA[Argh!!… Your web application has to sort a lot of data and you get the dreaded error message… “A script on this page may be busy, or it may have stopped responding…” Or maybe you’re writing some image processing code &#8230;<p
class="read-more"><a
href="http://www.storminthecastle.com/2013/04/19/make-your-ui-more-responsive-with-html5-web-workers/">Read more &#187;</a></p>]]></description> <content:encoded><![CDATA[<p><a
href="http://www.storminthecastle.com/2013/04/19/make-your-ui-more-responsive-with-html5-web-workers/"><img
class="alignleft size-full wp-image-403" style="border: none; background: none;" alt="HTML5 Web Workers" src="http://www.storminthecastle.com/wp-content/uploads/2013/04/HTML5_Badge_Perf_150.png?735384" width="150" height="150" /></a></p><p>Argh!!… Your web application has to sort a lot of data and you get the dreaded error message… <i>“A script on this page may be busy, or it may have stopped responding…” </i> Or maybe you’re writing some image processing code that takes forever on large images… Your UI is non-responsive. What are you going to do!!?… You could try to break up the work into small pieces and use timers to spread out the work. But what a PITA!</p><p>What if JavaScript had the ability to run your code in the background and not interfere with the responsiveness of your UI. What if you could spawn a thread to do long running computations such as image filtering and sorting. Well with <strong>HTML5 Web Workers</strong> you can do just that! In the rest of this article, I’m going to teach you how to use Web Workers within your own applications. <a
title="Web Workers Sample App" href="http://www.storminthecastle.com/projects/webworkers/workers.html" target="_blank">Click here to try the sample app.</a></p><p><span
id="more-401"></span></p><p>Web Workers are an HTML5 feature that allow a JavaScript developer to create additional threads of execution which can be used to execute long running code in the background. Normally your JavaScript runs on what is called the main UI thread. Everything you do from JavaScript including all DOM manipulations are executed sequentially on this single thread. If your JavaScript code runs too long without returning control to the browser, your UI will stop responding to the user. The following single line of code shows how to create a web worker:</p><pre><code>    
// A webworker is created and the JavaScript file longjob.js
// is loaded into its context.
worker = new Worker("longjob.js");
</code></pre><p>This code creates a new web worker object that has its own JavasScript context running in its own thread, loads the referenced JavaScript URL into that context and executes it.  In the next code block, we&#8217;ll walk through this again giving a bit more context.</p><pre><code>
var worker;

function runInWebWorker() {
  // Does our browser support webworkers?
  if (!worker &amp;&amp; window.Worker) {
    // A webworker is created and the JavaScript file longjob.js
    // is loaded into its context.
    worker = new Worker("longjob.js");
    if (worker) {
      // Register an event handler that will receive messages from our
      // web worker
      worker.addEventListener('message', function(e) {
        // Our webworker sends us a message when it is done.
        alert("longJob returned: " + e.data);
      });    
    }
    // Send a message to the worker to execute the longJob function
    // in the context of the workers thread.
    worker.postMessage(30);
  }
  else alert("Web Workers are not Supported in this Browser.");
}
</code></pre><p>Message passing is the mechanism used to communicate between a web worker and the main UI thread.  The web worker&#8217;s postMessage method is used to send messages to and from the web worker.  In order to receive a message an event handler must be registered with the addEventListener method.  In the code block above, after checking to see if the browser supports web workers and we’ve created the web worker, a &#8216;message&#8217; event handler is registered on the web worker object.  This particular event handler is used by the main UI thread to receive messages from our web worker.  Next a call to postMessage is made to send a message in the other direction to our web worker.  In the sample, we pass a simple numeric value of 30 as the message payload (which will be the number of seconds that we want our job to run).  <em>Note: You can send more complicated messages in the form of arrays or simple objects.</em>  In the next code block, we&#8217;ll look at the code loaded into our web worker, the contents of longjob.js:</p><pre><code>
// longjob.js
// function to simulate a long running job
// loops for approximately n seconds.
function longJob(n) {
  var start = new Date(); 
  var elapsedSeconds = 0;
  while(elapsedSeconds &lt; n) {
    var v = 0;
    for (var i = 0; i &lt; 1000000; i++) v += i;
    var end = new Date();
    elapsedSeconds = (end.getTime() - start.getTime())/1000.0;
  }
  return "All Done in " + elapsedSeconds + " seconds.";
}

// Our webworker registers for an message event so we can talk
// to it from our main thread and ask it to do something.
self.addEventListener('message', function(e) {

  // Invoke the longjob function within our worker thread
  // and pass in the parameter that was sent in.
  var result = longJob(e.data);

  //  Send a message back to the main thread with the result
  self.postMessage(result);
  }, false);
</code></pre><p>The longJob function simulates a long running function by taking a numeric value n and looping until n seconds have transpired.  Next an event handler is registered with a call to self.addEventListener so that our web worker can receive messages sent to it from the main UI thread.  <em>Note that within the context of our web worker the special variables <strong>this</strong> and <strong>self</strong> reference the web worker object itself.</em>  The parameter passed into the postMessage API is made available as a <em>data</em> property (shown as e.data in code above) on the event object passed into the event callback function.  When longJob completes our event handler sends a message back to the main thread using the postMessage method.</p><p>Web workers can be a very useful and empowering feature but they do have some limitations. All communication into and out of your web workers is done by passing in and out data in the form of messages.  All data is passed by value meaning that any object references are converted to a serialized copy of the objects data.  You can’t directly access or manipulate the DOM from a web worker.  While this may seem somewhat limiting these restrictions pretty much eliminate all of the synchronization bugs that can arise when using threads.</p><p><strong>Want more on Web Workers?</strong> Signup for my mailing list and I&#8217;ll send you a link to the updated code from my earlier article, “How You Can Do Cool Image Effects Using HTML5 Canvas”, that will now run the image filters in the background using Web Workers. Just drop your email in the form below!<br
/><div
id="mc_signup"><form
method="post" action="#mc_signup" id="mc_signup_form"> <input
type="hidden" id="mc_submit_type" name="mc_submit_type" value="html" /> <input
type="hidden" name="mcsf_action" value="mc_submit_signup_form" /> <input
type="hidden" id="_mc_submit_signup_form_nonce" name="_mc_submit_signup_form_nonce" value="daa8e9abab" /><div
class="mc_form_inside"><div
class="updated" id="mc_message"></div><div
class="mc_merge_var"> <label
for="mc_mv_EMAIL" class="mc_var_label">Email Address</label> <input
type="text" size="18" value="" name="mc_mv_EMAIL" id="mc_mv_EMAIL" class="mc_input"/></div><div
class="mergeRow"> <label>Preferred Format</label><div
class="field-group groups"><ul
class="mc_list"><li><input
type="radio" name="email_type" id="email_type_html" value="html" checked="checked"><label
for="email_type_html">HTML</label></li><li><input
type="radio" name="email_type" id="email_type_text" value="text"><label
for="email_type_text">Text</label></li><li><input
type="radio" name="email_type" id="email_type_mobile" value="mobile"><label
for="email_type_mobile">Mobile</label></li></ul></div></div><div
class="mc_signup_submit"> <input
type="submit" name="mc_signup_submit" id="mc_signup_submit" value="Subscribe" class="button" /></div></div></form></div></p><p>I hope you’ve enjoyed learning about web workers. You can get the <a
title="Full Source Code" href="http://www.storminthecastle.com/projects/webworkers/code.zip?735384">full source code for the article here</a> and try out the <a
title="Web Workers Sample App" href="http://www.storminthecastle.com/projects/webworkers/workers.html" target="_blank">sample app here</a>.</p> ]]></content:encoded> <wfw:commentRss>http://www.storminthecastle.com/2013/04/19/make-your-ui-more-responsive-with-html5-web-workers/feed/</wfw:commentRss> <slash:comments>8</slash:comments> </item> <item><title>How You Can Do Cool Image Effects Using HTML5 Canvas</title><link>http://www.storminthecastle.com/2013/04/06/how-you-can-do-cool-image-effects-using-html5-canvas/</link> <comments>http://www.storminthecastle.com/2013/04/06/how-you-can-do-cool-image-effects-using-html5-canvas/#comments</comments> <pubDate>Sat, 06 Apr 2013 08:05:52 +0000</pubDate> <dc:creator>John Robinson</dc:creator> <category><![CDATA[Uncategorized]]></category> <category><![CDATA[Canvas]]></category> <category><![CDATA[HTML5]]></category> <category><![CDATA[Javascript]]></category><guid
isPermaLink="false">http://www.storminthecastle.com/?p=358</guid> <description><![CDATA[You need to know how image filters work!  You’re writing an HTML5 application that works with images and you’d like to let your users dynamically alter the brightness of their images. Or maybe you’d like them to be able to &#8230;<p
class="read-more"><a
href="http://www.storminthecastle.com/2013/04/06/how-you-can-do-cool-image-effects-using-html5-canvas/">Read more &#187;</a></p>]]></description> <content:encoded><![CDATA[<p><a
href="http://www.storminthecastle.com/?p=358"><img
class="alignleft size-full wp-image-206" title="appicon" alt="" src="http://www.storminthecastle.com/wp-content/uploads/2013/04/filtered-150x150.jpg?735384" width="192" height="192" /></a>You need to know how image filters work!  You’re writing an HTML5 application that works with images and you’d like to let your users dynamically alter the brightness of their images. Or maybe you’d like them to be able to give their image a vintage look&#8230;. or convert it to black and white to give that sense of drama&#8230;</p><p>Wouldn’t it be great if you knew how to apply cool image effects such as these from JavaScript dynamically? Would you like to learn the code behind how these image filters work? You totally can… This article will give you the fundamentals for basic image processing using the HTML5 Canvas API. You’ll learn how to write code that accesses an image’s pixel data and transforms this pixel data programmatically to perform cool image effects. <a
title="Image Filters!" href="/projects/imagefilters1" target="_blank">Click here to try the sample app.</a></p><p><span
id="more-358"></span></p><p>The HTML 5 Canvas API is used here to access and manipulate the pixel data of an image. Once we have loaded an image, we can draw that image into the 2d context of a canvas object as the code snippet below shows.</p><pre><code>    
    var image = new Image();
    image.onload = function () {
      if (image.width != canvas.width)
        canvas.width = image.width;
      if (image.height != canvas.height)
        canvas.height = image.height;
      context.clearRect(0, 0, canvas.width, canvas.height);
      context.drawImage(image, 0, 0, canvas.width, canvas.height);
      filterCanvas(imageFilter);
    }
    image.src = imageURL;
  }
</code></pre><p>Once the image has been drawn into the context, we can access the pixel data of the context by invoking the context’s getImageData method. This method will return an object that has information about every pixel in the image.</p><pre><code>
  var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
</code></pre><p>The returned imageData object will contain a property called data which will reference a single dimension array of numbers. This array of numbers is a packed array containing a red, a green, a blue and an alpha value for each pixel in the image. Therefore the number of values in this array will be equal to W x H x 4. Where W is the width of the canvas, H is the height of the canvas and 4 is the number of color components (red, green, blue, alpha). The range for a color component value is from 0–255. If you try to assign a value to a color component outside of this range the value will be clamped. Using this array you can write code that inspects and manipulates the pixel data. To update the canvas&#8217;s context with any modifications to the imageData object the context’s putImageData method can be used to write the pixel data back.</p><pre><code>       
  context.putImageData(imageData, 0, 0);
</code></pre><p>What you do with the imageData between calling these two methods is really what this article is all about and where you can apply a filter to transform the appearance of the image. So putting it all together as follows:</p><pre><code>  
  // apply a filter to the image data contained in the canvas object
  function filterCanvas(filter) {
    if (canvas.width &gt; 0 &amp;&amp; canvas.height &gt; 0) {
      var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
      filter(imageData);
      context.putImageData(imageData, 0, 0);
    }
  }
</code></pre><p>The first filter that I&#8217;ll describe is often referred to as a grayscale filter. This filter sets the intensity of the red, green and blue color components to the arithmetic average of those values. This has the effect of changing a color image into a black and white or grayscale image. If you look at the snippet below you’ll see that the code loops through 1 pixel each time thru the loop. The value referenced by d[i] will always be the red component for the current pixel. The value referenced by d[i+1] will always be the green component. The value referenced by d[i+2] will always be the blue component. The value referenced by d[i+3] will always be the alpha component for the current pixel. <em>Note: The alpha value is used to specify the transparency of the pixel. In all of the filters shown in this article the alpha component is not referenced or altered; therefore leaving it intact.</em> The grayscale filter adds the red, green and blue values together and divides by three yielding an average value. This average value is assigned back to all 3 color components. Give this a try by clicking the grayscale link in the sample app.</p><pre><code>  
  // grayscale filter using an arithmetic average of the color 
  // components
  grayscale = function (pixels, args) {
    var d = pixels.data;
    for (var i = 0; i &lt; d.length; i += 4) {
      var r = d[i];
      var g = d[i + 1];
      var b = d[i + 2];
      d[i] = d[i + 1] = d[i + 2] = (r+g+b)/3;
    }
    return pixels;
  };
</code></pre><p>The next effect I’ll talk about is another popular one often referred to as a sepia filter. A sepia filter imparts a warm, antique look to an image. The math behind a sepia filter leverages a number of weighted formulas for each color component that factor in a contribution from each color component to arrive at a new value. Looking at the formulas in the code snippet below you’ll see a number of “magic” weights that will give us the desired effect. Each time through the loop the red, green and blue components for a single pixel will be updated. An interesting exercise for the reader is to experiment with these weights to come with your own  unique filter.</p><pre><code>  
  // sepia-style filter that gives a warm antique feel to an image
  sepia = function (pixels, args) {
    var d = pixels.data;
    for (var i = 0; i &lt; d.length; i += 4) {
      var r = d[i];
      var g = d[i + 1];
      var b = d[i + 2];
      d[i]     = (r * 0.393)+(g * 0.769)+(b * 0.189); // red
      d[i + 1] = (r * 0.349)+(g * 0.686)+(b * 0.168); // green
      d[i + 2] = (r * 0.272)+(g * 0.534)+(b * 0.131); // blue
    }
    return pixels;
  };
</code></pre><p>The next filter has a lot of similarities to the grayscale filter. But rather than applying the average back to all color components it only applies it to the red component thereby shifting all of the color information to red. The green and blue channels are zeroed out. Another excercise for the reader is to make a blue or a green filter.</p><pre><code>  
  // filter that shifts all color information to red
  red = function (pixels, args) {
    var d = pixels.data;
    for (var i = 0; i &lt; d.length; i += 4) {
      var r = d[i];
      var g = d[i + 1];
      var b = d[i + 2];
      d[i] = (r+g+b)/3;        // apply average to red channel
      d[i + 1] = d[i + 2] = 0; // zero out green and blue channel
    }
    return pixels;
  };
</code></pre><p>The brightness filter is the last one we’ll cover in this article. In this filter a positive or negative value is added to each red, green and blue component. This has the effect of either brightening the image given a positive value or darkening the image with a negative value. The function for this filter is slightly different than the others in that we use a JavaScript closure to create a parameterized function. By invoking the brightness function with a numeric parameter a new function instance is returned that will bound to the supplied delta parameter. This newly returned function object is the actual filter function.</p><pre><code>  
  // filter that brightens an image by adding a fixed value 
  // to each color component
  // a javascript closure is used to parameterize the filter 
  // with the delta value
  brightness = function(delta) {
      return function (pixels, args) {
        var d = pixels.data;
        for (var i = 0; i &lt; d.length; i += 4) {
          d[i] += delta;     // red
          d[i + 1] += delta; // green
          d[i + 2] += delta; // blue   
        }
        return pixels;
      };
  };
</code></pre><p>Want to learn more about image filters&#8230;</p><p><strong>Get My Free Bonus Article on Color Matrix Filters!</strong>  I&#8217;ll send you a link to a bonus article for my data-driven Color Matrix Filter and sample application when you join my mailing list.  A Color Matrix Filter can do almost an infinite number of different color filter effects.  You won&#8217;t want to miss adding this to your toolchest!  Just drop your email in the form below:</p><div
id="mc_signup"><form
method="post" action="#mc_signup" id="mc_signup_form"> <input
type="hidden" id="mc_submit_type" name="mc_submit_type" value="html" /> <input
type="hidden" name="mcsf_action" value="mc_submit_signup_form" /> <input
type="hidden" id="_mc_submit_signup_form_nonce" name="_mc_submit_signup_form_nonce" value="daa8e9abab" /><div
class="mc_form_inside"><div
class="updated" id="mc_message"></div><div
class="mc_merge_var"> <label
for="mc_mv_EMAIL" class="mc_var_label">Email Address</label> <input
type="text" size="18" value="" name="mc_mv_EMAIL" id="mc_mv_EMAIL" class="mc_input"/></div><div
class="mergeRow"> <label>Preferred Format</label><div
class="field-group groups"><ul
class="mc_list"><li><input
type="radio" name="email_type" id="email_type_html" value="html" checked="checked"><label
for="email_type_html">HTML</label></li><li><input
type="radio" name="email_type" id="email_type_text" value="text"><label
for="email_type_text">Text</label></li><li><input
type="radio" name="email_type" id="email_type_mobile" value="mobile"><label
for="email_type_mobile">Mobile</label></li></ul></div></div><div
class="mc_signup_submit"> <input
type="submit" name="mc_signup_submit" id="mc_signup_submit" value="Subscribe" class="button" /></div></div></form></div><p>&nbsp;</p><p>I hope you’ve enjoyed this brief tour on image filters.  You can get the <a
href="/projects/imagefilters1/imagefilters1.zip?735384">full source code for the article here</a> and try out the <a
title="Image Filters!" href="/projects/imagefilters1/" target="_blank">sample app here</a>.</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p> ]]></content:encoded> <wfw:commentRss>http://www.storminthecastle.com/2013/04/06/how-you-can-do-cool-image-effects-using-html5-canvas/feed/</wfw:commentRss> <slash:comments>11</slash:comments> </item> <item><title>Lights, Camera, Action!</title><link>http://www.storminthecastle.com/2013/03/23/lights-camera-action/</link> <comments>http://www.storminthecastle.com/2013/03/23/lights-camera-action/#comments</comments> <pubDate>Sat, 23 Mar 2013 19:20:36 +0000</pubDate> <dc:creator>John Robinson</dc:creator> <category><![CDATA[Uncategorized]]></category> <category><![CDATA[HTML5]]></category> <category><![CDATA[Javascript]]></category> <category><![CDATA[WebRTC]]></category><guid
isPermaLink="false">http://www.storminthecastle.com/?p=315</guid> <description><![CDATA[So You Want to Access Your Webcam from Javascript? Web Real-Time Communications or WebRTC is an exciting new HTML5 technology that not only gives JavaScript the ability to do peer-to-peer (P2P) audio/video conferencing and P2P data communications between browsers, it &#8230;<p
class="read-more"><a
href="http://www.storminthecastle.com/2013/03/23/lights-camera-action/">Read more &#187;</a></p>]]></description> <content:encoded><![CDATA[<p><a
href="http://www.storminthecastle.com/2013/03/23/lights-camera-action/"><img
class="alignleft size-full wp-image-206" title="appicon" src="http://www.storminthecastle.com/wp-content/uploads/2013/03/Camera-icon.png?735384" alt="" width="150" height="150" /></a><br
/><h3>So You Want to Access Your Webcam from Javascript?</h3></p><p><a
href="http://www.w3.org/2011/04/webrtc-charter.html">Web Real-Time Communications</a> or <a
href="http://www.w3.org/2011/04/webrtc-charter.html">WebRTC</a> is an exciting new HTML5 technology that not only gives JavaScript the ability to do peer-to-peer (P2P) audio/video conferencing and P2P data communications between browsers, it also lets you have programmatic access to attached cameras and microphones. Prior to WebRTC you had to rely on a browser plugin such as Adobe Flash to be able to do similar things. But recently there has been a big push to add these capabilites as intrinsic features to web browsers with <a
href="http://juberti.blogspot.com">Google</a> really leading the charge and through standardization efforts by the <a
href="http://www.w3.org/2011/04/webrtc-charter.html">W3C WebRTC working group</a>. It is a brave new world in that only some browsers have added WebRTC support and even those that do can have subtle (and some not so subtle) differences in both interface and implementation. But more and more you’re seeing real applications appearing that are using WebRTC in very cool and interesting ways. One great example of WebRTC in action is a PhotoBooth-like app called <a
href="http://webcamtoy.com">WebCam Toy</a>. This application should give you a sense of the possibilites that WebRTC is opening up.</p><p>In the rest of this article, I’m going to walk you through the minimum code needed to get your webcam to display video in your browser. The latest versions of <a
href="http://www.google.com/chrome">Chrome</a> or <a
href="http://www.mozilla.org/en-US/firefox/new">Firefox</a> are recommended for running the code included in this article and for experimenting with WebRTC. If you already have one of these browsers you can try out my <a
href="/projects/camera101/camera101.html" target="demo">example</a>.</p><p><strong><em>So lets get started&#8230;</em></strong></p><p><span
id="more-315"></span></p><p>WebRTC defines the getUserMedia method on the top level navigator object as the mechanism for getting access to an attached camera/microphone. Since WebRTC is still in a state of flux, we do have to shim a number of vendor prefixed variants to increase the portability of our code as follows:</p><pre><code>
// Alias the vendor prefixed variants of getUserMedia 
// so we can access them via navigator.getUserMedia
navigator.getUserMedia = navigator.getUserMedia ||  
    navigator.webkitGetUserMedia || navigator.mozGetUserMedia ||    
    navigator.msGetUserMedia;
</code></pre><p>After checking to make sure that the getUserMedia method is available it can be invoked as follows:</p><pre><code>
if (navigator.getUserMedia) {
    // Call the getUserMedia method here
    navigator.getUserMedia({video: true}, successCallback, 
        failureCallback);
}
</code></pre><p>This will cause the browser to prompt the user for permission to access an attached camera. <em>Note: This is done for security reasons so that a random website can’t access your camera without your permission.</em> If there is an attached camera and the user grants access then the function passed in as successCallback in the above example will get invoked; otherwise the failureCallback function will be called. <em>Note: Unfortunately at the time of this writing you can not determine whether the failure was due to the lack of an attached camera or whether the user denied access.</em> On success, the successCallback function will be passed a stream object that be used to stream the video data from the camera to the video object that cooresponds to our video tag.</p><pre><code>
// Alias the vendor prefixed variants of the URL object 
// so that we can access them via window.URL
window.URL = window.URL || 
    window.webkitURL || window.mozURL || window.msURL;

// This function will be called if a webcam is available 
// and the user has granted access for the web 
// application to use it.
function successCallback(stream) {
    if (video.mozSrcObject !== undefined) {
        video.mozSrcObject = stream;
    } else {
        video.src = (window.URL &amp;&amp; 
            window.URL.createObjectURL(stream)) ||
            stream;
    };
    video.play();
}
</code></pre><p>WebRTC leverages the HTML5 &lt;video&gt; tag as the DOM element for rendering video content from your camera. If you look at the example you’ll see that we included the video tag with no attributes in the body of our document.</p><pre><code>
&lt;video/&gt;
</code></pre><p>Now that we have a reference to the video stream. We need to connect it up to the video object defined by the video tag so we can see the video. Things get a little messy here because of some interface differences between browsers. Most browsers allow you to set the src property to a URL generated from the createObjectURL method but Firefox defines a different property called mozSrcObject that allows you to pass the stream object in directly. The code snippet shown above shows how to deal with this minor inconvenience. Once we’ve hooked up the stream to the video object, we simply have to call play on the video object to start rendering the video.</p><p><b><i>That’s all there is to it to get the output of your camera working in your browser with WebRTC. Very very cool&#8230;</i></b></p><p>All in all WebRTC is off to a great start for further enhancing the web. But there are a number of unfortunate and annoying limitations that hopefully get addressed in future enhancements to WebRTC. Currently you can’t enumerate the set of supported resolutions for a given camera and its not really possibly to cleanly probe for supported resolutions. However if you do know the set of resolutions supported by your camera you can specify them by passing in additional <a
href="http://tools.ietf.org/html/draft-alvestrand-constraints-resolution-00#page-4">constraints</a> to the getUserMedia method. As an example:</p><pre><code>
navigator.getUserMedia({video: {mandatory: {minWidth: 1024, 
    minHeight: 768 }}}, 
    successCallback, failureCallback);
</code></pre><p>Again you can get the <a
href="/projects/camera101/camera101.html" target="demo">full source code</a> for this article <a
href="/projects/camera101/camera101.html" target="demo">here</a> and I hope you have a great time exploring the new frontier that is WebRTC!</p><p>Join my mailing list to get my tips, tricks and articles delivered straight to your inbox.</p><div
id="mc_signup"><form
method="post" action="#mc_signup" id="mc_signup_form"> <input
type="hidden" id="mc_submit_type" name="mc_submit_type" value="html" /> <input
type="hidden" name="mcsf_action" value="mc_submit_signup_form" /> <input
type="hidden" id="_mc_submit_signup_form_nonce" name="_mc_submit_signup_form_nonce" value="daa8e9abab" /><div
class="mc_form_inside"><div
class="updated" id="mc_message"></div><div
class="mc_merge_var"> <label
for="mc_mv_EMAIL" class="mc_var_label">Email Address</label> <input
type="text" size="18" value="" name="mc_mv_EMAIL" id="mc_mv_EMAIL" class="mc_input"/></div><div
class="mergeRow"> <label>Preferred Format</label><div
class="field-group groups"><ul
class="mc_list"><li><input
type="radio" name="email_type" id="email_type_html" value="html" checked="checked"><label
for="email_type_html">HTML</label></li><li><input
type="radio" name="email_type" id="email_type_text" value="text"><label
for="email_type_text">Text</label></li><li><input
type="radio" name="email_type" id="email_type_mobile" value="mobile"><label
for="email_type_mobile">Mobile</label></li></ul></div></div><div
class="mc_signup_submit"> <input
type="submit" name="mc_signup_submit" id="mc_signup_submit" value="Subscribe" class="button" /></div></div></form></div><p>&nbsp;</p> ]]></content:encoded> <wfw:commentRss>http://www.storminthecastle.com/2013/03/23/lights-camera-action/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Future of UI on the Web?</title><link>http://www.storminthecastle.com/2011/11/13/future-of-ui-on-the-web/</link> <comments>http://www.storminthecastle.com/2011/11/13/future-of-ui-on-the-web/#comments</comments> <pubDate>Sun, 13 Nov 2011 13:10:53 +0000</pubDate> <dc:creator>John Robinson</dc:creator> <category><![CDATA[Uncategorized]]></category> <category><![CDATA[Future]]></category> <category><![CDATA[Graphics]]></category> <category><![CDATA[HTML]]></category> <category><![CDATA[Rants]]></category><guid
isPermaLink="false">http://www.storminthecastle.com/?p=195</guid> <description><![CDATA[HTML+CSS suck for building apps. There I said it&#8230; I mean lets face it, building apps in HTML+CSS is pretty much like doing word processing in LaTeX.  What ever happened to decent visual tools? And I&#8217;m tired of dealing with &#8230;<p
class="read-more"><a
href="http://www.storminthecastle.com/2011/11/13/future-of-ui-on-the-web/">Read more &#187;</a></p>]]></description> <content:encoded><![CDATA[<p><a
href="http://www.storminthecastle.com/2011/11/13/future-of-ui-on-the-web/"><img
class="alignleft size-full wp-image-206" title="appicon" src="http://www.storminthecastle.com/wp-content/uploads/2011/11/appicon.jpg?735384" alt="" width="240" height="203" /></a><span
class="Apple-style-span" style="color: #555555; font-size: 16px; font-weight: bold; line-height: 24px;">HTML+CSS suck for building apps.</span></p><p>There I said it&#8230; I mean lets face it, building apps in HTML+CSS is pretty much like doing word processing in <a
title="LaTeX" href="http://en.wikipedia.org/wiki/LaTeX">LaTeX</a>.  What ever happened to decent visual tools? And I&#8217;m tired of dealing with weird quirky layout issues.</p><p>Don&#8217;t get me wrong HTML for building apps is definitely (eh) OK and it&#8217;s been proven that you can create <a
href="http://www.gmail.com" target="_blank">applications at scale</a> with it.  But I think you end up working around quirks in layout behavior way too much.  HTML was originally designed for making non-wysiwyg &#8220;rich&#8221; text documents. The ability to build apps is bolted on and feels like it.</p><p>Also I can&#8217;t help but wonder will the pinnacle of visual application design tools be Interface Builder or Delphi.  I don&#8217;t think we&#8217;ve really moved forward in terms of the visual tools used to build apps since the advent of these tools.  Rich Internet Application frameworks and plugins like Flash and Silverlight (along with FlexBuilder and Blend) tried to solve this within the browser.  But it&#8217;s looking more and more like these are going to <a
title="The Death of Plugins" href="http://www.theregister.co.uk/2011/11/10/microsoft_killing_silverlight_rumours/" target="_blank">fizzle out of existence</a>.</p><p>So What to Do?</p><p><span
id="more-195"></span></p><p>I think the core issue is that there is too much layout policy baked into the browser.  The included layout primitives (and their paradigms) don&#8217;t really do enough and in a lot of ways just get in the way.  And its not like workable application layout isn&#8217;t a solved problem.  There are no signs of layout primitives like <a
title="Interface Builder" href="http://en.wikipedia.org/wiki/Interface_builder" target="_blank">springs and struts</a>, <a
title="Delphi" href="http://delphi.about.com/od/humorandfun/f/borland-delphi-codegear-delphi-embarcadero-delphi.htm" target="_blank">dock-based layout</a> or <a
title="XUL" href="http://en.wikipedia.org/wiki/Xul" target="_blank">flex box layout</a>.  Don&#8217;t get me wrong these things should not be baked into the HTML rendering of the browser.  Browsers should work more towards baking in less policy and favor more composible and programmable lower layers.  It turns out that HTML5 already has the right pieces.  Basically we just need a way to express visually what we need to express with minimal policy.  These are in the form of <a
title="Canvas2d" href="http://en.wikipedia.org/wiki/Canvas_element">Canvas2d</a> and <a
title="WebGL" href="http://en.wikipedia.org/wiki/Webgl">WebGL</a>.  Why not develop UI frameworks completely on these programmable foundations.  Just some examples of some interesting work that&#8217;s been done <a
title="paper.js" href="http://paperjs.org/">here</a> and <a
title="Lutz Roeder" href="http://html5tutorial.net/examples/samples-using-the-html5-canvas-element.html">here</a>.</p><p>The W3C should really focus on the edge.  HTML apps continue to inch closer and closer to being able to offer the richness of experience that a native app can.  The gaps really come down to insufficient edge interfaces and insufficient integration with the platform that the browser is running on.  Instead of focusing on enhancing HTML&#8217;s <a
title="Flex Box" href="http://www.w3.org/TR/css3-flexbox/">layout capabilities</a> the W3C should focus on innovations at the edge <em>(some illustrative examples)</em> such as defining a decent programmable audio pipeline for input and output or a programmable pipeline for video decode.</p><p>Here are a few more edge problems that i&#8217;d like to see solved that currently limit how well applications completely built on top of Canvas2d and WebGL would fare compared to apps being built using HTML.</p><ul><li><strong>Virtual Keyboard management</strong> &#8211; The ability to programmatically detect and invoke virtual keyboards and events related to screen geometry changes when these have been invoked.</li><li><strong>Accessibility/Screen Readers</strong> &#8211; The ability to expose accessible virtual objects and their metadata (eg. alternate text) to screen readers.</li><li><strong>Input Method Editors</strong> &#8211; for inputting international text</li><li><strong>Better clipboard and drag and drop support</strong></li><li><strong>Better geometry and orientation change events</strong></li><li><strong>Debugging</strong> - Exposing virtual DOM objects built as Javascript objects to visual debugging tools (in Chrome for example)</li></ul><div><span
class="Apple-style-span" style="line-height: 18px;"><br
/> </span></div> ]]></content:encoded> <wfw:commentRss>http://www.storminthecastle.com/2011/11/13/future-of-ui-on-the-web/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Google your evil is showing&#8230;</title><link>http://www.storminthecastle.com/2011/10/15/google-your-evil-is-showing/</link> <comments>http://www.storminthecastle.com/2011/10/15/google-your-evil-is-showing/#comments</comments> <pubDate>Sat, 15 Oct 2011 14:03:32 +0000</pubDate> <dc:creator>John Robinson</dc:creator> <category><![CDATA[Uncategorized]]></category> <category><![CDATA[Dart]]></category> <category><![CDATA[Eich]]></category> <category><![CDATA[Evil]]></category> <category><![CDATA[Google]]></category> <category><![CDATA[Javascript]]></category> <category><![CDATA[Rants]]></category> <category><![CDATA[Technology]]></category> <category><![CDATA[Trends]]></category> <category><![CDATA[Web]]></category><guid
isPermaLink="false">http://www.storminthecastle.com/?p=61</guid> <description><![CDATA[Back in the day, whenever I heard someone utter &#8220;embrace and extend&#8221; I immediately thought of the evil that WAS Microsoft. Using their once formidable position to lead everyone around by their nose. But the more I see from Google, the &#8230;<p
class="read-more"><a
href="http://www.storminthecastle.com/2011/10/15/google-your-evil-is-showing/">Read more &#187;</a></p>]]></description> <content:encoded><![CDATA[<p><a
href="http://www.storminthecastle.com/2011/10/15/google-your-evil-is-showing/"><img
src="http://www.storminthecastle.com/wp-content/uploads/2011/10/gevil2.jpeg?735384" alt="" title="gevil2" width="160" height="93" class="alignleft size-full wp-image-188" /></a>Back in the day, whenever I heard someone utter &#8220;embrace and extend&#8221; I immediately thought of the evil that WAS Microsoft. Using their once formidable position to lead everyone around by their nose. But the more I see from Google, the more they remind me of the evil empires of the past.</p><p>I mean there are SO many things to love from Google&#8230; Chrome, <a
title="Herf" href="http://stereopsis.com/" target="_blank">Picasa</a>, Maps, Search&#8230; But the <a
title="Joe Hewitt" href="http://joehewitt.com/2011/09/22/web-technologies-need-an-owner" target="_blank">problem</a> is that we&#8217;re again seeing fragmentation limiting what the Web could become and perhaps even threatening its long term survival.</p><p>Google seems to be shifting it&#8217;s mission away from let&#8217;s &#8220;<a
title="Managing Data" href="http://www.google.com/about/corporate/company/" target="_blank">organize the world‘s information and make it universally accessible and useful</a>&#8221; to one of let&#8217;s make &#8220;<a
title="A New World Order?" href="http://googleblog.blogspot.com/2011/09/fall-spring-clean.html" target="_blank">high impact products—the ones that improve the lives of billions of people</a>&#8220;.  Maybe Larry fancies himself being the second coming of Jobs&#8230; and I&#8217;ll be the first to say&#8230;<br
/> <span
id="more-61"></span><br
/> <em>NOT A BAD GOAL TO HAVE!!</em></p><p>The EVIL IS that they don&#8217;t seem to mind <a
title="World Wide web Domination" href="http://regulargeek.com/2009/11/15/google-makes-a-bid-to-control-the-internet/" target="_blank">subverting the web</a> to make it all happen.  Google&#8217;s apparent &#8220;<a
title="Eich" href="http://news.ycombinator.com/item?id=2982949">we&#8217;ll go it alone</a>&#8221; mindset pushing initiatives like <a
title="Leaked Dart Memo" href="https://gist.github.com/1208618" target="_blank">DART</a> and <a
title="SPDY IS PURE EVIL..." href="http://en.wikipedia.org/wiki/SPDY" target="_blank">SPDY</a>&#8230; and their continued product positioning of <a
title="Eich" href="http://news.ycombinator.com/item?id=2982949">Chrome As The Platform (chrome as opposed to the web)</a>&#8230; are threatening the very fabric of the Web.</p><p>And I think folks might be <a
title="Eich" href="http://news.ycombinator.com/item?id=2982949" target="_blank">underestimating</a> the threat&#8230; Whilst Chrome doesn&#8217;t have the monopoly browser position that IE once had to drive this fragmentation&#8230; To paraphrase what a friend of mine recently <a
title="Sree Kotay" href="http://sree.kotay.com/2011/10/kindle-fire-return-of-desktop.html" target="_blank">blogged</a> about&#8230; people won&#8217;t &#8220;buy&#8221; browsers but they will &#8220;buy&#8221; browsers+services&#8230;</p><p>Trust us you&#8217;ll work better with Chrome&#8230; GWEB anybody?</p><p>Joe just might get his <a
title="Joe Hewitt" href="http://joehewitt.com/2011/09/22/web-technologies-need-an-owner" target="_blank">wish</a>.</p> ]]></content:encoded> <wfw:commentRss>http://www.storminthecastle.com/2011/10/15/google-your-evil-is-showing/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>WebGL Sand Toy</title><link>http://www.storminthecastle.com/2011/10/09/webgl-sand-toy/</link> <comments>http://www.storminthecastle.com/2011/10/09/webgl-sand-toy/#comments</comments> <pubDate>Sun, 09 Oct 2011 19:59:29 +0000</pubDate> <dc:creator>John Robinson</dc:creator> <category><![CDATA[Uncategorized]]></category> <category><![CDATA[Code]]></category> <category><![CDATA[Fun]]></category> <category><![CDATA[Graphics]]></category> <category><![CDATA[Hacking]]></category> <category><![CDATA[WebGL]]></category><guid
isPermaLink="false">http://www.storminthecastle.com/?p=35</guid> <description><![CDATA[Here is a little WebGL experiment I wrote in the form of a fun particle simulation.  Individual pixels from a photo are rendered as separate GL points.  The particle physics are done on the GPU using a shader.  Somewhat directly &#8230;<p
class="read-more"><a
href="http://www.storminthecastle.com/2011/10/09/webgl-sand-toy/">Read more &#187;</a></p>]]></description> <content:encoded><![CDATA[<p>Here is a little WebGL experiment I wrote in the form of a fun particle simulation.  Individual pixels from a photo are rendered as separate GL points.  The particle physics are done on the GPU using a shader.  Somewhat directly inspired by <a
title="Sree Kotay" href="http://sree.kotay.com/2006/10/random-pixel-toy.html" target="_blank">a little app that a friend of mine wrote years ago</a>.  But this one is done solely in Javascript/WebGL in a browser rather than in native code.</p><p><a
title="WebGL Sand Toy" href="http://www.liquidthought.com/sandbox/sandbox.html" target="_blank">Give it a try.</a></p><p><a
title="WebGL Sand Toy" href="http://www.liquidthought.com/sandbox/sandbox.html" target="_blank"><img
class="alignleft size-full wp-image-36" alt="sandtoy" src="http://www.storminthecastle.com/wp-content/uploads/2011/10/sandtoyfixed2.jpg?735384" width="300" height="300" /></a><br
/> <a
href="http://www.chromeexperiments.com/detail/sand-toy/"><img
style="vertical-align: top;" alt="See my Experiment on ChromeExperiments.com" src="http://www.chromeexperiments.com/img/badge-black_black.png" /></a></p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p> ]]></content:encoded> <wfw:commentRss>http://www.storminthecastle.com/2011/10/09/webgl-sand-toy/feed/</wfw:commentRss> <slash:comments>5</slash:comments> </item> <item><title>I&#8217;ll Miss Steve</title><link>http://www.storminthecastle.com/2011/10/06/ill-miss-steve/</link> <comments>http://www.storminthecastle.com/2011/10/06/ill-miss-steve/#comments</comments> <pubDate>Thu, 06 Oct 2011 02:09:12 +0000</pubDate> <dc:creator>John Robinson</dc:creator> <category><![CDATA[Uncategorized]]></category> <category><![CDATA[Apple]]></category> <category><![CDATA[Steve Jobs]]></category><guid
isPermaLink="false">http://www.storminthecastle.com/?p=29</guid> <description><![CDATA[A wave of nostalgia sweeps over me when I think about the passing of Steve Jobs (1955-2011).  The phrases &#8220;insanely great&#8221; and &#8220;and one more thing&#8230;&#8221; spring to mind.  The world won&#8217;t be the same without you.]]></description> <content:encoded><![CDATA[<p>A wave of nostalgia sweeps over me when I think about the passing of Steve Jobs (1955-2011).  The phrases &#8220;insanely great&#8221; and &#8220;and one more thing&#8230;&#8221; spring to mind.  The world won&#8217;t be the same without you.</p><p><a
href="http://www.storminthecastle.com/wp-content/uploads/2011/10/s_hero.png?735384"><img
class="alignnone size-medium wp-image-30" title="Steve Jobs Passes Away" src="http://www.storminthecastle.com/wp-content/uploads/2011/10/s_hero-300x273.png?735384" alt="" width="300" height="273" /></a></p> ]]></content:encoded> <wfw:commentRss>http://www.storminthecastle.com/2011/10/06/ill-miss-steve/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> </channel> </rss>
<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Database Caching using disk: basic
Object Caching 1841/1856 objects using disk: basic

 Served from: www.storminthecastle.com @ 2013-05-26 05:24:51 by W3 Total Cache -->

<!-- W3 Total Cache: Page cache debug info:
Engine:             disk: enhanced
Cache key:          www.storminthecastle.com/feed/_index.html
Caching:            disabled
Reject reason:      Page is feed
Creation Time:      0.563s
Header info:
X-Pingback:          http://www.storminthecastle.com/xmlrpc.php
Last-Modified:       Thu, 23 May 2013 18:18:40 GMT
ETag:                "b9e1785f1409024c088ba2a066a184b7"
X-W3TC-Minify:       On
Content-Type:        text/xml; charset=UTF-8
-->