Solved

draw an image semi-transparent upon another

Posted on 1998-02-10
10
223 Views
Last Modified: 2010-05-18
Hi,
I would like to be able to draw an image on top of one
other. But i would be able to se trought it. I don't mean
here the thing with a transparent color. But a formula where
I can state the transparency. If I want the picture 0% transparent, that would mean I can't
see the image in he background. And 100% transparent
would make that I can't see the image in the foreground.
If possible I would like source code.
Any hint someone ?
Jeurk.
0
Comment
Question by:jeurk
[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
10 Comments
 
LVL 4

Expert Comment

by:d003303
ID: 1358879
This can be done with an additional channel to RGB, called alpha channel. It is like a grayscale picture where white means transparent and black means solid. You can store this channel as a separate image.
To draw the transparency, you will have to calculate each pixel. This mainly means you walk through the pixel array of the source, background and transparency mask bitmap and set each RGB value of the destination bitmap (this takes time and should be coded in assembler).

Slash/d003303
0
 
LVL 5

Expert Comment

by:JimBob091197
ID: 1358880
Hi

There must be a much better way of doing this, but here is a function that I wrote, and I have used it quite successfully.  It's a bit slow for big bitmaps (so don't use it for real-time fading animation for 800*600 bitmaps!) but it works really well for animating 32*32 bitmaps on About screens & splash screens!

procedure CombineBmps(Bmp1, Bmp2, ResultBmp: TBitmap; PercentBmp1: Integer);
var
  x, y: Integer;
  NewCol: TColor;
begin
  ResultBmp.Width := Bmp1.Width;
  ResultBmp.Height := Bmp1.Height;
 
  for x := 0 to Bmp1.Width - 1 do
    for y := 0 to Bmp1.Height - 1 do
      begin
        NewCol := GetCombinedColor(Bmp1.Canvas.Pixels[x, y], Bmp2.Canvas.Pixels[x, y], PercentBmp1);
        ResultBmp.Canvas.Pixels[x, y] := NewCol;
      end;
end;

The above procedure uses the following function:

function GetCombinedColor(Col1, Col2: TColor; PercentCol1: Integer): TColor;
var
  RVal1, RVal2, GVal1, GVal2, BVal1, BVal2, NewR, NewG, NewB: Byte;
  PercentCol2: Integer;
begin
  RVal1 := GetRValue(Col1);
  GVal1 := GetGValue(Col1);
  BVal1 := GetBValue(Col1);
  RVal2 := GetRValue(Col2);
  GVal2 := GetGValue(Col2);
  BVal2 := GetBValue(Col2);

  PercentCol2 := 100 - PercentCol1;

  NewR := ((RVal1 * PercentCol1) + (RVal2 * PercentCol2)) div 100;
  NewG := ((GVal1 * PercentCol1) + (GVal2 * PercentCol2)) div 100;
  NewB := ((BVal1 * PercentCol1) + (BVal2 * PercentCol2)) div 100;

  Result := RGB(NewR, NewG, NewB);
end;


As an example, where MyImage is a TImage, and Delay will wait X milliseconds while doing Application.ProcessMessages:
  for i := 0 to 10 do
    begin
      CombineBmps(Bmp1, Bmp2, NewBmp, i * 10);
      MyImage.Picture.Assign(NewBmp);
      Delay(50);
    end;


Regards,
JB
0
 
LVL 5

Expert Comment

by:inter
ID: 1358881
Actually JimBob is RIGHT, and his method is correct. But if you plan to do such thing in medium size bitmaps you may use 24 bit color images and do the operation very very fast. Here is the code: (what slows down the method above is extensive number functions called per pixel but in 24 bit we can get the whole image and do the same)

This function gets 2 24 bit bitmaps and return the resulting image in first bitmap.

procedure MergeBitmaps24(Bitmap1, Bitmap2 : TBitmap; percent : integer);
type
  PByte = ^byte;
  TBITMAPX = packed record // I do not know the name in delphi
   bmType : longint;
   bmWidth: longint;
   bmHeight: longint;
   bmWidthBytes: longint;
   bmPlanes : WORD;
   bmBitsPixel : WORD;
   bmBits : PByte;
  end;

var
  Bitmapbits1, Bitmapbits1 : PByte;
  bminfo : TBitmapX;
  len : longint;
  per1 : integer;
begin
  // assuming that the images are of the same size allocate
  GetObject(Bitmap1.Handle, sizeof(TBitmapX), @bmpinfo);
  BitmapBits1 := bmpinfo.bmBits;
  GetObject(Bitmap2.Handle, sizeof(TBitmapX), @bmpinfo);
  BitmapBits2 := bmpinfo.bmBits;
  // combine them with percent since we work inplace the bitmaps
  // are modified inplace so we need to refresh the bitmaps after
  // wards.
  len := bmpinfo.widthbytes * bmpinfo.height;
  per1 := 100 - percent;
  while len <> 0 do
  begin
    BitmapBits1^ := (percent *BitmapBits1^ + per1 * BitmapBits2^ )div 100;
    Inc(BitmapBits1,1); Inc(BitmapBits2,1);Dec(len);
  end;
  // upon return do not forget to refresh the container of Bitmap1  
end;

Igor
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 4

Author Comment

by:jeurk
ID: 1358882
Salut,
I still not have tryed the thing.
Please be patient ;)

Jeurk
0
 
LVL 4

Author Comment

by:jeurk
ID: 1358883
Ok guys,
I tried the things,
inter, they were some typo in your code ;)
It seems to work. But I have a question,
how do I convert an image to 24 bits ?
Jeurk.
0
 
LVL 5

Expert Comment

by:inter
ID: 1358884
In normal color bitmaps, you now, there is a palette table at the begining of the bitmap after BITMAPINFOHEADER. In 24 bitmap the following applies:

The bitmap has a maximum of 2^24 colors, and the bmiColors member is NULL. Each 3-byte triplet in the bitmap array represents the relative intensities of blue, green, and red, respectively, for a pixel.

So, if we want to convert a 256 color or 16 color bitmap to 24 bit bitmap we should get the palette table and substitude the pixel values as RGB as described above.

Example:

say the following is a partial palette table for 256 color bitmap:
           R   G   B
pal[0] = (100,101,102);
pal[1] = (200,201,202);
pal[2] = (240,241,242);
...
And the data of it goes as
0,0,1,2,1...

The 24 bit equivalent is
pal = nil;

and the data be
102,101,100, 102,101,100, 202,201,200, 240,241,242, 202,201,200...

such that...

What? No I do not have code for this, but I may write it.

The easiest way is to do this with a Painting program. But if you need dynamic, run time conversion, we should do this by hand.

Igor
0
 
LVL 4

Author Comment

by:jeurk
ID: 1358885
OK,
let's say we gonna close the question.
Post an answer inter and you will earn the points.
Thank You for the help.
Thanks goes to You too JimBob. If you want some points
tell me and you will earn some , let's say 60 points ?

CU
0
 
LVL 5

Accepted Solution

by:
inter earned 80 total points
ID: 1358886
Nice to work with you friend,

Igor
0
 
LVL 4

Author Comment

by:jeurk
ID: 1358887
Me too.

Jeurk
0
 

Expert Comment

by:perkley
ID: 3036752
Hey, I read this question and I can't seem to get inter's accepted answer to work.  I know there is typos and I am sure I fixed them correctly, and the code does run, but it doesn't seem to give me any wanted results.

Inter, in the code you mentioned to refresh the container upon return.  I tried Bmp1.Refresh, but Refresh isn't available.  What exactly are you talking about?

Does someone have source code for a full working example of this.  The entire unit source code, not just segments.
0

Featured Post

On Demand Webinar: Networking for the Cloud Era

Did you know SD-WANs can improve network connectivity? Check out this webinar to learn how an SD-WAN simplified, one-click tool can help you migrate and manage data in the cloud.

Question has a verified solution.

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

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Monitoring a network: why having a policy is the best policy? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the enormous benefits of having a policy-based approach when monitoring medium and large networks. Software utilized in this v…
In this video you will find out how to export Office 365 mailboxes using the built in eDiscovery tool. Bear in mind that although this method might be useful in some cases, using PST files as Office 365 backup is troublesome in a long run (more on t…
Suggested Courses
Course of the Month4 days, 11 hours left to enroll

635 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