<?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>Thoughtseed</title>
	<atom:link href="http://thoughts.enseed.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://thoughts.enseed.com</link>
	<description>Bits and thoughts from the people of Enseed</description>
	<lastBuildDate>Wed, 30 Jun 2010 13:41:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>Converting CMYK to RGB</title>
		<link>http://thoughts.enseed.com/converting-cmyk-to-rgb/</link>
		<comments>http://thoughts.enseed.com/converting-cmyk-to-rgb/#comments</comments>
		<pubDate>Mon, 07 Sep 2009 16:50:49 +0000</pubDate>
		<dc:creator>petit</dc:creator>
				<category><![CDATA[ITL]]></category>

		<guid isPermaLink="false">http://thoughts.enseed.com/?p=368</guid>
		<description><![CDATA[function updateCMYK() { var cyan = { red: 0, green: 255, blue: 255 }; var magenta = { red: 255, green: 0, blue: 255 }; var yellow = { red: 255, green: 255, blue: 0 }; var c = parseFloat(document.getElementById("cval").value); var m = parseFloat(document.getElementById("mval").value); var y = parseFloat(document.getElementById("yval").value); var k = parseFloat(document.getElementById("kval").value); var ck = [...]]]></description>
			<content:encoded><![CDATA[<script type="text/javascript" language="javascript">

function updateCMYK()
{
	var cyan = { red: 0, green: 255, blue: 255 };
	var magenta = { red: 255, green: 0, blue: 255 };
	var yellow = { red: 255, green: 255, blue: 0 };
	
    var c = parseFloat(document.getElementById("cval").value);
    var m = parseFloat(document.getElementById("mval").value);
    var y = parseFloat(document.getElementById("yval").value);
    var k = parseFloat(document.getElementById("kval").value);


	var ck = parseInt(c*(1-k)*100);
	var mk = parseInt(m*(1-k)*100);
	var yk = parseInt(y*(1-k)*100);
	var kk = parseInt(k*300);

	var remain = 300;
	
    document.getElementById("cell_cyan").style.width = ck + "px";
    remain -= ck;
    document.getElementById("cell_magenta").style.width = mk + "px";
    remain -= mk;
    document.getElementById("cell_yellow").style.width = yk + "px";
    remain -= yk;
    document.getElementById("cell_black").style.width = kk + "px";
    remain -= kk;
    document.getElementById("cell_white").style.width = remain + "px";



	$("#cslide").slider('value', c*100);
	$("#mslide").slider('value', m*100);
	$("#yslide").slider('value', y*100);
	$("#kslide").slider('value', k*100);


	var rgb = parseInt((1-k)*255);
	var black = parseInt((1-(k + c*(1-k)))*255);
    document.getElementById("cell_cblack").style.width = parseInt(k*100) + "px";
    document.getElementById("cell_ccyan").style.width = parseInt(c*(1-k)*100) + "px";
    document.getElementById("cell_cwhite").style.width = parseInt((1 - k - c*(1-k))*100) + "px";
    document.getElementById("cell_ccyan_final").style.backgroundColor = "rgb(" + black + ", " + parseInt(rgb) + ", " + parseInt(rgb) + ")";
    document.getElementById("cell_c_val").innerHTML = "rgb(" + black + ", " + parseInt(rgb) + ", " + parseInt(rgb) + ")";

	var rgb = parseInt((1-k)*255);
	var black = parseInt((1-(k + m*(1-k)))*255);
    document.getElementById("cell_mblack").style.width = parseInt(k*100) + "px";
    document.getElementById("cell_mmagenta").style.width = parseInt(m*(1-k)*100) + "px";
    document.getElementById("cell_mwhite").style.width = parseInt((1 - k - m*(1-k))*100) + "px";
    document.getElementById("cell_mmagenta_final").style.backgroundColor = "rgb(" + parseInt(rgb) + ", " + black + ", " + parseInt(rgb) + ")";
    document.getElementById("cell_m_val").innerHTML = "rgb(" + parseInt(rgb) + ", " + black + ", " + parseInt(rgb) + ")";

	var rgb = parseInt((1-k)*255);
	var black = parseInt((1-(k + y*(1-k)))*255);
    document.getElementById("cell_yblack").style.width = parseInt(k*100) + "px";
    document.getElementById("cell_yyellow").style.width = parseInt(y*(1-k)*100) + "px";
    document.getElementById("cell_ywhite").style.width = parseInt((1 - k - y*(1-k))*100) + "px";
    document.getElementById("cell_yyellow_final").style.backgroundColor = "rgb(" + parseInt(rgb) + ", " + parseInt(rgb) + ", " + black + ")";
    document.getElementById("cell_y_val").innerHTML = "rgb(" + parseInt(rgb) + ", " + parseInt(rgb) + ", " + black + ")";


	remain = 300;
    document.getElementById("cell_cyan_cmy").style.width = parseInt((c*(1-k) + k)*100) + "px";
    remain -= parseInt((c*(1-k) + k)*100);
    document.getElementById("cell_magenta_cmy").style.width = parseInt((m*(1-k) + k)*100) + "px";
    remain -= parseInt((m*(1-k) + k)*100);
    document.getElementById("cell_yellow_cmy").style.width = parseInt((y*(1-k) + k)*100) + "px";
    remain -= parseInt((y*(1-k) + k)*100);
    document.getElementById("cell_white_cmy").style.width = remain + "px";

	remain = 300;
    document.getElementById("cell_red").style.width = parseInt(100 - (c*(1-k) + k)*100) + "px";
    remain -= parseInt(100 - (c*(1-k) + k)*100);
    document.getElementById("cell_green").style.width = parseInt(100 - (m*(1-k) + k)*100) + "px";
    remain -= parseInt(100 - (m*(1-k) + k)*100);
    document.getElementById("cell_blue").style.width = parseInt(100 - (y*(1-k) + k)*100) + "px";
    remain -= parseInt(100 - (y*(1-k) + k)*100);
    document.getElementById("cell_black_rgb").style.width = remain + "px";

    
    document.getElementById("cell_final").style.backgroundColor = rgbColor(1-(c*(1-k) + k), 1-(m*(1-k) + k), 1-(y*(1-k) + k));
}

function rgbColor(r, g, b)
{
	return "rgb(" + parseInt(r*255) + ", "  + parseInt(g*255) + ", "  + parseInt(b*255) + ")";
}


</script>


<fieldset>
<legend>Representation of CMYK</legend>

(Values discussed here are in the range [0, 1])

In CMYK, black (K) is a minimum amount of black ink for all three CMY. The CMY components are then scaled inside the remaining range:

<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">C' = (1-K)*C;<br />
M' = (1-K)*M;<br />
Y' = (1-K)*Y;</div></td></tr></tbody></table></div>

<table>
<tr>
    <td><label for="kval">Black</label><input onchange="updateCMYK();"  id="kval" type="text" size="4" value="0.5"/><div id="kslide"></div></td>
    <td><label for="cval">Cyan</label><input onchange="updateCMYK();" id="cval" type="text" size="4" value="0.25"/><div id="cslide"></div></td>
    <td><label for="mval">Magenta</label><input onchange="updateCMYK();"  id="mval" type="text" size="4" value="0"/><div id="mslide"></div></td>
    <td><label for="yval">Yellow</label><input onchange="updateCMYK();"  id="yval" type="text" size="4" value="0.5"/><div id="yslide"></div></td>
</tr>
</table>

<h2>Ink Contribution (CMKY)</h2>
<table style="border-style: solid; border-width: 1px; height: 32px; padding: 0px; margin: 0px;" >
<tr style="padding: 0px; margin: 0px;">
	<td id="cell_black" style="padding: 0px; margin: 0px; background: black;"></td>
	<td id="cell_cyan" style="padding: 0px; margin: 0px; background: cyan;"></td>
	<td id="cell_magenta" style="padding: 0px; margin: 0px; background: magenta;"></td>
	<td id="cell_yellow" style="padding: 0px; margin: 0px; background: yellow;"></td>
	<td id="cell_white" style="padding: 0px; margin: 0px; background: white;"></td>
</tr>
</table>

<h2>Cyan-Black Contribution</h2>
<table><tr><td>
<table style="border-style: solid; border-width: 1px; height: 32px; padding: 0px; margin: 0px;" >
<tr style="padding: 0px; margin: 0px;">
	<td id="cell_cblack" style="padding: 0px; margin: 0px; background: black;"></td>
	<td id="cell_ccyan" style="padding: 0px; margin: 0px; background: cyan;"></td>
	<td id="cell_cwhite" style="padding: 0px; margin: 0px; background: white;"></td>
</tr></table></td>
	<td>Result: <table><tr><td style="width: 32px; height: 32px;" id="cell_ccyan_final"></td></tr></table></td>
	<td id="cell_c_val"></td>
</tr>
</table>

<h2>Magenta-Black Contribution</h2>
<table><tr><td>
<table style="border-style: solid; border-width: 1px; height: 32px; padding: 0px; margin: 0px;" >
<tr style="padding: 0px; margin: 0px;">
	<td id="cell_mblack" style="padding: 0px; margin: 0px; background: black;"></td>
	<td id="cell_mmagenta" style="padding: 0px; margin: 0px; background: magenta;"></td>
	<td id="cell_mwhite" style="padding: 0px; margin: 0px; background: white;"></td>
</tr></table></td>
	<td>Result: <table><tr><td style="width: 32px; height: 32px;" id="cell_mmagenta_final"></td></tr></table></td>
	<td id="cell_m_val"></td>
</tr>
</table>

<h2>Yellow-Black Contribution</h2>
<table><tr><td>
<table style="border-style: solid; border-width: 1px; height: 32px; padding: 0px; margin: 0px;" >
<tr style="padding: 0px; margin: 0px;">
	<td id="cell_yblack" style="padding: 0px; margin: 0px; background: black;"></td>
	<td id="cell_yyellow" style="padding: 0px; margin: 0px; background: yellow;"></td>
	<td id="cell_ywhite" style="padding: 0px; margin: 0px; background: white;"></td>
</tr></table></td>
	<td>Result: <table><tr><td style="width: 32px; height: 32px;" id="cell_yyellow_final"></td></tr></table></td>
	<td id="cell_y_val"></td>
</tr>
</table>

Once we scale the cyan, magenta and yellow components using the black component, we obtain a color on the CMY (no K) model.

<h2>Ink Contribution (CMY - no K)</h2>
<table style="border-style: solid; border-width: 1px; height: 32px; padding: 0px; margin: 0px;" >
<tr style="padding: 0px; margin: 0px;">
	<td id="cell_cyan_cmy" style="padding: 0px; margin: 0px; background: cyan;"></td>
	<td id="cell_magenta_cmy" style="padding: 0px; margin: 0px; background: magenta;"></td>
	<td id="cell_yellow_cmy" style="padding: 0px; margin: 0px; background: yellow;"></td>
	<td id="cell_white_cmy" style="padding: 0px; margin: 0px; background: white;"></td>
</tr>
</table>


These CMY are negatives of RGB, as in:

<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">R = 1.0 - C;<br />
G = 1.0 - M;<br />
B = 1.0 - Y;</div></td></tr></tbody></table></div>

<table style="height: 32px; padding: 0px; margin: 0px;" >
<tr style="padding: 0px; margin: 0px;">
	<td id="cell_red" style="padding: 0px; margin: 0px; background: red;"></td>
	<td id="cell_green" style="padding: 0px; margin: 0px; background: green;"></td>
	<td id="cell_blue" style="padding: 0px; margin: 0px; background: blue;"></td>
	<td id="cell_black_rgb" style="padding: 0px; margin: 0px; background: black;"></td>
</tr>
</table>

The final color:
<table><tr><td style="width: 32px; height: 32px;" id="cell_final"></td></tr></table>
</fieldset>



<link type="text/css" href="http://jqueryui.com/latest/themes/base/ui.all.css" rel="stylesheet" />
<script type="text/javascript" src="http://jqueryui.com/latest/jquery-1.3.2.js"></script>
<script type="text/javascript" src="http://jqueryui.com/latest/ui/ui.core.js"></script>
<script type="text/javascript" src="http://jqueryui.com/latest/ui/ui.slider.js"></script>
<style type="text/css">
#slider { margin: 10px; }
</style>
<script type="text/javascript">
$(document).ready(function(){
$("#cslide").slider( { animate: true, slide: function(event, ui) { document.getElementById("cval").value = $("#cslide").slider('value') / 100.0; updateCMYK(); } } );
$("#mslide").slider( { slide: function(event, ui) { document.getElementById("mval").value = $("#mslide").slider('value') / 100.0; updateCMYK(); } } );
$("#yslide").slider( { slide: function(event, ui) { document.getElementById("yval").value = $("#yslide").slider('value') / 100.0; updateCMYK(); } } );
$("#kslide").slider( { slide: function(event, ui) { document.getElementById("kval").value = $("#kslide").slider('value') / 100.0; updateCMYK(); } } );
});

updateCMYK();
</script>
]]></content:encoded>
			<wfw:commentRss>http://thoughts.enseed.com/converting-cmyk-to-rgb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>webbzr &#8211; php to browse a bzr repository from a web page</title>
		<link>http://thoughts.enseed.com/webbzr/</link>
		<comments>http://thoughts.enseed.com/webbzr/#comments</comments>
		<pubDate>Thu, 06 Aug 2009 15:55:36 +0000</pubDate>
		<dc:creator>petit</dc:creator>
				<category><![CDATA[Bazaar]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web Programming]]></category>

		<guid isPermaLink="false">http://thoughts.enseed.com/?p=306</guid>
		<description><![CDATA[- You can see webbzr in action here Latest changes Version 1.4 (Jun 30, 2010)Fixed a vulnerability where webbzr could be used to list content outside of the webbzr root. Version 1.3 (Jan 24, 2010) Branches and directories within branches can now be download as a tgz or tbz2 package straight from the bzr repository. [...]]]></description>
			<content:encoded><![CDATA[<strong><em> - You can see webbzr in action </em><a href="http://bazaar.enseed.com/app/webbzr/"><em>here</em></a></strong>

<h2>Latest changes</h2>
<ul>
<li><b>Version 1.4 (Jun 30, 2010)</b>Fixed a vulnerability where webbzr could be used to list content outside of the webbzr root.</li>
<li><b>Version 1.3 (Jan 24, 2010)</b> Branches and directories within branches can now be download as a tgz or tbz2 package straight from the bzr repository.</li>
<li><b>Version 1.2 (Jan 21, 2010)</b> Security fix (thanks to Andrew Bradley)</li>
<li><b>Version 1.1 (Oct. 6 2009)</b> Fix for repository that are not at the root of a url, for instance: http://www.site.com/~user/bzr/ (thanks to Dr. Rich Wareham)</li>
<li><b>Version 1.0 (Aug. 5 2009)</b> Initial version</li>
</ul>
<h1>Motivation</h1>
Bazaar (bzr) can push and pull branches on a remote server without having to install anything on the server side.  This is useful in cases where you have access to a web server without admin privileges (i.e. you could not install WebDAV or setup a svn site).  With bzr, you simply upload (sftp) your branch to a directory visible from your web page, and then people download (branch) using http.

Next step, I wanted to allow browsing of the branch from the web.  This feature is "free" with svn through WebDAV, and there have been extra tools to browse svn and cvs (e.g. <a href="http://www.viewvc.org/">ViewVC</a>).  For bzr however, all I could find was <a href="https://launchpad.net/loggerhead">LoggerHead</a> which works as an actual web server.  It has to start a daemon and open ports - pretty much defeating my initial motivation for using bzr.

I figured I'd just hack something quick.
<h1>webbzr</h1>
<h2>Features</h2>
webbzr is a php script that will:
<ul>
	<li>List the content of a directory and show normal and versioned files</li>
	<li>Allow browsing into the repository</li>
	<li>Allow viewing or downloading of files in the repository</li>
	<li>Allow downloading of branches or directories as a tgz/tbz2 package</li>
	<li>Allow browsing of revisions (going back in time)</li>
	<li>Display information about the last modifications</li>
</ul>
Files, not just directories, can be browsed by version. For example:
<ul>
	<li><a href="http://bazaar.enseed.com/app/webbzr/.webbzr/webbzr.php">http://bazaar.enseed.com/app/webbzr/.webbzr/webbzr.php</a>
grabs you the latest release of the file</li>
	<li><a href="http://bazaar.enseed.com/app/webbzr/.webbzr/webbzr.php?rev=1">http://bazaar.enseed.com/app/webbzr/.webbzr/webbzr.php?rev=1</a>
would get you revision 1 of the file.</li>
</ul>
<h2>Hiding the Parameters from the URL</h2>
Using mod_rewrite, browsing is transparent (you can browse using the actual path in the url).  For example, the link to <a href="http://bazaar.enseed.com/app/webbzr/">http://bazaar.enseed.com/app/webbzr/</a> brings you straight into a branch.  This is more convenient than using the equivalent url: <a href="http://bazaar.enseed.com/.webbzr/webbzr.php?path=app/webbzr/">http://bazaar.enseed.com/.webbzr/webbzr.php?path=app/webbzr/</a>.

To make this possible without configuring the web server directly, we use a .htaccess file that redirects requests to the script:

<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">RewriteEngine on<br />
RewriteCond %{REQUEST_URI} !^/\..*$<br />
RewriteRule ^(.*)$ /.webbzr/webbzr.php?path=$1 [L,QSA]</div></td></tr></tbody></table></div>

This reads: <em>given that the request uri does not start with a "." (the script in stored in <tt>.webbzr/</tt> to avoid recursive redirection), whatever the request was, pass it as an argument named <tt>path</tt> to webbzr.php</em>.
<h2>Formatting the Output</h2>
The webbzr.php script actually outputs xml, not html.  The xml is transformed on the client side with an xslt (<a href="http://bazaar.enseed.com/app/webbzr/.webbzr/webbzr.xsl">webbzr.xsl</a>) and styled with css (<a href="http://bazaar.enseed.com/app/webbzr/.webbzr/webbzr.css">webbzr.css</a>).  That means you can change the look if without having to touch the php code at all.
<h1>Installing</h1>
<h2>1. Download</h2>
To download:

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">bzr branch http:<span style="color: #000000; font-weight: bold;">//</span>bazaar.enseed.com<span style="color: #000000; font-weight: bold;">/</span>app<span style="color: #000000; font-weight: bold;">/</span>webbzr<span style="color: #000000; font-weight: bold;">/</span></div></td></tr></tbody></table></div>

<h2>2. Configure</h2>
Move to <tt>webbzr/.webbzr</tt>:

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #7a0874; font-weight: bold;">cd</span> &nbsp;webbzr<span style="color: #000000; font-weight: bold;">/</span>.webbzr<span style="color: #000000; font-weight: bold;">/</span></div></td></tr></tbody></table></div>

In the config.php file you will have to edit the following variables:
<ul>
	<li><tt>$BZRURL</tt>: this should be the url to the root of your web site (i.e. from where the script will run)</li>
	<li><tt>$BZRBINARY</tt>: how to invoke bzr. This may simply be "bzr" if it's in your path.</li>
	<li><tt>$XSLABSOLUTEURL</tt>: absolute url to the webbzr.xsl file.</li>
	<li><tt>$CSSABSOLUTEURL</tt>: absolute url to the webbzr.css file.</li>
</ul>
Move back to the webbzr directory (<code class="codecolorer bash default"><span class="bash"><span style="color: #7a0874; font-weight: bold;">cd</span> ..</span></code>) and edit the .htaccess file. Next to the RewriteRule, make sure the url to the <tt>webbzr.php</tt> is fine.  By default, it expects to be in <tt>/.webbzr/webbzr.php</tt>
<h2>3. Install</h2>
Copy the .htaccess file to the root of your browsing directory. Next to it, copy the .webbzr/ directory with the webbzr.php, config.php, webbzr.css, webbzr.xsl and the img/ directory.
<h2>4. Try it</h2>
And let me know if it works...]]></content:encoded>
			<wfw:commentRss>http://thoughts.enseed.com/webbzr/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Installing Bazaar (bzr) Locally on a Web Host</title>
		<link>http://thoughts.enseed.com/installing-bazaar-bzr-locally-on-a-web-host/</link>
		<comments>http://thoughts.enseed.com/installing-bazaar-bzr-locally-on-a-web-host/#comments</comments>
		<pubDate>Tue, 04 Aug 2009 13:15:54 +0000</pubDate>
		<dc:creator>petit</dc:creator>
				<category><![CDATA[Bazaar]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://thoughts.enseed.com/?p=286</guid>
		<description><![CDATA[Context Bazaar (bzr) is a nifty version control system. I'm still a fan of subversion (svn), but there are things that svn just won't do. For instance, if you want to publish your code to the open world, with svn, you end up with two options: You host it yourself on a dedicated server You [...]]]></description>
			<content:encoded><![CDATA[<h1>Context</h1>
<a href="http://bazaar-vcs.org/">Bazaar (bzr)</a> is a nifty version control system.  I'm still a fan of <a href="http://subversion.tigris.org/">subversion (svn)</a>, but there are things that svn just won't do.  For instance, if you want to publish your code to the open world, with svn, you end up with two options:
<ol>
	<li>You host it yourself on a dedicated server</li>
	<li>You have it hosted on either a paying site or for free (e.g. on <a href="http://sourceforge.net">SourceForge</a> or <a href="http://code.google.com">Google Code</a>)</li>
</ol>
I've been using the first solution for a while (got a dedicated server running in my closet with a dynamic dns), but I was at a point where I wanted to allow faster access to the repository.  I host sample code that I give to my students, and when they're all accessing the files at the same time, my internet connection is just not enough.  On the other hand, I have a <a href="http://www.hostrocket.com/">web host</a>, so I figured this is where the repository should be.  Except, my web host does not support subversion.
<h2>Why Bazaar</h2>
Bazaar is lightweight and decentralized. That's what caught my attention.  It's meant to be used as a distributed version control tool - meaning it can be used in a decentralized manner.  You checkout a branch anonymously, you work in it, you can commit changes to your local branch.  Once you're done, you can push back to the remote branch. Or, you can have other people checkout from your local branch and they can work on their side.  The best part (as far as I was concerned): pushing a branch can be done over sftp, pulling a branch can be done over http.  <span style="text-decoration: underline;">The server does not need to know anything about Bazaar</span>.  For instance.  You have a server on which you have ssh access and a web page (e.g. at school).
<h2 style="font-size: 1.5em;">Basics</h2>
You can create a new repository with a cpp file in it:

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$~<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #c20cb9; font-weight: bold;">mkdir</span> myproject<br />
$~<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #7a0874; font-weight: bold;">cd</span> myproject<br />
<span style="color: #007800;">$myproject</span><span style="color: #000000; font-weight: bold;">&gt;</span>bzr init<br />
Created a standalone <span style="color: #c20cb9; font-weight: bold;">tree</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>format: pack-<span style="color: #000000;">0.92</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
<span style="color: #007800;">$myproject</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #c20cb9; font-weight: bold;">ls</span> <span style="color: #660033;">-a</span><br />
. &nbsp; &nbsp; &nbsp; ..&nbsp; &nbsp; &nbsp; .bzr<br />
<span style="color: #007800;">$myproject</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #c20cb9; font-weight: bold;">touch</span> main.cpp<br />
<span style="color: #007800;">$myproject</span><span style="color: #000000; font-weight: bold;">&gt;</span>bzr add main.cpp<br />
adding main.cpp<br />
<span style="color: #007800;">$myproject</span><span style="color: #000000; font-weight: bold;">&gt;</span>bzr ci main.cpp <span style="color: #660033;">-m</span> <span style="color: #ff0000;">&quot;my first revision&quot;</span><br />
added main.cpp<br />
Committed revision <span style="color: #000000;">1</span>.</div></td></tr></tbody></table></div>

Notice the .bzr directory where Bazaar will keep information about this repository.

Then, you'll want to host this branch on your remote server.  You do that by pushing your branch:

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #007800;">$myproject</span><span style="color: #000000; font-weight: bold;">&gt;</span>bzr push sftp:<span style="color: #000000; font-weight: bold;">//</span>mylogin<span style="color: #000000; font-weight: bold;">@</span>myserver.com<span style="color: #000000; font-weight: bold;">/</span>~<span style="color: #000000; font-weight: bold;">/</span>public_html<span style="color: #000000; font-weight: bold;">/</span>mybzrdir<br />
Pushed up to revision <span style="color: #000000;">1</span>.</div></td></tr></tbody></table></div>

If mybzrdir is accessible from the web, people can now checkout (bzr calls it branching) from your repository:

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$~<span style="color: #000000; font-weight: bold;">&gt;</span>bzr branch http:<span style="color: #000000; font-weight: bold;">//</span>myserver.com<span style="color: #000000; font-weight: bold;">/</span>~mylogin<span style="color: #000000; font-weight: bold;">/</span>mybzrdir<br />
Branched <span style="color: #000000;">1</span> revision<span style="color: #7a0874; font-weight: bold;">&#40;</span>s<span style="color: #7a0874; font-weight: bold;">&#41;</span>.<br />
$~<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #c20cb9; font-weight: bold;">ls</span> <span style="color: #660033;">-a</span> mybzrdir<span style="color: #000000; font-weight: bold;">/</span><br />
. &nbsp; &nbsp; &nbsp; ..&nbsp; &nbsp; &nbsp; .bzr&nbsp; &nbsp; &nbsp; &nbsp; main.cpp</div></td></tr></tbody></table></div>

There you go.  You have a local branch of your remote repository (the server branch).  You can work in it, even commit changes (<code class="codecolorer bash default"><span class="bash">bzr ci</span></code>) and eventually, diff from the original branch and send the patch to the owner or, if you have access to the server branch, push it back with your local changes.
<h2>Identifying yourself</h2>
Since Bazaar works anonymously, you'll want to identify yourself when you make changes to the branches.  This is slightly different from most other revision control tools that I've used where you have an explicit login which is used both for access and identification.  Anonymous access with the other tools that I've used meant you had a dead branch.  You could still updated it, but you could not commit your changes.  With Bazaar, you can work in your local branch, even if it was checked out anonymously.

When you are about to commit changes, you use the "whoami" command to tell who you are:

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #007800;">$myproject</span><span style="color: #000000; font-weight: bold;">&gt;</span>bzr <span style="color: #c20cb9; font-weight: bold;">whoami</span> <span style="color: #ff0000;">&quot;John Doe &quot;</span><br />
<span style="color: #007800;">$myproject</span><span style="color: #000000; font-weight: bold;">&gt;</span>bzr <span style="color: #c20cb9; font-weight: bold;">whoami</span><br />
John Doe<br />
<span style="color: #007800;">$myproject</span><span style="color: #000000; font-weight: bold;">&gt;</span>bzr ci <span style="color: #660033;">-m</span> <span style="color: #ff0000;">&quot;my changes&quot;</span></div></td></tr></tbody></table></div>

By default, whoami will try to use the name associated with your login.  This is usually fine, but the email it will guess is most likely not the one you want to use (e.g. you@localhost).
<h1>Installing</h1>
<h2>Local Install on a Web Host</h2>
Here are the steps that I followed to install bzr locally (in my user directory without root access) without using gcc.

Although you do not need to install it on your server, I still wanted to.  The reason being that I cannot find any decent cgi that will let me browse the content of my bzr repository from the web.  The easiest way is to install bzr and have it used by a script query and stat your repository from your web page.

So again, <strong>you do not need to install bzr on the server</strong> (for me, that was the whole point of using Bazaar in the first place). Still here's how I got it to install:
<h4>1. Log on to Your Server</h4>

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">ssh</span> myserver</div></td></tr></tbody></table></div>

<h4>2. Get the Source</h4>
The source code is available from theBazaar Download page at <a href="http://bazaar-vcs.org/Download">http://bazaar-vcs.org/Download</a>. Under "Source of the stable release for any platform", you'll find a link to the source code:

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #007800;">$server</span>:~<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #c20cb9; font-weight: bold;">mkdir</span> bzr-temp<br />
<span style="color: #007800;">$server</span>:~<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #7a0874; font-weight: bold;">cd</span> bzr-temp<br />
<span style="color: #007800;">$server</span>:bzr-temp<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #c20cb9; font-weight: bold;">wget</span> http:<span style="color: #000000; font-weight: bold;">//</span>launchpad.net<span style="color: #000000; font-weight: bold;">/</span>bzr<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">2.0</span><span style="color: #000000; font-weight: bold;">/</span>2.0.5<span style="color: #000000; font-weight: bold;">/</span>+download<span style="color: #000000; font-weight: bold;">/</span>bzr-2.0.5.tar.gz<br />
<span style="color: #007800;">$server</span>:bzr-temp<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #c20cb9; font-weight: bold;">tar</span> <span style="color: #660033;">-zxvf</span> bzr-2.0.5.tar.gz<br />
<span style="color: #007800;">$server</span>:bzr-temp<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #7a0874; font-weight: bold;">cd</span> bzr-2.0.5</div></td></tr></tbody></table></div>

<h4>3. Compile the Source Locally Without gcc</h4>
My server does not give me access to gcc (they don't really want me to start programming on the web server, I guess installing custom software, even locally, is borderline...).

Usually, to install locally (in $HOME), you'd simply run the following command:

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$</span>server:bzr-2.0.5<span style="color: #000000; font-weight: bold;">&gt;</span>python setup.py <span style="color: #c20cb9; font-weight: bold;">install</span> <span style="color: #660033;">--home</span> <span style="color: #007800;">$HOME</span></div></td></tr></tbody></table></div>

But in this case, I ended up with

<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">gcc -pthread -fno-strict-aliasing -DNDEBUG -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fPIC -I/usr/include/python2.4 -c bzrlib/_annotator_pyx.c -o build/temp.linux-x86_64-2.4/bzrlib/_annotator_pyx.o<br />
unable to execute gcc: Permission denied<br />
<br />
Cannot build extension &quot;bzrlib._annotator_pyx&quot;.<br />
Use &quot;build_ext --allow-python-fallback&quot; to use slower python implementations instead.<br />
<br />
error: command 'gcc' failed with exit status 1</div></td></tr></tbody></table></div>

Since gcc cannot be used, we'll have to run the "slower" python implementation.  This was achieved by adding the suggested arguments:

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$</span>server:bzr-2.0.5<span style="color: #000000; font-weight: bold;">&gt;</span>python setup.py <span style="color: #c20cb9; font-weight: bold;">install</span> <span style="color: #660033;">--home</span> <span style="color: #007800;">$HOME</span> build_ext <span style="color: #660033;">--allow-python-fallback</span></div></td></tr></tbody></table></div>

This compiled and installed successfully.
<h4>4. Set the PYTHONPATH Environment Variable</h4>
Running "bzr" from the command line, I'd get the following error:

<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$server:~&gt;bzr<br />
bzr: ERROR: Couldn't import bzrlib and dependencies.<br />
Please check the directory containing bzrlib is on your PYTHONPATH.<br />
<br />
Traceback (most recent call last):<br />
File &quot;/home2/enseed/bin/bzr&quot;, line 107, in ?<br />
import bzrlib<br />
ImportError: No module named bzrlib</div></td></tr></tbody></table></div>

All you need to do is add the path to your local python libraries to the PYTHONPATH environment variable.  This can be done in your .bashrc by adding an export directive

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">PYTHONPATH</span>=~<span style="color: #000000; font-weight: bold;">/</span>lib64<span style="color: #000000; font-weight: bold;">/</span>python<span style="color: #000000; font-weight: bold;">/</span></div></td></tr></tbody></table></div>

(in your case, it might be at some other place than lib64, check it up)

Or, simply define the variable when you execute bzr:

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$</span>server:~<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #007800;">PYTHONPATH</span>=~<span style="color: #000000; font-weight: bold;">/</span>lib64<span style="color: #000000; font-weight: bold;">/</span>python<span style="color: #000000; font-weight: bold;">/</span> bzr</div></td></tr></tbody></table></div>

<h2>Installing on Mac OS X</h2>
I used <a href="http://www.finkproject.org/">fink</a> to install bzr on mac:

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$~<span style="color: #000000; font-weight: bold;">&gt;</span>fink <span style="color: #c20cb9; font-weight: bold;">install</span> bzr-py25<br />
$~<span style="color: #000000; font-weight: bold;">&gt;</span>fink <span style="color: #c20cb9; font-weight: bold;">install</span> paramiko-py25</div></td></tr></tbody></table></div>

I did not install bzr-py26 becase paramiko, which is used by bzr for for ssh connections,  was not available (at the time of this writing) for python 2.6.
<h2>Installing on Ubuntu</h2>
On Ubuntu, it was relatively painless to install:

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$</span>~<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get install</span> bzr</div></td></tr></tbody></table></div>

]]></content:encoded>
			<wfw:commentRss>http://thoughts.enseed.com/installing-bazaar-bzr-locally-on-a-web-host/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automatic login into WordPress</title>
		<link>http://thoughts.enseed.com/automatic-login-into-wordpress/</link>
		<comments>http://thoughts.enseed.com/automatic-login-into-wordpress/#comments</comments>
		<pubDate>Mon, 03 Aug 2009 13:15:07 +0000</pubDate>
		<dc:creator>petit</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web Programming]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://thoughts.enseed.com/?p=281</guid>
		<description><![CDATA[To make a WordPress private, it seemed like using an .htaccess would be the most straight-forward and secure approach. However, you end up having to type in your username name and password twice - once to get access to the web page (web server authentication) and once more to log into WordPress. I googled a [...]]]></description>
			<content:encoded><![CDATA[To make a WordPress private, it seemed like using an .htaccess would be the most straight-forward and secure approach. However, you end up having to type in your username name and password twice - once to get access to the web page (web server authentication) and once more to log into WordPress.

I googled a bit and ended up on <a title="WordPress Auto-Login" href="http://www.lbsharp.com/wordpress/index.php/2007/12/10/wordpress-auto-login/" target="_blank">this post</a> by Leon Bukhman. In his case, he wanted automatic login to a "guest" account. I changed the code a bit and got it working with the REMOTE_USER environment variable (this is set by the webserver).

<b>The full PHP script for WordPress is available at
</b><ul><li><a href="http://bazaar.enseed.com/utils/wordpress/plugins/autologin/">http://bazaar.enseed.com/utils/wordpress/plugins/autologin/</a></li></ul>

You still have to create two accounts:
<ol>
	<li>An entry in the .htaccess file for logging</li>
	<li>An account <strong>with the same username</strong> for the WordPress.</li>
</ol>
When you log into the website, you will be logged into WordPress with the same username. You can still log-out of WordPress (you'll be directed to the login page) and log-in with a different name (e.g. admin).

Here's the script for the plugin:

<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">function</span> auto_login<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>is_user_logged_in<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$user_login</span> <span style="color: #339933;">=</span> <span style="color: #990000;">getenv</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;REMOTE_USER&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$user_login</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$user</span> <span style="color: #339933;">=</span> get_userdatabylogin<span style="color: #009900;">&#40;</span><span style="color: #000088;">$user_login</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//get user's ID</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$user_id</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">ID</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//login</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; wp_set_current_user<span style="color: #009900;">&#40;</span><span style="color: #000088;">$user_id</span><span style="color: #339933;">,</span> <span style="color: #000088;">$user_login</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; wp_set_auth_cookie<span style="color: #009900;">&#40;</span><span style="color: #000088;">$user_id</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; do_action<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'wp_login'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$user_login</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
add_action<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'init'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'auto_login'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>

]]></content:encoded>
			<wfw:commentRss>http://thoughts.enseed.com/automatic-login-into-wordpress/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Loading Images using QuickTime</title>
		<link>http://thoughts.enseed.com/loading-images-using-quicktime/</link>
		<comments>http://thoughts.enseed.com/loading-images-using-quicktime/#comments</comments>
		<pubDate>Sat, 01 Aug 2009 18:25:56 +0000</pubDate>
		<dc:creator>petit</dc:creator>
				<category><![CDATA[C++ Classes]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://thoughts.enseed.com/?p=236</guid>
		<description><![CDATA[QuickTime can be used to open a variety of image files on Mac OS and Windows. I have put together a simple C++ class that will open image and read image files. By default, QuickTime will read jpeg, tiff, png, gif, bmp, targa, sgi, pdf (first page) and others such as JPEG 2000 (depending on [...]]]></description>
			<content:encoded><![CDATA[<a style="color: #003399;" href="http://www.apple.com/quicktime/">QuickTime</a> can be used to open a variety of image files on Mac OS and Windows. I have put together a simple C++ class that will open image and read image files. By default, QuickTime will read jpeg, tiff, png, gif, bmp, targa, sgi, pdf (first page) and others such as JPEG 2000 (depending on the version and on what components are installed).

Basically, here is how you can proceed to open an image with QuickTime:
<h3>Initialize QuickTime</h3>

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">OSStatus err <span style="color: #000080;">=</span> noErr<span style="color: #008080;">;</span><br />
<span style="color: #339900;">#ifdef _WIN32</span><br />
err <span style="color: #000080;">=</span> InitializeQTML<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// on windows, call InitializeQTML first</span><br />
<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>err<span style="color: #008000;">&#41;</span> &nbsp; &nbsp;<span style="color: #0000ff;">return</span> err<span style="color: #008080;">;</span> &nbsp;<span style="color: #666666;">// QuickTime is probably not installed</span><br />
<span style="color: #339900;">#endif // _WIN32</span><br />
<br />
err <span style="color: #000080;">=</span> EnterMovies<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>err<span style="color: #008000;">&#41;</span> &nbsp; &nbsp;<span style="color: #0000ff;">return</span> err<span style="color: #008080;">;</span> &nbsp;<span style="color: #666666;">// Failed to initialize QuickTime</span></div></td></tr></tbody></table></div>

<h3>Obtain a Graphics Importer ComponentInstance</h3>
Opening an image file happens in two steps. First find an image importer within QuickTime, then process the file:

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">OSStatus OpenQuickTimeImageFile<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>path<span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666;">//--------------------------------------------------------------------------</span><br />
&nbsp; &nbsp; <span style="color: #666666;">// &nbsp;Obtain a file reference</span><br />
<span style="color: #339900;">#ifdef _WIN32</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">const</span> CFStringBuiltInEncodings kNativeEncoding <span style="color: #000080;">=</span> kCFStringEncodingWindowsLatin1<br />
<span style="color: #339900;">#else</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">const</span> CFStringBuiltInEncodings kNativeEncoding <span style="color: #000080;">=</span> kCFStringEncodingMacRoman<span style="color: #008080;">;</span><br />
<span style="color: #339900;">#endif // _WIN32</span><br />
<br />
&nbsp; &nbsp; CFStringRef cfPath <span style="color: #000080;">=</span> CFStringCreateWithCString<span style="color: #008000;">&#40;</span>kCFAllocatorDefault, path, kNativeEncoding<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; Handle dataRef <span style="color: #000080;">=</span> NewHandle<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span>AliasHandle<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; OSType dataRefType<span style="color: #008080;">;</span><br />
<br />
&nbsp; &nbsp; OSStatus err <span style="color: #000080;">=</span> QTNewDataReferenceFromFullPathCFString<span style="color: #008000;">&#40;</span>cfPath, kQTNativeDefaultPathStyle, <span style="color: #0000dd;">0</span>, <span style="color: #000040;">&amp;</span>dataRef, <span style="color: #000040;">&amp;</span>dataRefType<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; CFRelease<span style="color: #008000;">&#40;</span>cfPath<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666;">//--------------------------------------------------------------------------</span><br />
&nbsp; &nbsp; <span style="color: #666666;">// &nbsp;Find the image importer</span><br />
<br />
&nbsp; &nbsp; ComponentInstance fileImporter<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; err <span style="color: #000080;">=</span> GetGraphicsImporterForDataRef<span style="color: #008000;">&#40;</span>dataRef, dataRefType, <span style="color: #000040;">&amp;</span>fileImporter<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; DisposeHandle<span style="color: #008000;">&#40;</span>dataRef<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>

<h3>Obtain Image Information</h3>
Once the image importer is found and loaded, information about the image can be obtained from the image description:

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; ImageDescriptionHandle imageInfo <span style="color: #000080;">=</span> <span style="color: #008000;">&#40;</span>ImageDescriptionHandle<span style="color: #008000;">&#41;</span>NewHandle<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span>ImageDescription<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; err <span style="color: #000080;">=</span> GraphicsImportGetImageDescription<span style="color: #008000;">&#40;</span>fileImporter, <span style="color: #000040;">&amp;</span>mImageInfo<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0000ff;">int</span> width <span style="color: #000080;">=</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">**</span>imageInfo<span style="color: #008000;">&#41;</span>.<span style="color: #007788;">width</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">int</span> height <span style="color: #000080;">=</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">**</span>imageInfo<span style="color: #008000;">&#41;</span>.<span style="color: #007788;">height</span><span style="color: #008080;">;</span><br />
<br />
&nbsp; &nbsp; DisposeHandle<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>Handle<span style="color: #008000;">&#41;</span>imageInfo<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>

<h3>Load the Image</h3>
Finally, loading the image has to be done within a GWorld:

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; Rect bounds<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; bounds.<span style="color: #007788;">left</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; bounds.<span style="color: #007788;">top</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; bounds.<span style="color: #007788;">right</span> <span style="color: #000080;">=</span> width<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; bounds.<span style="color: #007788;">bottom</span> <span style="color: #000080;">=</span> height<span style="color: #008080;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0000ff;">int</span> bpp <span style="color: #000080;">=</span> <span style="color: #0000dd;">4</span><span style="color: #008080;">;</span> <span style="color: #666666;">// bytes per pixel</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">int</span> rowBytes <span style="color: #000080;">=</span> bpp<span style="color: #000040;">*</span>width<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>data <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> <span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">char</span><span style="color: #008000;">&#91;</span>height<span style="color: #000040;">*</span>rowBytes<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span><br />
<br />
&nbsp; &nbsp; GWorldPtr buffer <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; err <span style="color: #000080;">=</span> QTNewGWorldFromPtr<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>buffer, k32RGBAPixelFormat, <span style="color: #000040;">&amp;</span>bounds, <span style="color: #0000ff;">NULL</span>, <span style="color: #0000ff;">NULL</span>, <span style="color: #0000dd;">0</span>, data, rowBytes<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
&nbsp; &nbsp; err <span style="color: #000080;">=</span> GraphicsImportSetGWorld<span style="color: #008000;">&#40;</span>fileImporter, buffer, <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; err <span style="color: #000080;">=</span> GraphicsImportDraw<span style="color: #008000;">&#40;</span>fileImporter<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
&nbsp; &nbsp; DisposeGWorld<span style="color: #008000;">&#40;</span>offscreenBuffer<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; CloseComponent<span style="color: #008000;">&#40;</span>fileImporter<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>

<h3>Special Case - 8bit Grayscale Images</h3>
In case you are reading an 8 bit grayscale image (with k8IndexedPixelFormat or k8IndexedGrayPixelFormat instead of k32RGBAPixelFormat), you have to know that QuickTime uses a color table that's inverted (black is 255 and white is 0). One option is to invert the grayscale image after it has been drawn in the gworld (i.e. data[i] = 255-data[i];) but a more efficient way is to provide QuickTime with a correct color table before drawing in the GWorld:

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>format <span style="color: #000080;">==</span> k8IndexedPixelFormat<span style="color: #008000;">&#41;</span> <span style="color: #666666;">// we're in 8 bit grayscale</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666;">// the default color table is inverted, so let's create </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CTabHandle grayCTab <span style="color: #000080;">=</span> GetCTable<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">40</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><span style="color: #666666;">// gray clut ID = color clut ID +32</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666;">// invert the default color table</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">256</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#40;</span><span style="color: #000040;">**</span>grayCTab<span style="color: #008000;">&#41;</span>.<span style="color: #007788;">ctTable</span><span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">rgb</span>.<span style="color: #007788;">red</span> <span style="color: #000080;">=</span> ~<span style="color: #008000;">&#40;</span><span style="color: #000040;">**</span>grayCTab<span style="color: #008000;">&#41;</span>.<span style="color: #007788;">ctTable</span><span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">rgb</span>.<span style="color: #007788;">red</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#40;</span><span style="color: #000040;">**</span>grayCTab<span style="color: #008000;">&#41;</span>.<span style="color: #007788;">ctTable</span><span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">rgb</span>.<span style="color: #007788;">green</span> <span style="color: #000080;">=</span> ~<span style="color: #008000;">&#40;</span><span style="color: #000040;">**</span>grayCTab<span style="color: #008000;">&#41;</span>.<span style="color: #007788;">ctTable</span><span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">rgb</span>.<span style="color: #007788;">green</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#40;</span><span style="color: #000040;">**</span>grayCTab<span style="color: #008000;">&#41;</span>.<span style="color: #007788;">ctTable</span><span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">rgb</span>.<span style="color: #007788;">blue</span> <span style="color: #000080;">=</span> ~<span style="color: #008000;">&#40;</span><span style="color: #000040;">**</span>grayCTab<span style="color: #008000;">&#41;</span>.<span style="color: #007788;">ctTable</span><span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">rgb</span>.<span style="color: #007788;">blue</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; err <span style="color: #000080;">=</span> QTNewGWorldFromPtr<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>buffer, k8IndexedPixelFormat, <span style="color: #000040;">&amp;</span>bounds, grayCTab, <span style="color: #0000ff;">NULL</span>, <span style="color: #0000dd;">0</span>, data, rowBytes<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; DisposeCTable<span style="color: #008000;">&#40;</span>grayCTab<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>

]]></content:encoded>
			<wfw:commentRss>http://thoughts.enseed.com/loading-images-using-quicktime/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Loading Images under Windows (an OLE Image Loader)</title>
		<link>http://thoughts.enseed.com/loading-images-under-windows-an-ole-image-loader/</link>
		<comments>http://thoughts.enseed.com/loading-images-under-windows-an-ole-image-loader/#comments</comments>
		<pubDate>Sat, 01 Aug 2009 18:25:22 +0000</pubDate>
		<dc:creator>petit</dc:creator>
				<category><![CDATA[C++ Classes]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://thoughts.enseed.com/?p=234</guid>
		<description><![CDATA[OLE can be used to open a few of image file formats (JPEG, BMP, GIF but no PNG) on Windows. I have put together a simple C++ class that will open image and read image files. Basically, here is how you can proceed to open an image with OLE (this is actually inspired from this [...]]]></description>
			<content:encoded><![CDATA[OLE can be used to open a few of image file formats (JPEG, BMP, GIF but no PNG) on Windows. I have put together a simple C++ class that will open image and read image files.

Basically, here is how you can proceed to open an image with OLE (this is actually inspired from <a href="http://www.codeproject.com/KB/graphics/render.aspx">this codeproject article</a>):
<h3>Obtain an IStream Pointer</h3>
Load the file into global memory and create an IStream*

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">// open the file</span><br />
HANDLE hFile <span style="color: #000080;">=</span> CreateFile<span style="color: #008000;">&#40;</span>path, GENERIC_READ, <span style="color: #0000dd;">0</span>, <span style="color: #0000ff;">NULL</span>, OPEN_EXISTING, <span style="color: #0000dd;">0</span>, <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #666666;">// allocate storage to read the file</span><br />
DWORD dwFileSize <span style="color: #000080;">=</span> GetFileSize<span style="color: #008000;">&#40;</span>hFile, <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
HGLOBAL hGlobal <span style="color: #000080;">=</span> GlobalAlloc<span style="color: #008000;">&#40;</span>GMEM_MOVEABLE, dwFileSize<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
LPVOID pvData <span style="color: #000080;">=</span> GlobalLock<span style="color: #008000;">&#40;</span>hGlobal<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
DWORD dwBytesRead <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #666666;">// read the file</span><br />
BOOL bRead <span style="color: #000080;">=</span> ReadFile<span style="color: #008000;">&#40;</span>hFile, pvData, dwFileSize, <span style="color: #000040;">&amp;</span>dwBytesRead, <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
GlobalUnlock<span style="color: #008000;">&#40;</span>hGlobal<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
CloseHandle<span style="color: #008000;">&#40;</span>hFile<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #666666;">// create the IStream* from the global memory</span><br />
LPSTREAM pstm <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span><br />
HRESULT hr <span style="color: #000080;">=</span> CreateStreamOnHGlobal<span style="color: #008000;">&#40;</span>hGlobal, TRUE, <span style="color: #000040;">&amp;</span>pstm<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>

<h3>Import with OleLoadPicture</h3>

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">LPPICTURE picture<span style="color: #008080;">;</span><br />
hr <span style="color: #000080;">=</span> <span style="color: #008080;">::</span><span style="color: #007788;">OleLoadPicture</span><span style="color: #008000;">&#40;</span>pstm, dwFileSize, FALSE, IID_IPicture, <span style="color: #008000;">&#40;</span>LPVOID <span style="color: #000040;">*</span><span style="color: #008000;">&#41;</span><span style="color: #000040;">&amp;</span><span style="color: #008000;">&#40;</span>picture<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>

<h3 >Obtain Image Information</h3>
Once we have obtained the PICTURE object, we can query its size:

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">long</span> hmWidth <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span>, hmHeight <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><br />
picture<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>get_Width <span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>hmWidth<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
picture<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>get_Height<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>hmHeight<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
HDC Screen <span style="color: #000080;">=</span> <span style="color: #008080;">::</span><span style="color: #007788;">CreateCompatibleDC</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #0000ff;">int</span> width <span style="color: #000080;">=</span> MulDiv<span style="color: #008000;">&#40;</span>hmWidth, GetDeviceCaps<span style="color: #008000;">&#40;</span>Screen, LOGPIXELSX<span style="color: #008000;">&#41;</span>, HIMETRIC_INCH<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">int</span> height <span style="color: #000080;">=</span> MulDiv<span style="color: #008000;">&#40;</span>hmHeight, GetDeviceCaps<span style="color: #008000;">&#40;</span>Screen, LOGPIXELSY<span style="color: #008000;">&#41;</span>, HIMETRIC_INCH<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #008080;">::</span><span style="color: #007788;">DeleteDC</span><span style="color: #008000;">&#40;</span>Screen<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>

<h3>Load the Image</h3>
Finally, loading the image has to be done within a custom DC:

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">HDC hDC <span style="color: #000080;">=</span> CreateCompatibleDC<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
BITMAPINFO bmInfo <span style="color: #000080;">=</span> <span style="color: #008000;">&#123;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span><br />
bmInfo.<span style="color: #007788;">bmiHeader</span>.<span style="color: #007788;">biSize</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span>BITMAPINFO<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
bmInfo.<span style="color: #007788;">bmiHeader</span>.<span style="color: #007788;">biSizeImage</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><br />
bmInfo.<span style="color: #007788;">bmiHeader</span>.<span style="color: #007788;">biPlanes</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">;</span><br />
bmInfo.<span style="color: #007788;">bmiHeader</span>.<span style="color: #007788;">biBitCount</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">32</span><span style="color: #008080;">;</span> <span style="color: #666666;">// or 24 if you don't care about alpha</span><br />
bmInfo.<span style="color: #007788;">bmiHeader</span>.<span style="color: #007788;">biWidth</span> <span style="color: #000080;">=</span> width<span style="color: #008080;">;</span><br />
bmInfo.<span style="color: #007788;">bmiHeader</span>.<span style="color: #007788;">biHeight</span> <span style="color: #000080;">=</span> height<span style="color: #008080;">;</span><br />
<br />
<span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>pixels<span style="color: #008080;">;</span><br />
HBITMAP bm <span style="color: #000080;">=</span> CreateDIBSection<span style="color: #008000;">&#40;</span>hDC, <span style="color: #000040;">&amp;</span>bmInfo, DIB_RGB_COLORS, <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">void</span><span style="color: #000040;">**</span><span style="color: #008000;">&#41;</span><span style="color: #000040;">&amp;</span>pixels, <span style="color: #0000ff;">NULL</span>, <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
HGDIOBJ old <span style="color: #000080;">=</span> SelectObject<span style="color: #008000;">&#40;</span>hDC, bm<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
RECT rc<span style="color: #008080;">;</span><br />
rc.<span style="color: #007788;">left</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><br />
rc.<span style="color: #007788;">top</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><br />
rc.<span style="color: #007788;">right</span> <span style="color: #000080;">=</span> width<span style="color: #008080;">;</span><br />
rc.<span style="color: #007788;">bottom</span> <span style="color: #000080;">=</span> height<span style="color: #008080;">;</span><br />
<br />
HRESULT hrP <span style="color: #000080;">=</span><br />
picture<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>Render<span style="color: #008000;">&#40;</span>hDC, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">0</span>, width, height, <span style="color: #0000dd;">0</span>, hmHeight, hmWidth, <span style="color: #000040;">-</span>hmHeight, <span style="color: #000040;">&amp;</span>rc<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
BITMAP b<span style="color: #008080;">;</span><br />
SelectObject<span style="color: #008000;">&#40;</span>hDC, old<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
GetObject<span style="color: #008000;">&#40;</span>bm, <span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span>b<span style="color: #008000;">&#41;</span>, <span style="color: #000040;">&amp;</span>b<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">int</span> rowLength <span style="color: #000080;">=</span> b.<span style="color: #007788;">bmWidthBytes</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #666666;">// allocate a buffer</span><br />
<span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>data <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> <span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">char</span><span style="color: #008000;">&#91;</span>width<span style="color: #000040;">*</span>height<span style="color: #000040;">*</span><span style="color: #0000dd;">4</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #666666;">// load the texture into the data buffer</span><br />
GetBitmapBits<span style="color: #008000;">&#40;</span>bm, b.<span style="color: #007788;">bmHeight</span><span style="color: #000040;">*</span>rowLength, data<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
DeleteObject<span style="color: #008000;">&#40;</span>bm<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
DeleteDC<span style="color: #008000;">&#40;</span>hDC<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>

<h3>Special Case - Loading Alpha Correctly</h3>
Older BMP did not support 32 bit with alpha channel. Support for an alpha channel was added in XP I believe. As a consequence, some BMP have been written as 32bit with an unused (at the time) alpha channel that's completely transparent. If you plan on using the alpha channel from the BMP files, it's generally a good idea to check if the entire alpha channel is transparent. In such a case, we would assume that the entire channel should make it fully opaque. This is what the following piece of code does:

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">// scan to check if the alpha is all transparent</span><br />
<span style="color: #0000ff;">bool</span> allTransp <span style="color: #000080;">=</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>row <span style="color: #000080;">=</span> data<span style="color: #008080;">;</span><br />
<br />
<span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> y <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> allTransp <span style="color: #000040;">&amp;&amp;</span> y <span style="color: #000080;">&lt;</span> b.<span style="color: #007788;">bmHeight</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>y<span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> x <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> allTransp <span style="color: #000040;">&amp;&amp;</span> x <span style="color: #000080;">&lt;</span> b.<span style="color: #007788;">bmWidth</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>x<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">int</span> a <span style="color: #000080;">=</span> row<span style="color: #008000;">&#91;</span>x<span style="color: #000040;">*</span><span style="color: #0000dd;">4</span><span style="color: #000040;">+</span><span style="color: #0000dd;">3</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>a <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; allTransp <span style="color: #000080;">=</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; row <span style="color: #000040;">+</span><span style="color: #000080;">=</span> rowLength<span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span><br />
<br />
<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>allTransp<span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666;">// if everything is transparent, make everything opaque</span><br />
&nbsp; &nbsp; row <span style="color: #000080;">=</span> data<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> y <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> y <span style="color: #000080;">&lt;</span> b.<span style="color: #007788;">bmHeight</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>y<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> x <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> x <span style="color: #000080;">&lt;</span> b.<span style="color: #007788;">bmWidth</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>x<span style="color: #008000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; row<span style="color: #008000;">&#91;</span>x<span style="color: #000040;">*</span><span style="color: #0000dd;">4</span><span style="color: #000040;">+</span><span style="color: #0000dd;">3</span><span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">255</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; row <span style="color: #000040;">+</span><span style="color: #000080;">=</span> rowLength<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>

]]></content:encoded>
			<wfw:commentRss>http://thoughts.enseed.com/loading-images-under-windows-an-ole-image-loader/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fast Fourier Transform in C++</title>
		<link>http://thoughts.enseed.com/fast-fourier-transform-in-c/</link>
		<comments>http://thoughts.enseed.com/fast-fourier-transform-in-c/#comments</comments>
		<pubDate>Sat, 01 Aug 2009 18:24:32 +0000</pubDate>
		<dc:creator>petit</dc:creator>
				<category><![CDATA[C++ Classes]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://thoughts.enseed.com/?p=232</guid>
		<description><![CDATA[To download: 1bzr branch http://bazaar.enseed.com/lib/Generic/ look under Math/Fourier.h This class is a work in progress. It works fine as it is, for most transforms I do are real-&#62;complex, and only half of the transform needs to be computed in such a case. So I plan on modifying this code eventually to deal with this case [...]]]></description>
			<content:encoded><![CDATA[To download:

<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">bzr branch http://bazaar.enseed.com/lib/Generic/ look under Math/Fourier.h</div></td></tr></tbody></table></div>

<strong>This class is a work in progress</strong>. It works fine as it is, for most transforms I do are real-&gt;complex, and only half of the transform needs to be computed in such a case. So I plan on modifying this code eventually to deal with this case and save half of the computation time.

This started when I needed a Fast Fourier Transform that was not GPL'ed. If you can deal with a GPL license, by all means use<a href="http://www.fftw.org/">FFTW</a> instead. In my tests, FFTW is about 35% faster than the current code for vectors size between 1 and 65536. There is still room for improvement in the current code though, as I mentioned above, it's a work in progress...
<h2>Forward Transform</h2>
Performing a forward transform is done like this:

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">std<span style="color: #008080;">::</span><span style="color: #007788;">complex</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">double</span><span style="color: #000080;">&gt;</span> data<span style="color: #008000;">&#91;</span>SIZE<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span><br />
Fourier<span style="color: #008080;">::</span><span style="color: #007788;">forwardTransform</span><span style="color: #008000;">&#40;</span>data, SIZE<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// if you don't know SIZE at compile time</span><br />
Fourier<span style="color: #008080;">::</span><span style="color: #007788;">forwardTransform</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">double</span>, SIZE<span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>data<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// if you know SIZE at compile time</span></div></td></tr></tbody></table></div>

Expect the second version (where you know SIZE at compile time) to be 2 to 10 times faster than the other (don't foget to turn on compiler optimizations - they will make a huge difference, especially code inlining). The transform is performed in-place</span>
<h2>Reverse Transform</h2>
Performing a reverse transform is done like this:

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">std<span style="color: #008080;">::</span><span style="color: #007788;">complex</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">double</span><span style="color: #000080;">&gt;</span> data<span style="color: #008000;">&#91;</span>SIZE<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span><br />
Fourier<span style="color: #008080;">::</span><span style="color: #007788;">reverseTransform</span><span style="color: #008000;">&#40;</span>data, SIZE<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// if you don't know SIZE at compile time</span><br />
Fourier<span style="color: #008080;">::</span><span style="color: #007788;">reverseTransform</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">double</span>, SIZE<span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>data<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// if you know SIZE at compile time</span></div></td></tr></tbody></table></div>

<h2>Scaling</h2>
<strong>This is important.</strong> The discrete Fourier transform reads like this:
<div><img src="http://www-etud.iro.umontreal.ca/~petitg/cpp/fft.png" alt="" height="60" /></div>
And the reverse discrete fourier transform:
<div><img src="http://www-etud.iro.umontreal.ca/~petitg/cpp/ifft.png" alt="" height="60" /></div>
I don't compute the one-over-square-root-of-n term (<img src="http://www-etud.iro.umontreal.ca/~petitg/cpp/scale.png" alt="" height="30" />) because often, we don't really care about actual values, but about the distribution. This means however, that the data will be scaled when you do a forward-reverse transform and you have to scale down it yourself:

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000ff;">double</span> factor <span style="color: #000080;">=</span> <span style="color:#800080;">1.0</span> <span style="color: #000040;">/</span><span style="color: #000080;">=</span> <span style="color: #0000dd;">sqrt</span><span style="color: #008000;">&#40;</span>SIZE<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
std<span style="color: #008080;">::</span><span style="color: #007788;">complex</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">double</span><span style="color: #000080;">&gt;</span> data<span style="color: #008000;">&#91;</span>SIZE<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span><br />
Fourier<span style="color: #008080;">::</span><span style="color: #007788;">forwardTransform</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">double</span>, SIZE<span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>data<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #000040;">***</span><span style="color: #000080;">&gt;</span> <span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> SIZE<span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span> data<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span> <span style="color: #000040;">*</span><span style="color: #000080;">=</span> factor<span style="color: #008080;">;</span><br />
<br />
Fourier<span style="color: #008080;">::</span><span style="color: #007788;">reverseTransform</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">double</span>, SIZE<span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>data<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #000040;">***</span><span style="color: #000080;">&gt;</span> <span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> SIZE<span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span> data<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span> <span style="color: #000040;">*</span><span style="color: #000080;">=</span> factor<span style="color: #008080;">;</span><br />
<br />
<span style="color: #666666;">// Or, sometimes you can wait until the end to scale</span><br />
<span style="color: #0000ff;">double</span> factor2 <span style="color: #000080;">=</span> <span style="color:#800080;">1.0</span> <span style="color: #000040;">/</span><span style="color: #000080;">=</span> SIZE<span style="color: #008080;">;</span><br />
Fourier<span style="color: #008080;">::</span><span style="color: #007788;">forwardTransform</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">double</span>, SIZE<span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>data<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
Fourier<span style="color: #008080;">::</span><span style="color: #007788;">reverseTransform</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">double</span>, SIZE<span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>data<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #000040;">***</span><span style="color: #000080;">&gt;</span> <span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> SIZE<span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span> data<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span> <span style="color: #000040;">*</span><span style="color: #000080;">=</span> factor2<span style="color: #008080;">;</span></div></td></tr></tbody></table></div>

If you think my recursive templates are overkill and you're a pure C fan, think again. Making a template-recursive LU decomposition or Fourier transform is not only fun, it's fast. The Fourier transform here is based on a standard Cooley-Tukey algorithm and it comes in two flavours. You can either call:

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">std<span style="color: #008080;">::</span><span style="color: #007788;">complex</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">double</span><span style="color: #000080;">&gt;</span> <span style="color: #000040;">*</span>myData <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> std<span style="color: #008080;">::</span><span style="color: #007788;">complex</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">double</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#91;</span>size<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span><br />
<span style="color: #666666;">// ...</span><br />
Fourier<span style="color: #008080;">::</span><span style="color: #007788;">forwardTransform</span><span style="color: #008000;">&#40;</span>myData, size<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>

or, if you know the size of your vector at compile time (which is often the case), for example, say size = 1024:

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">std<span style="color: #008080;">::</span><span style="color: #007788;">complex</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">double</span><span style="color: #000080;">&gt;</span> <span style="color: #000040;">*</span>myData <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> std<span style="color: #008080;">::</span><span style="color: #007788;">complex</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">double</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#91;</span><span style="color: #0000dd;">1024</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span><br />
<span style="color: #666666;">// ...</span><br />
Fourier<span style="color: #008080;">::</span><span style="color: #007788;">forwardTransform</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">double</span>, <span style="color: #0000dd;">1024</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>myData<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>

Cooley-Tukey is recursive - meaning it will find coefficients for the transform for a vector of size N by solving for a vector of size N/2. The naive implementation could use recursive functions, but get a lot of overhead if you don't inline. If you inline, or if you build a single function which loops, you have less overhead, but you still end up with loops that will have very small iterations (e.g, for (i = 0; i &lt; 4; ++i) ...) and there is still a lot of overhead in the loop. Still, this is the most common implementation you'll find of the Cooley-Tukey algorithm.

One possible way to gain speed is to unroll the loop, but it's not easy since the repetition of the loop might be as small as 1 or 2.

My solution was to have the size of the loop as a template parameter. The compiler <strong>knows</strong> how many iterations there are, and it will unroll the loop for you. Additionally, you can unroll small transforms and remove the loop completely. It's the same algorithm in the end, you just have far less overhead

If you're not convinced with the theory, here are the timings to compute various Fourier transforms. One version uses the naive loop approach you'll find all over the internet, the other uses recursive templates:

<div><img src="http://www-etud.iro.umontreal.ca/~petitg/cpp/recurfft.png" alt="" /></div>
The speed gain decreases as the size of the vector grows (it's normal since the overhead becomes less and less important). In my case, I work mostly with images and I'll rarely use vectors larger than 2048. For that size, the recursive-template implementation is more than 4 times faster...
]]></content:encoded>
			<wfw:commentRss>http://thoughts.enseed.com/fast-fourier-transform-in-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>LU Matrix Decomposition in C++</title>
		<link>http://thoughts.enseed.com/lu-matrix-decomposition-in-c/</link>
		<comments>http://thoughts.enseed.com/lu-matrix-decomposition-in-c/#comments</comments>
		<pubDate>Sat, 01 Aug 2009 18:24:03 +0000</pubDate>
		<dc:creator>petit</dc:creator>
				<category><![CDATA[C++ Classes]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://thoughts.enseed.com/?p=230</guid>
		<description><![CDATA[To download: 1bzr branch http://bazaar.enseed.com/lib/Generic/ look under Geometry/LUDecomposition.h A LU decomposition decomposes a matrix M into a Lower and Upper matrix pair such that L×U=M. This representation is useful in many ways - for example, it's easy to solve (L×U)x = b. (for more info, see LU Decomposition on Wikipedia or LU Decomposition on MathWorld. [...]]]></description>
			<content:encoded><![CDATA[To download:

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">bzr branch http:<span style="color: #000000; font-weight: bold;">//</span>bazaar.enseed.com<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>Generic<span style="color: #000000; font-weight: bold;">/</span> look under Geometry<span style="color: #000000; font-weight: bold;">/</span>LUDecomposition.h</div></td></tr></tbody></table></div>

A LU decomposition decomposes a matrix <strong>M</strong> into a <strong>L</strong>ower and <strong>U</strong>pper matrix pair such that <strong>L</strong>×<strong>U</strong>=<strong>M</strong>. This representation is useful in many ways - for example, it's easy to solve (<strong>L</strong>×<strong>U</strong>)x = <strong>b</strong>. (for more info, see <a style="color: #333399;" href="http://en.wikipedia.org/wiki/LU_decomposition">LU Decomposition on Wikipedia</a> or <a style="color: #333399;" href="http://mathworld.wolfram.com/LUDecomposition.html">LU Decomposition on MathWorld</a>.

This particular implementation uses the <a href="index.php?p=222">Matrix class</a> and the same philosophy. Since our matrix class has the size specified as a template parameter, the LU decomposition knows the size of the matrix at compile time. Like most LU decomposition algorithms, it will use a recursive method (For a NxN matrix, first solve for a (N<sup style="font-size: 10px;">-1</sup>)xN matrix...) except that this is done here using recursive templates. The compiler can thus generate the entire unrolled decomposition.
<h2 style="font-size: 22px; margin: 0px;">Decomposing a Matrix</h2>
Decomposing a matrix in its <strong>LU</strong> pair is done like this:

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Matrix4d m<span style="color: #008080;">;</span><br />
Matrix4d l, u<span style="color: #008080;">;</span><br />
LUDecomposition<span style="color: #008080;">::</span><span style="color: #007788;">decompose</span><span style="color: #008000;">&#40;</span>m, <span style="color: #000040;">&amp;</span>l, <span style="color: #000040;">&amp;</span>u<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #666666;">// l is now a lower matrix, u is an upper matrix, l*u = m</span></div></td></tr></tbody></table></div>

<h2>Solving Mx=b</h2>
You once you have a <strong>LU</strong> pair, you can solve <strong>M</strong>x = b = <strong>(L×U)</strong>x = b:

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Matrix xb<span style="color: #008080;">;</span> &nbsp;<span style="color: #666666;">// set this to b initially, you'll get x after</span><br />
LUDecomposition<span style="color: #008080;">::</span><span style="color: #007788;">solve</span><span style="color: #008000;">&#40;</span>l, u, <span style="color: #000040;">&amp;</span>xb<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #666666;">// xb now holds x</span></div></td></tr></tbody></table></div>

<h2>Matrix Inverse</h2>
In the previous example, x and b were vectors (or 1x4 matrices), but they could be nx4 matrices. For example, say we have <strong>MX</strong> =<strong>B</strong> where <strong>X</strong> = <strong>M<sup style="font-size: 10px;">-1</sup></strong> and <strong>B</strong> = <strong>I</strong>, solving for <strong>X</strong> would be solving for the inverse of our matrix <strong>M</strong>:

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Matrix4d inverse <span style="color: #000080;">=</span> Matrix4d<span style="color: #008080;">::</span><span style="color: #007788;">identityMatrix</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> &nbsp;<span style="color: #666666;">// set this to b initially, you'll get x after</span><br />
LUDecomposition<span style="color: #008080;">::</span><span style="color: #007788;">solve</span><span style="color: #008000;">&#40;</span>l, u, <span style="color: #000040;">&amp;</span>xb<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #666666;">// xb now holds x, which is the inverse of m (or l*u)</span></div></td></tr></tbody></table></div>

<h2>Being More Robust</h2>
Sometimes, matrices won't be well formed and the LU decomposition will generate large numerical errors. One way to prevent this is to solve for <strong>LU</strong> = <strong>PM</strong> where <strong>P</strong> is a pivot matrix (it changes the orders of the rows in <strong>M</strong>. When the ultimate goal is to use the decomposition to solve a system, we can live with this solution and obtain better precision:

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Matrix4d m<span style="color: #008080;">;</span><br />
Matrix4d l, u<span style="color: #008080;">;</span><br />
Point4i p<span style="color: #008080;">;</span> <span style="color: #666666;">// pivot</span><br />
LUDecomposition<span style="color: #008080;">::</span><span style="color: #007788;">decompose</span><span style="color: #008000;">&#40;</span>m, <span style="color: #000040;">&amp;</span>l, <span style="color: #000040;">&amp;</span>u, <span style="color: #000040;">&amp;</span>p<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #666666;">// we now have l*u = p*m.</span></div></td></tr></tbody></table></div>

Now, instead of solving <strong>M</strong>x = b, we'll have to solve for <strong>PM</strong>x = <strong>P</strong>b = <strong>LU</strong>x. In other words, we have to solve for <strong>P</strong>b instead of just b. Say we want to inverse our matrix like in the previous example:

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Matrix4d pivotMatrix <span style="color: #000080;">=</span> Matrix4d<span style="color: #008080;">::</span><span style="color: #007788;">zeroMatrix</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000040;">&amp;</span>lt<span style="color: #008080;">;</span> <span style="color: #0000dd;">4</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span> pivotMatrix<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#91;</span>p<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">;</span><br />
<br />
Matrix4d xb <span style="color: #000080;">=</span> Matrix4d<span style="color: #008080;">::</span><span style="color: #007788;">itentityMatrix</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// this is b</span><br />
xb <span style="color: #000080;">=</span> pivotMatirx <span style="color: #000040;">*</span> xb<span style="color: #008080;">;</span> <span style="color: #666666;">// this is Pb</span><br />
<br />
LUDecomposition<span style="color: #008080;">::</span><span style="color: #007788;">solve</span><span style="color: #008000;">&#40;</span>l, u, <span style="color: #000040;">&amp;</span>xb<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #666666;">// xb is now x, which is the inverse of our matrix</span></div></td></tr></tbody></table></div>

]]></content:encoded>
			<wfw:commentRss>http://thoughts.enseed.com/lu-matrix-decomposition-in-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quaternion Class</title>
		<link>http://thoughts.enseed.com/quaternion-class/</link>
		<comments>http://thoughts.enseed.com/quaternion-class/#comments</comments>
		<pubDate>Sat, 01 Aug 2009 18:23:28 +0000</pubDate>
		<dc:creator>petit</dc:creator>
				<category><![CDATA[C++ Classes]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://thoughts.enseed.com/?p=228</guid>
		<description><![CDATA[To download: 1bzr branch http://bazaar.enseed.com/lib/Generic/ look under Geometry/Quaternion.h I used quaternions mainly for rotations around an axis (for example, to implement a trackball that doesn't suffer from the gimbal lock like matrix-based trackballs do). Rotation of Points Around an Axis Rotation around an axis is done in three steps. First you create a quaternion q [...]]]></description>
			<content:encoded><![CDATA[To download:

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">bzr branch http:<span style="color: #000000; font-weight: bold;">//</span>bazaar.enseed.com<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>Generic<span style="color: #000000; font-weight: bold;">/</span> look under Geometry<span style="color: #000000; font-weight: bold;">/</span>Quaternion.h</div></td></tr></tbody></table></div>

I used quaternions mainly for rotations around an axis (for example, to implement a trackball that doesn't suffer from the gimbal lock like matrix-based trackballs do).
<h2>Rotation of Points Around an Axis</h2>
Rotation around an axis is done in three steps. First you create a quaternion <tt>q</tt> based on the axis and angle of rotation that you want. Then, you create a quaternion <tt>pt</tt> that will act as the point that you want to rotate. Finally, you multiply: <tt>q*pt*q.inverse()</tt>.

You have to take extra care that the axis that you supply is a unit vector. You will then obtain a unit quaternion, and instead of taking <tt>q.inverse()</tt>, you can use <tt>q.unitInverse()</tt> which is faster.

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Point3d axis <span style="color: #000080;">=</span> Point3d<span style="color: #008000;">&#40;</span><span style="color:#800080;">1.0</span>, <span style="color:#800080;">1.0</span>, <span style="color:#800080;">0.0</span><span style="color: #008000;">&#41;</span>.<span style="color: #007788;">normalized</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
Quatd q<span style="color: #008000;">&#40;</span>axis, <span style="color: #0000dd;">2</span><span style="color: #000040;">*</span>M_PI<span style="color: #000040;">/</span><span style="color: #0000dd;">9</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// 40 degrees</span><br />
<br />
Quatd pt<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">1</span>, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// w = 0, x = 1, y =0, z = 0</span><br />
<br />
<span style="color: #666666;">// do a 360 around the axis</span><br />
<span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000040;">&amp;</span>lt<span style="color: #008080;">;</span> <span style="color: #0000dd;">9</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; pt <span style="color: #000080;">=</span> q<span style="color: #000040;">*</span>pt<span style="color: #000040;">*</span>q.<span style="color: #007788;">unitInverse</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;(%f %f %f)<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, pt.<span style="color: #007788;">x</span>, pt.<span style="color: #007788;">y</span>, pt.<span style="color: #007788;">z</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>

Executing the above code, you should obtain:

<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">(0.883022 0.116978 -0.454519)<br />
(0.586824 0.413176 -0.696364)<br />
(0.250000 0.750000 -0.612372)<br />
(0.030154 0.969846 -0.241845)<br />
(0.030154 0.969846 0.241845)<br />
(0.250000 0.750000 0.612372)<br />
(0.586824 0.413176 0.696364)<br />
(0.883022 0.116978 0.454519)<br />
(1.000000 0.000000 -0.000000)</div></td></tr></tbody></table></div>

Obtaining a Rotation Matrix from a Quaternion</h2>
You can also choose to work with matrices instead and convert a quaternion to a 3x3 or 4x4 matrix:

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Point3d axis <span style="color: #000080;">=</span> Point3d<span style="color: #008000;">&#40;</span><span style="color:#800080;">1.0</span>, <span style="color:#800080;">1.0</span>, <span style="color:#800080;">0.0</span><span style="color: #008000;">&#41;</span>.<span style="color: #007788;">normalized</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
Quatd q<span style="color: #008000;">&#40;</span>axis, <span style="color: #0000dd;">2</span><span style="color: #000040;">*</span>M_PI<span style="color: #000040;">/</span><span style="color: #0000dd;">9</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
Point4d pt<span style="color: #008000;">&#40;</span><span style="color:#800080;">1.0</span>, <span style="color:#800080;">0.0</span>, <span style="color:#800080;">0.0</span>, <span style="color:#800080;">1.0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// x = 1, y = 0, z = 0 (homogeneous w = 1)</span><br />
<br />
Matrix4d m<span style="color: #008080;">;</span><br />
q.<span style="color: #007788;">to4x4Matrix</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span>m<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;rotation matrix:<span style="color: #000099; font-weight: bold;">\n</span> %s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, m.<span style="color: #007788;">serialize</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>.<span style="color: #007788;">c_str</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000040;">&amp;</span>lt<span style="color: #008080;">;</span> <span style="color: #0000dd;">9</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; pt <span style="color: #000080;">=</span> m<span style="color: #000040;">*</span>pt<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;(%f %f %f)<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, pt.<span style="color: #007788;">x</span>, pt.<span style="color: #007788;">y</span>, pt.<span style="color: #007788;">z</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>

And you obtain the following output

<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">rotation matrix :<br />
{ <br />
&nbsp; { 0.8830221891, 0.1169777811, -0.4545194805, 0.0000000000 }<br />
&nbsp; { 0.1169777811, 0.8830221891, 0.4545194805, 0.0000000000 }<br />
&nbsp; { 0.4545194805, -0.4545194805, 0.7660444379, 0.0000000000 }<br />
&nbsp; { 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000 }<br />
}<br />
(0.883022 0.116978 0.454519)<br />
(0.586824 0.413176 0.696364)<br />
(0.250000 0.750000 0.612372)<br />
(0.030154 0.969846 0.241845)<br />
(0.030154 0.969846 -0.241845)<br />
(0.250000 0.750000 -0.612372)<br />
(0.586824 0.413176 -0.696364)<br />
(0.883022 0.116978 -0.454519)<br />
(1.000000 -0.000000 0.000000)</div></td></tr></tbody></table></div>

<h2>Concatenating Several Multiplications</h2>
You can concatenate several multiplcations by simply multiplicating your rotation quaternions together. It's important to make sure that each quaternion is a unit quaternion though. If you created them with a unit axis, it should always be the case.
]]></content:encoded>
			<wfw:commentRss>http://thoughts.enseed.com/quaternion-class/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TrackBall Class (with no Gimbal Lock)</title>
		<link>http://thoughts.enseed.com/trackball-class-with-no-gimbal-lock/</link>
		<comments>http://thoughts.enseed.com/trackball-class-with-no-gimbal-lock/#comments</comments>
		<pubDate>Sat, 01 Aug 2009 18:22:47 +0000</pubDate>
		<dc:creator>petit</dc:creator>
				<category><![CDATA[C++ Classes]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://thoughts.enseed.com/?p=226</guid>
		<description><![CDATA[To download: 1bzr branch http://bazaar.enseed.com/lib/Generic/ look under Geometry/TrackBall.h A trackball is useful when you display 3D objects and want to let the user change the position of the camera around an object by click-and-dragging the mouse. A trackball simulates a 3D ball in the scene, and rotates as though the user was dragging a point [...]]]></description>
			<content:encoded><![CDATA[To download:

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">bzr branch http:<span style="color: #000000; font-weight: bold;">//</span>bazaar.enseed.com<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>Generic<span style="color: #000000; font-weight: bold;">/</span> look under Geometry<span style="color: #000000; font-weight: bold;">/</span>TrackBall.h</div></td></tr></tbody></table></div>

A trackball is useful when you display 3D objects and want to let the user change the position of the camera around an object by click-and-dragging the mouse. A trackball simulates a 3D ball in the scene, and rotates as though the user was dragging a point on the surface of sphere.

Here is how to trackball computes the rotation:
<ul>
	<li>find the line between the click point and the current point</li>
	<li>find the position of these points on the virtual sphere</li>
	<li>find the axis of rotation (it is perpendicular to the two points' line)</li>
	<li>estimate the angle of rotation based on the distance of the two points on the sphere</li>
	<li>represend that rotation using a <a style="color: #333399;" href="http://www-etud.iro.umontreal.ca/~petitg/cpp/quat.html">quaternion</a>. This quaternion can then be used to extract a rotation <a style="color: #333399;" href="http://www-etud.iro.umontreal.ca/~petitg/cpp/matrix.html">matrix</a>.</li>
</ul>
It's quite trivial to use. Say you have a 640x480 window. You would create a TrackBall with radius 240 and a center at (320, 240):

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">// create the trackball</span><br />
TrackBall trackball<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">240</span>, Point2f<span style="color: #008000;">&#40;</span><span style="color:#800080;">320.0f</span>, <span style="color:#800080;">240.0f</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>

When you get a "mouse down" event, you'd tell the trackball to begin tracking:

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">// we had a mouse down</span><br />
<span style="color: #0000ff;">void</span> MouseDown<span style="color: #008000;">&#40;</span>Point2f mousePos<span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; trackball.<span style="color: #007788;">beginTracking</span><span style="color: #008000;">&#40;</span>mousePos<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>

Finally, when the mouse is dragged, you update the trackball and extract the rotation

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">// we had a mouse drag event</span><br />
<span style="color: #0000ff;">void</span> MouseDrag<span style="color: #008000;">&#40;</span>Point2f mousePos<span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; Quatf q <span style="color: #000080;">=</span> trackball.<span style="color: #007788;">track</span><span style="color: #008000;">&#40;</span>mousePos<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; Matrix4x4 rotMatrix<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; q.<span style="color: #007788;">to4x4Matrix</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span>rotMatrix<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666;">// rotMatrix now holds a rotation matrix for our view or object</span><br />
<span style="color: #008000;">&#125;</span></div></td></tr></tbody></table></div>

If you are doing OpenGL, you can use this matrix to change your view:

<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">glMatrixMode<span style="color: #008000;">&#40;</span>GL_PROJECTION<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
glLoadIdentity<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #666666;">// setup your view here</span><br />
<span style="color: #666666;">// ...</span><br />
<br />
<span style="color: #666666;">// multiply with our rotation matrix. &nbsp;We have</span><br />
<span style="color: #666666;">// to transpose since OpenGL uses column vector matrices</span><br />
<span style="color: #666666;">// while we use row vector matrices...</span><br />
glMultMatrix<span style="color: #008000;">&#40;</span>rotMatrix.<span style="color: #007788;">transposed</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>.<span style="color: #007788;">ptr</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></div></td></tr></tbody></table></div>

]]></content:encoded>
			<wfw:commentRss>http://thoughts.enseed.com/trackball-class-with-no-gimbal-lock/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

