我有以下代码使用默认选项从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_PROPERTYUNEXPECCEDTYPE)。 MSDN说here,“ ImageQuality”属性的类型为VT_R4,但是由于我以前从未使用过Variant,因此我不确定该如何编写。而且我什至不确定压缩是否确实是无损的。
如何修改我的代码以使其生成质量1.0 jpg,并且它会无损?
最佳答案
我没有这方面的经验,但是根据阅读您链接到的文档,这是我的最佳建议。
首先,我认为您需要指定PropBagOptions
的更多成员:dwType
需要设置为PROPBAG2_TYPE_DATA
。vt
需要设置为VT_R4
。
您还需要确保变量确实是VT_R4
。这是一个4字节的实数,用Delphi表示是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 quality 1.0是否无损,不是。这个问题已经在这里很好地解决了:Is JPEG lossless when quality is set to 100?