0

我正在使用 Delphi 10.4.2,并且我有一个可以缩放图像(BMP、GIF、PNG、...)的应用程序。

我的问题是,如果输入图像是透明 BMP,则输出 BMP 不是透明的,而是黑色背景。当输入是透明 PNG 并且我想输出 BMP 时,也会发生这种情况。我怎样才能避免这种情况?

示例代码:

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;
4

2 回答 2

0

VCL 中不支持 alpha 通道透明度,这似乎是您想要的。我从来没有使用过 TWCImage 并且谷歌搜索它没有透露任何内容,所以我不确定如何建议你如何使用它。

一种能够做你想做的事情的简单方法是使用在 SourceForge 上免费下载的 Image32 库——它可以读取包括具有透明度的 PNG 在内的文件。您可以使用透明度渲染图像,并且可以将其与 VCL 和 FMX 一起使用。

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

(我建议这不是为了推广 Image32(尽管我认为它很棒),而是为了回答关于如何处理透明度的 OP 问题。

于 2021-09-22T08:34:53.940 回答
0

默认情况下,BMP 的 Windows 映像组件 (WIC) 编解码器不会为不支持“V5”标头的读者向后兼容编写32 位 BMP。但是,您可以通过EnableV5Header32bppBGRA属性启用它。

我不知道你是如何在 Delphi 中做到这一点的,但这里有一些 C++ 示例代码:

// 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;
...

请参阅Microsoft 文档

于 2021-10-03T19:25:32.850 回答