程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> GdiPlus[55]: 圖像(七) 圖像編碼的參數

GdiPlus[55]: 圖像(七) 圖像編碼的參數

編輯:Delphi

通過 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 文件時使用了三種不同的質量參數(壓縮級別):

GdiPlus[55]: 圖像(七) 圖像編碼的參數

  查看原圖(大圖)

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 編碼參數, 保存了旋轉後的圖片:

GdiPlus[55]: 圖像(七) 圖像編碼的參數

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 文件, 下次接上.




  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved