Solved

draw an image semi-transparent upon another

Posted on 1998-02-10
10
219 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
Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

 
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

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

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

Suggested Solutions

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…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…
Established in 1997, Technology Architects has become one of the most reputable technology solutions companies in the country. TA have been providing businesses with cost effective state-of-the-art solutions and unparalleled service that is designed…

816 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

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now