<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/2.2.3" -->
<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/"
	>

<channel>
	<title>Mark NelsonGraphics &#187; </title>
	<link>http://marknelson.us</link>
	<description>Programming, mostly.</description>
	<pubDate>Thu, 26 Aug 2010 13:32:59 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.2.3</generator>
	<language>en</language>
			<item>
		<title>Cashing in On Electronic Books</title>
		<link>http://marknelson.us/2008/02/11/cashing-in-on-e-books/</link>
		<comments>http://marknelson.us/2008/02/11/cashing-in-on-e-books/#comments</comments>
		<pubDate>Mon, 11 Feb 2008 20:19:05 +0000</pubDate>
		<dc:creator>Mark</dc:creator>
		
		<category><![CDATA[Graphics]]></category>

		<category><![CDATA[Business]]></category>

		<category><![CDATA[People]]></category>

		<category><![CDATA[Writing]]></category>

		<category><![CDATA[Data Compression]]></category>

		<guid isPermaLink="false">http://marknelson.us/2008/02/11/cashing-in-on-e-books/</guid>
		<description><![CDATA[

Jeff Bezos Hawks the Kindle


It&#8217;s still not clear whether electronic books are the wave of the future or a consumer products cul-de-sac. Technology continues to improve, and there are certainly lots of good reasons for a device like Amazon&#8217;s Kindle to be the leading edge of a major wave of adoption. A few of the [...]]]></description>
			<content:encoded><![CDATA[<table align="right" cellspacing="5" border="0">
<tr>
<td><center><img src="http://marknelson.us/attachments/2008/cashing-in-on-e-books/bezos.jpg"><br />
Jeff Bezos Hawks the Kindle</center></p>
<td></tr>
</table>
<p><font size="+1"><strong>It&#8217;s </strong></font>still not clear whether electronic books are the wave of the future or a consumer products cul-de-sac. Technology continues to improve, and there are certainly lots of good reasons for a device like Amazon&#8217;s Kindle to be the leading edge of a major wave of adoption. A few of the more obvious arguments include:</p>
<ul>
<li/>Reduced cost of distribution. The publishing industry wastes a lot of money printing and shipping books, and because of historical practices, creates huge numbers of books that never even get sold. Not very green, and a waste of money.
<li/>Niche markets that can be very well-served. For example, high school and college students can replace those 30-pound backbacks with a 30-ounce tablet-sized device.
<li/>Removal of barriers to publication. The news and magazine businesses are being revolutionized by self-publication in the form of blogs. Self-publication is possible in the printed book world, but it is still a rather awkward process. Publication to electronic format is presumably a trivial problem.
<li/>Integration of information resources. A device like the Kindle allows you to consult the Internet, written reference materials, and your personal notes all from the same device, making it a true information portal.
</ul>
<p>But consumer acceptance is a fickle thing, so we don&#8217;t know if these rational arguments are going to fly. And of course, every writer who reviews a device like the Kindle or the equally capable Sony Reader feels compelled to write something along the lines of &#8220;But I just can&#8217;t imagine forgoing the pleasure of curling up on my couch with a good book.&#8221; I&#8217;m sure that when Gutenberg introduced movable type there were millions of industry reviewers posting notes to their blogs saying &#8220;The uniformity of the type is just esthetically unpleasing - I love it when I recognize the script of one of my favorite transcribing brothers.&#8221;</p>
<p>And then of course there&#8217;s the Steve Job&#8217;s <a href="http://bits.blogs.nytimes.com/2008/01/15/the-passion-of-steve-jobs/index.html" class="newpage">money quote</a> on the subject:</p>
<blockquote><p>
“It doesn’t matter how good or bad the product is, the fact is that people don’t read anymore, forty percent of the people in the U.S. read one book or less last year. The whole conception is flawed at the top because people don’t read anymore.”
</p></blockquote>
<p>So it&#8217;s really pretty hard to be sure just which way this is going to go.<br />
 <a href="http://marknelson.us/2008/02/11/cashing-in-on-e-books/#more-119" class="more-link">(more&#8230;)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://marknelson.us/2008/02/11/cashing-in-on-e-books/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Rendering Transparent GIFs - Revisited</title>
		<link>http://marknelson.us/2002/07/01/rendering-transparent-gifs-revisited/</link>
		<comments>http://marknelson.us/2002/07/01/rendering-transparent-gifs-revisited/#comments</comments>
		<pubDate>Tue, 02 Jul 2002 05:59:33 +0000</pubDate>
		<dc:creator>Mark</dc:creator>
		
		<category><![CDATA[Graphics]]></category>

		<category><![CDATA[Magazine Articles]]></category>

		<guid isPermaLink="false">http://test.kewby.com/?p=24</guid>
		<description><![CDATA[Rendering GIFs with transparency under Win32. It's gotten a bit easier since I first wrote about it for DDJ in 1998. This article shows a couple of ways to implement transparent GIF rendering: the IPicture interface, and GDI+.]]></description>
			<content:encoded><![CDATA[













<p/>
<table border="0" width="400px">
<tbody>
<tr>
<td width="33%">
      <img src="http://marknelson.us/attachments/rendering-transparent-gifs-revisited/wdmag.jpg" alt="Windows Developer Journal, July, 2002" />
      </td>
<td>
        <b>Windows Developer Magazine</b></p>
<p>July, 2002</p>
</td>
</tr>
</tbody>
</table>
<p>Back in March 1998, Tom Armstrong and I published an article in Dr. Dobb's Journal showing a technique for implementing transparent regions in bitmapped images. In those days, Windows developers had to roll their own transparency solution, and the path was quite arduous. Today, Windows programmers can render images with transparency using Microsoft's <span class="inline_code">IPicture</span> COM interface, which is considerably easier than the solution Tom and I suggested. It's an easy way to accomplish the same task - if you watch out for its single notable drawback</p>
<p>The <span class="inline_code">IPicture</span> interface is a good way to draw images with transparency today. In the future, you'll probably want to use GDI+, Microsoft's new GDI interface for C++ programmers. I'll show you how to convert the sample program to write cleaner code with GDI+, and discuss the improvements it brings to the table.</p>
<h4>Transparent GIFs</h4>
<p>When creating a GIF file, you have the option of designating one color in the image as transparent. This transparency feature is normally used to make it appear as if an irregularly shaped image is floating on the background. An example of how this can be useful is shown in Figures 1 and 2.</p>
<p>In Figure 1, two news articles displayed on a Web page have graphical icons that illustrate article topics. The users of this particular web site have the ability to change their personal settings to use a different layout, which changes the background color of the page. In Figure 2, a different theme is used to show the same articles.</p>
<p>In both Figure 1 and Figure 2, the background of the GIF file used to illustrate the article is transparent. Web browsers know that they need to let the background color show through in the transparent regions of the graphic. You can see that the browser deals with the transparency properly in both cases, with nice effect. A beige background in Figure 1, a white background in Figure 2, and in both the topic images float nicely above the background.</p>
<p><center><br />
<img src="http://marknelson.us/attachments/rendering-transparent-gifs-revisited/Figure1.gif"/><br />
Figure 1 - Transparent GIFs on a light brown background<br />
</center></p>
<p><center><br />
<img src="http://marknelson.us/attachments/rendering-transparent-gifs-revisited/Figure2.gif"/><br />
Figure 2 - The same GIFs on a white background<br />
</center></p>
<h4>Loading the GIF File</h4>
<p>Getting an external file into a format Windows can display can be a chore. Tom and I chose to skirt the issue in our original article by working with files stored in Windows' Device Independent Bitmap format. Although not a popular file format, it was one of the few that Windows was able to read and write without help from third-party libraries.</p>
<p>The situation has improved quite a bit since then. You can now use Microsoft's <span class="inline_code">OleLoadPicture()</span> function to load both JPEG and GIF files. Given the popularity of these two file formats, you might find that <span class="inline_code">OleLoadPicture()</span> covers all your needs in this area.</p>
<p><span class="inline_code">OleLoadPicture()</span> loads data from an <span class="inline_code">IStream</span> object and stores it in an <span class="inline_code">IPicture</span> object. You'll find that having the data in <span class="inline_code">IPicture</span> format is quite convenient when it comes time to render it. However, the odds are good that you want to be able to load your data from a file, which is not quite the same thing as an <span class="inline_code">IStream</span> interface.</p>
<p>The easiest way I know of to get from a file to an <span class="inline_code">IStream</span> object is to simply read the whole thing into memory and then use <span class="inline_code">CreateStreamOnHGlobal()</span> to create an <span class="inline_code">IStream</span>. A fragment that accomplishes that is shown here: </p>
<div class="igBar"><span id="lcpp-1"><a href="#" onclick="javascript:showPlainTxt('cpp-1'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">C++:</span>
<div id="cpp-1">
<div class="cpp">
<ol>
<li class="li1">
<div class="de1"><span class="kw4">FILE</span> *f = <span class="kw3">fopen</span><span class="br0">&#40;</span> filename, <span class="st0">"rb"</span> <span class="br0">&#41;</span> ;</div>
</li>
<li class="li2">
<div class="de2"><span class="kw1">if</span> <span class="br0">&#40;</span> !f <span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">FALSE</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="kw4">long</span> size = _filelength<span class="br0">&#40;</span> fileno<span class="br0">&#40;</span> f <span class="br0">&#41;</span> <span class="br0">&#41;</span> ;</div>
</li>
<li class="li1">
<div class="de1">HGLOBAL hGlobal = GlobalAlloc<span class="br0">&#40;</span> GMEM_MOVEABLE, size <span class="br0">&#41;</span> ;</div>
</li>
<li class="li2">
<div class="de2">LPVOID pvData = GlobalLock<span class="br0">&#40;</span> hGlobal <span class="br0">&#41;</span> ;</div>
</li>
<li class="li1">
<div class="de1">read<span class="br0">&#40;</span> pvData, <span class="nu0">1</span>, size, f <span class="br0">&#41;</span> ;</div>
</li>
<li class="li2">
<div class="de2">GlobalUnlock<span class="br0">&#40;</span>hGlobal<span class="br0">&#41;</span> ;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw3">fclose</span><span class="br0">&#40;</span> f <span class="br0">&#41;</span> ;</div>
</li>
<li class="li2">
<div class="de2">LPSTREAM pStream = <span class="kw2">NULL</span>;</div>
</li>
<li class="li1">
<div class="de1">HRESULT hr = CreateStreamOnHGlobal<span class="br0">&#40;</span> hGlobal, <span class="kw2">TRUE</span>, &amp;amp;pStream <span class="br0">&#41;</span> ; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>At this point you have an <span class="inline_code">IStream</span> object ready for use, and all that remains is to make the call to load the <span class="inline_code">IPicture</span>object: </p>
<div class="igBar"><span id="lcpp-2"><a href="#" onclick="javascript:showPlainTxt('cpp-2'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">C++:</span>
<div id="cpp-2">
<div class="cpp">
<ol>
<li class="li1">
<div class="de1">hr = ::<span class="me2">OleLoadPicture</span><span class="br0">&#40;</span> pStream, </div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;size, </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw2">FALSE</span>, </div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;IID_IPicture,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#40;</span>LPVOID *<span class="br0">&#41;</span> &amp;m_pPicture <span class="br0">&#41;</span> ; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Although the code isn't particularly elegant looking, it has accomplished the goal of reading a GIF or JPEG file into memory in just a dozen  lines or so. All that remains is the task of drawing the code on the  appropriate display. </p>
<h4>The Drawing Part</h4>
<p>In our original article, Tom and I presented a straightforward method for displaying bitmaps with transparency. It required the use of three bitmaps:    </p>
<ol>
<li/>The background bitmap.
<li/>The bitmap to be displayed, with a known transparent color.
<li/>A special mask bitmap. The mask bitmap should have all bits set to zero in areas where the display bitmap is opaque, and all bits set to one in the areas where the display bitmap is transparent.
</ol>
<p>Displaying the bitmap is simply a matter of performing the following sequence of operations: </p>
<p><i>Output = Bitmap1 XOR Bitmap2 AND Bitmap3 XOR Bitmap 2</i></p>
<p>With just a little bit of work, you can see that the output will be  a copy of the pixel from Bitmap1 in every position where the mask  (Bitmap3) has a value of all ones. The output will be a copy from  Bitmap2 in every position where the mask has a value of all zeros. </p>
<p>That's all you really need to understand in order to draw bitmaps  with transparency in any sort of graphics environment. What made it  into a long article in 1998 was simply all the plumbing you had to  do in order to get the background bitmap, create the mask, get the  display bitmap, and so on.</p>
<p>The good news is that Microsoft's <span class="inline_code">IPicture</span> interface can take care of all of the messy details here with one call to its <span class="inline_code">Render()</span> function. Once you have loaded the GIF file into an <span class="inline_code">IPicture</span>  object, the snippet of code below is all you need to get it onto your  display:</p>
<div class="igBar"><span id="lcpp-3"><a href="#" onclick="javascript:showPlainTxt('cpp-3'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">C++:</span>
<div id="cpp-3">
<div class="cpp">
<ol>
<li class="li1">
<div class="de1"><span class="kw4">void</span> CChildView::<span class="me2">RenderPicture</span><span class="br0">&#40;</span> CDC &amp;dc,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CMainFrame *frame, </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CRect &amp;rect <span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; OLE_XSIZE_HIMETRIC width;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; OLE_YSIZE_HIMETRIC height;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; frame-&gt;m_pPicture-&gt;get_Width<span class="br0">&#40;</span> &amp;width <span class="br0">&#41;</span> ;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; frame-&gt;m_pPicture-&gt;get_Height<span class="br0">&#40;</span> &amp;height <span class="br0">&#41;</span> ;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; CSize sz<span class="br0">&#40;</span> width, height <span class="br0">&#41;</span> ;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; dc.<span class="me1">HIMETRICtoDP</span><span class="br0">&#40;</span> &amp;sz <span class="br0">&#41;</span> ;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw4">int</span> x = <span class="br0">&#40;</span> rect.<span class="me1">Width</span><span class="br0">&#40;</span><span class="br0">&#41;</span> - pt.<span class="me1">x</span> <span class="br0">&#41;</span> / <span class="nu0">2</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="kw4">int</span> y = <span class="br0">&#40;</span> rect.<span class="me1">Height</span><span class="br0">&#40;</span><span class="br0">&#41;</span> - pt.<span class="me1">y</span> <span class="br0">&#41;</span> / <span class="nu0">2</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; frame-&gt;m_pPicture-&gt;Render<span class="br0">&#40;</span> dc,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;x, </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;rect.<span class="me1">Height</span><span class="br0">&#40;</span><span class="br0">&#41;</span> - y,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;pt.<span class="me1">x</span>, pt.<span class="me1">y</span>,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="nu0">0</span>, </div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="nu0">0</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;width, </div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;height,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw2">NULL</span> <span class="br0">&#41;</span> ; </div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Note that the code shown here centers the image in the client window, which complicates things just a bit. It also has to deal with the fact that <span class="inline_code">IPicture</span> uses the <span class="inline_code">HIMETRIC</span> mapping mode, which I  have to convert to the more convenient pixel measurements.  </p>
<h4>A First Pass</h4>
<p>Pressing this code into service reveals one striking problem with the <span class="inline_code">IPicture</span> interface. Calling its <span class="inline_code">Render()</span> function with the intention of writing directly to your display window leads to a somewhat unpleasant surprise. It turns out that <span class="inline_code">IPicture</span> uses the standard algorithm I describe earlier to implement transparency. Unfortunately,  it performs each of the three steps directly on the display, so you get  to see each intermediate bitmap in the process. The four screen shots  below show it in all its glory. </p>
<p><center><br />
<img src="http://marknelson.us/attachments/rendering-transparent-gifs-revisited/Figure3a.gif"><br />
Figure 3a - Opening the file<br />
</center></p>
<p><center><br />
<img src="http://marknelson.us/attachments/rendering-transparent-gifs-revisited/Figure3b.gif"><br />
Figure 3b - The background has been XORed with the image<br />
</center></p>
<p><center><br />
<img src="http://marknelson.us/attachments/rendering-transparent-gifs-revisited/Figure3c.gif"><br />
Figure 3c - The resulting bitmap has now been ANDed with the special transparency mask<br />
</center></p>
<p><center><br />
<img src="http://marknelson.us/attachments/rendering-transparent-gifs-revisited/Figure3d.gif"><br />
Figure 3d - After a final XOR, the image is rendered with transparency<br />
</center></p>
<p>This sequence might be interesting to the average DDJ reader, but the end users of your program are hardly going to want to see these three images  flashing in quick succession across their screen. The flickering is barely  noticeable with small images, but on slow machines, big images go through  the painting sequence with painful precision. </p>
<p>The solution to this problem is straightforward. Instead of drawing  directly to the screen, you can create an off-screen bitmap, have <span class="inline_code">Render()</span> draw to that bitmap, then copy the completed product  to the display. Having done that, you'll find that not only is the flicker eliminated, but the drawing operation actually completes much more  quickly.  </p>
<p>An MFC routine that accomplishes this in conjunction with the rendering routine above is shown here:  </p>
<div class="igBar"><span id="lcpp-4"><a href="#" onclick="javascript:showPlainTxt('cpp-4'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">C++:</span>
<div id="cpp-4">
<div class="cpp">
<ol>
<li class="li1">
<div class="de1"><span class="kw4">void</span> CChildView::<span class="me2">DrawOff</span><span class="br0">&#40;</span> CDC &amp;dc,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CRect &amp;rect,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CMainFrame *frame, </div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CBrush &amp;brush <span class="br0">&#41;</span> </div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; CDC odc;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; odc.<span class="me1">CreateCompatibleDC</span><span class="br0">&#40;</span> &amp;dc <span class="br0">&#41;</span> ;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; CBitmap obm;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; obm.<span class="me1">CreateCompatibleBitmap</span><span class="br0">&#40;</span> &amp;dc, rect.<span class="me1">Width</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, rect.<span class="me1">Height</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span> ;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; odc.<span class="me1">SelectObject</span><span class="br0">&#40;</span> &amp;obm <span class="br0">&#41;</span> ;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; odc.<span class="me1">FillRect</span><span class="br0">&#40;</span> rect, &amp;brush <span class="br0">&#41;</span> ;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; RenderPicture<span class="br0">&#40;</span> odc, frame, rect <span class="br0">&#41;</span> ;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; dc.<span class="me1">BitBlt</span><span class="br0">&#40;</span><span class="nu0">0</span>, <span class="nu0">0</span>, rect.<span class="me1">Width</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, rect.<span class="me1">Height</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, &amp;dc, <span class="nu0">0</span>, <span class="nu0">0</span>, SRCCOPY <span class="br0">&#41;</span> ;</div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>You can see that it only takes a few lines to create the off-screen  bitmap. The code above creates a bitmap of the correct size, fills it  with the correct background pattern, then calls the rendering routine.  Once that is done, all that is left is a <span class="inline_code">BitBlt()</span> call which  copies the result to the screen.   </p>
<h4>The Sample Program</h4>
<p>To demonstrate this, I created an MFC program named <i>TransparentGif</i>, forgoing the usual document/view architecture. Instead, I just paint the entire client background of the window with a pattern, the better  to view the transparency of the loaded image.    </p>
<p>When the program first starts up, by default it draws directly to the screen. If you are blessed with a sub-Gigahertz CPU, you should be able  to see the flickering effect quite clearly when loading the  sample GIF included  with the source. I added code to force a redraw every time you click on the image, which allows you to see the effect  in all its beauty.</p>
<p>You can then use the <i>Options|Off</i> Screen Draw menu item to switch to the use of the off-screen bitmap.  A little sampling between the two should be enough to convince you of the value of the off-screen drawing technique.</p>
<h4>Switcing to GDI+</h4>
<p>Looking forward to the future, you might find that this task is going to become a bit easier. Microsoft has developed a new interface to GDI for Windows programmers called GDI+. The class libraries and supporting DLL for GDI+ are shipping as part of Windows XP, and can be installed as an add-on to Windows NT, 2000, 98, and ME. </p>
<p>The header files and import libraries required for GDI+ are part of  Microsoft's Platform SDK. To get this SDK, you'll have to have to  subscribe to Microsoft's MSDN program at the Operating System Level  or better, which has a list price of $699.  </p>
<p>You need to perform two installations to develop and test GDI+ programs:  the Win32 Platform SDK and the GDI+ runtime files. Both of these can  be found on your MSDN CDs or can be downloaded directly from the MSDN  site The GDI+ runtime kit can also be distributed with your software, so your  end users need no special licensing.  </p>
<h4>Additions to the project</h4>
<p>I made a copy of the <i>TransparentGif</i> program, renaming all the files and classes so that the new project goes by the name <i>TransparentPlus</i>. I then set to work making the changes needed to use GDI+ as the graphics interface. </p>
<p>The first few changes are the ones you typically have to make when using a new library. I added an include of the master header file,  <i>gdiplus.h</i>, to <i>stdafx.h</i>. This ensures that I have all the correct prototypes and class definitions. To make sure that the compiler was able to find the header file, I had to add the SDK include directory to the preprocessor settings for the C++ compiler. I used the default  installation location for the SDK, so I simply inserted the path:</p>
<p><i>C:\Program Files\Microsoft SDK\Include</i> </p>
<p>into the list of additional  directories for the compiler.</p>
<p>All of the classes and identifiers in GDI+ are placed in the <i>Gdiplus</i> namespace, so I also added a <span class="inline_code">using namespace Gdiplus;</span> declaration to <i>stdafx.h</i>. In a larger project, I probably wouldn't do this; the use of explicit namespaces in the source would add readability to the code. </p>
<p>Likewise, the import library was in the default SDK directory, so all I had  to do was drag:</p>
<p><i>C:\Program Files\Microsoft SDK\lib\GdiPlus.lib</i> </p>
<p>into my workspace pane, thereby adding it to the project.  </p>
<h4>Startup code</h4>
<p>GDI+ programs require a few lines of code for initialization, as well as a cleanup call. I added the following lines to the <span class="inline_code">InitInstance()</span> function in my application class:</p>
<div class="igBar"><span id="lcpp-5"><a href="#" onclick="javascript:showPlainTxt('cpp-5'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">C++:</span>
<div id="cpp-5">
<div class="cpp">
<ol>
<li class="li1">
<div class="de1">GdiplusStartupInput gdiplusStartupInput;</div>
</li>
<li class="li2">
<div class="de2">ULONG_PTR gdiplusToken;</div>
</li>
<li class="li1">
<div class="de1">GdiplusStartup<span class="br0">&#40;</span> &amp;gdiplusToken, &amp;gdiplusStartupInput, <span class="kw2">NULL</span><span class="br0">&#41;</span> ; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>This code is lifted cookie-cutter style straight out of the GDI+ documentation. The token initialized by the startup function is passed  to the <span class="inline_code">GdiplusShutdown()</span>method when you are done using the library.  </p>
<h4>File Loading</h4>
<p>As you recall, the file loading code in the standard GDI program was a real rat's nest. The hoops I had to jump through in order to load a file  into an <span class="inline_code">IPicture</span> object gave a classic demonstration of  an ugly Microsoft  API.</p>
<p>I'm happy to say that someone working in API design in Redmond has  seen the light in this area. Loading images is an order of magnitude easier with  GDI+. Instead of loading into an <span class="inline_code">IPicture</span> COM object, GDI+ supports  a C++ <span class="inline_code">Image</span> object. This requires that I change  the type of <span class="inline_code">CMainFrame::m_pPicture</span> in the appropriate header file.  I can then reduce the file loading code from the ugly mess I had before to this picture of simplicity:  </p>
<div class="igBar"><span id="lcpp-6"><a href="#" onclick="javascript:showPlainTxt('cpp-6'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">C++:</span>
<div id="cpp-6">
<div class="cpp">
<ol>
<li class="li1">
<div class="de1"><span class="kw4">void</span> CMainFrame::<span class="me2">LoadPicture</span><span class="br0">&#40;</span>CString filename<span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; USES_CONVERSION;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; LPWSTR wname = A2W<span class="br0">&#40;</span> filename <span class="br0">&#41;</span> ;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> m_pPicture <span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">delete</span> m_pPicture;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; m_pPicture = Image::<span class="me2">FromFile</span><span class="br0">&#40;</span> wname, <span class="kw2">FALSE</span> <span class="br0">&#41;</span> ;</div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>This is a huge improvement, and by itself is almost worth the cost of the SDK. </p>
<h4>Drawing</h4>
<p>The drawing code with GDI+ is a bit simpler as well, mostly because the <span class="inline_code">Image</span> object uses pixels for measurement instead of the <span class="inline_code">HIMETRIC</span> units from <span class="inline_code">IPicture</span>. Other than that a simple replacement of the <span class="inline_code">Render()</span> function with a call to <span class="inline_code">DrawImage()</span> constitutes most of the work. The updated routine is shown here: </p>
<div class="igBar"><span id="lcpp-7"><a href="#" onclick="javascript:showPlainTxt('cpp-7'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">C++:</span>
<div id="cpp-7">
<div class="cpp">
<ol>
<li class="li1">
<div class="de1"><span class="kw4">void</span> CChildView::<span class="me2">RenderPicture</span><span class="br0">&#40;</span> CDC &amp;dc,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CMainFrame *frame, </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CRect &amp;rect <span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> frame-&gt;m_pPicture <span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> width = frame-&gt;m_pPicture-&gt;GetWidth<span class="br0">&#40;</span><span class="br0">&#41;</span> ;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> height = frame-&gt;m_pPicture-&gt;GetHeight<span class="br0">&#40;</span><span class="br0">&#41;</span> ;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> x = <span class="br0">&#40;</span> rect.<span class="me1">Width</span><span class="br0">&#40;</span><span class="br0">&#41;</span> - width <span class="br0">&#41;</span> / <span class="nu0">2</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> y = <span class="br0">&#40;</span> rect.<span class="me1">Height</span><span class="br0">&#40;</span><span class="br0">&#41;</span> - height <span class="br0">&#41;</span> / <span class="nu0">2</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; Graphics graphics<span class="br0">&#40;</span> dc <span class="br0">&#41;</span> ;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; graphics.<span class="me1">DrawImage</span><span class="br0">&#40;</span> frame-&gt;m_pPicture,&nbsp; x, y, width, height <span class="br0">&#41;</span> ;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>GDI+ makes my code look a lot nicer, and informal tests show that GDI+ renders a bit faster as well. Better yet, GDI+ is smart enough to  avoid rendering all three steps directly on to the screen, which  means you won't  see a flash of the XOR'd or masked image.  </p>
<p>Despite the speed of GDI+, I think you'll still find that you need to do this image rendering in an off-screen bitmap. Experimenting with the second test program shows that although you don't see intermediate  images, you still get an annoying flickering as the image as drawn. Rendering off-screen eliminates that problem.  </p>
<h4>Conclusion</h4>
<p>This article gives you a couple of different ways to effectively use transparent GIF files in your Win32 programs. For today, the <span class="inline_code">IPicture</span> interface does a pretty good job. When GDI+ rolls  out as a standard part of Visual Studio, you'll probably want to  switch over to it for your imaging needs. Either way, you've got  good options that make things look a lot nicer  than they did in 1998.</p>
<h4>Links</h4>
<p><a href="http://marknelson.us/attachments/rendering-transparent-gifs-revisited/source.zip">Source for both demo programs</a>    </p>
]]></content:encoded>
			<wfw:commentRss>http://marknelson.us/2002/07/01/rendering-transparent-gifs-revisited/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Intel&#8217;s JPEG Library</title>
		<link>http://marknelson.us/2002/07/01/intels-jpeg-library/</link>
		<comments>http://marknelson.us/2002/07/01/intels-jpeg-library/#comments</comments>
		<pubDate>Tue, 02 Jul 2002 05:58:27 +0000</pubDate>
		<dc:creator>Mark</dc:creator>
		
		<category><![CDATA[Graphics]]></category>

		<category><![CDATA[Magazine Articles]]></category>

		<guid isPermaLink="false">/2002/07/01/intels-jpeg-library/</guid>
		<description><![CDATA[An article that takes a look at Intel's free JPEG Library for Win32, and compares it to doing things the Microsoft Way.]]></description>
			<content:encoded><![CDATA[

<table border="0" width="400px">
<tbody>
<tr>
<td width="33%">
      <img src="http://marknelson.us/attachments/intels-jpeg-library/cover.gif" alt="Dr. Dobb's Journal, July, 2002" />
      </td>
<td>
        <b>Dr. Dobb's Journal</b></p>
<p>July, 2002</p>
</td>
</tr>
</tbody>
</table>
<p><b>Update:</b> <i>Intel is no longer giving these libraries away for free - be prepared to fork out real money for this code. Does this render the information in this article useless? I don't know, add your comments below!</i></p>
<p>In this article I take a look at Intel's Win32 JPEG Library, and  present a slide-show app I built to test it. I found it quite easy to render JPEG images using this library, and I think the demo code I provide will provide you with a good starting point for your own work. I'll also perform a short comparison of Intel's library against Microsoft's standard <span class="inline_code">IPicture</span> component, both in terms of performance and ease of use.</p>
<h4>Intel's Performance Libraries</h4>
<p>Not too many people are aware of the fact that Intel dedicates a substantial amount of energy to its software products. As you would expect, most of the software Intel creates is designed to pull through more hardware sales, not to generate revenue of its own. One good example of this is Intel's JPG Library.</p>
<p>Intel added the MMX instruction sets to their CPU chips starting with their <strike>486</strike> Pentium MMX processors. The MMX instructions are designed to speed up certain operations needed in multimedia applications. One of these is the <i>Inverse Discrete Cosine Transform</i> (IDCT), which is used to when decoding JPEG images.</p>
<p>Developers typically can't take advantage of extended instruction sets in products designed for a widespread market, because they can't count on their target machines having the correct extensions. Companies like Intel or AMD can still leverage their proprietary processor features by providing device drivers, browser plugins, or other components, but this doesn't completely satisfy their desire for market penetration.</p>
<p>For example, my sample slide-show program doesn't use operating system components to decode JPEG files, meaning I can't take advantage of the MMX instruction set without writing specific routines to detect the target processor type, then branch to one of two different decoders depending on the result. </p>
<p>Intel correctly figures that they can convince me to offer support for their hardware if they dish it up on a silver platter, and that's exactly what they do with their series of Performance Libraries. At this time, Intel is offering the following roster of libraries:</p>
<ul>
<li/>Intel Integrated Performance Primitives - an abstraction layer for multimedia processing.
<li/>Intel Math Kernel Library - linear algebra and FFT routines.
<li/>Intel Recognition Primitives Library - code for speech and character recognition software.
<li/>Intel Signal Processing Library - access to Intel CPU functionality similar to that used in Digital Signal Processors.
<li/>Intel Image Processing Library - image manipulation functions, including filtering, thresholding, morphing, FFT, and DCT.
<li/>Intel JPEG Library - encoding and decoding of JPEG images.
</ul>
<p>All of these libraries have processor specific routines for various families of Intel CPUs, and all have generic code that will also run on any standard Intel Architecture CPU.</p>
<h4>What's the Catch</h4>
<p>In a clear case of enlightened self-interest, Intel is making these libraries freely available to software developers. You will have to go through a licensing procedure to in order to redistribute the libraries with your products, but as far as I can tell there aren't any circumstances under which Intel will require payments or royalties.</p>
<p>Support is another matter, as you might expect. Intel's web site has FAQ material, known issues, and so on. Talking to a person will require subscription to a premium support service.  </p>
<h4>Where to go</h4>
<p>You can find Intel's JPEG library  on their Web site, <a href="http://www.intel.com">www.intel.com</a>, by following the links to<br />
<i>Products/Software/Performance Libraries</i>. At the time this article is going to press, the direct link is at:</p>
<p><a href="http://www.intel.com/cd/software/products/asmo-na/eng/perflib/ipp/index.htm"><br />
http://www.intel.com/cd/software/products/asmo-na/eng/perflib/ipp/index.htm</a>.</p>
<p>The library has many of the niceties that you would expect from Intel. Figure 1 shows one of the first screens from the professional installation program, which naturally allows for a full uninstall as well. </p>
<p><center><br />
<img src="http://marknelson.us/attachments/intels-jpeg-library/Figure01.gif">
<p/>
Figure 1 - Installing the Library<br />
</center></p>
<p>As you install the library, you'll also see that it includes examples, white papers, documentation, and support for C/C++, Visual Basic, and Delphi. </p>
<h4>Using the Library - an Example</h4>
<p>I originally stumbled upon Intel's library while searching for a solution to a pressing problem. My friend Darrick Deel and I were intent on supplying some entertainment to a company shindig at Cisco's development offices in Dallas. We were going to act as roving digital photographers, snapping candid shots of our coworkers as they engaged in atypical mirth and merriment. </p>
<p>Our goal was to use a notebook PC and a projector to randomly display shots of partygoers during the event. What we needed was a slideshow<br />
program that would randomly display JPEG photos from a directory tree. We were hoping for a program that would run in unattended mode, but would still be able to periodically scan the photo archive looking for new shots. This would allow Darrick and I to add photos across the network without having to break into the show.</p>
<p>Slideshow software is easy to come by. As Figure 2 shows, a simple search on a popular download site turns up literally hundreds of possibilities. A surprisingly large percentage of this software is either free or quite cheap.</p>
<p><center><br />
<img src="http://marknelson.us/attachments/intels-jpeg-library/Figure02.gif">
<p/>
Figure 2- Searching for Slide Show Software<br />
</center></p>
<p>Despite the bountiful selection of software, Darrick and I were suffering from the Goldilocks syndrome - nothing we tried out was just right. Following in an age-old tradition among programmers, I decided to reinvent the wheel. Having recently downloaded Intel's JPEG Library, I knew I had just the tool I needed to make a quick<br />
job of it.</p>
<h4>Using Intel's Library</h4>
<p>The library ships from Intel with a pretty decent manual in PDF format, and a nicely fleshed out sample program called JPGView. The manual is full of code fragments that do a good job of illustrating the various features of the library. After reading the manual and examining the sample code, the process of displaying a JPEG image on the screen looked pretty straightforward: </p>
<ol>
<li/>Initialize the library.
<li/>Read the JPEG file header to get the basic image information, including size and color space.
<li/>Set up the various members of the data structure that will hold a Win32 <i>Device Independent Bitmap</i> (DIB.)
<li/>Read the JPEG image data into the DIB.
<li/>Display the DIB.
</ol>
<p>The first four steps here are accomplished in a single routine I wrote called <span class="inline_code">CreateImage</span>. This function takes an input file name as a parameter and returns a pointer to a <span class="inline_code">JPEG_CORE_PROPERTIES</span> structure, which is where the Intel library stores all its information. </p>
<p>The final step is done in the <span class="inline_code">WM_PAINT</span> handler for the program's <span class="inline_code">WndProc</span>. Since the first four steps create a fully functional DIB, all the <span class="inline_code">WM_PAINT</span> handler has to do is set up some parameters and draw the DIB to the output device context. </p>
<h4>SlideShow</h4>
<p>I put this knowledge together in an imaginatively named program called <em>SlideShow</em>. Although the code is built using Visual C++, it doesn't use MFC, so you should have good luck using the program with Brand X C++ compilers.</p>
<p><em>SlideShow</em> starts off as a console program that takes a directory name as a command line argument. That directory name should be the root directory of your album of JPEG files. Slideshow then creates a full-screen main window, starts a five second timer, and proceeds to process the message loop.</p>
<p>Other than a little bit of glue code, the message handling routine for this program really only cares about two messages: <span class="inline_code">WM_PAINT</span> and <span class="inline_code">WM_TIMER</span>.</p>
<h4>WM_TIMER</h4>
<p>The main window of <em>SlideShow</em> gets a timer tick once every five seconds. It has three main jobs to do when this timer tick occurs:</p>
<ol>
<li/>If needed, reload the list of pictures to display.
<li/>Destroy the current picture object.
<li/>Create a new picture object.
</ol>
<p><em>SlideShow </em>keeps a list of all the pictures it finds in the JPEG directory in a C++ <span class="inline_code">vector</span> named <span class="inline_code">WindowData::picture_names</span>. It also keeps an index of the next picture to decode in <span class="inline_code">WindowData::current_picture</span>. As soon as the timer handler is entered, it checks to see if the current_picture value is at or past the end of the picture_names vector. If it is, the current contents of the vector are erased and the picture directories are scanned for a new list of picture names. (Note that this happens naturally the first time the <span class="inline_code">WM_TIMER</span> tick is processed.) The picture names are randomized so the sequences aren't repeated each time the program is executed.</p>
<p>After potential maintenance of the image name list, it's a simple matter to delete the current image and create a new one. <span class="inline_code">CreateImage</span>,<br />
described a bit earlier in this article, does all the processing needed to load the JPEG image into a Device Independent Bitmap. This new image is ready to be painted on the screen, and I force that to happen by calling the Windows API function, <span class="inline_code">InvalidateRect()</span>. This forces a <span class="inline_code">WM_PAINT</span> message to be sent to the main window.</p>
<h4>WM_PAINT</h4>
<p>The <span class="inline_code">WM_PAINT</span> message means it is time to paint the JPEG image onto the screen. I've characterized this as being an easy task since the image is now in a DIB, and examination of the <span class="inline_code">WM_PAINT</span> handler in Listing 1 bears this out.</p>
<p>The actual painting is done via a call to Windows API function <span class="inline_code">StretchDIBits()</span>. This routine not only copies the image to the screen, but scales it as well. There are a dozen or so lines of code that set up the call to this function. I scale the image so that it fills as much of the screen as possible without clipping any bits, filling any unused space with the desktop background color.</p>
<p>Figure 3 shows what this looks like on the screen of a PC. The program quietly paints a new random image on the screen every five seconds. The machine shown here is a modified I-opener, which runs Windows 98 and has full network access. With no cooling fan to create ambient noise, the I-opener is an ideal desktop photo album.</p>
<p><center><br />
<img src="http://marknelson.us/attachments/intels-jpeg-library/Figure3.jpg"><br />
Figure 3 - The Slideshow in Action<br />
</center></p>
<p/>
<h4>Making Windows into Objects</h4>
<p>If you are used to using MFC for all of your C++ projects under Windows, you might find this to-the-API program a bit different. One thing I did to try and make it a little more structured is to encapsulate the Window data in a C struct, which could just as easily be a class.</p>
<p>When the program first starts, I create a <span class="inline_code">WindowData</span> object, which contains all the information regarding the currently selected<br />
picture, the list of file names, and so on. When the window is created, I stuff a pointer to this object into the <span class="inline_code">GWL_USERDATA</span> DWORD owned by the window. From that point on, every time I enter the <span class="inline_code">WndProc</span> I can get a pointer to the structure, eliminating the need for global variables.</p>
<h4>Integrating with Visual Studio</h4>
<p>The download package for this program contains a project file, but you may need to do a bit of modification after you install Intel's JPG Library.</p>
<p>First of all, the <i>SlideShow.cpp</i> file includes Intel's header file, <i>ijl.h</i>, as shown in this section of code from the source file:</p>
<div class="igBar"><span id="lcpp-8"><a href="#" onclick="javascript:showPlainTxt('cpp-8'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">C++:</span>
<div id="cpp-8">
<div class="cpp">
<ol>
<li class="li1">
<div class="de1"><span class="co2">#include &lt;windows.h&gt;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="co2">#include &quot;ijl.h&quot;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co2">#include &lt;iostream&gt;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="co2">#include &lt;string&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co2">#include &lt;vector&gt;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="co2">#include &lt;ctime&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co2">#include &lt;algorithm&gt;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="kw2">using</span> <span class="kw2">namespace</span> std; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Naturally, this file won't be in your normal include path. I take care of this by going to the <i>Project|Settings</i> dialog in Visual C++, selecting the <i>C/C++</i> pane, then the <i>Preprocessor</i> category. You should then enter Intel's header directory in the <i>Additional Include Directories</i> edit box. If you take the default installation, your dialog will look like Figure 4.</p>
<p><center><br />
<img src="http://marknelson.us/attachments/intels-jpeg-library/Figure04.gif"></p>
<p>Figure 4 - Configuring the Include Path<br />
</center></p>
<p>The project file I built for SlideShow includes the static library, <i>ijl5l.lib</i>. If you took the default path for Intel's install, you don't need to make any changes whatsoever. Figure 5 shows the path that is defined in the current project.</p>
<p>If you would like to use Intel's DLL instead of the static library, or if you chose a different install path, you'll need to delete the current library from the project. After deleting, use menu option <i>Project|Add to Project|Files</i> to add the correct library. </p>
<p><center><br />
<img src="http://marknelson.us/attachments/intels-jpeg-library/Figure05.gif"></p>
<p>Figure 5 - The correct properties for the Intel Library in Visual Studio<br />
</center></p>
<h4>Intel vs. Microsoft</h4>
<p>There are any number of reasons you might choose to use Intel's library to display JPEG images. But what about Microsoft's solution? Does the standard distribution of Windows come with components that can perform just as well?</p>
<p>As it happens, Microsoft ships with a standard COM object called <span class="inline_code">IPicture</span> that  shares much of the functionality with Intel's library. It not only handles JPEG files, but works with GIF, BMP, and other formats as well.</p>
<h4>Ease of use</h4>
<p>To get a handle on its ease of use, I reworked my SlideShow.cpp to use an all Micrsoft solution. The resulting program, SlideShowMS.cpp (available for download) shares the same structure, and is probably nearly identical in terms of structure and complexity. The major changes are:</p>
<ul>
<li/>Microsoft's image data is stored in the <span class="inline_code">IPicture</span> component, Intel's is in a <span class="inline_code">JPEG_CORE_PROPERTIES</span> structure.
<li/>Reading the file data requires two steps and a bit of coding for Intel. Microsoft makes reading easier with the simple <span class="inline_code">OleLoadPicture</span> function, but loses points for not reading from standard files. Setting up the <span class="inline_code">IStream</span> object Microsoft needs throws away any advantage they have in this area.
<li/>I used a standard Windows GDI function to draw the Intel object to the screen. <span class="inline_code">IPicture</span> has a <span class="inline_code">Render</span> method that is somewhat easier to use and requires less setup.
</ul>
<p>After examining these points, I think you'll agree that there's no clear winner here. If all that matters to you is how much work you have to perform to solve your imaging problems, you can stick with your personal preference and not worry about making a big mistake.</p>
<h4>Performance</h4>
<p>When it comes to decoding JPEG files and rendering them to the screen, Intel's library stole the show. I ran the Slideshow program through a batch of 20 JPEG files that were mostly 1600x1200 pixels in size. My non-scientific test game the following performance results:</p>
<p><center></p>
<table border=1 cellspacing=2>
<tbody>
<tr>
<th>CPU</th>
<th>Intel Batch Time</th>
<th>Microsoft Test Time</th>
</tr>
<tr>
<td>AMD K6-450</td>
<td>13 seconds</td>
<td>28 seconds</td>
</tr>
<tr>
<td>WinChip 200</td>
<td>50 seconds</td>
<td>130 seconds</td>
</tr>
<tr>
<td>Celeron 600</td>
<td>8 seconds</td>
<td>15 seconds</td>
</tr>
</tbody>
</table>
<p>Table 1 - Benchmark results<br />
</center></p>
<p>Intel's library seems to take Microsoft's time and cut it in half!  It appears that Intel's attention to performance paid off. (Interestingly, I would have expected to see a bigger delta between Intel and Microsoft on the Celeron CPU, but was disappointed.)</p>
<p>I'm sure there are ways to tweak my SlideShowMS program to get better performance from Microsoft's implementation. But the point of this article is to look at an off-the-shelf solution for use by programmers who may not be graphics experts. And for a straightforward implementation, Intel appears to really deliver when it comes to CPU cycles.</p>
<h4>What about IJG?</h4>
<p>The JPEG file format enjoys great acceptance in the software world. This is due in no small part to the availability of the Independent JPEG Group's (IJG) source code. The IJG created a non-commercial source code package that has been used as a reference and/or library by literally hundreds of programs out there. It enjoys a great deal of respect for its flexibility and feature depth.</p>
<p>Intel knows that many developers have already integrated the IJG code into their products, so they have created a 26-page white paper that discusses what you need to perform open-heart library replacement. There are major structural differences between the two sets of code, so this isn't an exercise for the faint of heart. But it can be done.</p>
<h4>Summary</h4>
<p>I found Intel's library quite easy to work with, which is probably evident given the length of my sample application. While I didn't do too much objective performance testing, I was happy with the speed I achieved when decoding and displaying multi-megapixel JPEG files on various PCs. </p>
<p>My satisfaction with the library is certainly only enhanced by the absence of a price tag. Intel's JPG library is definitely part of my image processing toolbox, you might want to add it to yours as well.</p>
<p><a href="http://marknelson.us/attachments/intels-jpeg-library/Source.zip">Article Source Code</a></p>
]]></content:encoded>
			<wfw:commentRss>http://marknelson.us/2002/07/01/intels-jpeg-library/feed/</wfw:commentRss>
		</item>
		<item>
		<title>CubeShow</title>
		<link>http://marknelson.us/2002/07/01/cubeshow/</link>
		<comments>http://marknelson.us/2002/07/01/cubeshow/#comments</comments>
		<pubDate>Mon, 01 Jul 2002 13:12:05 +0000</pubDate>
		<dc:creator>Mark</dc:creator>
		
		<category><![CDATA[Graphics]]></category>

		<category><![CDATA[Magazine Articles]]></category>

		<guid isPermaLink="false">http://marknelson.us/2002/07/01/cubeshow/</guid>
		<description><![CDATA[

&#160;
PC Magazine July, 2002


Remember when PC Magazine used to give away their utilities for free? Ah yes, those where the days. The earliest PC Magazine utilities were distributed as PC-BASIC programs printed up in the Utilities section, which made good typing accuracy an important skill. Eventually this was supplanted by electronic distribution via BBS and [...]]]></description>
			<content:encoded><![CDATA[<table border="0">
<tr>
<td style="width: 30%"><img src="http://marknelson.us/attachments/2002/cubeshow/pcmag_cover.png" /></td>
<td width="5%">&nbsp;</td>
<td style="width: 65%"><strong>PC Magazine</strong> July, 2002<br />
</tr>
</table>
<p>Remember when <a href="http://pcmag.com" class="newpage">PC Magazine</a> used to give away their utilities for free? Ah yes, those where the days. The earliest PC Magazine utilities were distributed as PC-BASIC programs printed up in the Utilities section, which made good typing accuracy an important skill. Eventually this was supplanted by electronic distribution via BBS and then the Internet. A lot of useful programs were thrown our way for free, and PC Magazine presumably bathed in good will and reflected glory.</p>
<p>Back in July, 2002, I wrote one of those free utilities for PC Magazine. CubeShow was a screensaver that featured a tumbling representation of a 3D cube, adorned with photos of your choice. Having never written a line of DirectX code in my life, it was quite an adventure, but I think I managed to produce something that worked and was popular.</p>
<p>Some of the more interesting problems involved with writing this utility were:</p>
<ul>
<li/>Finding the right rotation parameters to achieve smooth animation
<li/>Figuring out how to change photos on a cube fact only when it was hidden
<li/>Keeping a photo upright as the cube rotated
</ul>
<p>A lot of fun!<br />
<center><br />
<img src="http://marknelson.us/attachments/2002/cubeshow/cubeshow.jpg"><br />
Figure 1 - CubeShow in action<br />
</center><br />
Sadly, PC Magazine's free utility policy bit the dust during some corporate belt-tightening, and now it's a for-profit operation. As a result, they are rather tight-fisted about their rights to CubeShow, so I can't give you a copy, or even give you the source. And worse yet, when they converted their Utilities department to a store, they didn't grandfather previously free utilities. So if you want a copy of CubeShow, you'll either pay $7.97 for a <a href="http://www.pcmag.com/join/0%2C1213%2C%2C00.asp?join_page=8&#038;offers=/offer/ppv/OneDownload&#038;content_id=0" class="newpage">one time download</a>, or $19.97 for a year of unlimited downloads. Not a bad deal, and there are some good utilities on the site. If you download all 140 of them you'll surely feel like you got your money's worth!</p>
<h4>Links</h4>
<p><a href="http://www.pcmag.com/article2/0,4149,138094,00.asp" class="newpage">CubeShow on PCMag.com</a><br />
<a href="http://www.pcmag.com/data_process_yaga_module/0,1320,,00.asp?dr=1&#038;content_id=1380&#038;success_page=http%3A%2F%2Fwww%2Epcmag%2Ecom%2Farticle2%2F0,1759,177062,00%2Easp&#038;success_title=&#038;failure_page=&#038;discuss=" class="newpage">CubeShow download link</a></p>
<h4>Recommended Reading</h4>
<p>If you are interested in 3D Graphics Programming, the texts below are all excellent reference material. If you purchase them after clicking through on the links below, you'll be expanding your knowledge and supporting this site at the same time. Thanks. (Note: all links will open in a new window.)<br />
<center></p>
<table border="0">
<tr>
<td>
<iframe src="http://rcm.amazon.com/e/cm?t=theinternetdatac&#038;o=1&#038;p=8&#038;l=as1&#038;asins=1598633619&#038;fc1=000000&#038;IS2=1&#038;lt1=_blank&#038;lc1=0000FF&#038;bc1=000000&#038;bg1=FFFFFF&#038;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
</td>
<td>
<iframe src="http://rcm.amazon.com/e/cm?t=theinternetdatac&#038;o=1&#038;p=8&#038;l=as1&#038;asins=193184125X&#038;fc1=000000&#038;IS2=1&#038;lt1=_blank&#038;lc1=0000FF&#038;bc1=000000&#038;bg1=FFFFFF&#038;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
</td>
<td>
<iframe src="http://rcm.amazon.com/e/cm?t=theinternetdatac&#038;o=1&#038;p=8&#038;l=as1&#038;asins=1592003699&#038;fc1=000000&#038;IS2=1&#038;lt1=_blank&#038;lc1=0000FF&#038;bc1=000000&#038;bg1=FFFFFF&#038;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
</td>
<td>
<iframe src="http://rcm.amazon.com/e/cm?t=theinternetdatac&#038;o=1&#038;p=8&#038;l=as1&#038;asins=0387689923&#038;fc1=000000&#038;IS2=1&#038;lt1=_blank&#038;lc1=0000FF&#038;bc1=000000&#038;bg1=FFFFFF&#038;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
</td>
</tr>
</table>
<p></center></p>
]]></content:encoded>
			<wfw:commentRss>http://marknelson.us/2002/07/01/cubeshow/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Transparent ATL Controls</title>
		<link>http://marknelson.us/1998/03/01/transparent-atl-controls/</link>
		<comments>http://marknelson.us/1998/03/01/transparent-atl-controls/#comments</comments>
		<pubDate>Sun, 01 Mar 1998 14:58:03 +0000</pubDate>
		<dc:creator>Mark</dc:creator>
		
		<category><![CDATA[Graphics]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Magazine Articles]]></category>

		<guid isPermaLink="false">http://marknelson.us/1998/03/01/transparent-atl-controls/</guid>
		<description><![CDATA[Tom Armstrong and I wrote an article describing our technique for building an ATL control that displays bitmaps with transparent sections.]]></description>
			<content:encoded><![CDATA[<table border="0">
<tr>
<td style="width: 33%"><img src="http://marknelson.us/attachments/1998/transparent-atl-controls/ddj_cover_03_1998.jpg" /></td>
<td style="width: 66%"><strong>Dr. Dobb's Journal</strong> March, 1998<br/>by Mark Nelson and Tom Armstrong</td>
</tr>
</table>
<p/>
<h4>Introduction</h4>
<p>Implementing transparent ActiveX controls seems to be one of those programming tasks that is rapidly approaching FAQ status.  The ability to display transparent GIF files in most popular Web browsers has apparently put quite a few developers into "me-too" mode.  Unfortunately for programmers, Windows 95 and NT don’t provide much native support for the display of graphical images with transparent components.  In this article, we provide a fairly simple set of steps that can be used to work around the shortcomings in the O/S. Using Microsoft’s Active Template Library (ATL) we develop an ActiveX control that will display a bitmap with a single transparent color.  The control can be used with current  and some past versions of Internet Explorer, Netscape Navigator (with the ScriptActive plug-in), Visual Basic, and most other ActiveX containers.<br />
 <a href="http://marknelson.us/1998/03/01/transparent-atl-controls/#more-16" class="more-link">(more...)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://marknelson.us/1998/03/01/transparent-atl-controls/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
