Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: GDI on Win32 vs Win64


This question is answered.


Permlink Replies: 6 - Last Post: Mar 4, 2016 3:36 AM Last Post By: David Millington
Richard Zarr

Posts: 74
Registered: 7/1/98
GDI on Win32 vs Win64  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 2, 2016 12:49 PM
We have a video overlay processing class that adds motion detection and other features to a video window. We have noticed that the behavior between GDI on Windows 32 bit is different than 64 bit. We are using a TBitmap with the pixel format set to pf32bit knowing the alpha channel is in the MSB. In our 32 bit deployment, the overlays (using AlphaBlend) work perfectly. When we deploy to a 64 bit machine, we lose most of the GDI specific functions such as TextOut (they are now transparent). We've somewhat traced the problem to a difference on how Windows handles the alpha channel between both versions.

Question: Is there a definitive document that shows how GDI behaves in both Win32 and Win64 environments? Or, does anyone have specifics from experience on how to correct the issue.

Our initial step was to set the alpha channel to $FF and anywhere the GDI wrote $00, we fixed it using the ScanLine feature of the bitmap. This works for the 32 bit version of windows, but seems to partially work or fail on 64 bit. We need to look closer on why some of our overlays continue to partially work (incorrect opaque-ness.. changes colors, not transparency) and others are missing (transparent now). Any insight is greatly appreciated.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: GDI on Win32 vs Win64
Helpful
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 2, 2016 1:26 PM   in response to: Richard Zarr in response to: Richard Zarr
Richard wrote:

We are using a TBitmap with the pixel format set to pf32bit knowing the
alpha channel is in the MSB. In our 32 bit deployment, the overlays (using
AlphaBlend) work perfectly. When we deploy to a 64 bit machine, we lose
most of the GDI specific functions such as TextOut (they are now transparent).

MOST GDI functions do not support an alpha channel at all. If you draw
on a 32bit bitmap, they will set the alpha channel to 0, thus making things
like text render transparently. When dealing with GDI, you should use a
24bit bitmap instead, and then you can upgrade/copy it to a 32bit bitmap
to set its alpha channel as needed.

--
Remy Lebeau (TeamB)
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: GDI on Win32 vs Win64
Helpful
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 2, 2016 1:29 PM   in response to: Richard Zarr in response to: Richard Zarr
Richard wrote:

In our 32 bit deployment, the overlays (using AlphaBlend) work perfectly.

Also, are you pre-multiplying the bitmap correctly on 32bit and 64bit before
calling AlphaBlend()? If not, you can get side effects.

--
Remy Lebeau (TeamB)
Richard Zarr

Posts: 74
Registered: 7/1/98
Re: GDI on Win32 vs Win64  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 3, 2016 7:29 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
Richard wrote:

In our 32 bit deployment, the overlays (using AlphaBlend) work perfectly.

Also, are you pre-multiplying the bitmap correctly on 32bit and 64bit before
calling AlphaBlend()? If not, you can get side effects.

--
Remy Lebeau (TeamB)

Can you be more specific with the above statement? We are doing much of the processing in a linear frame buffer (W x H x 4 bytes). We then copy the buffer to a bitmap for rendering via the ScanLine() property. Can you elaborate? We do see some strange artifacts where colors are changing where they should not on Win64 (but not on Win32).
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: GDI on Win32 vs Win64
Correct
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 3, 2016 9:56 AM   in response to: Richard Zarr in response to: Richard Zarr
Richard wrote:

Can you be more specific with the above statement?

You do know that you have to pre-multipy the pixel values before you can
successfully alpha-blend them, don't you?

BLENDFUNCTION structure
https://msdn.microsoft.com/en-us/library/windows/desktop/dd183393.aspx

AlphaFormat
This member controls the way the source and destination bitmaps are interpreted.
AlphaFormat has the following value.

AC_SRC_ALPHA
This flag is set when the bitmap has an Alpha channel (that is, per-pixel
alpha). **Note that the APIs use premultiplied alpha, which means that the
red, green and blue channel values in the bitmap must be premultiplied with
the alpha channel value**. For example, if the alpha channel value is x,
the red, green and blue channels must be multiplied by x and divided by 0xff
prior to the call.

Premultiplied alpha
http://blogs.msdn.com/b/shawnhar/archive/2009/11/06/premultiplied-alpha.aspx

Premultiplied alpha and image composition
http://blogs.msdn.com/b/shawnhar/archive/2009/11/07/premultiplied-alpha-and-image-composition.aspx

--
Remy Lebeau (TeamB)
Richard Zarr

Posts: 74
Registered: 7/1/98
Re: GDI on Win32 vs Win64  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 3, 2016 11:50 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
Richard wrote:

Can you be more specific with the above statement?

You do know that you have to pre-multipy the pixel values before you can
successfully alpha-blend them, don't you?

BLENDFUNCTION structure
https://msdn.microsoft.com/en-us/library/windows/desktop/dd183393.aspx

AlphaFormat
This member controls the way the source and destination bitmaps are interpreted.
AlphaFormat has the following value.

AC_SRC_ALPHA
This flag is set when the bitmap has an Alpha channel (that is, per-pixel
alpha). **Note that the APIs use premultiplied alpha, which means that the
red, green and blue channel values in the bitmap must be premultiplied with
the alpha channel value**. For example, if the alpha channel value is x,
the red, green and blue channels must be multiplied by x and divided by 0xff
prior to the call.

Premultiplied alpha
http://blogs.msdn.com/b/shawnhar/archive/2009/11/06/premultiplied-alpha.aspx

Premultiplied alpha and image composition
http://blogs.msdn.com/b/shawnhar/archive/2009/11/07/premultiplied-alpha-and-image-composition.aspx

--
Remy Lebeau (TeamB)

OK... this provides some insight to what we are seeing. We didn't realize the interrelationship between the RGB values and the alpha channel when used for transparency. Sounds like we need to add some additional math to the overlays. What seems strange is that this issue doesn't appear in Windows 32 bit OSs. Only the 64 bit versions. We are setting the blend function like this:

 // setup the alpha blending levels
 FOverlayAlphaLevel := DEF_ALPHA_LEVEL;
 FOverlayOpacity := DEF_OPACITY_LEVEL;
 // create the alpha blending function
 FAlphaBlend.BlendOp := AC_SRC_OVER;
 FAlphaBlend.BlendFlags := 0;
 FAlphaBlend.SourceConstantAlpha := FOverlayAlphaLevel;
 FAlphaBlend.AlphaFormat := AC_SRC_ALPHA;  // source has alpha channel


The SCA is updated in a SetOverlayAlphaLevel(value : byte) routine and the alpha blend is done like this:

   AlphaBlend(
    Canvas.Handle,          // destination canvas handle
    0, 0,                   // destination upper left corner
    Width, Height,          // destination Width & Height
    FOverlayMotion.Canvas.Handle, // source canvas handle
    0, 0,                   // source upper left corner
    Width, Height,          // source Width & Height
    FAlphaBlend             // alpha blending function record
   );


Works absolutely perfectly on Win32... but fails to render correctly on Win64. The other issue is that GDI doesn't support alpha (works on Win32, draws transparent on Win64), so we're thinking we need to do the following:

1) Change all overlay bitmap (there are several and could be more) pixel formats to pf24bit.
2) Pre-fill overlay bitmaps with black (0x000000) as required - some algorithms fill the entire frame while processing. This would provide a "transparent" window (excludes black as a color option - work around use 0x010101)
3) Draw on overlay bitmaps as before (GDI, ScanLine access, etc.) - no change required here...
4) use pre-instantiated intermediate 32 bit overlay bitmap to copy 24 bit source overlay data (need help here - need a fast way to do this).
5) using fixed alpha levels, pre-multiply values to create the correct overlay image (correct alpha and RGB values)
6) AlphaBlend() intermediate 32 bit image with correct values with display bitmap

maybe steps 4 & 5 can be combined into a single operation (using ScanLine access). The motion vector analysis is done as frequently as 30 times a second... so processing efficiency is paramount! We may provide an option to skip frames to lighten the load... still debating that.
David Millington

Posts: 257
Registered: 5/29/05
Re: GDI on Win32 vs Win64  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 4, 2016 3:36 AM   in response to: Richard Zarr in response to: Richard Zarr
I'm surprised you're seeing it work correctly on Win32 and not on
Win64, since the requirement for premultiplying is the same on both
platforms.

If you are interested in a Delphi implementation of blending,
premultiplying, etc, check out TTransparentCanvas. You don't have to
use the library - there are a number of blog posts explaining how it
works, which you can read and use as a guide. Blog links are at the
bottom of this page:
https://parnassus.co/open-source/ttransparentcanvas/

TTransparentCanvas itself is used for drawing semitransparent shapes,
text, "glow" text etc easily. It's not quite so necessary in newer RTL
versions since TBitmap supports blending but it's still useful. If you
want to use ScanLine to draw to a bitmap, then blend it, you may be
able to adapt TTransparentcanvas to do so - there's currently no direct
Scanline support built in but exposing the internal array would be very
easy.

Anyway - read the blog posts, you may find them very useful.

Cheers,

David
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02