2

我有以下代码使用默认选项从 IWICBitmapSource 创建 jpg 文件:

function SaveWICBitmapToJpgFile(WICFactory: IWICImagingFactory;
  WICBitmap: IWICBitmapSource; SrcRect: TRect; FileName: string): HRESULT;
var
  hr: HRESULT;
  Encoder: IWICBitmapEncoder;
  Frame: IWICBitmapFrameEncode;
  PropBag: IPropertyBag2;
  S: IWICStream;
  PixelFormatGUID: WICPixelFormatGUID;
  R: WICRect;
begin

  hr := WICFactory.CreateStream(S);

  if Succeeded(hr) then begin
    hr := S.InitializeFromFilename(PChar(FileName), GENERIC_WRITE);
  end;

  if Succeeded(hr) then begin
    hr := WICFactory.CreateEncoder(GUID_ContainerFormatJpeg, GUID_NULL,
      Encoder);
  end;

  if Succeeded(hr) then begin
    hr := Encoder.Initialize(S, WICBitmapEncoderNoCache);
  end;

  if Succeeded(hr) then begin
    hr := Encoder.CreateNewFrame(Frame, PropBag);
  end;

  if Succeeded(hr) then begin
    hr := Frame.Initialize(PropBag);
  end;

  if Succeeded(hr) then begin
    hr := Frame.SetSize(SrcRect.Width, SrcRect.Height);
  end;

  if Succeeded(hr) then begin
    PixelFormatGUID := GUID_WICPixelFormat24bppBGR;
    hr := Frame.SetPixelFormat(PixelFormatGUID);
  end;

  if Succeeded(hr) then begin
    hr := IfThen(PixelFormatGUID = GUID_WICPixelFormat24bppBGR, S_OK, E_FAIL);
  end;

  if Succeeded(hr) then begin
    R.X := SrcRect.Left;
    R.Y := SrcRect.Top;
    R.Width := SrcRect.Width;
    R.Height := SrcRect.Height;
    Frame.WriteSource(WICBitmap, @R);
  end;

  if Succeeded(hr) then begin
    hr := Frame.Commit;
  end;

  if Succeeded(hr) then begin
    hr := Encoder.Commit;
  end;

  Result := hr;

end;

我想更改编解码器选项以生成无损 jpg。据我了解我在 MSDN 中阅读的内容,我必须使用 IPropertyBag2 来实现这一点。尽管不知道如何做,我尝试在 Frame 创建和 Frame 初始化之间插入这段代码:

var
[...]
  PropBagOptions: TPropBag2;
  V: Variant;
[...]

if Succeeded(hr) then begin
  FillChar(PropBagOptions, SizeOf(PropBagOptions), 0);
  PropBagOptions.pstrName := 'ImageQuality';
  V := 1.0;
  hr := PropBag.Write(1, @PropBagOptions, @V);
end;

它不起作用:hr = 0x88982F8E (WINCODEC_ERR_PROPERTYUNEXPECTEDTYPE)。MSDN在这里说“ImageQuality”属性的类型是 VT_R4,但由于我以前从未使用过 Variant,所以我不知道如何编写。而且我什至不确定压缩是否确实是无损的。

我如何修改我的代码以使其生成质量为 1.0 的 jpg,并且它会是无损的吗?

4

1 回答 1

3

我没有这方面的经验,但这是基于阅读您链接到的文档的最佳建议。

首先,我认为您需要指定更多的成员PropBagOptions

  • dwType需要设置为PROPBAG2_TYPE_DATA
  • vt需要设置为VT_R4

您还需要确保变体确实是VT_R4. 这是一个 4 字节的实数,在 Delphi 中是 type 的变体varSingle

V := VarAsType(1.0, varSingle);

我认为应该完成它。

把它们放在一起,它看起来像这样:

FillChar(PropBagOptions, SizeOf(PropBagOptions), 0);
PropBagOptions.pstrName := 'ImageQuality';
PropBagOptions.dwType := PROPBAG2_TYPE_DATA;
PropBagOptions.vt := VT_R4;
V := VarAsType(1.0, varSingle);
hr := PropBag.Write(1, @PropBagOptions, @V);

至于JPEG质量1.0是否无损,它不是。这里已经很好地解决了这个问题:当质量设置为 100 时,JPEG 是否无损?

于 2013-01-29T14:34:28.150 回答