通過 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 文件時使用了三種不同的質量參數(壓縮級別):
查看原圖(大圖)
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 編碼參數, 保存了旋轉後的圖片:
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 文件, 下次接上.