Project Resistance: Transparency in the Compact Framework sucks

Alex made some headway over the weekend on Project Resistance with the ResistorView and doing some drawing.  Now (on the WinMo classic emulator) it looks like this:



Notice the white border around the bands.  Nicely enough, Alex gave me a bug item for this, so I started looking at it this morning, thinking that maybe the images simply have some non-transparency problem along the edges.  Well, not so simple.  Here’s a close up (using Paint.NET if you’re curious) along the right edge of a Ring1 Yellow band (the one used for generating this view):


 



You can see that there’s nothing wrong here.  What appears to be happening is that pixels with partial transparency (or partial opacity if you’re a glass-half-empty kind of person) are getting incorrectly rendered as white.  So now we’re off to chase down a redering problem instead of spending time developing logic for our actual business problem.  My off-the-cuff guess is that it’s because we’re storing the bands as a Bitmap class, which probably has no notion of an alpha channel, and therefore is just replacing these pixels with white.


It’s worth noting that just getting this far with drawing has been heavily reliant on non-CF classes, and if my guess on the Bitmap being the problem is corrrect it means that even more of the drawing code will rely on objects not in the CF.  Again, this exemplifies the pain of creating WinMo apps that have the aethetics users have come to expect since iPhone came on the scene.

11 Comments

  1. Hi Chris,

    You probably have already figured this out, but unfortunately in order to get that kind of alpha blending in .net cf you are going to have to use the IImage and IImagingFactory COM interfaces. All of the built in .net cf APIs for dealing with images will not load the alpha channel, which means you have to resort to these COM objects instead. This is indeed a very painful part of WinMo development.

  2. @mse: I’ve seen the library, but not played with it.

    @tim & joel: The IImage stuff is already part of the SDF, and it’s already heavily in use in this project. It’s how we achieved the trasparency of the blank over the background. The issue is actually slightly different here – this has to do with the way Graphics.Clear(Color.Transparent) actually fills with *white* not transparent (that certainly smells like a bug to me).

  3. Yeah, I came in here to post about IImagingFactory too, but if that’s not the problem, it’d be great if you could post a version of the source that succinctly demonstrates the issue and we can look at it.

  4. The source code is all fully public over on the CodePlex site, and it’s about as simple as it gets. I believe Alex already has worked around the bug (though not checked that fix in). For now I’ve opted to chase other functionality that needs to be completed.

  5. Sorry, I looked at "downloads" on codeplex and saw nothing there. Having now looked, I see what you mean. However, it’s because CF doesn’t support alpha blending as such, so creating a bitmap and filling it with Transparent doesn’t work when it comes to blending with it. You have a few options, firstly – to demonstrate, if you were to swap the g.clear call with a double nested loop (for x & y) and call

    bmp.SetPixel (x, y, Color.FromArgb (0×00000000));

    on each (I did try and post the loop code, but my post got rejected), you’ll see that it now works since I’m setting the alpha bit to 0 directly. However, it’s a bit rubbish (and slow), so I’d be tempted to create a fully transparent blank image in the same way as you’ve done your bands and then load it and blend with that. Alternatively, the best way (and probably what Alex has done), is to simply blend the bands directly onto the image of the blank resistor in the first place and side step the issue.

  6. @Andy – That may work, but I can’t see ever performaing operations on one pixel at a time through GDI. I get the feeling the overhead of making the function call would exceed the time it took for the function to actually do it’s work. About the only time I do pixel-by-pixel manipulations is when I’m doing some form of image processing. And in those cases I use pointers (significantly faster but I need not speak of the dangers of pointers).

  7. Yes, I didn’t suggest it as a solution (I said it was rubbish & slow), but I was simply demonstrating the difference in setting the alpha bit directly, in the clearest fashion. I would expect some kind of resistance (hoho!)

Leave a Reply