0
votes

I have a Delphi 6 application where I have an array of TBitmaps each containing an image (sub-image) that was created by making a call to FillRect() with clWhite to flood the TBitmap's Canvas with white, followed by a call toTextOut() to print some text to the Bitmap's Canvas.

I have a timer that updates the main Canvas, which belongs to a TImage component, with the contents of the array every Interval to reflect changes made to each sub-images X, Y coordinates since they are in motion. First I use FillRect() with clWhite to flood the main Canvas with white. To "print" the sub-images I simply iterate the array and call Alphablend() to "print" each sub-image on to the main Canvas. Each sub-image has a Z coordinate that is used to control the level of opacity. Sub-images with higher Z coordinates have a lower Alphablend() value to make them appear more transparent than those that are "up close".

The alpha-blending works great with each individual sub-image and those that have higher coordinates do indeed appear to be more transparent than those with lower Z coordinates. However, I'm having a problem with sub-images that overlap in Z space. Alpha-blending between overlapping sub-images does not appear to work. Instead, the sub-image "behind" the overlapping sub-image is occluded by the white background belonging to the image that overlays it. What I want is for the two sub-images to overlap properly so it looks like two text strings are written on top of each other. Instead I see the front text string and everywhere the white background that comprises it's TBitmap's Canvas exists, wiping out the text string "behind" it.

Can anyone tell me why alpha-blending is working between each individual sub-image and the main Canvas, but not between sub-images? I say between sub-images only in a temporal context and not as objects because they should all become part of the main Canvas as they print and I would expect alpha-blend to blend them properly, which is not happening.

It's almost as if the "white" between sub-images is not being treated the same as the "white" between a sub-image and the "white" belonging to the main Canvas.

FOLLOW-UP: In response to Andreas comment I set the PixelFormat of all sub-image TBitmap's to pf32bit. Now alpha-blending is taking place "between" sub-images. Unfortunately, the the sub-image's white areas are not being treated as a Transparent color. Instead the white background of the sub-image that is on top is being alpha-blended with the text belonging to the underlying sub-image creating a light gray frame around the sub-image on top as if it was smeared. To get the effect I want I need the white background of a sub-image to be completely ignored.

1
I think you should give code and instructions to reproduce the problem, in as few steps as possible. Then you'll probably get a very accurate answer rather soon. Now we can only guess (e.g. "Have you tried to play with PixelFormat?").Andreas Rejbrand
Ok Andreas. I'll go work something up. I've updated my description of the problem since it appears that since I set the PixelFormat of all the sub-images to pf32bit, alpha-blending is taking place between sub-images. Unfortunately, it's not treating the sub-image's white areas as Transparent so instead of the sub-image background completely occluding (wiping out) an underlying sub-image in Z space as before, it's being alpha-blended with the text of the overlayed sub-image, creating a smeared grey frame around the sub-image that is "on top".Robert Oschler

1 Answers

1
votes

If you would like to show some images with Alphablending, try to use the Graphics32 library. In this, you will find a component "ImgView32". With this one, you can easily show any kind of bitmaps with any position and alpbablend value. You have to use TBitmapLayer and make your drawings to them.

ImgView1:TImgView32;
a:array of TBitmapLayer;

procedure TForm1.FormCreate(Sender: TObject);
  var i:integer;

  begin
    ImgView1.Layers.Clear;
    SetLength (a,10);
    for i:=0 to High (a) do
      begin
        a[i]:=TBitmapLayer.Create(ImgView1.Layers);
        a[i].Location:=FloatRect(0,0,ImgView1.Width,ImgView1.Height);
        a[i].Scaled:=false;
        a[i].Bitmap.DrawMode:=dmOpaque;
        a[i].Bitmap.MasterAlpha:=255;
      end;
  end;

procedure TForm1.FormDestroy(Sender: TObject);
  begin
    ImgView1.Layers.Clear;
  end;

procedure Form1.DrawTextToLayer(Layer:TBitmapLayer;Text:string;X,Y:integer);
var I:TImage32;

begin
  I:=TImage32.Create(Form1);
  I.Width:=ImgView1.Width;
  I.Height:=ImgView1.Height;
  I.SetupBitmap;
  I.Bitmap.DrawMode:=dmBlend;
  I.Bitmap.Font.Size:=20;
  I.Bitmap.Font.Name:='Arial';
  I.Bitmap.Font.Style:=[fsBold];
  I.Bitmap.RenderText(x,Y,Text,2,clBlack32);
  Layer.Bitmap.Assign(I.Bitmap);
  I.Free        
end;

procedure TForm1.Button1Click(Sender: TObject);
   begin
     DrawTextToLayer(a[0],'Testing 1',10,10);
     DrawTextToLayer(a[1],'Testing 2',20,20);
     a[0].Bitmap.MasterAlpha:=255;
     a[1].Bitmap.MasterAlpha:=100;
   end;