DELPHI中图片处理若干小问题
2008-10-07 14:41
309 查看
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,该函数定义如下:
function ColorToRGB(Color: TColor): Longint;
begin
if Color < 0 then
Result := GetSysColor(Color and $000000FF) else
Result := Color;
end;
根据TCOLOR的结构原始类型是longint,红色是$000000ff,绿色是$0000ff00,蓝色是$00ff0000,利用and运算,我们可以将三原色的数值分离出来。如下:
var
colour:TColor; r,g,b:byte;
begin
colour:=clsilver;
r:=(colour and $000000ff);
g:=(colour and $0000ff00);
b:=(colour and $00ff0000);
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色。设置该属性的函数定义如下:
procedure TBitmap.SetPixelFormat(Value: TPixelFormat);
const
BitCounts: array [pf1Bit..pf32Bit] of Byte = (1,4,8,16,16,24,32);
var
DIB: TDIBSection;
Pal: HPalette;
DC: HDC;
KillPal: Boolean;
begin
if Value = GetPixelFormat then Exit;
case Value of
pfDevice:
begin
HandleType := bmDDB;
Exit;
end;
pfCustom: InvalidGraphic(@SInvalidPixelFormat);
else
FillChar(DIB, sizeof(DIB), 0);
DIB.dsbm := FImage.FDIB.dsbm;
KillPal := False;
with DIB, dsbm, dsbmih do
begin
bmBits := nil;
biSize := sizeof(DIB.dsbmih);
biWidth := bmWidth;
biHeight := bmHeight;
biPlanes := 1;
biBitCount := BitCounts[Value];
Pal := FImage.FPalette;
case Value of
pf4Bit: Pal := SystemPalette16;
pf8Bit: //设置成256色。
begin
DC := GDICheck(GetDC(0));
Pal := CreateHalftonePalette(DC);
KillPal := True;
ReleaseDC(0, DC);
end;
pf16Bit:
begin
biCompression := BI_BITFIELDS;
dsBitFields[0] := $F800;
dsBitFields[1] := $07E0;
dsBitFields[2] := $001F;
end;
end;
try
CopyImage(Handle, Pal, DIB);
PaletteModified := Pal <> 0;
finally
if KillPal then DeleteObject(Pal);
end;
Changed(Self);
end;
end;
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。
procedure TForm1.BitBtn1Click(Sender: TObject);
var i,j,r :integer;tmp:TColor;rgbcolor:array[1..3] of byte;
begin
for i:=0 to 39 do begin
for j:=0 to 39 do begin
with self.Image1.Picture.Bitmap.Canvas do begin
tmp:= Pixels[i,j];
rgbcolor[1]:=GetRValue( tmp);
rgbcolor[2]:=GetGValue( tmp);
rgbcolor[3]:=GetBValue( tmp);
r:=(rgbcolor[1]*299+rgbcolor[2]*587+rgbcolor[3]*114+ 500) div 1000;
Pixels[i,j]:=rgb(r,r,r);
end;
end;
end;
end;
点击按钮后qq头像变灰,达到QQ下线后的灰头像效果。
===================================
非注明转载的文章和blog在未特殊声明情况下一般为本人原创或整理,版权 lonefox 所有,
http://blog.csdn.net/boythl
欢迎转载,但请注明出处,保留作者和版权信息。
===================================
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,该函数定义如下:
function ColorToRGB(Color: TColor): Longint;
begin
if Color < 0 then
Result := GetSysColor(Color and $000000FF) else
Result := Color;
end;
根据TCOLOR的结构原始类型是longint,红色是$000000ff,绿色是$0000ff00,蓝色是$00ff0000,利用and运算,我们可以将三原色的数值分离出来。如下:
var
colour:TColor; r,g,b:byte;
begin
colour:=clsilver;
r:=(colour and $000000ff);
g:=(colour and $0000ff00);
b:=(colour and $00ff0000);
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色。设置该属性的函数定义如下:
procedure TBitmap.SetPixelFormat(Value: TPixelFormat);
const
BitCounts: array [pf1Bit..pf32Bit] of Byte = (1,4,8,16,16,24,32);
var
DIB: TDIBSection;
Pal: HPalette;
DC: HDC;
KillPal: Boolean;
begin
if Value = GetPixelFormat then Exit;
case Value of
pfDevice:
begin
HandleType := bmDDB;
Exit;
end;
pfCustom: InvalidGraphic(@SInvalidPixelFormat);
else
FillChar(DIB, sizeof(DIB), 0);
DIB.dsbm := FImage.FDIB.dsbm;
KillPal := False;
with DIB, dsbm, dsbmih do
begin
bmBits := nil;
biSize := sizeof(DIB.dsbmih);
biWidth := bmWidth;
biHeight := bmHeight;
biPlanes := 1;
biBitCount := BitCounts[Value];
Pal := FImage.FPalette;
case Value of
pf4Bit: Pal := SystemPalette16;
pf8Bit: //设置成256色。
begin
DC := GDICheck(GetDC(0));
Pal := CreateHalftonePalette(DC);
KillPal := True;
ReleaseDC(0, DC);
end;
pf16Bit:
begin
biCompression := BI_BITFIELDS;
dsBitFields[0] := $F800;
dsBitFields[1] := $07E0;
dsBitFields[2] := $001F;
end;
end;
try
CopyImage(Handle, Pal, DIB);
PaletteModified := Pal <> 0;
finally
if KillPal then DeleteObject(Pal);
end;
Changed(Self);
end;
end;
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。
procedure TForm1.BitBtn1Click(Sender: TObject);
var i,j,r :integer;tmp:TColor;rgbcolor:array[1..3] of byte;
begin
for i:=0 to 39 do begin
for j:=0 to 39 do begin
with self.Image1.Picture.Bitmap.Canvas do begin
tmp:= Pixels[i,j];
rgbcolor[1]:=GetRValue( tmp);
rgbcolor[2]:=GetGValue( tmp);
rgbcolor[3]:=GetBValue( tmp);
r:=(rgbcolor[1]*299+rgbcolor[2]*587+rgbcolor[3]*114+ 500) div 1000;
Pixels[i,j]:=rgb(r,r,r);
end;
end;
end;
end;
点击按钮后qq头像变灰,达到QQ下线后的灰头像效果。
===================================
非注明转载的文章和blog在未特殊声明情况下一般为本人原创或整理,版权 lonefox 所有,
http://blog.csdn.net/boythl
欢迎转载,但请注明出处,保留作者和版权信息。
===================================
相关文章推荐
- 多列列表控件中图片尺寸处理的若干问题
- 从sql库里读取二进制图片的问题 (参数无效 未处理ArgumentException 错误的解决办法)
- Java处理某些图片红色问题
- Android开发中处理图片OOM的若干方法小结
- 关于Java Label里设置图片的若干问题
- delphi 处理图片(剪切,压缩)
- Android处理图片OOM的若干方法小结
- Android处理图片报OOM的问题解决
- Magento导入产品图片名称问题处理
- javaweb-图片的下载实现及分别处理浏览器乱码问题
- 处理IE6下PNG图片透明背景问题
- JAVA处理不正确处理图片ICC信息蒙上红色的问题 放弃ImageIO.read()
- Android处理图片OOM的若干方法小结
- Android处理图片OOM的若干方法小结
- 爬虫之爬取知乎下某个问题下的全部图片(处理AJAX请求,解析json数据)
- 图片加到json中,提交到服务器端处理异常问题。
- Java处理某些图片红色问题
- Android中处理加载图片时内存溢出问题
- Android:相机适配及图片处理的一些问题
- 关于使用 ps脚本来处理图片的排层问题