Friday, July 15, 2005

Speed freaks...

I've been working for a client who had a Win32 based application that did some graphics creation tasks for a consumer product. They wanted to update the look and feel of the program and hired someone to create a new application for them. This engineer did a pretty good job but, through lack of personal funds and the availability of a freebie, wrote the application using the C# express beta for C#2.0.

The customer took delivery of the partial code and then discovered that to release it to their customers they'd have to back-port it to .NET version 1.1 and finish up the program. Because of the highly graphical nature of the application and because the original implementation was rather slow they asked me to pep it up a bit.

After solving many of the drawing issues and getting the application up and running we got to the stage where people were installing it to test and everyone who saw it was horrified at the startup time. Some machines saw a 35 second wait between the initial first click and the appearance of the application window. They had never seen a fat .NET app before.

There were two problems with the whole scenario. First, the cycle was to install a new copy of the app, to click the application icon and sit there with a stopwatch waiting for something to appear. This meant that every time they saw it it was going through the process of creating the native image copy for the application cache. Secondly, even though the application had a splash screen this was a part of the application that needed JIT compiling too so often it didn't appear for some time. This encouraged the user to click a second time.

To solve these problems I've tried two things. To make the splash screen appear instantly I wrote a small program launcher that just displayed the desired image and then used Process.Start to launch the real program. This gives the user the feeling that something is happening and discourages them from clicking the icon again and again. Secondly I wrote a custom installer clas that used ngen, the .NET framework native image generator, to create the native-code compiled version of the program at install time. This meant that the first run of the code already had the native image in the cache and reduced load times to the barest minimum. On a test machine I got the load time from 30 seconds down to 6 seconds total using this method.

Sunday, June 19, 2005

Duality of purpose.

I find myself embarrased at times when answering questions in the various forums I hang out in. On occasion, I find myself with no other answer than "Buy the tool I created to do that".

This sometimes seems to be mercenary and is not well recieved by the users of the forum. Last year I practically gave up offering advice in a VB forum because the people who frequented it thought that the only reason I was there was to tout my wares.

To be honest, I always hesitate to answer "if you're interested in a commercial solution..." and think more than twice about posting a link to my business site but recently I've begun to wonder why people are so anti a good solution.

Looking at the situation logically, the kinds of questions I answer with a commercial offering are the ones that would start out with "Well, you need to build yourself a small nuclear power station. First mine some uranium and then..." followed by a couple of pages of complex overview. These are not trivial questions then and hence have no trivial answer.

What I really don't understand is when someone pops up on line and demands a FREE-SOURCE-CODE-INCLUDED tool that does just exactly what they want and moans like the clappers if someone suggests they should pay a few bucks registration fee or even buy a developer license

Work is money and money is work. If someone is faced with a weeks work figuring out how to do a specific task and can get the answer for a thirty buck registration fee then how can they be so indignant when someone says "Ok, I'll save you a weeks worth of finding out how to do this yourself in exchange for the cost of one hour of your precious time.

If it were me, and it frequently has been, I'd jump at the chance and register there and then. Then again, like my dad says "Theres nought so strange as folk"

Wednesday, April 20, 2005

GPS Software

I recently purchased a GPS system for my car. The hardware is a Windows CE device running dedicated software from the German Navigon company. This little box of tricks will plan routes for you and speaks instructions such as "At the next junction, turn right" or "Leave the roundabout at the third exit".

In itself, the machine is an excellent companion to anyone who needs door-to-door driving instructions with intelligent route planning and re-planning if you, despite all the instructions, take a wrong turn or end up on a detour that closes the roads the machine thinks you should be taking.

What makes this, in my opinion, the greatest thing since sliced bread is Navigon's customer support service. I had a problem with my machine that was my own fault and contacted Navigon to see if I could fix the problem. I fully expected to have to pay for the fix but Navigon exchanged a few e-mails and have fixed me up like new.

So many companies these days make you jump through hoops and do as much as possible to place the blame for the fault on the purchaser to save money on support. Navigon's excellent customer support policies were a real breath of fresh-air.

Thursday, April 14, 2005

More printer ink thoughts


After printing a 1000 page PDF file I decided that the printer ink situation should be resolved once and for all.



I wrote this article to show how to refil Epson TO452, TO453, TO454 and TO441 cartridges.


Friday, March 25, 2005

Serif fonts.

I have developed an aversion to serif fonts such as Times New Roman. For preference I use Verdana which has subtle differences from Arial or MS Sans-Serif and which I think is a far more readable typeface.
Arial is a slightly cramped typeface that has connotations of a serif font particularly because of the lower case "a" which I find to stand out almost as though it was purposefully created in a different style from the rest of the font.
Verdana has an open style which is far better proportioned and the "a" fits right in with the rest of the font as if it belongs.
Times is a very cramped typeface, this paragraph is the same point size as the Verdana above but you must agree is not nearly as easy on the eye. It reminds me of cheap paperback books and seems to lower the quality of the text. I know it's almost a 'traditional' font but I do wish that it wasn't the default for everything.
Georgia is Verdana's serif cousin and is more open and readable so as a compromise I tend to use it when serif fonts are required.
For me, Verdana is the queen of fonts.

Unsafe isn't

I've noticed that many programmers seem to have an irrational fear of the "unsafe" keyword in C#. It's almost as though they are afraid that if they use it in their code then program will turn into a Frankenstiens Monster and leap opon them in their sleep.
Unsafe refers only to the fact that the code might reference unmanaged and hence non type-safe code. Not that one is taking a calculated risk by using it.
Personally, I only use unsafe where the highest performance is required and I don't want anything to intervene between my code and the bytes it's working on. In most of my puplicly available examples these days I use the Marshal class because it enables me to create code in C# which is readily translated to VB. This is of course just my lazy nature and not a fear of the evil that may befall me if I use that dreaded keyword.

Monday, March 14, 2005

Turn the world on it's head!

Today I have had a bit of a shock. In response to a newsgroup posting I decided to update my article on generating 1 bit per pixel images from 24bpp colour. The original article used a mixture of Bitmap.GetPixel and LockBits to determine the pixel brightness and write the single bit pixel to the image array and I had decided to convert this to a LockBits solution on both sides of the equation for the sake of completeness.
I re-wrote the C# code so that instead of using unsafe pointers it used the Marshal class to read and write the bytes. This made the code identical in function to the VB conversion. After testing the C# code I did a quick conversion to VB and wran the two applications on the same image.
I noticed that the VB application seemed to be faster so I added a diagnostic routing to time how long the central part of the loop, the one that actually does the conversion, took. To make sure the code had a good chunk of data to work with I used an image that was 4000*3200 pixels.
To my great surprise the VB code is consistently faster by over three seconds with the C# doing the loop in around eight seconds and the VB running the functionally identical code in only five.
I have seen instances before where the VB compiler was demonstrably better at generating code than the C# one but have never seen it so clearly shown to be superior at simple tasks than the C# compiler.
The timed code is shown in both C# and VB here:
C#
DateTime dt=DateTime.Now;

//scan through the pixels Y by X
int x,y;
for(y=0;y {
for(x=0;x {
//generate the address of the colour pixel
int index=y*bmdo.Stride+(x*4);
//check its brightness
if(Color.FromArgb(Marshal.ReadByte(bmdo.Scan0,index+2),
Marshal.ReadByte(bmdo.Scan0,index+1),
Marshal.ReadByte(bmdo.Scan0,index)).GetBrightness()>0.5f)
this.SetIndexedPixel(x,y,bmdn,true); //set it if its bright.
}
}

//tidy up
bm.UnlockBits(bmdn);
img.UnlockBits(bmdo);

//show the time taken to do the conversion
TimeSpan ts=dt-DateTime.Now;
VB
'for diagnostics
Dim dt As DateTime = DateTime.Now

'scan through the pixels Y by X
Dim y As Integer
For y = 0 To img.Height - 1
Dim x As Integer
For x = 0 To img.Width - 1
'generate the address of the colour pixel
Dim index As Integer = y * bmdo.Stride + x * 4
'check its brightness
If Color.FromArgb(Marshal.ReadByte(bmdo.Scan0, index + 2), Marshal.ReadByte(bmdo.Scan0, index + 1), Marshal.ReadByte(bmdo.Scan0, index)).GetBrightness() > 0.5F Then
Me.SetIndexedPixel(x, y, bmdn, True) 'set it if its bright.
End If
Next x
Next y
'tidy up
bm.UnlockBits(bmdn)
img.UnlockBits(bmdo)

'show the time taken to do the conversion
Dim ts As TimeSpan = dt.Subtract(DateTime.Now)
I'll have to compare the IL for the two compiled sections to see where the C# compiler fails to get that extra few ergs.

Friday, March 11, 2005

Does there have to be a reason?

I am a proponent of wordy explanations but there are some times when a simple and definitive answer should be taken at face value and not questioned.

Children often ask "Daddy, what would happen if I were to poke my tongue in the electrical outlet?" wherupon daddy will reply "You'll die a horrible and painful death son". This should be enough of an answer and should be heeded by all small boys.

When a programmer asks "Can I store the Graphics object?" the answer is "No!". This is one of those definitive answers that is usually questioned but which always ends up being "No!" however many times or in however many different ways it's asked.

Just to recap....

Do not store the Graphics object. Do not store it in a local variable, a static variable, a shared variable, an object, a structure or a database. Do not put it in an envelope and post it to your aunt, do not draw a picture of it, do not photocopy it, do not have Monet make a painting of it.
Do not put it in your pocket for later, do not hash encode it and e-mail it to the CIA, do not put it on a Post-it note and stick it to your screen, do not grind it into powder and sniff it up your nose with the other stuff you just had. In short....

DO NOT STORE THE GRAPHICS OBJECT!

Saturday, February 12, 2005

Falling in love again.

I have always been a "client side" kinda guy. Most of the work I do is fairly heavy graphics code and I'm reasonably good at problem solving when I can sit down in front of a good algorithm and bash out some code.
I am forced through circumstance to do work in HTML and I generally use FrontPage for my web site work but I can honestly say that HTML and presentation stuff of that nature is BORING BORING BORING so I tend not to put as much effort into it as I normally do my other work. I find that this reluctance is also affected by the fact that it's so dammned complicated to get a web site to do anything at-all interesting and the mix of script and the hokey way it fits into HTML coupled with the truly abysmal debugging options one has for working with it means that I do the minimum possible to make my sites work.
Up until recently, I had hosted my sites on cheap servers that didn't offer ASP.NET services so I was stuck with whatever active stuff I could be bothered to learn in the JavaScript fashion. About a year ago however I moved BobPowell.NET to a server at Brinkster because they had much more bandwidth than the godaddy servers I had been on before.
Now, I'm a great believer in "If it ain't broke, don't fix it!" so I have used the brinkster service as a high bandwidth home for my old site and not made that many changes to it. Within the last few weeks however I have got back into using ASP.NET beause I'm writing a complete licensing, support and customer management package for XRay tools. Of course, I knew how this all worked from a theoreical standpoint and had done lots of sample stuff on ASP.NET but never sat down to write an end-to-end application in it.
Well folks, I'm in love. What an excellent way to create an application. It has all the visual afdvantages of HTML with all the algorithmic advantages of client-side work. I can write my web-site in the same way that I'd write a Windows Forms application and it works so well!
I'll definitely be putting LOTS more active stuff on my sites from now on. GO ASP+!!!

Friday, February 11, 2005

Bitmap manipulations.

I keep having online conversations with people who bemoan the fact that their computers have a spot of bother dealing with images with pixel counts of 10,000 * 8,000 or 13,000 * 18,000. They complain that the image scrolls slowly and they can't drag an image about but they obviously haven't the faintest idea of the implications of such an image.

One bright spark complained of the poor performance of an image having 13000 by 18000 pixels so I sat and did a little calculation which, I think, brings home just how much information is stored in such an image.

13000 * 18000 is 234000000. Multiply this by 4 for the bit depth of images stored in memory on the computer and you get 936000000 (936 million). Ok, A page of type in a programmere reference book runs out at about 88 characters by 36 lines. Thats 3168 characters per side and 6336 for a single sheet of paper.

On my bookshelves I have several books over 1000 pages in length and a thousand page book works out to be somewhere in the region of two inches thick. Our 6336 characters goes into 936000000 about 147727 times. This means a book with 148 thousand pages, 2 inches per thousand remember, is 24.6 feet thick.

Now I don't have many bookshelves in my house that are 25 feet long but if I had one I'd know that that was one fat book!

Even given the power of todays computers that's one huge chunk of info to mess around with. Why don't people understand that before they start whining about the scrolling performance of their image viewer application?

Friday, January 14, 2005

Still alive and kickin'

You may ask yourself "What the heck is that Bob Powell up to these days?" It's true that I've not paid attention to the Blog much because my work has just gone crazy and I've had months of pretty intense stuff going on and no time to report on other things.

I'm writing a book. This is not too surprising I suppose but what will really blow your socks off is that it's a book for Visual Basic programmers.

As a self-promoting guru I get vast amounts of mail from people who ask for help on every subject, not just Graphics, and I have seen a dire need for a book that explains how to create a correctly object-oriented architecture for VB users. So many people come from the VB6 world and discover that although VB.NET is syntactically similar the principles of software architecture in an object-oriented system such as .NET is a mystery. Consequently they make the most fundamental mistakes and create truly horrible applications that are beset with faults.

The book is entitled "Object Oriented Programming for .NET" and is presented in both VB and C# but with the emphasis on the VB angle.

The "day job" is keeping me well employed doing exiting things with public-address advertizing systems. I must say that there is rarely a boring day.

Keeping an amount of churn in the GDI+ FAQ and Windows Forms Tips and Tricks also puts a load on.

Finally WellFormed is on my list of important items and I'm working on a new system that will deliver content to subscribers via the web. I originally hosted the service with a provider who shall remain nameless but which SUCKED! and cost me too much money and time. Now WellFormed.NET is on Brinkster but the application that serves the content is even more work for my thinly spread working day. I have a prelim version working but it has bugs that I just don't have time to chase at this second.

I suppose being over-employed is better than being under-employed :-)