【问题标题】:TWICImage: how to save transparent BMP?TWICImage:如何保存透明的 BMP?
【发布时间】:2021-09-22 08:12:07
【问题描述】:

我使用的是 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;

【问题讨论】:

  • LImageOut 是否保留pf32bit 格式?
  • 为什么要使用TBitmap?为什么不只坚持TWICImage?见Resize TWICImage without losing transparency
  • @MBo PixelFormatTWICImage 上不存在,我可以检查一下类似的吗?
  • @AmigoJack 我尝试了链接的代码,这次我没有使用任何TBitmap var,但我仍然有黑色背景。使用链接的代码,如果我跳过调整大小,透明度会保留,所以我猜它与调整大小方法有关

标签: image delphi delphi-10.4-sydney wic delphi-10.4.2


【解决方案1】:

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

一个简单的方法是使用 Image32 库,可以在 SourceForge 上免费下载 - 它可以读取包括透明的 PNG 在内的文件。您可以使用透明度渲染图像,并且可以将其与 VCL 和 FMX 一起使用。

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

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

【讨论】:

  • 谢谢!为什么这种情况只发生在 BMP 文件中? TWICImage 可以处理所有其他图像格式的透明度..
  • 在不了解 TWICImage 的情况下,我怀疑这是因为您没有使用 32 位(包括 alpha 通道)模式。您必须检查该控件和该模式的设置。如果它忽略了 Alpha 通道,那么任何设置为 $00000000 的像素都将是黑色的,而不是完全透明的。
【解决方案2】:

默认情况下,BMP 的 Windows 映像组件 (WIC) 编解码器不会写入 32 位 BMP,以便向后兼容不支持“V5”标头的阅读器。但是,您可以通过 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 Docs

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-25
    • 2013-11-30
    • 1970-01-01
    • 1970-01-01
    • 2013-06-13
    • 2013-04-14
    • 2015-04-17
    相关资源
    最近更新 更多