DELPHI中图片处理若干小问题

 

1.  delphi中TColor格式
  TColor类使用四个字节表示颜色,用十六进制表示就是   $PPBBGGRR   高   8   位指明使用的调色板(允许   0-2),次高   8   位指明颜色中绿)色的亮度(允许0-254),次低   8   位指明绿)色的亮度(允许0-254),低   8   位指明色的亮度(允许0-254)。  
  对于调色板,0   表示   使用系统的调色板,1   表示使用与当前调色板最匹配的调色板,2   表示使用与当前设备的逻辑调色板最接近的颜色。  
  对于颜色的亮度,数值约大表示亮度越高。

2.  TColor和RGB颜色转换
  有三个API可以从颜色值中取出R/G/B三个分量,
    R:=GetRValue(Color);  
    G:=GetGValue(Color);  
    B:=GetBValue(Color);  
 而另外一个API可以将R/G/B三分量合成一个颜色值,就是RGB函数,返回COLORREF
    Color:=RGB(R,G,B);
 
  一般地,GetRValue的参数可以直接用TCOLOR类型数据,但某些情况下,TCOLOR值小于0时(我尚不知何种情况下会为负数),需要转换,delphi提供了一个函数ColorToRGB,该函数定义如下:

  1. function ColorToRGB(Color: TColor): Longint;
  2. begin
  3.   if Color < 0 then
  4.     Result := GetSysColor(Color and $000000FFelse
  5.     Result := Color;
  6. end;

    根据TCOLOR的结构原始类型是longint,红色是$000000ff,绿色是$0000ff00,蓝色是$00ff0000,利用and运算,我们可以将三原色的数值分离出来。如下: 

  1.   var   
  2.         colour:TColor;     r,g,b:byte;   
  3.   begin   
  4.       colour:=clsilver;   
  5.       r:=(colour   and   $000000ff);   
  6.       g:=(colour   and   $0000ff00);   
  7.       b:=(colour   and   $00ff0000);   
  8.   end;

3. BMP模式转换
  TBitmap中有个PixelFormat属性,官方解释如下:
pfDevice The bitmap is stored as a device-dependent bitmap.
pf1bit The bitmap is a device-independent bitmap with one bit per pixel (black and white palette)  //黑白
pf4bit The bitmap is a device-independent bitmap that uses a 16-color palette.   //16色
pf8bit The bitmap is a device-independent bitmap that uses a 256color palette.   //256 色
pf15bit The bitmap is a device-independent true-color bitmap that uses 15 bits per pixel (RGB compression).
pf16bit The bitmap is a device-independent true-color bitmap that uses 16 bits per pixel (bitfield compression).

pf24bit The bitmap is a device-independent true-color bitmap that uses 24 bits per pixel. //24位真彩色
pf32bit The bitmap is a device-independent true-color bitmap that uses 32 bits per pixel (RGB compression).//32位真彩色
pfCustom The bitmap uses some other format. TBitmap does not support pfCustom.

  因此,将Bitmap.PixelFormat修改成pf8bit就可以简单的将bmp转为256色。设置该属性的函数定义如下:

  1. procedure TBitmap.SetPixelFormat(Value: TPixelFormat);
  2. const
  3.   BitCounts: array [pf1Bit..pf32Bit] of Byte = (1,4,8,16,16,24,32);
  4. var
  5.   DIB: TDIBSection;
  6.   Pal: HPalette;
  7.   DC: HDC;
  8.   KillPal: Boolean;
  9. begin
  10.   if Value = GetPixelFormat then Exit;
  11.   case Value of
  12.     pfDevice:
  13.       begin
  14.         HandleType := bmDDB;
  15.         Exit;
  16.       end;
  17.     pfCustom: InvalidGraphic(@SInvalidPixelFormat);
  18.   else
  19.     FillChar(DIB, sizeof(DIB), 0);
  20.     DIB.dsbm := FImage.FDIB.dsbm;
  21.     KillPal := False;
  22.     with DIB, dsbm, dsbmih do
  23.     begin
  24.       bmBits := nil;
  25.       biSize := sizeof(DIB.dsbmih);
  26.       biWidth := bmWidth;
  27.       biHeight := bmHeight;
  28.       biPlanes := 1;
  29.       biBitCount := BitCounts[Value];
  30.       Pal := FImage.FPalette;
  31.       case Value of
  32.         pf4Bit: Pal := SystemPalette16;
  33.         pf8Bit:    //设置成256色。
  34.           begin
  35.             DC := GDICheck(GetDC(0));
  36.             Pal := CreateHalftonePalette(DC);
  37.             KillPal := True;
  38.             ReleaseDC(0, DC);
  39.           end;
  40.         pf16Bit:
  41.           begin
  42.             biCompression := BI_BITFIELDS;
  43.             dsBitFields[0] := $F800;
  44.             dsBitFields[1] := $07E0;
  45.             dsBitFields[2] := $001F;
  46.           end;
  47.       end;
  48.       try
  49.         CopyImage(Handle, Pal, DIB);
  50.         PaletteModified := Pal <> 0;
  51.       finally
  52.         if KillPal then DeleteObject(Pal);
  53.       end;
  54.       Changed(Self);
  55.     end;
  56.   end;
  57. end;

   若自己写算法修改像素值实现,普遍使用如下公式:
     Gray = R*0.299 + G*0.587 + B*0.114
  而实际应用时,希望避免低速的浮点运算,所以需要整数算法。
     Gray = (R*299 + G*587 + B*114 + 500) / 1000
  RGB一般是8位精度,现在缩放1000倍,所以上面的运算是32位整型的运算。注意后面那个除法是整数除法,所以需要加上500来实现四舍五入。由于该算法需要32位运算,所以该公式的另一个变种很流行:
     Gray = (R*30 + G*59 + B*11 + 50) / 100

  如下算法经过测试通过,delphi7 +winxp,窗体上一个TImage,长宽各40像素,内装QQbmp头像一张,一个Tbitbtn。

  1. procedure TForm1.BitBtn1Click(Sender: TObject);
  2. var i,j,r :integer;tmp:TColor;rgbcolor:array[1..3of byte;
  3. begin
  4.   for i:=0 to 39 do begin
  5.     for j:=0 to 39 do begin
  6.       with      self.Image1.Picture.Bitmap.Canvas do begin
  7.         tmp:= Pixels[i,j];
  8.         rgbcolor[1]:=GetRValue(  tmp);
  9.         rgbcolor[2]:=GetGValue(  tmp);
  10.         rgbcolor[3]:=GetBValue(  tmp);
  11.         r:=(rgbcolor[1]*299+rgbcolor[2]*587+rgbcolor[3]*114500div 1000;
  12.         Pixels[i,j]:=rgb(r,r,r);
  13.       end;
  14.     end;
  15.   end;
  16. end;

  点击按钮后qq头像变灰,达到QQ下线后的灰头像效果。

 

===================================

非注明转载的文章和blog在未特殊声明情况下一般为本人原创或整理,版权 lonefox 所有,

http://blog.youkuaiyun.com/boythl

欢迎转载,但请注明出处,保留作者和版权信息。

===================================

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值