TWICImage: how to save transparent BMP?

378 Views Asked by At

I'm using Delphi 10.4.2 and I have an application that scales images (BMP, GIF, PNG, ...).

My problem is that if the input image is a transparent BMP the output BMP is not transparent, instead it has a black backgound. This also happens when the input is a transparent PNG and I want to output a BMP. How can I avoid that?

Sample code:

procedure TFrmTestGenImg.Resize;
var
  LInputImgPath, LOutputImgPath: string;
  LImageIn, LImageOut: TWICImage;
  LBitmap: TBitmap;
begin
  LInputImgPath := 'C:\temp\Input.bmp';

  LOutputImgPath := 'C:\temp\Output.bmp';

  LImageIn := TWICImage.Create;
  try
    LImageOut := TWICImage.Create;
    try
      LImageIn.Transparent := True;
      LImageIn.LoadFromFile(Trim(LInputImgPath));

      LBitmap := TBitmap.Create;
      try
        LBitmap.PixelFormat := pf32bit;
        LBitmap.Assign(LImageIn);
        LBitmap.Transparent := True;
        { ... Resizing bitmap ... }

        LImageOut.Assign(LBitmap);
        LImageOut.ImageFormat := wifBmp;
        LImageOut.Transparent := LImageIn.Transparent;
        LImageOut.SaveToFile(LOutputImgPath);
      finally
        LBitmap.Free;
      end;
    finally
      LImageOut.Free;
    end;
  finally
    LImageIn.Free;
  end;
end;
2

There are 2 best solutions below

2
On

There is no support for alpha channel transparency in the VCL which it seems like is what you want. I have never used TWCImage and googling for it did not reveal anything so I'm not sure how to advise how you to use that.

An easy way to be able to do what you want is to use the Image32 library free to download on SourceForge - it can read files including PNG with transparency. You can the render the image with transparency and you can use it with both VCL and FMX.

https://sourceforge.net/projects/image32/

(I suggest this not to promote Image32 (although I think it's excellent) but to answer the OP question on how to handle transparency.

0
On

By default the Windows Imaging Component (WIC) codec for BMP does not write 32-bit BMPs for backwards compatibly for readers that don't support the "V5" header. You can, however, enable it via the EnableV5Header32bppBGRA property.

I don't know how you do that in Delphi, but here's some C++ sample code:

// pWIC is a pointer to IWICImagingFactory
ComPtr<IWICBitmapEncoder> encoder;
HRESULT hr = pWIC->CreateEncoder(containerFormat, nullptr, encoder.GetAddressOf());
if (FAILED(hr))
    return hr;

ComPtr<IWICBitmapFrameEncode> frame;
ComPtr<IPropertyBag2> props;
hr = encoder->CreateNewFrame(frame.GetAddressOf(), props.GetAddressOf());
if (FAILED(hr))
    return hr;

// Opt-in to the WIC2 support for writing 32-bit Windows BMP files with an alpha channel
PROPBAG2 option = {};
option.pstrName = const_cast<wchar_t*>(L"EnableV5Header32bppBGRA");

VARIANT varValue;
varValue.vt = VT_BOOL;
varValue.boolVal = VARIANT_TRUE;
(void)props->Write(1, &option, &varValue);

hr = frame->Initialize(props);
if (FAILED(hr))
    return hr;
...

See Microsoft Docs.