<?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>Brooks Andrus &#187; thumbnails</title>
	<atom:link href="http://www.brooksandrus.com/blog/tag/thumbnails/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.brooksandrus.com/blog</link>
	<description>This is the blog of Brooks Andrus. Here, at irregular intervals, you may find digital noise centered around the activities of an early 21st century technologist. I work for TechSmith Corporation, but this web space and the views found on it are entirely my own.</description>
	<lastBuildDate>Fri, 13 May 2011 19:19:28 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Bilinear Resampling, ShaderJob, Pixel Bender And Flash Player</title>
		<link>http://www.brooksandrus.com/blog/2009/03/11/bilinear-resampling-with-flash-player-and-pixel-bender/</link>
		<comments>http://www.brooksandrus.com/blog/2009/03/11/bilinear-resampling-with-flash-player-and-pixel-bender/#comments</comments>
		<pubDate>Thu, 12 Mar 2009 04:09:44 +0000</pubDate>
		<dc:creator>brooks</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[bilinear]]></category>
		<category><![CDATA[thumbgenie]]></category>
		<category><![CDATA[thumbnails]]></category>

		<guid isPermaLink="false">http://www.brooksandrus.com/blog/?p=927</guid>
		<description><![CDATA[*Update* Sometimes you&#8217;re an idiot and you spend a lot of time reinventing the wheel because you misread one little line of documentation. This is one of those times where I get to be that idiot. I invented a solution for bilinear resampling in Flash Player when I didn&#8217;t need to. You can actually get [...]]]></description>
			<content:encoded><![CDATA[<p><strong>*Update*</strong></p>
<p>Sometimes you&#8217;re an idiot and you spend a lot of time reinventing the wheel because you misread one little line of documentation. This is one of those times where I get to be that idiot. I invented a solution for bilinear resampling in Flash Player when I didn&#8217;t need to. You can actually get the same results pretty simply using just BitmapData.draw() method with smoothing on (I had read this didn&#8217;t work when down sizing), but it requires creating a temp BitmapData object if the source you&#8217;re feeding the BitmapData.draw() method is not another BitmapData object (i.e. a DisplayObject). Here&#8217;s what that scenario would look like.<br />
<code></p>

<div class="wp_syntax"><div class="code"><pre class="actionscript" style="font-family:monospace;">            <span style="color: #808080; font-style: italic;">// source in this example is a DisplayObject</span>
            <span style="color: #000000; font-weight: bold;">var</span> temp:BitmapData = <span style="color: #000000; font-weight: bold;">new</span> BitmapData<span style="color: #66cc66;">&#40;</span> sourceWidth, sourceHeight <span style="color: #66cc66;">&#41;</span>;
            temp.<span style="color: #006600;">draw</span><span style="color: #66cc66;">&#40;</span> source <span style="color: #66cc66;">&#41;</span>;
&nbsp;
            <span style="color: #000000; font-weight: bold;">var</span> output:BitmapData = <span style="color: #000000; font-weight: bold;">new</span> BitmapData<span style="color: #66cc66;">&#40;</span> outputWidth, outputHeight <span style="color: #66cc66;">&#41;</span>;
&nbsp;
            <span style="color: #000000; font-weight: bold;">var</span> matrix:Matrix = <span style="color: #000000; font-weight: bold;">new</span> Matrix<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
            matrix.<span style="color: #006600;">scale</span><span style="color: #66cc66;">&#40;</span> outputWidth <span style="color: #66cc66;">/</span> sourceWidth, outputHeight <span style="color: #66cc66;">/</span> sourceHeight <span style="color: #66cc66;">&#41;</span>;
&nbsp;
            output.<span style="color: #006600;">draw</span><span style="color: #66cc66;">&#40;</span> temp, matrix, <span style="color: #000000; font-weight: bold;">null</span>, <span style="color: #000000; font-weight: bold;">null</span>, <span style="color: #000000; font-weight: bold;">null</span>, <span style="color: #000000; font-weight: bold;">true</span> <span style="color: #66cc66;">&#41;</span>;
            temp.<span style="color: #006600;">dispose</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</pre></div></div>

<p></code><br />
<span id="more-927"></span><br />
Many thanks to Felix for leaving a comment that made me question myself and go back to the problem with fresh eyes.</p>
<p>Now I can take some consolation in the fact that I actually learned a lot by going down this path. I dug in to Pixel Bender again and learned how to use ShaderJob. To that end, portions of this &#8220;tutorial&#8221; illustrate how to use a PixelBender shader and a ShaderJob together. ShaderJob, when run with the async flag (false), is as close as you can come to creating new threads in Flash&#8211;that&#8217;s some pretty neat Flash hackery.</p>
<p>So, if you find yourself reading this, you&#8217;re advised to skip down to the code included below and take a look at the embedded filter, Shader / ShaderJob portion. </p>
<p><strong>*End of Update*</strong></p>
<p>If you&#8217;re looking to generate high quality scaled bitmaps in Flash Player / AIR, you&#8217;ll need to do some form of bilinear or bicubic resampling. Why you ask? Because, Flash Player resampling is, by default, nearest neighbor and that looks, well, like ass (see evidence directly below).</p>
<p><img src="http://www.brooksandrus.com/images/nearest_neighbor_controls.jpg" alt="nearest neighbor resample" /><br />
 If you dig around long enough on the net you&#8217;ll find some AS3 libraries (Java ports) like <a href="http://www.clevr.com/blog/2008/resize-actionscript-bicubic-bilinear-interpolation/">clevrlib</a> which will do bilinear or bicubic resampling using BitmapData methods like getPixel / setPixel. As seen below, clevrlib definitely decreases jaggies and improves the legibility of text, but its extremely slow&#8211;scaling a 960&#215;540 BitmapData object to 640&#215;360 takes around 1.5 &#8211; 2 seconds for  bilinear resampling and around 3 &#8211; 5 seconds for bicubic resampling (mileage will vary based on the type of imagery and size of the picture). Also, the results, in some cases, exhibit noticeable resampling artifacts (check out the fullscreen icon in the right corner of the examples immediately below).</p>
<p><img src="http://www.brooksandrus.com/jing2/cleverlib_resampling.png" alt="cleverlib resampling" /></p>
<p>I was looking to implement bilinear resampling in <a href="http://www.brooksandrus.com/blog/thumbgenie-an-air-thumbnail-generator/">ThumbGenie</a>, but, as the old saying goes&#8211;speed kills. I just couldn&#8217;t tolerate 2 or 3 seconds to resample an image&#8211;there had to to be a better way. After a bit of thought I fell on the answer&#8211;<a href="http://labs.adobe.com/technologies/pixelbender/">PixelBender</a>. </p>
<p>Flash Player 10 PixelBender bytecode is designed to manipulate individual pixels in a bitmap super fast. In fact, it executes fast enough to apply real time filter effects to video. This seemed promising and sure enough after reading through the sdk docs and playing around for awhile (read I spent a Saturday evening trying to wrap my little melon around the issue), I was able to find a built-in PixelBender method that does bilinear sampling. Slap a parameter on that biatch (aka kernel) controlling the desired scale of the output  and little ol&#8217; me was rendering silky-smooth, scaled bitmaps out of Flash Player in mere milliseconds (8-13 milliseconds scaling a 960&#215;540 bitmap to 640&#215;360&#8211;take that suckaz).</p>
<p><img src="http://www.brooksandrus.com/images/bilinear_controls.jpg" alt="Pixel Bender bilinear resampling" /></p>
<p>Interested in chasing the same dream? Here&#8217;s, the rough outline you&#8217;ll need to follow:</p>
<ol>
<li>Create Pixel Bender kernel that does bilinear resampling.</li>
<li>Compile Pixel Bender bytecode for Flash Player 10 (.pbj file).</li>
<li>Embed PBJ bytecode in AS3 class.</li>
<li>Generate <a href="http://livedocs.adobe.com/flex/3/langref/flash/display/BitmapData.html">BitmapData</a> from a <a href="http://livedocs.adobe.com/flex/3/langref/flash/display/DisplayObject.html">DisplayObjec</a>t (BitmapData.draw( obj )).</li>
<li>Create an AS3 <a href="http://livedocs.adobe.com/flex/3/langref/flash/display/Shader.html">Shader</a> object, instantiate embedded Pixel Bender bytecode, configure Shader.</li>
<li>Create an output BitmapData object (this will hold the scaled bitmap we create.</li>
<li>Create a <a href="http://livedocs.adobe.com/flex/3/langref/flash/display/ShaderJob.html">ShaderJob</a> &#8211; this is a process that will run the Shader and return its output to an object (as opposed to being applied to a DisplayObject wrapped in a <a href="http://livedocs.adobe.com/flex/3/langref/flash/filters/ShaderFilter.html">ShaderFilter</a>).</li>
<li>Run the ShaderJob by calling the ShaderJob.start( true ) method.</li>
<li>Do something with the BitmapData thumbnail (display, push to server, or encode and save to disk)</li>
</ol>
<p>Ouch, that&#8217;s pretty painful. And believe me, I did some serious bleeding before figuring this one out&#8211;I really had to push the two or three sleep deprived brain cells I have left in order to get the job done. And well, this is just a long-winded way of saying that I&#8217;ll be providing y&#8217;all the Pixel Bender kernel (.pbk) and bytcode (.pbj) plus the AS3 implementation that I developed for <a href="http://www.brooksandrus.com/blog/thumbgenie-an-air-thumbnail-generator/">ThumbGenie</a> (just my way of saying thanks for all of the code you Flash / Flex cats so liberally share all of time).</p>
<p>Whew, you made it this far, now its time for the good stuff. Download the PixelBender source / bytecode <a href="http://www.brooksandrus.com/resources/bilinearresample.zip">here</a> and feel free to peruse / use the implementation seen below.</p>
<p><code></p>

<div class="wp_syntax"><div class="code"><pre class="actionscript" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/**
 * Copyright 2009 (c) , Brooks Andrus
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 * 
 */</span>
package com.<span style="color: #006600;">brooksandrus</span>.<span style="color: #006600;">utils</span>
<span style="color: #66cc66;">&#123;</span>
    <span style="color: #0066CC;">import</span> flash.<span style="color: #006600;">display</span>.<span style="color: #006600;">BitmapData</span>;
    <span style="color: #0066CC;">import</span> flash.<span style="color: #006600;">display</span>.<span style="color: #006600;">DisplayObject</span>;
    <span style="color: #0066CC;">import</span> flash.<span style="color: #006600;">display</span>.<span style="color: #006600;">Shader</span>;
    <span style="color: #0066CC;">import</span> flash.<span style="color: #006600;">display</span>.<span style="color: #006600;">ShaderJob</span>;
&nbsp;
    <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">class</span> BilinearResample
    <span style="color: #66cc66;">&#123;</span>
        <span style="color: #66cc66;">&#91;</span>Embed <span style="color: #66cc66;">&#40;</span> source=<span style="color: #ff0000;">&quot;../../../../assets/bilinearresample.pbj&quot;</span>, mimeType=<span style="color: #ff0000;">&quot;application/octet-stream&quot;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#93;</span>
        <span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> BilinearScaling:<span style="color: #000000; font-weight: bold;">Class</span>;
&nbsp;
        <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> BilinearResample<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
        <span style="color: #66cc66;">&#123;</span>
            <span style="color: #0066CC;">super</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
        <span style="color: #66cc66;">&#125;</span>
&nbsp;
        <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> resampleBitmap<span style="color: #66cc66;">&#40;</span> input:BitmapData, desiredWidth:<span style="color: #0066CC;">int</span>, desiredHeight:<span style="color: #0066CC;">int</span>, cleanup:<span style="color: #0066CC;">Boolean</span> = <span style="color: #000000; font-weight: bold;">true</span> <span style="color: #66cc66;">&#41;</span>:BitmapData
        <span style="color: #66cc66;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">var</span> aspectRatio:<span style="color: #0066CC;">Number</span> = input.<span style="color: #0066CC;">width</span> <span style="color: #66cc66;">/</span> input.<span style="color: #0066CC;">height</span>;
&nbsp;
            <span style="color: #000000; font-weight: bold;">var</span> factor:<span style="color: #0066CC;">Number</span> = <span style="color: #0066CC;">Math</span>.<span style="color: #0066CC;">max</span><span style="color: #66cc66;">&#40;</span> input.<span style="color: #0066CC;">width</span> <span style="color: #66cc66;">/</span> desiredWidth, input.<span style="color: #0066CC;">height</span> <span style="color: #66cc66;">/</span> desiredHeight <span style="color: #66cc66;">&#41;</span>;
&nbsp;
            <span style="color: #808080; font-style: italic;">// create and configure a Shader object</span>
            <span style="color: #000000; font-weight: bold;">var</span> shader:Shader = <span style="color: #000000; font-weight: bold;">new</span> Shader<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
            shader.<span style="color: #006600;">byteCode</span> = <span style="color: #000000; font-weight: bold;">new</span> BilinearScaling<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #808080; font-style: italic;">// instantiate embedded Pixel Bender bytecode</span>
            shader.<span style="color: #0066CC;">data</span>.<span style="color: #006600;">src</span>.<span style="color: #006600;">input</span> = input; <span style="color: #808080; font-style: italic;">// supply the shader with BitmapData it will manipulate</span>
            shader.<span style="color: #0066CC;">data</span>.<span style="color: #006600;">scale</span>.<span style="color: #006600;">value</span> = <span style="color: #66cc66;">&#91;</span>factor<span style="color: #66cc66;">&#93;</span>; <span style="color: #808080; font-style: italic;">// scale factor. shader params are all stored in arrays.</span>
&nbsp;
            <span style="color: #000000; font-weight: bold;">var</span> outputWidth:<span style="color: #0066CC;">int</span>;
            <span style="color: #000000; font-weight: bold;">var</span> outputHeight:<span style="color: #0066CC;">int</span>;
&nbsp;
            <span style="color: #808080; font-style: italic;">// determine output bitmap dimensions</span>
            <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> input.<span style="color: #0066CC;">width</span> <span style="color: #66cc66;">&gt;</span> input.<span style="color: #0066CC;">height</span> <span style="color: #66cc66;">&#41;</span>
            <span style="color: #66cc66;">&#123;</span>
                outputWidth = desiredWidth;
                outputHeight = desiredWidth <span style="color: #66cc66;">/</span> aspectRatio;
            <span style="color: #66cc66;">&#125;</span>
            <span style="color: #b1b100;">else</span>
            <span style="color: #66cc66;">&#123;</span>
                outputWidth = desiredHeight <span style="color: #66cc66;">*</span> aspectRatio;
                outputHeight = desiredHeight;
            <span style="color: #66cc66;">&#125;</span>
&nbsp;
            <span style="color: #808080; font-style: italic;">// create a bitmap - our shader will return its data (an image) to this bitmap</span>
            <span style="color: #000000; font-weight: bold;">var</span> output:BitmapData = <span style="color: #000000; font-weight: bold;">new</span> BitmapData<span style="color: #66cc66;">&#40;</span> outputWidth, outputHeight <span style="color: #66cc66;">&#41;</span>;
&nbsp;
            <span style="color: #808080; font-style: italic;">// shader jobs are wicked cool</span>
            <span style="color: #000000; font-weight: bold;">var</span> job:ShaderJob = <span style="color: #000000; font-weight: bold;">new</span> ShaderJob<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
            job.<span style="color: #0066CC;">target</span> = output; <span style="color: #808080; font-style: italic;">// ShaderJob returns to this object</span>
            job.<span style="color: #006600;">shader</span> = shader; <span style="color: #808080; font-style: italic;">// The Shader assigned to this job</span>
            job.<span style="color: #0066CC;">start</span><span style="color: #66cc66;">&#40;</span> <span style="color: #000000; font-weight: bold;">true</span> <span style="color: #66cc66;">&#41;</span>; <span style="color: #808080; font-style: italic;">// true flag runs the job synchronously.</span>
&nbsp;
            <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> cleanup <span style="color: #66cc66;">&#41;</span>
            <span style="color: #66cc66;">&#123;</span>
                input.<span style="color: #006600;">dispose</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
            <span style="color: #66cc66;">&#125;</span>
&nbsp;
            <span style="color: #b1b100;">return</span> output;
        <span style="color: #66cc66;">&#125;</span>
&nbsp;
        <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> resampleDisplayObject<span style="color: #66cc66;">&#40;</span> source:DisplayObject, desiredWidth:<span style="color: #0066CC;">int</span>, desiredHeight:<span style="color: #0066CC;">int</span> <span style="color: #66cc66;">&#41;</span>:BitmapData
        <span style="color: #66cc66;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">var</span> aspectRatio:<span style="color: #0066CC;">Number</span> = source.<span style="color: #0066CC;">width</span> <span style="color: #66cc66;">/</span> source.<span style="color: #0066CC;">height</span>;
&nbsp;
            <span style="color: #000000; font-weight: bold;">var</span> factor:<span style="color: #0066CC;">Number</span> = <span style="color: #0066CC;">Math</span>.<span style="color: #0066CC;">max</span><span style="color: #66cc66;">&#40;</span> source.<span style="color: #0066CC;">width</span> <span style="color: #66cc66;">/</span> desiredWidth, source.<span style="color: #0066CC;">height</span> <span style="color: #66cc66;">/</span> desiredHeight <span style="color: #66cc66;">&#41;</span>;
&nbsp;
            <span style="color: #000000; font-weight: bold;">var</span> input:BitmapData = <span style="color: #000000; font-weight: bold;">new</span> BitmapData<span style="color: #66cc66;">&#40;</span> source.<span style="color: #0066CC;">width</span>, source.<span style="color: #0066CC;">height</span>, <span style="color: #000000; font-weight: bold;">true</span> <span style="color: #66cc66;">&#41;</span>;
            input.<span style="color: #006600;">draw</span><span style="color: #66cc66;">&#40;</span> source <span style="color: #66cc66;">&#41;</span>;
&nbsp;
            <span style="color: #808080; font-style: italic;">// configure the shader</span>
            <span style="color: #000000; font-weight: bold;">var</span> shader:Shader = <span style="color: #000000; font-weight: bold;">new</span> Shader<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
            shader.<span style="color: #006600;">byteCode</span> = <span style="color: #000000; font-weight: bold;">new</span> BilinearScaling<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
            shader.<span style="color: #0066CC;">data</span>.<span style="color: #006600;">src</span>.<span style="color: #006600;">input</span> = input;
            shader.<span style="color: #0066CC;">data</span>.<span style="color: #006600;">scale</span>.<span style="color: #006600;">value</span> = <span style="color: #66cc66;">&#91;</span>factor<span style="color: #66cc66;">&#93;</span>; <span style="color: #808080; font-style: italic;">// scale factor. shader params are all stored in arrays.</span>
&nbsp;
            <span style="color: #000000; font-weight: bold;">var</span> outputWidth:<span style="color: #0066CC;">int</span>;
            <span style="color: #000000; font-weight: bold;">var</span> outputHeight:<span style="color: #0066CC;">int</span>;
&nbsp;
            <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> input.<span style="color: #0066CC;">width</span> <span style="color: #66cc66;">&gt;</span> input.<span style="color: #0066CC;">height</span> <span style="color: #66cc66;">&#41;</span>
            <span style="color: #66cc66;">&#123;</span>
                outputWidth = desiredWidth;
                outputHeight = desiredWidth <span style="color: #66cc66;">/</span> aspectRatio;
            <span style="color: #66cc66;">&#125;</span>
            <span style="color: #b1b100;">else</span>
            <span style="color: #66cc66;">&#123;</span>
                outputWidth = desiredHeight <span style="color: #66cc66;">*</span> aspectRatio;
                outputHeight = desiredHeight;
            <span style="color: #66cc66;">&#125;</span>
&nbsp;
            <span style="color: #000000; font-weight: bold;">var</span> output:BitmapData = <span style="color: #000000; font-weight: bold;">new</span> BitmapData<span style="color: #66cc66;">&#40;</span> outputWidth, outputHeight <span style="color: #66cc66;">&#41;</span>;
&nbsp;
            <span style="color: #000000; font-weight: bold;">var</span> job:ShaderJob = <span style="color: #000000; font-weight: bold;">new</span> ShaderJob<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
            job.<span style="color: #0066CC;">target</span> = output;
            job.<span style="color: #006600;">shader</span> = shader;
            job.<span style="color: #0066CC;">start</span><span style="color: #66cc66;">&#40;</span> <span style="color: #000000; font-weight: bold;">true</span> <span style="color: #66cc66;">&#41;</span>; <span style="color: #808080; font-style: italic;">// true flag runs the job synchronously.</span>
&nbsp;
            input.<span style="color: #006600;">dispose</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
            <span style="color: #b1b100;">return</span> output;
        <span style="color: #66cc66;">&#125;</span>
    <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.brooksandrus.com/blog/2009/03/11/bilinear-resampling-with-flash-player-and-pixel-bender/feed/</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>ThumbGenie 1.2 Now Supports Bilinear Image Resampling (improved scaling in non-geek speak)</title>
		<link>http://www.brooksandrus.com/blog/2009/03/10/thumbgenie-12-now-supports-bilinear-image-resampling-improved-scaling-in-non-geek-speak/</link>
		<comments>http://www.brooksandrus.com/blog/2009/03/10/thumbgenie-12-now-supports-bilinear-image-resampling-improved-scaling-in-non-geek-speak/#comments</comments>
		<pubDate>Wed, 11 Mar 2009 04:17:08 +0000</pubDate>
		<dc:creator>brooks</dc:creator>
				<category><![CDATA[thumbgenie]]></category>
		<category><![CDATA[AIR]]></category>
		<category><![CDATA[bilinear]]></category>
		<category><![CDATA[resampling]]></category>
		<category><![CDATA[thumbnails]]></category>

		<guid isPermaLink="false">http://www.brooksandrus.com/blog/?p=914</guid>
		<description><![CDATA[One of the things that&#8217;s sort of sucked about ThumbGenie has been the quality of scaled thumbnails. The 640&#215;360 image below was generated from a 960&#215;540 video frame. Notice the edge degradation (jaggies) and poorly rendered text that results from the nearest neighbor scaling. ThumbGenie 1.2 makes some very noticeable improvements to the quality of [...]]]></description>
			<content:encoded><![CDATA[<p>One of the things that&#8217;s sort of sucked about <a href="http://www.brooksandrus.com/blog/thumbgenie-an-air-thumbnail-generator/">ThumbGenie</a> has been the quality of scaled thumbnails. The 640&#215;360 image below was generated from a 960&#215;540 video frame.  Notice the edge degradation (jaggies) and poorly rendered text that results from the nearest neighbor scaling.<span id="more-914"></span></p>
<p><img src="http://www.brooksandrus.com/images/nearest_neighbor.jpg" alt="ThumbGenie image scaled down using nearest neighbor resampling." /></p>
<p><a href="http://www.brooksandrus.com/blog/thumbgenie-an-air-thumbnail-generator/">ThumbGenie 1.2</a> makes some very noticeable improvements to the quality of scaled thumbnails, as seen below, by doing bilinear resampling using a <a href="http://labs.adobe.com/technologies/pixelbender/">Pixel Bender</a> kernel.</p>
<p><img src="http://www.brooksandrus.com/images/bilinear.jpg" alt="ThumbGenie image generated using bilinear resampling" /></p>
<p>The update also includes some bug fixes:</p>
<ul>
<li>Fixed bug that caused aspect ratio to be incorrectly displayed in the output dimensions field when &#8220;retain&#8221; was checked and video of a different aspect ratio was loaded. Because this bug has been fixed the &#8220;R&#8221; reset button has been removed from the UI.</li>
<li>FIxed bug that prevented text from being pasted into the embed code window when the the keyboard shortcut for paste was used.</li>
</ul>
<p>If you&#8217;re dying to get your hands on ThumbGenie, or have no idea what it is, check out its home page for an overview and some helpful videos:</p>
<p><a href="http://www.brooksandrus.com/blog/thumbgenie-an-air-thumbnail-generator/">http://www.brooksandrus.com/blog/thumbgenie-an-air-thumbnail-generator/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.brooksandrus.com/blog/2009/03/10/thumbgenie-12-now-supports-bilinear-image-resampling-improved-scaling-in-non-geek-speak/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ThumbGenie 1.1.0 Now Generates Embed Code</title>
		<link>http://www.brooksandrus.com/blog/2009/02/23/thumbgenie-110-now-generates-embed-code/</link>
		<comments>http://www.brooksandrus.com/blog/2009/02/23/thumbgenie-110-now-generates-embed-code/#comments</comments>
		<pubDate>Mon, 23 Feb 2009 14:11:46 +0000</pubDate>
		<dc:creator>brooks</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[h.264]]></category>
		<category><![CDATA[Jing]]></category>
		<category><![CDATA[jing pro]]></category>
		<category><![CDATA[mpeg4-avc]]></category>
		<category><![CDATA[thumbgenie]]></category>
		<category><![CDATA[thumbnails]]></category>

		<guid isPermaLink="false">http://www.brooksandrus.com/blog/?p=886</guid>
		<description><![CDATA[I updated ThumbGenie over the weekend to support generation of embed code. Now, every time you create a thumbnail from an MPEG4-AVC file or SWF embed code will be generated. ThumbGenie ships with a default &#8220;object / embed&#8221; code template, but you can easily modify or replace the template with your own code. I created [...]]]></description>
			<content:encoded><![CDATA[<p>I updated <a href="http://www.brooksandrus.com/blog/thumbgenie-an-air-thumbnail-generator/">ThumbGenie</a> over the weekend to support generation of embed code. Now, every time you create a thumbnail from an MPEG4-AVC file or SWF embed code will be generated. ThumbGenie ships with a default &#8220;object / embed&#8221; code template, but you can easily modify or replace the template with your own code.<span id="more-886"></span></p>
<p>I created a short video that explains how embed code generation works and what you need to modify or replace the sample template code.<br />
Go fullscreen <img class="jing-fullscreen-icon" src="http://www.brooksandrus.com/media/jing_fullscreen_icon.png" alt="fullscreen icon" /> to see the video in full 1:1 pixel clarity.</p>

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
			id="fm_player_271315051"
			class="flashmovie"
			width="640"
			height="360">
	<param name="movie" value="http://www.brooksandrus.com/media/player.swf" />
	<param name="flashvars" value="content=http://www.brooksandrus.com/media/thumbgenie_embed_code.mp4&amp;thumb=http://www.brooksandrus.com/media/thumbgenie_embed_code.jpg&amp;windowbox=true&amp;analytics=UA-6435642-1&amp;showbranding=true&amp;containerwidth=640&amp;containerheight=360" />
	<param name="allowfullscreen" value="true" />
	<!--[if !IE]>-->
	<object	type="application/x-shockwave-flash"
			data="http://www.brooksandrus.com/media/player.swf"
			name="fm_player_271315051"
			width="640"
			height="360">
		<param name="flashvars" value="content=http://www.brooksandrus.com/media/thumbgenie_embed_code.mp4&amp;thumb=http://www.brooksandrus.com/media/thumbgenie_embed_code.jpg&amp;windowbox=true&amp;analytics=UA-6435642-1&amp;showbranding=true&amp;containerwidth=640&amp;containerheight=360" />
		<param name="allowfullscreen" value="true" />
	<!--<![endif]-->
		
<p><a href="http://adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></p>
<p><a href="http://www.brooksandrus.com/media/thumbgenie_embed_code.mp4">Download</a> video.</p>

	<!--[if !IE]>-->
	</object>
	<!--<![endif]-->
</object><br />
</p>
<p>If you&#8217;re using <a href="http://www.brooksandrus.com/blog/2009/01/19/jing-pro-ftp-a-complete-solution/">Jing Pro + FTP</a> the ability to generate thumbnails and embed code should significantly enhance your blogging workflow. Here&#8217;s a short example of how I use ThumbGenie in my workflow.<br />
Go fullscreen <img class="jing-fullscreen-icon" src="http://www.brooksandrus.com/media/jing_fullscreen_icon.png" alt="fullscreen icon" /> to see the video in full 1:1 pixel clarity.</p>

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
			id="fm_player_1602629064"
			class="flashmovie"
			width="640"
			height="360">
	<param name="movie" value="http://www.brooksandrus.com/media/player.swf" />
	<param name="flashvars" value="content=http://www.brooksandrus.com/media/thumbgenie_blog_workflow.mov&amp;thumb=http://www.brooksandrus.com/media/thumbgenie_blog_workflow.jpg&amp;windowbox=true&amp;analytics=UA-6435642-1&amp;showbranding=true&amp;containerwidth=640&amp;containerheight=360" />
	<param name="allowfullscreen" value="true" />
	<!--[if !IE]>-->
	<object	type="application/x-shockwave-flash"
			data="http://www.brooksandrus.com/media/player.swf"
			name="fm_player_1602629064"
			width="640"
			height="360">
		<param name="flashvars" value="content=http://www.brooksandrus.com/media/thumbgenie_blog_workflow.mov&amp;thumb=http://www.brooksandrus.com/media/thumbgenie_blog_workflow.jpg&amp;windowbox=true&amp;analytics=UA-6435642-1&amp;showbranding=true&amp;containerwidth=640&amp;containerheight=360" />
		<param name="allowfullscreen" value="true" />
	<!--<![endif]-->
		
<p><a href="http://adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></p>
<p><a href="http://www.brooksandrus.com/media/thumbgenie_blog_workflow.mov">Download</a> video.</p>

	<!--[if !IE]>-->
	</object>
	<!--<![endif]-->
</object>
<p>If you&#8217;re interested in generating thumbnails from MPEG4-AVC files or SWF files created by Jing hit the install badge below. After installing, head over to <a href="http://www.brooksandrus.com/blog/thumbgenie-an-air-thumbnail-generator/">ThumbGenie central</a> to view some helpful videos.</p>

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
			id="fm_AIRInstallBadge_1740583781"
			class="flashmovie"
			width="215"
			height="180">
	<param name="movie" value="http://www.brooksandrus.com/thumbgenie/AIRInstallBadge.swf" />
	<param name="flashvars" value="airversion=1.5&amp;appname=ThumbGenie&amp;image=http://www.brooksandrus.com/thumbgenie/thumbgenie_badge.png&amp;appurl=http://www.brooksandrus.com/thumbgenie/thumbgenie_1.3.0.air&amp;appid=com.brooksandrus.air.thumbgenie&amp;pubid=A3C411C2D522700600AC8D2902787FED2272C2C5.1&amp;appversion=1.3.0" />
	<param name="bgcolor" value="#333333" />
	<!--[if !IE]>-->
	<object	type="application/x-shockwave-flash"
			data="http://www.brooksandrus.com/thumbgenie/AIRInstallBadge.swf"
			name="fm_AIRInstallBadge_1740583781"
			width="215"
			height="180">
		<param name="flashvars" value="airversion=1.5&amp;appname=ThumbGenie&amp;image=http://www.brooksandrus.com/thumbgenie/thumbgenie_badge.png&amp;appurl=http://www.brooksandrus.com/thumbgenie/thumbgenie_1.3.0.air&amp;appid=com.brooksandrus.air.thumbgenie&amp;pubid=A3C411C2D522700600AC8D2902787FED2272C2C5.1&amp;appversion=1.3.0" />
		<param name="bgcolor" value="#333333" />
	<!--<![endif]-->
		
<p><a href="http://adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></p>

	<!--[if !IE]>-->
	</object>
	<!--<![endif]-->
</object>
]]></content:encoded>
			<wfw:commentRss>http://www.brooksandrus.com/blog/2009/02/23/thumbgenie-110-now-generates-embed-code/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
<enclosure url="http://www.brooksandrus.com/media/thumbgenie_blog_workflow.mov" length="22054636" type="video/quicktime" />
<enclosure url="http://www.brooksandrus.com/media/thumbgenie_embed_code.mp4" length="20781654" type="video/mp4" />
		</item>
		<item>
		<title>ThumbGenie: An AIR Thumbnail Generator for MPEG4-AVC / SWF Files</title>
		<link>http://www.brooksandrus.com/blog/2009/02/18/thumbgenie-an-air-thumbnail-generator-for-mpeg4-avc-swf-files/</link>
		<comments>http://www.brooksandrus.com/blog/2009/02/18/thumbgenie-an-air-thumbnail-generator-for-mpeg4-avc-swf-files/#comments</comments>
		<pubDate>Wed, 18 Feb 2009 07:25:21 +0000</pubDate>
		<dc:creator>brooks</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[Jing]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[RIA]]></category>
		<category><![CDATA[thumbnails]]></category>

		<guid isPermaLink="false">http://www.brooksandrus.com/blog/?p=841</guid>
		<description><![CDATA[One of the not so nice aspects of hosting your own Jing / Jing Pro videos is generating thumbnails that can be used for the &#8220;click-to-play&#8221; screen that viewers initiate video playback with. My current thumbnail workflow works something like this: Capture video. Save video to local disk (desktop). Open video with QuickTime Pro ($30). [...]]]></description>
			<content:encoded><![CDATA[<p>One of the not so nice aspects of hosting your own Jing / Jing Pro videos is generating thumbnails that can be used for the &#8220;click-to-play&#8221; screen that viewers initiate video playback with. My current thumbnail workflow works something like this:</p>
<ol>
<li>Capture video.</li>
<li>Save video to local disk (desktop).</li>
<li>Open video with QuickTime Pro ($30).</li>
<li>Select a video frame and Choose QuickTime&#8217;s &#8220;Export Movie as Bitmap&#8221; option.</li>
<li>Open .bmp file generated by QuickTime Pro in Fireworks (beaucoup $$$).</li>
<li>Resize image in Fireworks to fit my embed dimensions (embed dimensions are different than video dimensions).</li>
<li>Export out JPEG file (.jpg) with some compression applied (trade quality for size).</li>
</ol>
<p>Jing&#8217;s supposed to be all about the easy, but the workflow above is decidedly not. It shouldn&#8217;t be that hard to generate thumbnail images from your JIng videos and it shouldn&#8217;t be ultra expensive. Enter <a href="http://www.brooksandrus.com/blog/thumbgenie-an-air-thumbnail-generator/">ThumbGenie</a>, an AIR application, written by moi, that allows you to load MPEG4-AVC or SWF files, select a video frame and generate a thumbnail image as either a JPEG or PNG file. Wait, it gets better. You can apply JPEG compression and scale the exported image down. Best of all its completely <a href="http://en.wikipedia.org/wiki/Gratis_versus_Libre">free, as in beer</a>. So what are you waiting for, <a href="http://www.brooksandrus.com/blog/thumbgenie-an-air-thumbnail-generator/">download</a> ThumbGenie and start generating thumbnails pronto!</p>
<p>If you head over to <a href="http://www.brooksandrus.com/blog/thumbgenie-an-air-thumbnail-generator/">ThumbGenie central</a> you&#8217;ll find some helpful &#8220;getting started&#8221; videos as well as the installer badge.</p>

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
			id="fm_AIRInstallBadge_1996843572"
			class="flashmovie"
			width="215"
			height="180">
	<param name="movie" value="http://www.brooksandrus.com/thumbgenie/AIRInstallBadge.swf" />
	<param name="flashvars" value="airversion=1.5&amp;appname=ThumbGenie&amp;image=http://www.brooksandrus.com/thumbgenie/thumbgenie_badge.png&amp;appurl=http://www.brooksandrus.com/thumbgenie/thumbgenie_1.3.0.air&amp;appid=com.brooksandrus.air.thumbgenie&amp;pubid=A3C411C2D522700600AC8D2902787FED2272C2C5.1&amp;appversion=1.3.0" />
	<param name="bgcolor" value="#333333" />
	<!--[if !IE]>-->
	<object	type="application/x-shockwave-flash"
			data="http://www.brooksandrus.com/thumbgenie/AIRInstallBadge.swf"
			name="fm_AIRInstallBadge_1996843572"
			width="215"
			height="180">
		<param name="flashvars" value="airversion=1.5&amp;appname=ThumbGenie&amp;image=http://www.brooksandrus.com/thumbgenie/thumbgenie_badge.png&amp;appurl=http://www.brooksandrus.com/thumbgenie/thumbgenie_1.3.0.air&amp;appid=com.brooksandrus.air.thumbgenie&amp;pubid=A3C411C2D522700600AC8D2902787FED2272C2C5.1&amp;appversion=1.3.0" />
		<param name="bgcolor" value="#333333" />
	<!--<![endif]-->
		
<p><a href="http://adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></p>

	<!--[if !IE]>-->
	</object>
	<!--<![endif]-->
</object>
]]></content:encoded>
			<wfw:commentRss>http://www.brooksandrus.com/blog/2009/02/18/thumbgenie-an-air-thumbnail-generator-for-mpeg4-avc-swf-files/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

