通过 IGPImage.GetEncoderParameterList 可以获取指定编码格式的参数列表;
通过此列表可以遍历出各参数的指针: PGPNativeEncoderParameter(TGPNativeEncoderParameter 的指针);
TGPNativeEncoderParameter 是一个结构体:
TGPNativeEncoderParameter = record Guid: TGUID; { 参数标识 } NumberOfValues: ULONG; { 参数数组的元素数 } ValueType: TGPEncoderParameterValueType; { 参数类型 } Value: Pointer; { 参数数据指针 } end; //其中的 TGPEncoderParameterValueType 是个枚举, 枚举值有: EncoderParameterValueTypeByte = 1 { 字节数组 } EncoderParameterValueTypeASCII = 2 { PAnsiChar } EncoderParameterValueTypeShort = 3 { Word } EncoderParameterValueTypeLong = 4 { Cardinal } EncoderParameterValueTypeRational = 5 { Cardinal/Cardinal; 第一个数是分子, 第二个数是分母 } EncoderParameterValueTypeLongRange = 6 { 一对 Cardinal, 表示一个数值范围 } EncoderParameterValueTypeUndefined = 7 { 可包含任何数据类型的字节数组 } EncoderParameterValueTypeRationalRange = 8 { 四个整数: Cardinal/Cardinal, Cardinal/Cardinal } EncoderParameterValueTypePointer = 9 { 指针 } //EncoderParameterValueTypeRationalRange 中的四个整数通过分数运算得到的两个值: 最小值...最大值.
每个编码器的参数肯定会有区别, 下面代码获取了 JPEG 编码器所能支持的参数信息:
uses GdiPlus; procedure TForm1.Button1Click(Sender: TObject); var Image: IGPImage; Parameters: IGPEncoderParameters; Param: PGPNativeEncoderParameter; begin Image := TGPBitmap.Create(1, 1); Parameters := Image.GetEncoderParameterList(TGPImageFormat.Jpeg.CodecId); Memo1.Clear; for Param in Parameters do with Memo1.Lines do begin Add(Format('Guid: %s', [GUIDToString(Param.Guid)])); Add(Format('NumberOfValues: %d', [Param.NumberOfValues])); Add(Format('ValueType: %d', [Ord(Param.ValueType)])); Add(Format('Value: $%p', [Param.Value])); Add(EmptyStr); end; end; (* 结果: Guid: {8D0EB2D1-A58E-4EA8-AA14-108074B7B6F9} NumberOfValues: 5 ValueType: 4 Value: $00AD8190 Guid: {1D5BE4B5-FA4A-452D-9CDD-5DB35105E7EB} NumberOfValues: 1 ValueType: 6 Value: $00AD81A4 Guid: {EDB33BCE-0266-4A77-B904-27216099E717} NumberOfValues: 0 ValueType: 3 Value: $00AD81AC Guid: {F2E455DC-09B3-4316-8260-676ADA32481C} NumberOfValues: 0 ValueType: 3 Value: $00AD81AC *)
IGPImage.GetEncoderParameterList 方法得到的类型是: IGPEncoderParameters;
IGPImage.Save 方法就有一个 IGPEncoderParameters 类型的默认参数, 通过它可以传入编码参数.
编码参数有很多类型, 譬如 EncoderQuality 是决定图片压缩比率的.
下面的例子在保存 JPG 文件时使用了三种不同的质量参数(压缩级别):
![](https://images.cnblogs.com/cnblogs_com/del/214030/o_09122901.png)
uses GdiPlus; procedure TForm1.Button1Click(Sender: TObject); var Prams: IGPEncoderParameters; Image: IGPImage; Graphics: IGPGraphics; Quality: Integer; begin ChDir('C:\GdiPlusImg\'); Image := TGPImage.Create('GrapeBunch.bmp'); Prams := TGPEncoderParameters.Create; Quality := 1; Prams.Add(EncoderQuality, Quality); Image.Save('GrapeBunch_1.jpg', TGPImageFormat.Jpeg, Prams); Prams.Clear; Quality := 50; Prams.Add(EncoderQuality, Quality); Image.Save('GrapeBunch_50.jpg', TGPImageFormat.Jpeg, Prams); Prams.Clear; Quality := 100; Prams.Add(EncoderQuality, Quality); Image.Save('GrapeBunch_100.jpg', TGPImageFormat.Jpeg, Prams); //显示 Graphics := TGPGraphics.Create(Handle); Image := TGPImage.Create('GrapeBunch_1.jpg'); Graphics.DrawImage(Image, 10, 10); Graphics.TranslateTransform(Image.Width + 10, 0); Image := TGPImage.Create('GrapeBunch_50.jpg'); Graphics.DrawImage(Image, 10, 10); Graphics.TranslateTransform(Image.Width + 10, 0); Image := TGPImage.Create('GrapeBunch_100.jpg'); Graphics.DrawImage(Image, 10, 10); end;
IGPEncoderParameters 的成员:
IGPEncoderParameters.GetEnumerator; IGPEncoderParameters.Clear; IGPEncoderParameters.Add(); IGPEncoderParameters.Count; IGPEncoderParameters.Param[]; IGPEncoderParameters.NativeParams; //其中的 Add 方法有多种重载, 这便于添加各种类型的数据; 参数类型常数: EncoderCompression { 压缩 } EncoderColorDepth { 颜色深度 } EncoderScanMethod { 扫描方法 } EncoderVersion { 版本 } EncoderRenderMethod { 呈现方法 } EncoderQuality { 质量 } EncoderTransformation { 转换 } EncoderLuminanceTable { 亮度表 } EncoderChrominanceTable { 色度表 } EncoderSaveFlag { 保存标志 } CodecIImageBytes { } { 下面是 GDI+1.1 才开始支持的: } EncoderColorSpace { } EncoderImageItems { } EncoderSaveAsCMYK { }
五种编码器(BMP、JPEG、GIF、TIFF、PNG)分别能支持哪些 "参数类型" 呢?
支持的参数类型的参数又是什么格式的呢? 尽管 Add 方法已准备好了多种重载, 用哪个呢?
下面的程序列出了各种编码器的参数信息:
uses GdiPlus; const ParamValueTypeArr: array[1..9] of string = ( 'ValueTypeByte', 'ValueTypeASCII', 'ValueTypeShort', 'ValueTypeLong', 'ValueTypeRational', 'ValueTypeLongRange', 'ValueTypeUndefined', 'ValueTypeRationalRange', 'ValueTypePointer' ); //自定义函数 function GetGuidName(g: TGUID): string; var s: string; begin s := EmptyStr; if IsEqualGUID(g, EncoderCompression) then s := 'EncoderCompression'; if IsEqualGUID(g, EncoderColorDepth) then s := 'EncoderColorDepth'; if IsEqualGUID(g, EncoderScanMethod) then s := 'EncoderScanMethod'; if IsEqualGUID(g, EncoderVersion) then s := 'EncoderVersion'; if IsEqualGUID(g, EncoderRenderMethod) then s := 'EncoderRenderMethod'; if IsEqualGUID(g, EncoderQuality) then s := 'EncoderQuality'; if IsEqualGUID(g, EncoderTransformation) then s := 'EncoderTransformation'; if IsEqualGUID(g, EncoderLuminanceTable) then s := 'EncoderLuminanceTable'; if IsEqualGUID(g, EncoderChrominanceTable) then s := 'EncoderChrominanceTable'; if IsEqualGUID(g, EncoderSaveFlag) then s := 'EncoderSaveFlag'; if IsEqualGUID(g, CodecIImageBytes) then s := 'CodecIImageBytes'; {$IF (GDIPVER >= $0110)} if IsEqualGUID(g, EncoderColorSpace) then s := 'EncoderColorSpace'; if IsEqualGUID(g, EncoderImageItems) then s := 'EncoderImageItems'; if IsEqualGUID(g, EncoderSaveAsCMYK) then s := 'EncoderSaveAsCMYK'; {$IFEND} Result := s; end; procedure TForm1.Button1Click(Sender: TObject); var Image: IGPImage; Parameters: IGPEncoderParameters; Param: PGPNativeEncoderParameter; Encoder: IGPImageCodecInfo; begin Image := TGPBitmap.Create(1, 1); Memo1.Clear; for Encoder in TGPImageCodecInfo.GetImageEncoders do with Memo1.Lines do begin Parameters := Image.GetEncoderParameterList(Encoder.ClsId); Add('----------------------'); Add(Format('编码器类型: %s', [Encoder.FormatDescription])); if Parameters.Count = 0 then begin Add('无参数'); Add(EmptyStr); Continue; end; Add(Format('参数个数: %d', [Parameters.Count])); for Param in Parameters do begin Add(Format('参数类型: %s', [GetGuidName(Param.Guid)])); Add(Format('参数值类型: %s', [ParamValueTypeArr[Ord(Param.ValueType)]])); Add(Format('参数值个数: %d', [Param.NumberOfValues])); Add(Format('参数值指针: $%p', [Param.Value])); Add(EmptyStr); end; end; end; (* 显示结果: ---------------------- 编码器类型: BMP 无参数 ---------------------- 编码器类型: JPEG 参数个数: 4 参数类型: EncoderTransformation 参数值类型: ValueTypeLong 参数值个数: 5 参数值指针: $00AD8190 参数类型: EncoderQuality 参数值类型: ValueTypeLongRange 参数值个数: 1 参数值指针: $00AD81A4 参数类型: EncoderLuminanceTable 参数值类型: ValueTypeShort 参数值个数: 0 参数值指针: $00AD81AC 参数类型: EncoderChrominanceTable 参数值类型: ValueTypeShort 参数值个数: 0 参数值指针: $00AD81AC ---------------------- 编码器类型: GIF 无参数 ---------------------- 编码器类型: TIFF 参数个数: 3 参数类型: EncoderCompression 参数值类型: ValueTypeLong 参数值个数: 5 参数值指针: $00AD8190 参数类型: EncoderColorDepth 参数值类型: ValueTypeLong 参数值个数: 5 参数值指针: $00AD81A4 参数类型: EncoderSaveFlag 参数值类型: ValueTypeLong 参数值个数: 1 参数值指针: $00AD81B8 ---------------------- 编码器类型: PNG 无参数 *)
从上面例子可以看出:
BMP、GIF、PNG 三种编码器没有编码参数(GIF 在 GDI+1.1 中是不是支持还没有测试).
JPEG 支持:
EncoderTransformation (转换)
EncoderQuality (质量)
EncoderLuminanceTable (亮度表)
EncoderChrominanceTable (色度表)
TIFF 支持:
EncoderCompression (压缩)
EncoderColorDepth (颜色深度)
EncoderSaveFlag (保存标志)
进而可以得知:
JPEG 编码的参数类型 EncoderTransformation 的可选值是:
TGPEncoderValue(13): EncoderValueTransformRotate90
TGPEncoderValue(14): EncoderValueTransformRotate180
TGPEncoderValue(15): EncoderValueTransformRotate270
TGPEncoderValue(16): EncoderValueTransformFlipHorizontal
TGPEncoderValue(17): EncoderValueTransformFlipVertical
JPEG 编码的参数类型 EncoderQuality 的可选值是: 0..100
TIFF 编码的参数类型 EncoderCompression 的可选值是:
TGPEncoderValue(2): EncoderValueCompressionLZW
TGPEncoderValue(3): EncoderValueCompressionCCITT3
TGPEncoderValue(4): EncoderValueCompressionCCITT4
TGPEncoderValue(5): EncoderValueCompressionRle
TGPEncoderValue(6): EncoderValueCompressionNone
TIFF 编码的参数类型 EncoderColorDepth 的可选值是: 1,4,8,24,32
这些值可以从下面程序获取:
uses GdiPlus; var Image: IGPImage; Parameters: IGPEncoderParameters; p: PCardinal; procedure TForm1.FormCreate(Sender: TObject); begin Image := TGPBitmap.Create(1, 1); end; {$PointerMath On} procedure TForm1.Button1Click(Sender: TObject); begin Parameters := Image.GetEncoderParameterList(TGPImageFormat.Jpeg.CodecId); p := Parameters[0].Value; { EncoderTransformation } ShowMessageFmt('%d,%d,%d,%d,%d', [p[0],p[1],p[2],p[3],p[4]]); { 13,14,15,16,17 } end; procedure TForm1.Button2Click(Sender: TObject); begin Parameters := Image.GetEncoderParameterList(TGPImageFormat.Jpeg.CodecId); p := Parameters[1].Value; { EncoderQuality } ShowMessageFmt('%d..%d', [p[0],p[1]]); { 0..100 } end; procedure TForm1.Button3Click(Sender: TObject); begin Parameters := Image.GetEncoderParameterList(TGPImageFormat.Tiff.CodecId); p := Parameters[0].Value; { EncoderCompression } ShowMessageFmt('%d,%d,%d,%d,%d', [p[0],p[1],p[2],p[3],p[4]]); { 2,3,5,4,6 } end; procedure TForm1.Button4Click(Sender: TObject); begin Parameters := Image.GetEncoderParameterList(TGPImageFormat.Tiff.CodecId); p := Parameters[1].Value; { EncoderColorDepth } ShowMessageFmt('%d,%d,%d,%d,%d', [p[0],p[1],p[2],p[3],p[4]]); { 1,4,8,24,32 } end;
下面例子通过设置 JPEG 的 EncoderTransformation 编码参数, 保存了旋转后的图片:
![](https://images.cnblogs.com/cnblogs_com/del/214030/o_09123001.png)
uses GdiPlus; procedure TForm1.Button1Click(Sender: TObject); var Graphics: IGPGraphics; Prams: IGPEncoderParameters; Image: IGPImage; begin ChDir('C:\GdiPlusImg\'); Image := TGPImage.Create('Grapes.jpg'); Prams := TGPEncoderParameters.Create; Prams.Add(EncoderTransformation, EncoderValueTransformRotate90); Image.Save('Grapes_Rotate90.jpg', TGPImageFormat.Jpeg, Prams); Graphics := TGPGraphics.Create(Handle); Graphics.DrawImage(Image, 10, 10, Image.Width, Image.Height); end; //为什么只有 JPEG 提供这种编码参数呢? 因为 jpg 文件在自动保存过程中会降低品质, 通过这种变换则不会.
另外:
1、编码参数值类型很多是 Cardinal, 这都是官方资料上的; 但 Add 函数中要的是 Integer 类型.
2、从上面获取的信息可以知道, GDI+1.0 还无法写入 gif 动画; GDI+1.1 能不能还没有测试.
3、通过设置 TIFF 编码器的 EncoderSaveFlag 类型参数可保存多页的 TIFF 文件, 下次接上.