📜 ⬆️ ⬇️

Compact Framework: Facets of Transparency

Introduction


Unfortunately, developers of the Compact Framework, and the native functions too, do not support the alpha channel with different transparency of individual pixels. This means that it is not possible to create indescribable beauty with smooth transitions between images. However, what to do if you want to have at least a kind of “full” alpha channel, namely, to display translucent images that also have completely transparent sections?

Consider two ways to display images with transparency.

Method number 1. Fixed color is transparent


public static void DrawImageTransparent( Graphics g, Bitmap b, Point location, Color transColor)
{
if (b == null || g == null )
return ;

ImageAttributes attrib = new ImageAttributes();
attrib.SetColorKey(transColor, transColor);

Rectangle destRect = new Rectangle(location.X, location.Y, b.Width, b.Height);

g.DrawImage(b, destRect, 0, 0, b.Width, b.Height, GraphicsUnit.Pixel, attrib);
}


* This source code was highlighted with Source Code Highlighter .

')
It is worth noting that only this tricky version of DrawImage allows you to display an image with the specified ColorKey, which determines which pixels should not be drawn. Elegant set of parameters, is not it? :) Where to draw, we ask through Rectange, and from where - through 4 parameters. Well, this is me, a lyrical digression towards Microsoft.

Actually, DrawImageTransparent is the main way to draw images with transparent pixels. However, the minus of this method is obvious, there are only two states of transparency: completely transparent and completely opaque.

Example:
transparent pixels

In fact, quite well, you can stop at this. But I want something more :)

Method number 2. The entire image has a fixed opacity


In this case, without DllImport is not enough, we will prepare everything that is necessary for this:

public struct BlendFunction
{
public byte BlendOp;
public byte BlendFlags;
public byte SourceConstantAlpha;
public byte AlphaFormat;
}

public enum BlendOperation : byte
{
AC_SRC_OVER = 0x00
}

public enum BlendFlags : byte
{
Zero = 0x00
}

public enum SourceConstantAlpha : byte
{
Transparent = 0x00,
Opaque = 0xFF
}

public enum AlphaFormat : byte
{
AC_SRC_ALPHA = 0x01
}

public class PlatformAPI
{
[DllImport( "coredll.dll" )]
extern public static Int32 AlphaBlend( IntPtr hdcDest, Int32 xDest, Int32 yDest, Int32 cxDest, Int32 cyDest, IntPtr hdcSrc, Int32 xSrc, Int32 ySrc, Int32 cxSrc, Int32 cySrc, BlendFunction blendFunction);
}


* This source code was highlighted with Source Code Highlighter .


As you can see, everything that can be truncated is truncated - in the enum by one parameter, etc. But nevertheless, we continue. Actually, our function:

public static void DrawAlpha( Graphics g, Bitmap b, Point location, byte opacity)
{
if (b == null || g == null )
return ;

using ( Graphics gxSrc = Graphics .FromImage(g))
{
IntPtr hdcDst = g.GetHdc();
IntPtr hdcSrc = gxSrc.GetHdc();
BlendFunction blendFunction = new BlendFunction();
blendFunction.BlendOp = ( byte )BlendOperation.AC_SRC_OVER;
blendFunction.BlendFlags = ( byte )BlendFlags.Zero;
blendFunction.SourceConstantAlpha = opacity;
blendFunction.AlphaFormat = ( byte )0;
PlatformAPI.AlphaBlend(hdcDst, location.X, location.Y, b.Width, b.Height, hdcSrc, 0, 0, b.Width, b.Height, blendFunction);
g.ReleaseHdc(hdcDst);
gxSrc.ReleaseHdc(hdcSrc);
}
}


* This source code was highlighted with Source Code Highlighter .


Small comments on the code - the parameters of the BlendFunction cannot be changed, they are put down the only possible ones. It's a shame, but nothing to do.

Example:

alpha blend

Scary, huh? Nasty purple pixels have not gone away, and also became a bit transparent: (

Combined use of both methods


Unfortunately, we have few combination options. At first glance, they are not at all :) But there is still one way.

So, the solution is as follows. Since we can’t simultaneously set a ColorKey and call AlphaBlend , we’ll use them one by one. First we will draw the background with a standard sposb without frills, then the button with the first sposb, and at the end ... we draw the second sposb over the background with a small opacity coefficient!

g.DrawImage(background, 0, 0);
DrawImageTransparent(g, button, new Point(10, 10), Color.FromArgb(255, 0, 255));
DrawAlpha(g, background, new Point(0, 0), 75);


* This source code was highlighted with Source Code Highlighter .


Result:
alpha and pixel transparency

The method described above is quite viable. I use it and I am completely satisfied with the speed of work - on drawing of all interface elements in a similar style, it takes an average of 60 to 80 milliseconds (tested on various devices). To create an application in this style, of course, standard controls will not work, but who promised it would be easy? In any case, to create indescribable beauty without its own framework for rendering graphic elements is indispensable.

Source: https://habr.com/ru/post/44327/


All Articles