Bill
Bill

Reputation: 3033

Is it possible to open a image with TImage and GDIPlus and maintain full transparency

I can get a 32-bit image to be displayed in TImage with GDIPlus that has partial (masked) transparency but the alpha values are either 0 or 255 with no values in between. I have tried loading PngImage, 32-bit bitmaps and icons all produce the same... masked transparency but not full transparency.

Is there another way to get TImage to display a GDI+ graphic with full transparency as shown in the Desired Result image?

enter image description here GDI Plus After Open

enter image description here Desired Result

procedure TFormMain.Open1Click ( Sender: TObject );
// Load a GDIPlus Bitmap into TImage
var
  GPBitmap: TGPBitmap;
  iHBitmap: HBITMAP;
  iStatus: TStatus;
const
  TRANS_COLOR = clBlack;
begin

  if OpenPictureDialog1.Execute then
  begin

    FilePath := OpenPictureDialog1.FileName;
    begin

      GPBitmap := TGpBitmap.Create ( FilePath );
      try

        iStatus := GPBitmap.GetHBITMAP ( aclBlack, iHBitmap );
        // As best as I can determine from the internet, the GetHBitmap which is needed to assign a GPbitmap to TImage
        // does not hold an alphachannel, so loaded images alpha are either 0 or 255, but drawing with alphachannel values does work.
        if iStatus = Ok then
        begin

          Image1.Picture.Bitmap.Handle := iHBitmap;
          Image1.Picture.Bitmap.TransparentColor := Image1.Picture.Bitmap.Canvas.Pixels [ 0, Image1.Picture.Bitmap.Height - 1 ];
          StatusBar1.Panels [ 0 ].Text := FileCtrl.MinimizeName ( ExtractFileDir ( FilePath ), Canvas, 200 ); // Folder
          StatusBar1.Panels [ 1 ].Text := FileCtrl.MinimizeName ( ExtractFileName ( FilePath ), Canvas, 75 ); // Filename
          StatusBar1.Panels [ 2 ].Text := 'Width: ' + IntegerToString ( Image1.Picture.Bitmap.Width ); // Width
          StatusBar1.Panels [ 3 ].Text := 'Height: ' + IntegerToString ( Image1.Picture.Bitmap.Height ); // Height
          StatusBar1.Panels [ 4 ].Text := BitDepthToColorString ( GetPixelFormatSize ( GPBitmap.GetPixelFormat ) ); // Bitdepth

          Image1.Refresh;

        end;

      finally
        GPBitmap.Free;
      end;

    end;

  end;

end;

Upvotes: 3

Views: 2389

Answers (1)

Sertac Akyuz
Sertac Akyuz

Reputation: 54772

What you need to do is to choose a background color that will blend with the surface that the image is drawn on when it is transferred. I.e. instead of

iStatus := GPBitmap.GetHBITMAP ( aclBlack, iHBitmap );

use

iStatus := GPBitmap.GetHBITMAP(ColorRefToARGB(ColorToRGB(clBtnFace)), iHBitmap);

if the image is on a default colored form for instance.

At this point you already know that the image has no alpha channel, but it has been flattened using a suitable color. The Transparent.. properties of 'TBitmap' will not help with partial transparency. If you set the Transparent property of the TBitmap, it will still be like the first image of your question when you put it on a different colored background, probably with a nicer edge color. In any case, if you use it, do not forget to set the 'TransparentColor' to 'clBtnFace' instead of 'clBlack'.

Upvotes: 2

Related Questions