Introduction
On my first blog I promised of Part II. Here is the Part – II. We shall look deep
inside into the AlphaImage Control here.
The first problem is: .NET CF does not support image transparency. So, when ever
we ask for transparent color it is translated as white. To add to this the gif images
with transparent background won’t work here.
AlphaMobileControls has a control “AlphaPictureBox” which derives from AlphaControl.
If we use this one then it would fix the transparency prolem.
How to use
Just place an alphapicturebox control to your form. At the constructor of the form
set the image that would be displayed in the picture box:
alphaPictureBox1.Image = AlphaImage.CreateFromResource("mConcierge.Resources.backgroundNormal.jpg");
You are done. If you need backgroung transparency then the image shound a normal
background transparent gif.
What’s happening Inside
The image property that is exposed by AlphaPicture box is a AlphaImage.
This Alpha Image is created form a normal image.
public static AlphaImage CreateFromStream(MemoryStream stream)<br>
{<br>
PlatformAPI.IImaging.IImagingFactory factory = CreateFactory();<br>
AlphaImage alphaImage = new AlphaImage();<br>
byte[] pbBuf = stream.GetBuffer();<br>
uint cbBuf = (uint)stream.Length;<br>
factory.CreateImageFromBuffer(pbBuf, cbBuf, PlatformAPI.IImaging.BufferDisposalFlag.BufferDisposalFlagNone,
out alphaImage._image);<br>
}
IImagingFactory interface defines native (COM) OS operations as shown below:
[ComImport, Guid("327ABDA7-072B-11D3-9D7B-0000F81EF32E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]<br>
[ComVisible(true)]<br>
public interface IImagingFactory<br>
{<br>
uint CreateImageFromStream(IStream stream, out IImage image);<br>
uint CreateImageFromFile(string filename, out IImage image);<br>
uint CreateImageFromBuffer([MarshalAs(UnmanagedType.LPArray)] byte[] buffer, uint
size, BufferDisposalFlag disposalFlag, out IImage image);<br>
uint CreateNewBitmap(uint width, uint height, PixelFormatID pixelFormat, out IBitmapImage
bitmap);
uint CreateBitmapFromImage(IImage image, uint width, uint height, PixelFormatID
pixelFormat, InterpolationHint hints, out IBitmapImage bitmap);
uint CreateBitmapFromBuffer(BitmapData bitmapData, out IBitmapImage bitmap);
uint CreateImageDecoder();
uint CreateImageEncoderToStream();
uint CreateImageEncoderToFile();
uint GetInstalledDecoders();
uint GetInstalledEncoders();
uint InstallImageCodec();
uint UninstallImageCodec();
}
Rest of things are Pretty simple. As alphapicturebox controls derives from alphacontrol
base class, it overrides the draw method of alphacontrol. This inturn calls draw
method of alphaimage. Draw method inside alpha image draws the image on the form
calling a COM function as defined here :
[ComImport, Guid("327ABDA9-072B-11D3-9D7B-0000F81EF32E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComVisible(true)]
public interface IImage
{<br>
uint GetPhysicalDimension(out Size size);
uint GetImageInfo(out ImageInfo info);
uint SetImageFlags(uint flags);
uint Draw(IntPtr hdc, ref Rectangle dstRect, IntPtr srcRect);<br>
uint PushIntoSink();
uint GetThumbnail(uint thumbWidth, uint thumbHeight, out IImage thumbImage);
}
Sleepless Nights
The shock came to me when I was planning for a party. My application started to
get excetions when I was navigating through the forms. I reached everywhere for
a solution but it took long time to find one from codeplex.
The problem is because a managed array is passed to the COM object. Once the garbage
collector decides to free/move this array all hell break loose.
Here’s a fix:
In IImagingFactory.cs, replace:
uint CreateImageFromBuffer([MarshalAs(UnmanagedType.LPArray)] byte[] buffer, uint
size, BufferDisposalFlag disposalFlag, out IImage image);
With:
uint CreateImageFromBuffer(IntPtr buffer, uint size, BufferDisposalFlag disposalFlag, out IImage image);
In AlphaImage.cs add this in the top of the file:
using System.Runtime.InteropServices;
And replace:
factory.CreateImageFromBuffer(pbBuf, cbBuf,BufferDisposalFlag.BufferDisposalFlagNone,
out alphaImage._image);
With:
once image is decoded<br>
IntPtr p = Marshal.AllocHGlobal((int)cbBuf);
Marshal.Copy(pbBuf, 0, p, (int)cbBuf);
factory.CreateImageFromBuffer(p, cbBuf, BufferDisposalFlag.BufferDisposalFlagGlobalFree,
out alphaImage._image);
The code and the controls could be here
here