Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Alpha Blending / BNitblt'ing in VB6

Posted on 2004-10-21
18
Medium Priority
?
1,340 Views
Last Modified: 2010-05-18
Ok, this is a follow-up to http://www.experts-exchange.com/Web/Web_Languages/PHP/Q_21165330.html which was about using masks.

I have a white(ish) BG and a grayscale sketch. Currently, I'm able to put the sketch onto the page, using a mask to define an outline. This works well enough on a white BG but if I wanted to use, say, a light blue BG, the BG would be blue but the sketch would still appear to be on "white" so the edge of the mask would be visible.

What I really need is: To take the "whiteness" of the sketch to mean the % alpha blend, so the white bits are transparent and the black bits are opaque and the bits in the middle are halway in-between.

Is it possible and if so, how can it be done?

Thanks
0
Comment
Question by:basiclife
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 5
  • 5
18 Comments
 
LVL 8

Expert Comment

by:List244
ID: 12371230
Only way I could think of to solve this is to use:

GetPixel
and
SetPixel

One of two ways..

1) Maybe you know your bg color? if so:

For X = 0 to PICNAME.ScaleWidth -1 'Scalemode must be 3
   For Y = 0 to PICNAME.ScaleHeight -1 ' ^^^
      SColor = GetPixel (PICNAME.Hdc,X,Y)
      B = int(SColor/65536)
      SColor = Int(SColor - (B*65536))
      G = Int(SColor/256)
      SColor = int(SColor-(G*256))
      R = Int(Scolor)
      If R < 0 Then R = 0 'Prevent error
      If B < 0 Then B = 0
      if G < 0 then G = 0
      if GetPixel(PICNAME.Hdc,x,y) <> IGNOREDCOLOR then
          SetPixel WHERETOCOPYTO.Hdc,x,y,Rgb(R,G,B)
      End If
   Next Y
Next X

Draws everything EXCEPT that color

However...

2) Maybe... you dont...

Now you would need to look at your R G and B values and say...

If R >= 230 and G >= 230 and b >=230 then
   'ignore
else
   'Draw (set the pixel.)
endif

If R G and B are all 230 or above, its a whitish point.
So, now you have within 20, or you could say if all
are 200 or above ETC.
0
 
LVL 8

Expert Comment

by:List244
ID: 12371313
     B = int(SColor/65536)
      SColor = Int(SColor - (B*65536))
      G = Int(SColor/256)
      SColor = int(SColor-(G*256))
      R = Int(Scolor)
      If R < 0 Then R = 0 'Prevent error
      If B < 0 Then B = 0
      if G < 0 then G = 0

Understanding this.

How a color is built is like so:

Say we have a color RGB (230,12,25)

That color will be written as:

1641702

1 point for each red value = 230
256 points for each green value = 3072
and 65536 for each blue = 1638400

230+3072+1638400 = 1641702

So, we know how a color is built. To take it apart, you
must work backwords. First divide it by 65536 and see
how many even numbers you get, that is your blue.
Then, subtract that from 1641702. Now you are left
with the total of red and green. Divide that by 256,
now you have your green. Subtract out the green,
and you are left with red.

Then, always make sure nothing came out below 0,
that will just crash your program, so if you happen
to get a -1 or lower.. Tell it that it is 0.
0
 
LVL 32

Expert Comment

by:Erick37
ID: 12372077
You can use GDI+ to draw a bitmap to your form using alpha blending.  The following code opens a file and paints it to the form at 50% transparency.

The following code requires gdiplus.tlb which can be downloaded here:
http://www.vbaccelerator.com/home/VB/Type_Libraries/GDIPlus_Type_Library/article.asp

This sample uses a matrix transform to set the entire picture to 50% transparency.  If you need a per pixel level of alpha adjustment, then this can be done too.

Here's the code:

Option Explicit

'Needed to close GDI+
Private token As Long

Private Sub Form_Load()
   
    Dim graphics As Long, bitmap As Long
    Dim stat As GpStatus
    Dim lHeight As Single, lWidth As Single
    Dim imgAttr As Long
    Dim clrMatrix As ColorMatrix
    Dim graMatrix As ColorMatrix
    Dim sFile As String
   
    Show
    DoEvents
    Me.AutoRedraw = True
   
    ' Load the GDI+ Dll
    ' Very important!!
    Dim GpInput As GdiplusStartupInput
    GpInput.GdiplusVersion = 1
    If GdiplusStartup(token, GpInput) <> Ok Then
      MsgBox "Error loading GDI+!", vbCritical
      Unload Me
    End If
   
    ' Initialize the graphics class using Picture1.hDC
    stat = GdipCreateFromHDC(Me.hDC, graphics)
   
    'Load a sample bitmap with alpha channel
    sFile = "c:\lake.bmp"
    stat = GdipLoadImageFromFile(sFile, bitmap)
   
    'Get the height and width of the image
    If (stat = Ok) Then
        stat = GdipGetImageDimension(bitmap, lWidth, lHeight)
        Debug.Print "w = " & lWidth, "h = " & lHeight
    Else
        MsgBox "Cannot open file" & vbCrLf & sFile
    End If
   
    'Create storage for the image attributes struct
    stat = GdipCreateImageAttributes(imgAttr)
   
    'Setup the transform matrix for alpha adjustment
    clrMatrix.m(0, 0) = 1
    clrMatrix.m(1, 1) = 1
    clrMatrix.m(2, 2) = 1
    clrMatrix.m(3, 3) = 0.5 'Alpha transform (50%)
    clrMatrix.m(4, 4) = 1
   
    'Setup the image attributes using the color matrix
    stat = GdipSetImageAttributesColorMatrix(imgAttr, ColorAdjustTypeBitmap, 1, clrMatrix, graMatrix, ColorMatrixFlagsSkipGrays)
   
    'Draw the bitmap using the Image Attributes
    stat = GdipDrawImageRectRect(graphics, bitmap, 0, 0, lWidth, lHeight, 0, 0, lWidth, lHeight, UnitPixel, imgAttr)
   
    Me.Refresh
   
    ' Cleanup
    Call GdipDeleteGraphics(graphics)
    Call GdipDisposeImage(bitmap)
    Call GdipDisposeImageAttributes(imgAttr)
   
End Sub

Private Sub Form_Unload(Cancel As Integer)
   ' Unload the GDI+ Dll
   Call GdiplusShutdown(token)
End Sub

0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 32

Expert Comment

by:Erick37
ID: 12372113
Documentation corrections:

    ' Initialize the graphics class using The form hDC <-- Corrected (not Picture1.hDC)
    stat = GdipCreateFromHDC(Me.hDC, graphics)
   
    'Load a sample bitmap <-- Corrected (not using alpha info from file)
    sFile = "c:\lake.bmp"
    stat = GdipLoadImageFromFile(sFile, bitmap)
0
 
LVL 5

Author Comment

by:basiclife
ID: 12372629
List244: That looks like a horrendously slow bit of code, although I'll havea  look at it, I'm hoping to be able to move the sketch smoothly across the BG.

Erick37: If I use that and the sketch has a white BG, it'll have a 50% opaque white rectangle around the sketch when I draw it so if I have a blue BG on the main screen, I'll have half-white box visible which I don't want

Thanks for the ideas guys, please keep themc oming or tell me why my objections are wrong...
0
 
LVL 8

Expert Comment

by:List244
ID: 12372771
Basic, try the code, it is actually quite fast.
I don't know if you tried it or just looked at
it, but go ahead and try it out. It runs for
me NEARLY at the speed of bitblt itself.
Other than that, I can not however think
of a way to do it. I like to code myself,
I don't like to use other peoples engines
and such, so I don't know if there is
one to do that.

Other than that.. you are best off
using the example I just gave you
to create a new image where the
background is turned to pure white
and just use bitblit to rid it of the pure
white color.
0
 
LVL 8

Expert Comment

by:List244
ID: 12373047
Oh! and what you can do, is use the second method
I gave you to make a new picture. Then use BITBLT
to move that picture across. So, you create a working
bitmap with a pure white bg, then copy it across with
bitblt. It should be pretty fast, and even if its not as
fast as you'd like it, you only have to do the method
I gave you once, the rest can be blitted.
0
 
LVL 32

Expert Comment

by:Erick37
ID: 12373400
>>If I use that and the sketch has a white BG, it'll have a 50% opaque white rectangle around the sketch

Correct...but I am working on a solution which uses a per pixel alpha value to meet your requirements of having an image which is fully transparent where white, and fully opaque where black, with varying transparencies in between.
0
 
LVL 8

Expert Comment

by:List244
ID: 12373461
Erick, what he wants is not fully transparent where white, but
Fully transparent when CLOSE to white. Which means, it could
just be whitish. And how I am understanding it, he wants the
rest displayed with NO transparency.
0
 
LVL 5

Author Comment

by:basiclife
ID: 12374129
Nope, sorry my fault. The opposite - I want fully transparent when white and half transparent when gray (or 3/4 when 3/4 black etc...) up to opaque when black. Awkward situation, I know. I'm going to havea  play with your code now List244 although I'm guessing it'll not be quite what I'm after. Either way, as I said, you're both helping loads. Please keep it coming!!!
0
 
LVL 8

Expert Comment

by:List244
ID: 12374964
Okay, I see what you mean..

I can not think of a way other than pixel by pixel...
You would have to take each pixel, discover its
whiteness by RGB. Turn that to a percent, then
blend pixels together... But I am thinking that
would be a bit slow...

There is the alphablend function.. Yet, that would
do the whole image at once.

If I think of another way I'll let you know.. Otherwise
maybe Erick will get his for you.
0
 
LVL 5

Author Comment

by:basiclife
ID: 12375922
Yeah you can see why this is such a b*tch ... And as you say, 3-4+ operations per pixel is REALLY slow. This is really worth > 500 points, but EE rules are absolute 8-D

The only vague idea I've had while typing this is:

If I invert the Sketch and the target area, then alpha blend, it'll do nothing for the BG? or will it make it "blacker" if it would ignore the black and blend the white, I could then invert it back afterwards
0
 
LVL 8

Assisted Solution

by:List244
List244 earned 1000 total points
ID: 12381333
Is it all grayscale??? If so what you could do is
use bitblt and SrcAnd the picture to the form,
and ignore the mask altogether. This would make
white 100% transparent and black 100% opaque,
keeping everything inbetween between 0-100.
However, once you add color it WILL be thought
as black. Then, however, if you need color you
can do a search and copy the color over,only
having to do one action to the pixels. And if
you keep it grayscale, its all fine.
0
 
LVL 8

Expert Comment

by:List244
ID: 12381484
By the way by if you use colo, I mean for the picture
you are copying, the background can have all the color
you want.
0
 
LVL 32

Accepted Solution

by:
Erick37 earned 1000 total points
ID: 12381746
Hi basiclife:

After a short refresher course on matrix multiplication, I have come up with what I believe you need to do your alpha blending.  The code I posted above remains the same, but replace the matrix assignments with this:

With clrMatrix
.m(0, 0) = 1: .m(3, 0) = -0.299
.m(1, 1) = 1: .m(3, 1) = -0.587
.m(2, 2) = 1: .m(3, 2) = -0.114
.m(3, 3) = 1
.m(4, 4) = 1
End With

This matrix operation takes the grayscale value of each pixel and assigns its compliment to the alpha value.  The obvious advantage of using a matrix is speed.  The entire image is drawn with per pixel alpha adjustment without having to loop and set each value.

The result is this:
White = alpha 0 (transparent)
middle gray = alpha 128 (50% transparent)
black = alpha 255 (opaque)

The operation works on grayscale as well as full color bitmaps.

The alpha value is calculated like this:

ALPHA = 255 - ((RED * 0.299) + (GREEN * 0.587) + (BLUE * 0.114))

Give it a try and let me know how you make out.

E

0
 
LVL 5

Author Comment

by:basiclife
ID: 12381946
Ok, guys. Thanks for the input. I'm going to go and play now. I'll get back to you some time this evening
0
 
LVL 32

Expert Comment

by:Erick37
ID: 12382049
One more modification. In the call to GdipSetImageAttributesColorMatrix, change the last parameter to ColorMatrixFlagsDefault.  I originally had the SkipGrays flag in there wich will not work for grayscale images, obviously.

The new line should read:
'Setup the image attributes using the color matrix
stat = GdipSetImageAttributesColorMatrix(imgAttr, ColorAdjustTypeBitmap, 1, clrMatrix, graMatrix, ColorMatrixFlagsDefault)
0
 
LVL 5

Author Comment

by:basiclife
ID: 12406945
Sorry for the delay in getting back to you. Have gone with a modified version of the matrix manipulation but all comments greatly appreciated so a poijnt split unless anyone objects
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction While answering a recent question about filtering a custom class collection, I realized that this could be accomplished with very little code by using the ScriptControl (SC) library.  This article will introduce you to the SC library a…
Background What I'm presenting in this article is the result of 2 conditions in my work area: We have a SQL Server production environment but no development or test environment; andWe have an MS Access front end using tables in SQL Server but we a…
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…
Suggested Courses

636 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question