Solved

draw an image semi-transparent upon another

Posted on 1998-02-10
10
216 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
 
LVL 4

Author Comment

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

Jeurk
0
 
LVL 4

Author Comment

by:jeurk
Comment Utility
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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 5

Expert Comment

by:inter
Comment Utility
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
Comment Utility
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
Comment Utility
Nice to work with you friend,

Igor
0
 
LVL 4

Author Comment

by:jeurk
Comment Utility
Me too.

Jeurk
0
 

Expert Comment

by:perkley
Comment Utility
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

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Suggested Solutions

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

771 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

14 Experts available now in Live!

Get 1:1 Help Now