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
Solved

draw an image semi-transparent upon another

Posted on 1998-02-10
10
220 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
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
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

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

 
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

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone 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

Suggested Solutions

Title # Comments Views Activity
how to center only a line in richedit? 4 61
Run video youtube webbrowse 10 65
DBGrid or StringGrid ? 6 103
DBCtrlGrid, Delphi, Scroll 8 37
The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
I've attached the XLSM Excel spreadsheet I used in the video and also text files containing the macros used below. https://filedb.experts-exchange.com/incoming/2017/03_w12/1151775/Permutations.txt https://filedb.experts-exchange.com/incoming/201…

840 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