<?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>Mark Nelson &#187; Graphics</title>
	<atom:link href="http://marknelson.us/category/graphics/feed/" rel="self" type="application/rss+xml" />
	<link>http://marknelson.us</link>
	<description>Programming, mostly.</description>
	<lastBuildDate>Fri, 13 Apr 2012 19:25:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<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 Nelson</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Data Compression]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[People]]></category>
		<category><![CDATA[Writing]]></category>

		<guid isPermaLink="false">http://marknelson.us/2008/02/11/cashing-in-on-e-books/</guid>
		<description><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/2008/02/11/cashing-in-on-e-books/' addthis:title='Cashing in On Electronic Books' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div>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 [...]]]></description>
			<content:encoded><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/2008/02/11/cashing-in-on-e-books/' addthis:title='Cashing in On Electronic Books' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div><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 &#8211; 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 />
<span id="more-119"></span></p>
<h4>Looking Beyond The Reader</h4>
<table align="right" cellspacing="5" border="0">
<tr>
<td><center><img src="http://marknelson.us/attachments/2008/cashing-in-on-e-books/sony.jpg"><br />
Sony&#8217;s Reader</center></p>
<td></tr>
</table>
<p><font size="+1"><strong>For </strong></font>electronic books to succeed, one thing is certain: the physical reading experience needs to match up well with the one we have right now for our printed media. In some ways this problem is already solved &#8211; readers like the products from Amazon and Sony are book-sized and lightweight, with displays that are doing their best to match the various good qualities of paper.</p>
<p>But there are still issues that need work. One of the most important is in the area of layout and markup. A presentation format such as HTML is designed to work with multiple display sizes, repositioning elements as needed. This doesn&#8217;t necessarily work so well with textbooks, magazines, etc., where graphic artists invest huge amounts of time and energy on positioning, font selection, and other esthetic issues.</p>
<p>Additionally, there is am staggering amount of material that is simply not in a format compatible with today&#8217;s electronic books. Even magazines being published today are not always ready for transfer to an eBook format, and there is of course a massive backlog of valuable material in the world that has never existed in digital format.</p>
<p>Into this void steps Robert Maxwell Case, who has developed a system called ReadAllOver, and is attempting to exploit it via his company, <a href="http://seeandbelieve.com/" class="newpage">SeeAndBelieve.com</a>. SeeAndBelieve.com has created a digital layout technology called ReadAllOver (the company seemingly has a love affair with awkward CamelCase constructions) that does a superior job of preserving the look of printed materials. The company web site gives a good demonstration of exactly what they are capable of doing &#8211; it is definitely worth your time to take a look.</p>
<p>I asked Robert if he could take the time to answer a few questions about ReadAllOver, and he was gracious enough to respond.</p>
<h4>Questions With Robert Maxwell Case</h4>
<p><strong>Mark Nelson:</strong> Hi Robert. I just recently became aware of your company, SeeAndBelieve.Com, and your imaging system, ReadAllOver. Before we get into the details of your technology, can you tell me a little bit about the history of your company? How long have you been at it? Are you working mostly solo or do you have some help? What kind of background do you have that got you into your current work?</p>
<p><strong>Robert Maxwell Case:</strong> Sure, Mark. I come from a background of being a full-time musician and a part-time graphic designer. Around 1991-92, I was unhappy with then-current digital halftoning routines and began experimenting on my own. So I&#8217;ve been at it 15-plus years. </p>
<table align="right" cellspacing="5" border="0">
<tr>
<td><center><img src="http://marknelson.us/attachments/2008/cashing-in-on-e-books/AtWorkSABC.JPG"><br />
Jimmy Kung (left) and Robert</center></p>
<td></tr>
</table>
<p>I&#8217;m not a programmer, so I have had a succession of programming assistants.  In recent years, they have come from my affiliation with the Computer Science department at Texas State University-San Marcos where I am a seven-year member of the Industrial Advisory Board. Currently SeeAndBelieve.Com, in addition to myself, has one full-time employee, Jimmy Kung, and several part-timers. </p>
<p>The first of my five U.S. patents (three issued, two pending) was filed in 1993 in response to some interest expressed by Steve Carlsen, developer of the .TIF  graphics file format at Aldus (he&#8217;s now with Adobe Systems.)</p>
<p><strong>MN:</strong> Can you give me a capsule summary of ReadAllOver? How does it differ from page layout systems like we see in web browsers or PDF viewers? Does it differ from the rendering systems used in Sony and Amazon&#8217;s current eBook readers?</p>
<p><strong>RC:</strong> Well, ReadAllOver in a nutshell is a digital halftone-based graphics system suitable for eBooks. It renders on the screen a digital page with the &#8220;look and feel&#8221; of a <a href="http://www.gi.alaska.edu/ScienceForum/ASF8/823.html" target="_blank">printed page</a>, with all included graphic elements, typography and images, placed precisely as the graphic designer intended. It differs from existing web browsers and .PDF viewers in that it relies less on text files and font metrics and instead places more emphasis on a simplified, highly-compressible bitmap image. In many respects, it is a &#8220;picture&#8221; of the page, with an ancillary text file. </p>
<p>The Sony and Amazon eBook readers are primarily text-based, offering a limited number of typefaces and few graphics. They both use the E-<a href="http://www.clickinks.com/" target="_blank">Ink</a> subtractive screen and we think ReadAllOver&#8217;s halftone system can be tailored to enable a good fit with that screen.</p>
<p><strong>MN:</strong> It looks like your technology emulates the halftone process used to render photographic <a href="http://householdproducts.nlm.nih.gov/cgi-bin/household/brands?tbl=brands&#038;id=8020031" target="_blank">images</a> in newspapers and magazines. How does it improve on that process to achieve smaller file sizes? Do you have data showing the level of compression you get for specific images? And do you also render type as halftone images? That would seem a lot less efficient than treating type as marked-up <a href="http://www.misterinkjet.com/bulk-inks.htm" target="_blank">text</a>.</p>
<p><strong>RC:</strong> That&#8217;s right, ReadAllOver does emulate the halftone process with one major difference, and that is that typography can be processed with it and not fall apart. </p>
<table align="left" cellspacing="5" border="0">
<tr>
<td><center><img src="http://marknelson.us/attachments/2008/cashing-in-on-e-books/sample.png"><br />
Samples of ReadAllOver output<br/>(Detail may not be representative, images were resized)</center></p>
<td></tr>
</table>
<p>The big idea is that the output image starts as an interim monochromatic checkerboard pattern, beginning from gray. To simplify, we derive the output image by rendering local areas of the input image that are darker than checkerboard gray by turning corresponding output monochrome white pixels to black. Conversely, we render local areas of the input image that are lighter than checkerboard gray by turning corresponding output monochrome black pixels to white. The result is a checkerboard-based ordered dither that can be re-ordered for variable-length run-length compression. </p>
<p>We presently are comparing compression levels for specific images and plan to publish the results. So with typography, abrupt gray level changes such as font outlines fall on the black pixels of the interim checkerboard to render any font without reliance on font metrics or hinting. For example, ReadAllOver pages containing <em>only</em> typography are competitive in file size to marked-up systems, and with the additional attribute that our system is able to efficiently render any font, in any language, and any image, placed correctly. That&#8217;s exciting.</p>
<p><strong>MN:</strong> I get digital delivery of some magazines already. For example, IEEE Spectrum is delivered using technology from Qmags. Do you think you can do a better job than they are already doing?</p>
<p><strong>RC:</strong> Qmags has selected Adobe PDF as its preferred file format, so the comparisons I&#8217;ve made previously between ReadAllOver and PDF come into play here. Taking a quick look at Qmags&#8217; file sizes, I would say that ReadAllOver is competitive and looks subjectively more &#8220;print-like.&#8221;</p>
<p><strong>MN:</strong> Have you released any sample code or SDKs for people to work with your compression technology?</p>
<p><strong>RC:</strong> Not at the present time &#8230; we have been too busy developing our prototype (you can see it at SeeAndBelieve.Com ).</p>
<p><strong>MN:</strong> The idea of an electronic book reader has been floating around for a long time, but right now it seems like we&#8217;re finally seeing designs that are actually gaining some traction. There are still a lot of naysayers, however. What do you see in the future for the electronic book reader? Will it eventually do for reading what the iPod did for music? Or will it forever be a niche product that is stuck on the verge of popular success? And how hard will it be for you to get the manufacturers of eBook readers to adopt ReadAllOver?</p>
<p><strong>RC:</strong> Mark, I do believe that an electronic book reader will achieve iPod-like popular success, and, hopefully, in the near-term. In my opinion, the more book-like the readers become, the closer we will get to that so-called tipping point. Then the public will recognize the added benefit of having access to any publication, including one&#8217;s own library, available whenever and wherever they desire. There are some of obstacles still to be overcome, like screen pixels that are pretty large, and wired and wireless transmission pipes that are pretty small. </p>
<p>I personally would like to see a reading device with 8-1/2&#8243; x 11&#8243; facing screens, about the size and weight of a coffee-table book, with graphics-intensive magazines and newspapers rendered on screen nearly indistinguishable from paper and ink. I certainly can imagine a college student not having to carry a backpack full of textbooks around campus.</p>
<p>Here&#8217;s my vision for our product: We&#8217;re hoping to make adapting to ReadAllOver as seamless and easy as possible. We envision three communities of ReadAllOver users: </p>
<ol>
<li/>The reader</p>
<li/>The publisher/bookseller
<li/>The hardware manufacturer.
</ol>
<p>We plan to provide each of these groups with a cost effective, easy-to-use solution. The ReadAllOver Viewer will be free for readers. They&#8217;ll read .RAO files on dedicated eBook devices, and most likely on other devices that could emulate a book-like reading experience. The inherent look and feel of printed material should reduce eye strain and, of course, we plan to offer such extras as page flipping, content search, printing, etc.</p>
<p>Publishers and booksellers will use ReadAllOver Publisher, our media content production system. They&#8217;ll be able to convert content from scanned material, as well as from existing editing and page layout systems and standards, including Adobe InDesign and FrameMaker, Quark XPress, MS/Office, Open Office, etc. (and, of course, we&#8217;ll include a .PDF to .RAO converter.) This community will appreciate a built-in high level of content protection with ReadAllOver&#8217;s emphasis on bitmaps. Hopefully they won&#8217;t need more, but if they do, our product should easily be able to incorporate additional encryption and DRM mechanisms. </p>
<p>We also plan to collaborate with eBook (and other display device) manufacturers in order to provide built-in support for the ReadAllOver rendering system. We feel we can efficiently adapt our system to display components with limited available grayscale and color levels. We also hope to offer a fixed-bit-rate option where every delivered page is the same file size. </p>
<h4>Conclusion</h4>
<p><font size="+1"><strong>Thanks </strong></font>Robert, this is all interesting stuff. I can see advantages to ReadAllOver that we don&#8217;t get from layout systems like PDF or HTML, so perhaps you will be able to hammer out an effective market position. I don&#8217;t have an eBook reader yet, but I think when the technology reaches the point where I can have a color Kindle I&#8217;ll probably jump on board. I&#8217;m almost there now, but since the Kindle is perpetually sold out at Amazon.com, my dollars are still safely in my wallet.</p>
]]></content:encoded>
			<wfw:commentRss>http://marknelson.us/2008/02/11/cashing-in-on-e-books/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Rendering Transparent GIFs &#8211; 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 04:59:33 +0000</pubDate>
		<dc:creator>Mark Nelson</dc:creator>
				<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Magazine Articles]]></category>

		<guid isPermaLink="false">http://test.kewby.com/?p=24</guid>
		<description><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/2002/07/01/rendering-transparent-gifs-revisited/' addthis:title='Rendering Transparent GIFs &#8211; Revisited' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div>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[













<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/2002/07/01/rendering-transparent-gifs-revisited/' addthis:title='Rendering Transparent GIFs &#8211; Revisited' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div><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>
		<slash:comments>0</slash:comments>
		</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 04:58:27 +0000</pubDate>
		<dc:creator>Mark Nelson</dc:creator>
				<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Magazine Articles]]></category>

		<guid isPermaLink="false">/2002/07/01/intels-jpeg-library/</guid>
		<description><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/2002/07/01/intels-jpeg-library/' addthis:title='Intel&#8217;s JPEG Library' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div>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[

<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/2002/07/01/intels-jpeg-library/' addthis:title='Intel&#8217;s JPEG Library' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div><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"></p>
<p>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>
		<slash:comments>8</slash:comments>
		</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 Nelson</dc:creator>
				<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Magazine Articles]]></category>

		<guid isPermaLink="false">http://marknelson.us/2002/07/01/cubeshow/</guid>
		<description><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/2002/07/01/cubeshow/' addthis:title='CubeShow' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div>&#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 [...]]]></description>
			<content:encoded><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/2002/07/01/cubeshow/' addthis:title='CubeShow' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div><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>
]]></content:encoded>
			<wfw:commentRss>http://marknelson.us/2002/07/01/cubeshow/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</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 Nelson</dc:creator>
				<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Magazine Articles]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://marknelson.us/1998/03/01/transparent-atl-controls/</guid>
		<description><![CDATA[<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/1998/03/01/transparent-atl-controls/' addthis:title='Transparent ATL Controls' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div>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[













<div class="addthis_toolbox addthis_default_style" addthis:url='http://marknelson.us/1998/03/01/transparent-atl-controls/' addthis:title='Transparent ATL Controls' ><a class="addthis_button_twitter"></a><a class="addthis_button_favorites"></a><a class="addthis_button_print"></a><a class="addthis_button_facebook_like"></a><a class="addthis_button_google_plusone"></a><a class="addthis_button_compact"></a></div><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 />
<span id="more-16"></span></p>
<h4>Transparency under Windows</h4>
<p>When referring to bitmapped images, the term <I>transparency</I> has a straightforward meaning.  A given image has an arbitrary number of transparent areas.  When the image is drawn, the transparent areas don’t obscure the area behind the image in the Z-order.  In the simplest case, we've all seen this used to good effect on the Web, producing images of complex objects that appear to be floating on top of a background.</p>
<p>Figure 1 shows a pair of transparent GIF files that float nicely above a background on a typical Web page.<br />
<center><br />
<img src="http://marknelson.us/attachments/1998/transparent-atl-controls/Image1.gif"><br />
Figure 1 - Screen capture of a pair of transparent GIF files used in a banner<br />
</center></p>
<p>Sites such as Mr. Showbiz typically have a standard background pattern that shows up on many or all of their pages.  In Figure 1, the GIF on the left side has navigation bars that are used in an image map.  A GIF file with the site logo is shown on the right.  Both images feature transparent areas that let them blend in nicely with the background.</p>
<h4>How do they do that?</h4>
<p>After seeing this esthetically pleasing effect on the Web, we set ourselves to the task of duplicating it in an ActiveX control.  For Windows programmers, encapsulation of a feature in an ActiveX control is definitely the method of choice.</p>
<p>Research turned up a couple of different ways to implement transparency in a control.  The most straightforward of these methods requires the programmer to set up a windows HRGN object, used to define a non-rectangular drawing area.  Figure 2 shows a simple example of a drawing region.  As long as you can define your region as a path connecting a series of points (or elliptical regions), you can create a drawing region that Windows understands.</p>
<p><center><br />
<img src="http://marknelson.us/attachments/1998/transparent-atl-controls/Image2.gif"><br />
Figure 2 - A Windows Drawing Region<br />
</center><br />
Once you have a drawing region defined, transparency is easy. In the simplest case, you can take advantage of an existing Windows 95 capability by defining a non-rectangular window.  Once that's done, you simply draw the window as you normally would.  The areas outside the region will be drawn by whatever resides behind the window.</p>
<p>Defining a drawing region works well with containers that implement the OCX 96 specification from Microsoft (shipping with the ActiveX SDK).  In the best case, you can implement two pass drawing, which lets you draw the foreground part of your control first, then lets the container draw the background.  This provides fast and flicker-free drawing of controls.</p>
<h4>Ointment ready, enter fly</h4>
<p>Defining drawing regions is great for some applications, but it might not be the best general purpose technique.  We wanted to be able to draw any type of image with randomly configured transparent areas.  This means having transparency controlled on a pixel by pixel basis. Attempting to define a region for any arbitrary bitmap is simply asking for a headache!</p>
<p>For our control, we instead used a masking technique that is described by Ron Gery in an MSDN article.  This technique uses a simple masking technique that makes it trivial to use arbitrarily complex transparent regions.</p>
<p>The Gery algorithm assumes that you have a bitmap with a single color that defines the transparent area.  Given that, the drawing portion of your code needs to execute the following steps:</p>
<ul>
<li/>Create a monochrome bitmap the same size as the bitmap you are going to draw.
<li/>Set all the transparent pixels in the monochrome bitmap to 1, and all the opaque pixels to 0.
<li/>XOR the screen region with the bits in your image bitmap.
<li/>AND the screen with your monochrome bitmap.  This has the effect of leaving all the transparent areas unchanged, and setting the opaque areas to be black.
<li/>XOR the screen region with the image bits again.  This sets all the transparent areas back to their original color, since the two XOR operations cancel one another.  The opaque areas now contain the desired image bits, since XORing with solid black is the same as simply setting the bits.
</ul>
<p>This drawing algorithm is simple to implement using standard Windows raster operations.  If you step through it and watch the effects when using the debugger, it will even start to make sense after a few passes.</p>
<h4>Background checks</h4>
<p>This drawing scheme works pretty well with containers that adhere to the OCX 96 recommendations, but it makes one important assumption. The XOR/Mask sequence preserves the background behind transparent areas, but only if the background has already been drawn.</p>
<p>To programs like Internet Explorer 3.0, the ActiveX control is simply a child window that is responsible for drawing its entire rectangular area.  So when IE3 is drawing the background for a Web Page, it will exclude the areas occupied by child windows, allowing them to draw their own background.  So if I've set up a pleasing (or not!) background GIF, IE3 won't bother to draw it in any areas covered by my control, making any attempt at transparent drawing doomed from the start.</p>
<p>Microsoft has documented a way around this problem in Knowledge Base article Q165073. This article gives a code snippet that you can drop into a control's WM_ERASEBKGND handler. MFC code similar to that in the Knowledge Base article is shown in Figure 3.</p>
<p><center></p>
<table border="0">
<tr>
<td>
<div class="igBar"><span id="lcpp-9"><a href="#" onclick="javascript:showPlainTxt('cpp-9'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">C++:</span>
<div id="cpp-9">
<div class="cpp">
<ol>
<li class="li1">
<div class="de1"><span class="kw4">BOOL</span> CTransCtrl::<span class="me2">OnEraseBkgnd</span><span class="br0">&#40;</span>CDC* pDC<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; CWnd*&nbsp; pWndParent = GetParent<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; POINT&nbsp; pt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; pt.<span class="me1">x</span> = pt.<span class="me1">y</span> = <span class="nu0">0</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; MapWindowPoints<span class="br0">&#40;</span>pWndParent, &amp;pt, <span class="nu0">1</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; OffsetWindowOrgEx<span class="br0">&#40;</span>pDC-&gt;m_hDC, pt.<span class="me1">x</span>, pt.<span class="me1">y</span>, &amp;pt<span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; ::<span class="me2">SendMessage</span><span class="br0">&#40;</span> pWndParent-&gt;m_hWnd,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;WM_ERASEBKGND,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#40;</span>WPARAM<span class="br0">&#41;</span>pDC-&gt;m_hDC,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="nu0">0</span> <span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; SetWindowOrgEx<span class="br0">&#40;</span> pDC-&gt;m_hDC, pt.<span class="me1">x</span>, pt.<span class="me1">y</span>, <span class="kw2">NULL</span> <span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">1</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p>
</td>
</tr>
<tr>
<td><center>Figure 3 -The Transparency Kludge for IE3</center></tr>
</td>
</table>
<p></center></p>
<p>In a nutshell, this code sends a WM_ERASEBKGND message to Internet Explorer, along with the device context for the ActiveX control.  This convinces Internet Explorer to draw the background behind the control as if it didn't belong to a child window.  This code doesn't cause any trouble for more sophisticated containers, such as IE4, because the WM_ERASEBKGND never gets sent to controls. Newer containers that implement the OCX '96 specification don't create child windows for each embedded control. Instead, each control renders itself directly on the container's device context.</p>
<h4>Putting it together using ATL</h4>
<p>To demonstrate the concepts discussed here, we created an ActiveX control called TransCtl that displays an eight bit BMP file, and treats all solid white areas ( RGB(255,255,255) ) as transparent. To keep things simple, the control doesn’t do any palette management, so if you are using it on 256 color displays you need to stick to the 20 system colors. (The system colors are generally always going to be present, regardless of the remaining 236 colors in the palette.)</p>
<p>We created this control using Visual C++ 5.0, and Microsoft's framework of the month, the Active Template Library. Programming with the ATL is somewhat more difficult than with MFC, but the resulting ActiveX controls are usually faster, smaller, and can eliminate dependencies on corpulent DLLs.</p>
<p>Working with the ATL is a Wizard-driven process, which means that programming isn’t just typing in code, it also involves quite a few menu selections and button depressions.  The next section of this article will walk you through the process from start to finish.</p>
<h4>Follow the bouncing ball</h4>
<p>In the old days of command line compilers, we could have just included a single C file that held all the source code for this project.  Things aren't so easy for authors using IDEs that feature Wizard-based development.  The instructions for building this project with Visual C++ look more like a recipe in a cookbook, with an interesting mixture of dialog boxes, button presses, menu options and code snippets.</p>
<p>To build any ATL project using Visual C++, you select File|New|Project|ATL COM AppWizard.  The dialog box asks you for a Project Name, which we set to TransparentControl, and a Location, which we filled in with C:\. We selected the default values on the next dialog, creating a DLL with no MFC support, and no merging of proxy/stub code.  The Wizard provides the following dialog to confirm what you’ve just done:</p>
<p><center><br />
<img src="http://marknelson.us/attachments/1998/transparent-atl-controls/Image4.gif"><br />
Figure 4 - ATL COM AppWizard output<br />
</center></p>
<p>At this point we need to create the actual ActiveX control that will display our BMP files. To do this, we use Insert|New ATL Object, which brings up the ATL Object Wizard, shown in Figure 4.  We select Controls|Full Control and click the Next button, which brings up a tabbed properties dialog.  In the edit box asking for a short name, we entered TransCtl.  In the Miscellaneous sheet of the properties dialog, we turned off the Opaque option.</p>
<p>The Stock Properties tab allows you to specify which stock properties your control will support. Our control needs the ReadyState stock property, which is completely supported by the ATL, but for some reason is absent from the Stock Properties tab. So, to include it in our control’s implementation we have to add the code ourselves, which we discuss later.</p>
<p><center><br />
<img src="http://marknelson.us/attachments/1998/transparent-atl-controls/Image5.gif"><br />
Figure 5 - The ATL Object Wizard<br />
</center></p>
<p>Clicking the OK button at this point generates all the files necessary to create the basic ActiveX control.  You can build the control at this point, and insert it into Microsoft’s ActiveX Control Test Container (accessible from the Tools menu item.)  But before it can do anything interesting, we need to add the code that assigns an image file to the control, loads the image file into memory, and draws it on the screen.</p>
<p><H4>Dealing with the image file</H4></p>
<p>Since the goal of the TransCtl is to display an image file, we clearly need a property that gives the name of the file.  Adding properties to an ATL project is another Wizard driven process.  In the ClassView tab of the Workspace window, you should have two classes defined: CTransCtl, and ITransCtl.  Right click on ITransCtl item in the tree, and select Add Property.  Choose a property type of BSTR, which is the canonical string type used in ActiveX controls.  Choose a property name of ImageFile, and use the default get and put functions the Wizard suggests.</p>
<p><center><br />
<img src="http://marknelson.us/attachments/1998/transparent-atl-controls/Image6.gif"><br />
Figure 6 - Adding a property<br />
</center></p>
<p>While the Visual C++ Wizards help you quite a bit by adding the properties to the control, they don’t actually supply the internal implementation of the property.  This needs to be done manually.  First, we add a new member variable called m_bstrImageFile, of type CComBSTR to class CTransCtl in file TransCtl.h.  Next, we initialize it with an empty string in the CTransCtl constructor.  Finally, we implement the get_ImageFile() and put_ImageFile() functions in TransCtl.cpp.</p>
<p>The put_ImageFile() (shown in Listing 2) function has to do more than just copy a string into our member variable.  It clears our internal bitmap that actually holds the image, starts up the download process, and informs the user that the control is in an incomplete state. We’ll cover the details of this whole process in the next few sections.</p>
<h4>Asynchronous Properties</h4>
<p>Until recently, a control's property values, such as the bits of an image,  had to be stored directly within a file managed by its container. As the control is instantiated within the container, its property values are provided by the container via COM-based interfaces. This process of binding a control's property values is a synchronous operation. The container opens its storage file, locates the control’s persistent data, queries for the control's persistence interface (usually IPersistStreamInit or IPersistPropertyBag), and then calls IPersist*::Load, whereby the control sets its property values.</p>
<p>This technique works fine for most control properties such as background color, font, and so on because the data is small. However, large property values like the bits of an image, can be quite large, and in today's low-bandwidth environments, where 28.8 modems are considered fast, synchronously binding a control's properties just isn't tolerated. As an example, a Web page containing four ActiveX controls that each displayed a 100KB image would take several minutes before any aspect of the page would actually "display."</p>
<p>Back in early 1996, when Microsoft finally realized that the Web was much more than a passing fad, they developed a COM-based technology to solve the synchronous binding problem. This new specification provided a way for controls and containers to bind their properties through something called an Asynchronous Moniker. Microsoft also provided an implementation of the specification and deemed it a URL Moniker.</p>
<p>Monikers are used to name specific instances of COM classes. A moniker is itself a COM object that implements the IMoniker interface and whose purpose is to encapsulate the details of instantiating a particular object. The moniker hides, from the client, the process of locating, instantiating, and initializing a specific COM class. In other words, clients work through the standard IMoniker interface or the MkParseDisplayNameEx API and can ignore class-specific details.</p>
<p>Typically, monikers are used to bind to a specific instance of a COM object. However, they can also be used to bind to a remote storage or stream. Microsoft's URL moniker implementation allows a client application to asynchronously bind to a Web resource specified by a URL. The client application, by implementing the IBindStatusCallback interface, can treat the resource as a stream of bytes (via an IStream pointer). In other words, a client can download a remote file in an asynchronous manner by specifying only its URL, which is exactly what we need for our ImageFile property implementation.</p>
<p>The ImageFile property, then, becomes a string that holds just the URL for our bitmap file. The persistent data for our ImageFile property is no longer the bits of the image itself, but an embedded reference to them. To give you an idea of how this looks in a Web page, examine the ImageFile property in Figure 7.</p>
<p><center></p>
<table border="0">
<tr>
<td>
<div class="igBar"><span id="lhtml-10"><a href="#" onclick="javascript:showPlainTxt('html-10'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">HTML:</span>
<div id="html-10">
<div class="html">
<ol>
<li class="li1">
<div class="de1"><span class="sc2"><a href="http://december.com/html/4/element/html.html"><span class="kw2">&lt;HTML&gt;</span></a></span></div>
</li>
<li class="li2">
<div class="de2"><span class="sc2"><a href="http://december.com/html/4/element/head.html"><span class="kw2">&lt;HEAD&gt;</span></a></span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc2"><a href="http://december.com/html/4/element/title.html"><span class="kw2">&lt;TITLE&gt;</span></a></span>Test page for TransCtl<span class="sc2"><span class="kw2">&lt;/TITLE&gt;</span></span></div>
</li>
<li class="li2">
<div class="de2"><span class="sc2"><span class="kw2">&lt;/HEAD&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc2"><a href="http://december.com/html/4/element/body.html"><span class="kw2">&lt;BODY</span></a> <span class="kw3">BACKGROUND</span>=<span class="st0">"background.gif"</span><span class="kw2">&gt;</span></a></span></div>
</li>
<li class="li2">
<div class="de2"><span class="sc2"><a href="http://december.com/html/4/element/object.html"><span class="kw2">&lt;OBJECT</span></a> <span class="kw3">ID</span>=<span class="st0">"TransCtl"</span> <span class="kw3">WIDTH</span>=<span class="nu0">128</span> <span class="kw3">HEIGHT</span>=<span class="nu0">128</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp;<span class="kw3">CLASSID</span>=<span class="st0">"CLSID:B25D9AF5-E760-11D0-A052-00A0247B7657"</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp;<span class="kw3">CODEBASE</span>=<span class="st0">"TransparentControl.dll"</span><span class="kw2">&gt;</span></a></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp;<span class="sc2"><a href="http://december.com/html/4/element/param.html"><span class="kw2">&lt;PARAM</span></a> <span class="kw3">NAME</span>=<span class="st0">"ImageFile"</span> <span class="kw3">VALUE</span>=<span class="st0">"http://www.widgetware.com/image01.bmp"</span><span class="kw2">&gt;</span></a></span></div>
</li>
<li class="li2">
<div class="de2"><span class="sc2"><span class="kw2">&lt;/OBJECT&gt;</span></span> </div>
</li>
</ol>
</div>
</div>
</div>
<p>
<center>Figure 7 - HTML for our transparent control</center>
</td>
</tr>
</table>
<p></center></p>
<p>Loading the image proceeds like this. As the control is instantiated by the container, it passes the image's URL as part of the synchronous property binding process. Once we have the URL, we initiate the asynchronous download process. The download occurs in a background thread, and when it is complete, we render the transparent control using our image data.</p>
<p>As developers we don't typically want to mess with all this detail, because the implementation is basically the same for any URL that we might access. This, of course, is why frameworks such as the ATL are so popular. ATL provides the CBindStatusCallback class for handling asynchronous downloads, and that's what we'll use to download our image data.</p>
<p>If you look closely at Listing 2, you'll notice that instead of using ATL's CBindStatusCallback class, we instead developed and uses a derived class named COurBindStatusCallback. The CBindStatusCallback implementation provided with version 2.1 of the ATL isn't quite ready for prime time. We had to tweak a few of its methods in order to get everything to work properly. You can examine the minor changes by downloading the code for our example.</p>
<p>The download process begins with a call to COurBindStatusCallback::Download. The Download() method is shown in Figure 8. The implementation is a little hard to understand at first, as is nearly every aspect of ATL, but with a look through ATL's source, we can figure it out.</p>
<p><center><br />
<table border="0">
<tr>
<td>
<div class="igBar"><span id="lcpp-11"><a href="#" onclick="javascript:showPlainTxt('cpp-11'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">C++:</span>
<div id="cpp-11">
<div class="cpp">
<ol>
<li class="li1">
<div class="de1"><span class="kw4">static</span> HRESULT Download<span class="br0">&#40;</span> T* pT, ATL_PDATAAVAILABLE pFunc,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;BSTR bstrURL,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;IUnknown* pUnkContainer = <span class="kw2">NULL</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw4">BOOL</span> bRelative = <span class="kw2">FALSE</span><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;CComObject&lt;COurBindStatusCallback&lt;T&gt;&gt; *pbsc;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;HRESULT hRes =</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; CComObject&lt;COurBindStatusCallback&lt;T&gt;&gt;::<span class="me2">CreateInstance</span><span class="br0">&#40;</span>&amp;pbsc<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>FAILED<span class="br0">&#40;</span>hRes<span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; <span class="kw1">return</span> hRes;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="kw1">return</span> pbsc-&gt;StartAsyncDownload<span class="br0">&#40;</span> pT, pFunc, bstrURL,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pUnkContainer, bRelative<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p>
<center>Figure 8 - COurBindStatusCallback::Download() method</center>
</td>
</tr>
</table</center>
<p>COurBindStatusCallback is itself an actual COM object. Whenever we need to download a URL- based file, we just call the its static Download() method. As you can see from Figure 8, Download() creates an instance of itself and then starts the download process. The key point is that we pass in our control's this pointer and the address of our callback method. As the download proceeds, we will be notified through our OnData() callback method.</p>
<p>The implementation of the our callback method is shown in Listing 1. As data arrives, the OnData() method is called with a buffer containing the remote data and a flag indicating if this is the first, intermediate, or last data notification. We use the flag value to manage our download buffer. When the download is finished, we set the control's ReadyState property to complete. The rest of the code is general buffer management.</p>
<h4>Are You Ready?</h4>
<p>Before the addition of asynchronous properties, a control was ready for use as soon as it was instantiated and initialized by its container. Now, for those controls with asynchronous properties, their internal state may not allow immediate use after loading. Microsoft has added a new standard control property called ReadyState. A control that implements asynchronous properties uses this property to communicate its readiness to its users. Figure 9 shows the defined values for the ready state property.<br />
<center><br />
<table border="0">
<tr>
<td>
<div class="igBar"><span id="lcpp-12"><a href="#" onclick="javascript:showPlainTxt('cpp-12'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">C++:</span>
<div id="cpp-12">
<div class="cpp">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">enum</span> tagREADYSTATE</div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;READYSTATE_UNINITIALIZED = <span class="nu0">0</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp;READYSTATE_LOADING&nbsp; &nbsp; &nbsp; &nbsp;= <span class="nu0">1</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;READYSTATE_LOADED&nbsp; &nbsp; &nbsp; &nbsp; = <span class="nu0">2</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp;READYSTATE_INTERACTIVE&nbsp; &nbsp;= <span class="nu0">3</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;READYSTATE_COMPLETE&nbsp; &nbsp; &nbsp; = <span class="nu0">4</span></div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span>&nbsp; READYSTATE; </div>
</li>
</ol>
</div>
</div>
</div>
<p>
<center>Figure 9 - ReadyState property values</center>
</td>
</tr>
</table</center>
<p>Most of the states are self-explanatory. The difference between the INTERACTIVE and COMPLETE states is up to the control implementor. Those controls that provided interaction  with the user (e.g., mouse clicks) should move to the interactive state as soon as possible, even if asynchronous downloading is still in progress.</p>
<p>For example, we might develop a button control that displays a bitmap. The control should move to the interactive state and allow its click event to fire even as the bitmap is downloading. Once the download is finished and the bitmap is rendered, the control moves into the complete state. A control developer should provide the user with interactive functionality as soon as possible.</p>
<p>For our transparent control, we don’t really provide any interactive behavior, and so we stay in the loaded state until our bitmap has finished downloading. By examining the OnDraw code in listing 2 and the excerpt in Figure 10, you can see that we defer rendering of the control until the bitmap download has completed.</p>
<p><center><br />
<table border="0">
<tr>
<td>
<div class="igBar"><span id="lcpp-13"><a href="#" onclick="javascript:showPlainTxt('cpp-13'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">C++:</span>
<div id="cpp-13">
<div class="cpp">
<ol>
<li class="li1">
<div class="de1"><span class="co1">// If we're still downloading the image,</span></div>
</li>
<li class="li2">
<div class="de2"><span class="co1">// draw some text and return</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">if</span> <span class="br0">&#40;</span> m_nReadyState != READYSTATE_COMPLETE <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;DrawString<span class="br0">&#40;</span> di.<span class="me1">hdcDraw</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">"Downloading bitmap..."</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&amp;rc <span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp;<span class="kw1">return</span> S_OK;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p>
<center>Figure 10 - Checking the control's ReadyState before rendering</center>
</td>
</tr>
</table</center>
<p>There is also a new standard control event called ReadyStateChange that a control implementor can use to directly notify any users that the ReadyState property has change. For simplicity’s sake, though, we’ve left out this detail in our example.</p>
<p>Adding support for the ReadyState property to our control is easy. Just add a data member of type long with the name of m_nReadyState, and update the control’s IDL file with the get and put methods (See listing 5). Your control must also derive from CStockPropImpl instead of IDispatchImpl, and you need to add the property to your control’s property map. Discussion of ATL's implementation of stock properties is beyond the scope of this article. Beware, though, it involves large macros, blind unions, and unusual C++ syntax.</p>
<h4>We've got DIBs</h4>
<p>URL Monikers treat URL resources as a stream of bytes. It is up to the client application to add meaning to the returned stream. In our example, the stream contains a Windows DIB, or bitmap. A DIB object is different than a GIF file in that it doesn’t support progressive rendering, so our implementation requires the complete bitmap before we can draw the transparent image.</p>
<p>In most cases working with DIBs involves reading the bitmap structure in from a local file and working with a handle to the DIB. There’s even a nice API call (LoadImage) that makes this process easy. However, in our case, we have to manage a DIB structure in memory that is assembled asynchronously. Once the structure contains all of the necessary information, we need to realize the DIB within a Windows device context. To encapsulate this behavior we developed a DIB management class called CDib, which is based loosely on the WebImage example in the Win32 SDK. The header file is shown in Listing 3.</p>
<p>As data is downloaded it is stored in a buffer contained in our control's implementation class. Once the bitmap data is completely downloaded, the control's ReadyState transitions to complete. This allows the code from OnDraw() shown in Figure 11 to execute. The buffer information is passed to the DIB class, a device context is created based on the DC provided by the container, a DIB section is created, and finally the actual bits of the image are passed to the DIB section.<br />
<center><br />
<table border="0">
<tr>
<td>
<div class="igBar"><span id="lcpp-14"><a href="#" onclick="javascript:showPlainTxt('cpp-14'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">C++:</span>
<div id="cpp-14">
<div class="cpp">
<ol>
<li class="li1">
<div class="de1"><span class="co1">// If this is the first time through OnDraw,</span></div>
</li>
<li class="li2">
<div class="de2"><span class="co1">// we need to setup the DIB</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">if</span> <span class="br0">&#40;</span>! m_dib.<span class="me1">IsInitialized</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <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;m_dib.<span class="me1">SetBitmapInfoHeader</span><span class="br0">&#40;</span> m_pbBuffer <span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp;m_dib.<span class="me1">Create</span><span class="br0">&#40;</span> di.<span class="me1">hdcDraw</span> <span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;m_dib.<span class="me1">SetBits</span><span class="br0">&#40;</span> m_pbBuffer <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>
<center>Figure 11 - Preparing the downloaded bitmap for rendering</center>
</td>
</tr>
</table>
<p></center></p>
<p>We are now ready to render our transparent image.</p>
<h4>Displaying the CDib object</h4>
<p>Once the image has been loaded into memory, all we have to worry about is displaying it.  As we discussed earlier in this article, compatibility with IE 3.0 and other older containers means we need to add a handler for WM_ERASEBKGND, and use it to spoof the container into drawing the background for our control.  Listing 1 shows the code that is added to the CTransCtl definition to process this message. First, we add an entry to the message map for the control, then we add the message handler itself.  Essentially, all this handler does is pass the WM_ERASEBKGND message up to the parent window, along with a copy of the control's device context. (Note that the ATL Object Wizard doesn’t help you add message handlers, this is strictly a manual process.)</p>
<p>The actual drawing of the image is done in the OnDraw() member function of the CTransCtl class.  If you've slogged through all this lengthy article wondering when we were actually going to show how to do transparent drawing, you have finally made it!</p>
<p>The OnDraw() function is called by the ATL framework, passing in a structure that contains various bits of information needed to actually paint information on the screen. Our implementation isn’t much more complicated than it would be if we were simply displaying the BMP file. We just have to add the code to create the monochrome bit mask, then perform the XOR/AND/XOR drawing method discussed earlier in this article.</p>
<p>The code shown in Figure 12 creates a monochrome bit mask in a compatible DC, relying on a Windows specific characteristic of monochrome bitmaps.  When copying from a color bitmap to a monochrome bitmap, any color pixel that is identical to the color bitmap’s background color will get set to 1 in the monochrome bitmap.  All other bits will get set to 0.  With this knowledge in hand, you can see how the code shown below will handily create the bitmap needed by the masking algorithm.<br />
<center><br />
<table>
<tr>
<td>
<div class="igBar"><span id="lcpp-15"><a href="#" onclick="javascript:showPlainTxt('cpp-15'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">C++:</span>
<div id="cpp-15">
<div class="cpp">
<ol>
<li class="li1">
<div class="de1">HDC hdcMask = ::<span class="me2">CreateCompatibleDC</span><span class="br0">&#40;</span> di.<span class="me1">hdcDraw</span> <span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">HBITMAP bmMask = ::<span class="me2">CreateBitmap</span><span class="br0">&#40;</span> columns, rows, <span class="nu0">1</span>, <span class="nu0">1</span>, <span class="kw2">NULL</span> <span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">HBITMAP hOldMaskBitmap = <span class="br0">&#40;</span>HBITMAP<span class="br0">&#41;</span> SelectObject<span class="br0">&#40;</span> hdcMask, bmMask <span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">SetBkColor<span class="br0">&#40;</span> HDC<span class="br0">&#40;</span> m_dib <span class="br0">&#41;</span>, RGB<span class="br0">&#40;</span> <span class="nu0">255</span>, <span class="nu0">255</span>, <span class="nu0">255</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">SetTextColor<span class="br0">&#40;</span> HDC<span class="br0">&#40;</span> m_dib <span class="br0">&#41;</span>, RGB<span class="br0">&#40;</span> <span class="nu0">0</span>, <span class="nu0">0</span>, <span class="nu0">0</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">BitBlt<span class="br0">&#40;</span> hdcMask,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span>, <span class="nu0">0</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; columns, rows,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; HDC<span class="br0">&#40;</span> m_dib <span class="br0">&#41;</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; SRCCOPY <span class="br0">&#41;</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p>
<center>Figure 12 - Creating the monochrome bitmap mask</center>
</td>
</tr>
</table>
<p></center><br />
Once the mask has been created, we can do the actual drawing using three device contexts. di.hdcDraw contains the screen device context, HDC(m_dib) is the device context containing the color bitmap for our image file, and hdcMask is the device context containing the monochrome bitmap.  The three consecutive BitBlt() function calls in Figure 13 are all that is required to perform the transparent draw.</p>
<p><center><br />
<table>
<tr>
<td>
<div class="igBar"><span id="lcpp-16"><a href="#" onclick="javascript:showPlainTxt('cpp-16'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">C++:</span>
<div id="cpp-16">
<div class="cpp">
<ol>
<li class="li1">
<div class="de1">BitBlt<span class="br0">&#40;</span> di.<span class="me1">hdcDraw</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; rc.<span class="me1">left</span>, rc.<span class="me1">top</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; columns, rows,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; HDC<span class="br0">&#40;</span> m_dib <span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span>, <span class="nu0">0</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; SRCINVERT <span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">BitBlt<span class="br0">&#40;</span> di.<span class="me1">hdcDraw</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; rc.<span class="me1">left</span>, rc.<span class="me1">top</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; columns, rows,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; hdcMask,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span>, <span class="nu0">0</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; SRCAND <span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">BitBlt<span class="br0">&#40;</span> di.<span class="me1">hdcDraw</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; rc.<span class="me1">left</span>, rc.<span class="me1">top</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; columns, rows,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; HDC<span class="br0">&#40;</span> m_dib <span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="nu0">0</span>, <span class="nu0">0</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; SRCINVERT <span class="br0">&#41;</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p>
<center>Figure 13 - Performing the transparent draw</center>
</td>
</tr>
</table>
<p></center></p>
<h4>Details, Details.</h4>
<p>Developing controls with the ATL isn't quite as easy as with MFC, and we've left out some of the details of finalizing the implementation of our control. The details are covered briefly below and can be clarified by downloading and browsing the source.</p>
<p>Controls need to implement two additional interfaces to work effectively in the Web environment: IPersistPropertyBag and IObjectSafety. The IPersistPropertyBag interface allows a control and its container to work together to provide textual persistence. The older control persistence mechanism uses IPersistStreamInit, through which the container treats a controls properties as a stream of bytes. With IPersistPropertyBag, a control’s properties can be saved in an HTML-friendly format. Implementing IPersistPropertyBag is easy with ATL, just include IPersistPropertyBagImpl in your derivation.</p>
<p>A Web-enabled control implements IObjectSafety to inform its container that potential users cannot use it for malicious behavior. In other words, the control does not expose any functionality through which a user could harm the local system. Implementing IObjectSafety is only slightly more difficult, and this is because ATL's version of IObjectSafetyImpl doesn't work correctly. Instead of deriving directly from IObjectSafetyImpl, you derive from IObjectSafety and provide implementations for its two methods: GetInterfaceSafetyOptions() and SetInterfaceSafetyOptions().</p>
<p>Another important aspect of a Web-based implementations is that of control signing. An ActiveX control is really just a Windows DLL and so can easily corrupt (especially if the developer is trying to) a user's system. Microsoft's approach to dealing with this is possibility is to let you, the user, decide which ActiveX controls you choose to trust. Trust is handled by ensuring that each control is developed and distributed by a known entity. To be downloaded and installed on a user’s machine, a control must be digitally signed by such a known entity. To obtain a digital signature, just browse to www.verisign.com and agree to hand over your first born child (and $20.00). The rest is easy.</p>
<h4>The final product</h4>
<p>Since this is an ActiveX control, we can not only use it in our desktop applications, but in our Internet Applications as well.  For a quick demo, we've set up an HTML page on Tom's web site that uses this control to display some transparent BMP files.  You can view the control with either Internet Explorer or Netscape Navigator (with NCompass Lab's ScriptActive plug-in) by following this link to <del>www.widgetware.com</del>, (<i>mn: sorry, this site is no longer functional</i>) and looking in the table of contents.</p>
<p>You can still use our control verbatim in your Windows applications, as long as your framework supports control containment.  Fortunately, this includes the current releases of nearly all Windows development tools. But fear not, if you want to avoid the rigors of being an ActiveX user, you should still be able to take the old-fashioned approach to re-use by cutting and pasting our drawing code directly into your application. Sometimes the old ways are still best ways!</p>
<h4>Project Files</h4>
<p><center><br />
<table>
<tr>
<td>Project Source</td>
<td><a HREF="http://marknelson.us/attachments/1998/transparent-atl-controls/trans.zip">trans.zip</a></td>
</tr>
<tr>
<td>The actual control</td>
<td><a HREF="http://marknelson.us/attachments/1998/transparent-atl-controls/TransparentControl.dll">TransparentControl.dll</a></td>
</tr>
<tr>
<td>The necessary runtime ATL DLL</td>
<td><a HREF="http://marknelson.us/attachments/1998/transparent-atl-controls/atl.dll">atl.dll</a></td>
</tr>
</table>
<p></center></p>
]]></content:encoded>
			<wfw:commentRss>http://marknelson.us/1998/03/01/transparent-atl-controls/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

