首页  编辑  

Delphi中的基本图象处理代码~~~

Tags: /超级猛料/Picture.图形图像编程/图形处理算法/   Date Created:

ehom ( ?!)

Delphi中的基本图象处理代码~~~

[图像的旋转和翻转]

以下代码用ScanLine配合指针移动实现,用于24位色,至于其它色深的处理和有些代码为什么要这样写的问题可查看我的另一篇文章!

//旋转90度

procedure Rotate90(const Bitmap:TBitmap);

var

 i,j:Integer;

 rowIn,rowOut:pRGBTriple;

 Bmp:TBitmap;

 Width,Height:Integer;

begin

 Bmp:=TBitmap.Create;

 Bmp.Width := Bitmap.Height;

 Bmp.Height := Bitmap.Width;

 Bmp.PixelFormat := pf24bit;

 Width:=Bitmap.Width-1;

 Height:=Bitmap.Height-1;

 for  j := 0 to Height do

 begin

   rowIn  := Bitmap.ScanLine[j];

   for i := 0 to Width do

   begin

     rowOut := Bmp.ScanLine[i];

     Inc(rowOut,Height - j);

     rowOut^ := rowIn^;

     Inc(rowIn);

   end;

 end;

 Bitmap.Assign(Bmp);

end;

//旋转180度

procedure Rotate180(const Bitmap:TBitmap);

var

 i,j:Integer;

 rowIn,rowOut:pRGBTriple;

 Bmp:TBitmap;

 Width,Height:Integer;

begin

 Bmp:=TBitmap.Create;

 Bmp.Width := Bitmap.Width;

 Bmp.Height := Bitmap.Height;

 Bmp.PixelFormat := pf24bit;

 Width:=Bitmap.Width-1;

 Height:=Bitmap.Height-1;

 for  j := 0 to Height do

 begin

   rowIn  := Bitmap.ScanLine[j];

   for i := 0 to Width do

   begin

     rowOut := Bmp.ScanLine[Height - j];

     Inc(rowOut,Width - i);

     rowOut^ := rowIn^;

     Inc(rowIn);

   end;

 end;

 Bitmap.Assign(Bmp);

end;

//旋转270度

procedure Rotate270(const Bitmap:TBitmap);

var

 i,j:Integer;

 rowIn,rowOut:pRGBTriple;

 Bmp:TBitmap;

 Width,Height:Integer;

begin

 Bmp:=TBitmap.Create;

 Bmp.Width := Bitmap.Height;

 Bmp.Height := Bitmap.Width;

 Bmp.PixelFormat := pf24bit;

 Width:=Bitmap.Width-1;

 Height:=Bitmap.Height-1;

 for  j := 0 to Height do

 begin

   rowIn  := Bitmap.ScanLine[j];

   for i := 0 to Width do

   begin

     rowOut := Bmp.ScanLine[Width - i];

     Inc(rowOut,j);

     rowOut^ := rowIn^;

     Inc(rowIn);

   end;

 end;

 Bitmap.Assign(Bmp);

end;

任意角度旋转就是将原图上的像素映射到新图上,以下代码为了好理解,并未进行充分优化!但速度上已经比较快了!我的另一篇文章中对优化问题进行了些简单说明,也就是尽量少用浮点运算!

前面为判断部分,如果是90,180,270这类特殊角度,将调用上面的代码,这样效率更高!

//任意角度

function RotateBitmap(Bitmap:TBitmap;Angle:Integer;BackColor:TColor):TBitmap;

var

 i,j,iOriginal,jOriginal,CosPoint,SinPoint : integer;

 RowOriginal,RowRotated : pRGBTriple;

 SinTheta,CosTheta : Extended;

 AngleAdd : integer;

begin

 Result:=TBitmap.Create;

 Result.PixelFormat := pf24bit;

 Result.Canvas.Brush.Color:=BackColor;

 Angle:=Angle Mod 360;

 if Angle<0 then Angle:=360-Abs(Angle);

 if Angle=0 then

   Result.Assign(Bitmap)

 else if Angle=90 then

 begin

   Result.Assign(Bitmap);

   Rotate90(Result);//如果是旋转90度,直接调用上面的代码

 end

 else if (Angle>90) and (Angle<180) then

 begin

   AngleAdd:=90;

   Angle:=Angle-AngleAdd;

 end

 else if Angle=180 then

 begin

   Result.Assign(Bitmap);

   Rotate180(Result);//如果是旋转180度,直接调用上面的过程

 end

 else if (Angle>180) and (Angle<270) then

 begin

   AngleAdd:=180;

   Angle:=Angle-AngleAdd;

 end

 else if Angle=270 then

 begin

   Result.Assign(Bitmap);

   Rotate270(Result);//如果是旋转270度,直接调用上面的过程

 end

 else if (Angle>270) and (Angle<360) then

 begin

   AngleAdd:=270;

   Angle:=Angle-AngleAdd;

 end

 else

   AngleAdd:=0;

 if (Angle>0) and (Angle<90) then

 begin

 SinCos((Angle + AngleAdd) * Pi / 180, SinTheta, CosTheta);

 if (SinTheta * CosTheta) < 0 then

 begin

   Result.Width := Round(Abs(Bitmap.Width * CosTheta - Bitmap.Height * SinTheta));

   Result.Height := Round(Abs(Bitmap.Width * SinTheta - Bitmap.Height * CosTheta));

 end

 else

 begin

   Result.Width := Round(Abs(Bitmap.Width * CosTheta + Bitmap.Height * SinTheta));

   Result.Height := Round(Abs(Bitmap.Width * SinTheta + Bitmap.Height * CosTheta));

 end;

 CosTheta:=Abs(CosTheta);

 SinTheta:=Abs(SinTheta);

 if (AngleAdd=0) or (AngleAdd=180) then

 begin

   CosPoint:=Round(Bitmap.Height*CosTheta);

   SinPoint:=Round(Bitmap.Height*SinTheta);

 end

 else

 begin

   SinPoint:=Round(Bitmap.Width*CosTheta);

   CosPoint:=Round(Bitmap.Width*SinTheta);

 end;

 for j := 0 to Result.Height-1 do

 begin

   RowRotated := Result.Scanline[j];

   for i := 0 to Result.Width-1 do

   begin

     Case AngleAdd of

       0:

       begin

         jOriginal := Round((j+1)*CosTheta-(i+1-SinPoint)*SinTheta)-1;

         iOriginal := Round((i+1)*CosTheta-(CosPoint-j-1)*SinTheta)-1;

       end;

       90:

       begin

         iOriginal := Round((j+1)*SinTheta-(i+1-SinPoint)*CosTheta)-1;

         jOriginal := Bitmap.Height-Round((i+1)*SinTheta-(CosPoint-j-1)*CosTheta);

       end;

       180:

       begin

         jOriginal := Bitmap.Height-Round((j+1)*CosTheta-(i+1-SinPoint)*SinTheta);

         iOriginal := Bitmap.Width-Round((i+1)*CosTheta-(CosPoint-j-1)*SinTheta);

       end;

       270:

       begin

         iOriginal := Bitmap.Width-Round((j+1)*SinTheta-(i+1-SinPoint)*CosTheta);

         jOriginal := Round((i+1)*SinTheta-(CosPoint-j-1)*CosTheta)-1;

       end;

     end;

     if (iOriginal >= 0) and (iOriginal <= Bitmap.Width-1)and

        (jOriginal >= 0) and (jOriginal <= Bitmap.Height-1)

     then

     begin

       RowOriginal := Bitmap.Scanline[jOriginal];

       Inc(RowOriginal,iOriginal);

       RowRotated^ := RowOriginal^;

       Inc(RowRotated);

     end

     else

     begin

       Inc(RowRotated);

     end;

   end;

 end;

 end;

end;

虽然这已经实现了图像任意角度的旋转,但注意看看上面的代码,都是用Round取整,也就是在原图中找最近的像素填充到新图中,这样在边缘会产生锯齿!如果想效果更好,应该是用四个像素的值运算后得到新像素的值!

如对应到原图的坐标是(6.3,8.6),用第一种方法可能就用(6,9)填充了该像素,但如果想消除边缘锯齿,就应该用(6,8)、(6,9)、(7,8)、(7,9)运算得出新点的像素,而边缘就用颜色等于背景色的点代替!

感兴趣的朋友可以找些二次线性插值资料看看,或者以后再讨论,这里就不多说了!

后面的浮雕滤镜效果其实就用到了线性插值的思想!

//水平翻转

procedure FlipHorz(const Bitmap:TBitmap);

var

 i,j:Integer;

 rowIn,rowOut:pRGBTriple;

 Bmp:TBitmap;

 Width,Height:Integer;

begin

 Bmp:=TBitmap.Create;

 Bmp.Width := Bitmap.Width;

 Bmp.Height := Bitmap.Height;

 Bmp.PixelFormat := pf24bit;

 Width:=Bitmap.Width-1;

 Height:=Bitmap.Height-1;

 for  j := 0 to Height do

 begin

   rowIn  := Bitmap.ScanLine[j];

   for i := 0 to Width do

   begin

     rowOut := Bmp.ScanLine[j];

     Inc(rowOut,Width - i);

     rowOut^ := rowIn^;

     Inc(rowIn);

   end;

 end;

 Bitmap.Assign(Bmp);

end;

//垂直翻转

procedure FlipVert(const Bitmap:TBitmap);

var

 i,j:Integer;

 rowIn,rowOut:pRGBTriple;

 Bmp:TBitmap;

 Width,Height:Integer;

begin

 Bmp:=TBitmap.Create;

 Bmp.Width := Bitmap.Height;

 Bmp.Height := Bitmap.Width;

 Bmp.PixelFormat := pf24bit;

 Width:=Bitmap.Width-1;

 Height:=Bitmap.Height-1;

 for  j := 0 to Height do

 begin

   rowIn  := Bitmap.ScanLine[j];

   for i := 0 to Width do

   begin

     rowOut := Bmp.ScanLine[Height - j];

     Inc(rowOut,i);

     rowOut^ := rowIn^;

     Inc(rowIn);

   end;

 end;

 Bitmap.Assign(Bmp);

end;

其实旋转90、180、270度,水平垂直翻转的原理基本类似,所以也可以改写为一个过程!

如果灵活的使用指针,减少用ScanLine的次数,代码效率还能有所提升~~~

[亮度、对比度、饱和度的调整]

function Min(a, b: integer): integer;

begin

 if a < b then

   result := a

 else

   result := b;

end;

function Max(a, b: integer): integer;

begin

 if a > b then

   result := a

 else

   result := b;

end;

//亮度调整

procedure BrightnessChange(const SrcBmp,DestBmp:TBitmap;ValueChange:integer);

var

 i, j: integer;

 SrcRGB, DestRGB: pRGBTriple;

begin

 for i := 0 to SrcBmp.Height - 1 do

 begin

   SrcRGB := SrcBmp.ScanLine[i];

   DestRGB := DestBmp.ScanLine[i];

   for j := 0 to SrcBmp.Width - 1 do

   begin

     if ValueChange > 0 then

     begin

       DestRGB.rgbtRed := Min(255, SrcRGB.rgbtRed + ValueChange);

       DestRGB.rgbtGreen := Min(255, SrcRGB.rgbtGreen + ValueChange);

       DestRGB.rgbtBlue := Min(255, SrcRGB.rgbtBlue + ValueChange);

     end else begin

       DestRGB.rgbtRed := Max(0, SrcRGB.rgbtRed + ValueChange);

       DestRGB.rgbtGreen := Max(0, SrcRGB.rgbtGreen + ValueChange);

       DestRGB.rgbtBlue := Max(0, SrcRGB.rgbtBlue + ValueChange);

     end;

     Inc(SrcRGB);

     Inc(DestRGB);

   end;

 end;

end;

//对比度调整

procedure ContrastChange(const SrcBmp,DestBmp:TBitmap;ValueChange:integer);

var

 i, j: integer;

 SrcRGB, DestRGB: pRGBTriple;

begin

 for i := 0 to SrcBmp.Height - 1 do

 begin

   SrcRGB := SrcBmp.ScanLine[i];

   DestRGB := DestBmp.ScanLine[i];

   for j := 0 to SrcBmp.Width - 1 do

   begin

     if ValueChange>=0 then

     begin

     if SrcRGB.rgbtRed >= 128 then

       DestRGB.rgbtRed := Min(255, SrcRGB.rgbtRed + ValueChange)

     else

       DestRGB.rgbtRed := Max(0, SrcRGB.rgbtRed - ValueChange);

     if SrcRGB.rgbtGreen >= 128 then

       DestRGB.rgbtGreen := Min(255, SrcRGB.rgbtGreen + ValueChange)

     else

       DestRGB.rgbtGreen := Max(0, SrcRGB.rgbtGreen - ValueChange);

     if SrcRGB.rgbtBlue >= 128 then

       DestRGB.rgbtBlue := Min(255, SrcRGB.rgbtBlue + ValueChange)

     else

       DestRGB.rgbtBlue := Max(0, SrcRGB.rgbtBlue - ValueChange);

     end

     else

     begin

     if SrcRGB.rgbtRed >= 128 then

       DestRGB.rgbtRed := Max(128, SrcRGB.rgbtRed + ValueChange)

     else

       DestRGB.rgbtRed := Min(128, SrcRGB.rgbtRed - ValueChange);

     if SrcRGB.rgbtGreen >= 128 then

       DestRGB.rgbtGreen := Max(128, SrcRGB.rgbtGreen + ValueChange)

     else

       DestRGB.rgbtGreen := Min(128, SrcRGB.rgbtGreen - ValueChange);

     if SrcRGB.rgbtBlue >= 128 then

       DestRGB.rgbtBlue := Max(128, SrcRGB.rgbtBlue + ValueChange)

     else

       DestRGB.rgbtBlue := Min(128, SrcRGB.rgbtBlue - ValueChange);

     end;

     Inc(SrcRGB);

     Inc(DestRGB);

   end;

 end;

end;

//饱和度调整

procedure SaturationChange(const SrcBmp,DestBmp:TBitmap;ValueChange:integer);

var

 Grays: array[0..767] of Integer;

 Alpha: array[0..255] of Word;

 Gray, x, y: Integer;

 SrcRGB,DestRGB: pRGBTriple;

 i: Byte;

begin

ValueChange:=ValueChange+255;

for i := 0 to 255 do

 Alpha[i] := (i * ValueChange) Shr 8;

x := 0;

for i := 0 to 255 do

begin

 Gray := i - Alpha[i];

 Grays[x] := Gray;

 Inc(x);

 Grays[x] := Gray;

 Inc(x);

 Grays[x] := Gray;

 Inc(x);

end;

for y := 0 to SrcBmp.Height - 1 do

begin

 SrcRGB := SrcBmp.ScanLine[Y];

 DestRGB := DestBmp.ScanLine[Y];

 for x := 0 to SrcBmp.Width - 1 do

 begin

   Gray := Grays[SrcRGB.rgbtRed + SrcRGB.rgbtGreen + SrcRGB.rgbtBlue];

   if Gray + Alpha[SrcRGB.rgbtRed]>0 then

     DestRGB.rgbtRed := Min(255,Gray + Alpha[SrcRGB.rgbtRed])

   else

     DestRGB.rgbtRed := 0;

   if Gray + Alpha[SrcRGB.rgbtGreen]>0 then

     DestRGB.rgbtGreen := Min(255,Gray + Alpha[SrcRGB.rgbtGreen])

   else

     DestRGB.rgbtGreen := 0;

   if Gray + Alpha[SrcRGB.rgbtBlue]>0 then

     DestRGB.rgbtBlue := Min(255,Gray + Alpha[SrcRGB.rgbtBlue])

   else

     DestRGB.rgbtBlue := 0;

   Inc(SrcRGB);

   Inc(DestRGB);

 end;

end;

end;

//RGB调整

procedure RGBChange(SrcBmp,DestBmp:TBitmap;RedChange,GreenChange,BlueChange:integer);

var

 SrcRGB, DestRGB: pRGBTriple;

 i,j:integer;

begin

 for i := 0 to SrcBmp.Height- 1 do

 begin

   SrcRGB := SrcBmp.ScanLine[i];

   DestRGB :=DestBmp.ScanLine[i];

   for j := 0 to SrcBmp.Width - 1 do

   begin

     if RedChange> 0 then

       DestRGB.rgbtRed := Min(255, SrcRGB.rgbtRed + RedChange)

     else

       DestRGB.rgbtRed := Max(0, SrcRGB.rgbtRed + RedChange);

     if GreenChange> 0 then

       DestRGB.rgbtGreen := Min(255, SrcRGB.rgbtGreen + GreenChange)

     else

       DestRGB.rgbtGreen := Max(0, SrcRGB.rgbtGreen + GreenChange);

     if BlueChange> 0 then

       DestRGB.rgbtBlue := Min(255, SrcRGB.rgbtBlue + BlueChange)

     else

       DestRGB.rgbtBlue := Max(0, SrcRGB.rgbtBlue + BlueChange);

     Inc(SrcRGB);

     Inc(DestRGB);

   end;

 end;

end;

如果有些图像处理的基础,这些代码都比较好理解,主要是三原色的值不要超过(0-255)的范围,有些朋友没有注意这问题,当超过范围后,会出现些难看的"色斑"!

[颜色调整]

//RGB<=>BGR

procedure RGB2BGR(const Bitmap:TBitmap);

var

 X: Integer;

 Y: Integer;

 PRGB: pRGBTriple;

 Color: Byte;

begin

 for Y := 0 to (Bitmap.Height - 1) do

 begin

   for X := 0 to (Bitmap.Width - 1) do

   begin

     Color := PRGB^.rgbtRed;

     PRGB^.rgbtRed := PRGB^.rgbtBlue;

     PRGB^.rgbtBlue := Color;

     Inc(PRGB);

   end;

   end

 end;

end;

//灰度化(加权)

procedure Grayscale(const Bitmap:TBitmap);

var

 X: Integer;

 Y: Integer;

 PRGB: pRGBTriple;

 Gray: Byte;

begin

 for Y := 0 to (Bitmap.Height - 1) do

 begin

   PRGB := Bitmap.ScanLine[Y];

   for X := 0 to (Bitmap.Width - 1) do

   begin

     Gray := (77 * Red + 151 * Green + 28 * Blue) shr 8;

     PRGB^.rgbtRed:=Gray;

     PRGB^.rgbtGreen:=Gray;

     PRGB^.rgbtBlue:=Gray;

     Inc(PRGB);

   end;

 end;

end;

关于灰度化,我的另一篇文章中进行了详细的探讨!

 

[常用滤镜效果]

过于浮雕效果,代码网上也有,但一般不支持角度变化!这里根据角度的不同,在一个像素周围的8个像素中取不同的两个运算得到新颜色值,用这个值和它求差值实现浮雕效果。用到了线性插值的思想。这里没有使用浮点运算!

//浮雕

procedure Emboss(SrcBmp,DestBmp:TBitmap;AzimuthChange:integer);overload;

var

 i, j, Gray, Azimuthvalue, R, G, B: integer;

 SrcRGB, SrcRGB1, SrcRGB2, DestRGB: pRGBTriple;

begin

 for i := 0 to SrcBmp.Height - 1 do

 begin

   SrcRGB := SrcBmp.ScanLine[i];

   DestRGB := DestBmp.ScanLine[i];

   if (AzimuthChange >= -180) and (AzimuthChange < -135) then

   begin

     if i > 0 then

       SrcRGB1 := SrcBmp.ScanLine[i-1]

     else

       SrcRGB1 := SrcRGB;

     Inc(SrcRGB1);

     SrcRGB2 := SrcRGB;

     Inc(SrcRGB2);

   end

   else if (AzimuthChange >= -135) and (AzimuthChange < -90) then

   begin

     if i > 0 then

       SrcRGB1 := SrcBmp.ScanLine[i-1]

     else

       SrcRGB1 := SrcRGB;

     SrcRGB2 := SrcRGB1;

     Inc(SrcRGB2);

   end

   else if (AzimuthChange >= -90) and (AzimuthChange < -45) then

   begin

     if i > 0 then

       SrcRGB1 := SrcBmp.ScanLine[i-1]

     else

       SrcRGB1 := SrcRGB;

     SrcRGB2 := SrcRGB1;

   end

   else if (AzimuthChange >= -45) and (AzimuthChange < 0) then

   begin

     SrcRGB1 := SrcRGB;

     if i > 0 then

       SrcRGB2 := SrcBmp.ScanLine[i-1]

     else

       SrcRGB2 := SrcRGB;

   end

   else if (AzimuthChange >= 0) and (AzimuthChange < 45) then

   begin

     SrcRGB2 := SrcRGB;

     if (i < SrcBmp.Height - 1) then

       SrcRGB1 := SrcBmp.ScanLine[i+1]

     else

       SrcRGB1 := SrcRGB;

   end

   else if (AzimuthChange >= 45) and (AzimuthChange < 90) then

   begin

     if (i < SrcBmp.Height - 1) then

       SrcRGB1 := SrcBmp.ScanLine[i+1]

     else

       SrcRGB1 := SrcRGB;

     SrcRGB2 := SrcRGB1;

   end

   else if (AzimuthChange >= 90) and (AzimuthChange < 135) then

   begin

     if (i < SrcBmp.Height - 1) then

       SrcRGB1 := SrcBmp.ScanLine[i+1]

     else

       SrcRGB1 := SrcRGB;

     SrcRGB2 := SrcRGB1;

     Inc(SrcRGB1);

   end

   else if (AzimuthChange >= 135) and (AzimuthChange <= 180) then

   begin

     if (i < SrcBmp.Height - 1) then

       SrcRGB2 := SrcBmp.ScanLine[i+1]

     else

       SrcRGB2 := SrcRGB;

     Inc(SrcRGB2);

     SrcRGB1 := SrcRGB;

     Inc(SrcRGB1);

   end;

   for j := 0 to SrcBmp.Width - 1 do

   begin

     if (AzimuthChange >= -180) and (AzimuthChange < -135) then

     begin

       Azimuthvalue := AzimuthChange + 180;

       R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed)*Azimuthvalue div 45)-((SrcRGB2.rgbtRed)*(45-Azimuthvalue) div 45)+78;

       G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen)*Azimuthvalue div 45)-((SrcRGB2.rgbtGreen)*(45-Azimuthvalue) div 45)+78;

       B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue)*Azimuthvalue div 45)-((SrcRGB2.rgbtBlue)*(45-Azimuthvalue) div 45)+78;

     end

     else if (AzimuthChange >= -135) and (AzimuthChange < -90) then

     begin

       Azimuthvalue := AzimuthChange + 135;

       R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed)*Azimuthvalue div 45)-((SrcRGB2.rgbtRed)*(45-Azimuthvalue) div 45)+78;

       G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen)*Azimuthvalue div 45)-((SrcRGB2.rgbtGreen)*(45-Azimuthvalue) div 45)+78;

       B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue)*Azimuthvalue div 45)-((SrcRGB2.rgbtBlue)*(45-Azimuthvalue) div 45)+78;

     end

     else if (AzimuthChange >= -90) and (AzimuthChange < -45) then

     begin

       if j=1 then Inc(SrcRGB1,-1);

       Azimuthvalue := AzimuthChange + 90;

       R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed)*Azimuthvalue div 45)-((SrcRGB2.rgbtRed)*(45-Azimuthvalue) div 45)+78;

       G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen)*Azimuthvalue div 45)-((SrcRGB2.rgbtGreen)*(45-Azimuthvalue) div 45)+78;

       B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue)*Azimuthvalue div 45)-((SrcRGB2.rgbtBlue)*(45-Azimuthvalue) div 45)+78;

     end

     else if (AzimuthChange >= -45) and (AzimuthChange < 0) then

     begin

       if j=1 then

       begin

         Inc(SrcRGB1,-1);

         Inc(SrcRGB2,-1);

       end;

       Azimuthvalue := AzimuthChange + 45;

       R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed)*Azimuthvalue div 45)-((SrcRGB2.rgbtRed)*(45-Azimuthvalue) div 45)+78;

       G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen)*Azimuthvalue div 45)-((SrcRGB2.rgbtGreen)*(45-Azimuthvalue) div 45)+78;

       B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue)*Azimuthvalue div 45)-((SrcRGB2.rgbtBlue)*(45-Azimuthvalue) div 45)+78;

     end

     else if (AzimuthChange >= 0) and (AzimuthChange < 45) then

     begin

       if j=1 then

       begin

         Inc(SrcRGB1,-1);

         Inc(SrcRGB2,-1);

       end;

       Azimuthvalue := AzimuthChange;

       R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed)*Azimuthvalue div 45)-((SrcRGB2.rgbtRed)*(45-Azimuthvalue) div 45)+78;

       G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen)*Azimuthvalue div 45)-((SrcRGB2.rgbtGreen)*(45-Azimuthvalue) div 45)+78;

       B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue)*Azimuthvalue div 45)-((SrcRGB2.rgbtBlue)*(45-Azimuthvalue) div 45)+78;

     end

     else if (AzimuthChange >= 45) and (AzimuthChange < 90) then

     begin

       if j=1 then Inc(SrcRGB2,-1);

       Azimuthvalue := AzimuthChange - 45;

       R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed)*Azimuthvalue div 45)-((SrcRGB2.rgbtRed)*(45-Azimuthvalue) div 45)+78;

       G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen)*Azimuthvalue div 45)-((SrcRGB2.rgbtGreen)*(45-Azimuthvalue) div 45)+78;

       B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue)*Azimuthvalue div 45)-((SrcRGB2.rgbtBlue)*(45-Azimuthvalue) div 45)+78;

     end

     else if (AzimuthChange >= 90) and (AzimuthChange < 135) then

     begin

       Azimuthvalue := AzimuthChange - 90;

       R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed)*Azimuthvalue div 45)-((SrcRGB2.rgbtRed)*(45-Azimuthvalue) div 45)+78;

       G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen)*Azimuthvalue div 45)-((SrcRGB2.rgbtGreen)*(45-Azimuthvalue) div 45)+78;

       B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue)*Azimuthvalue div 45)-((SrcRGB2.rgbtBlue)*(45-Azimuthvalue) div 45)+78;

     end

     else if (AzimuthChange >= 135) and (AzimuthChange <= 180) then

     begin

       Azimuthvalue := AzimuthChange - 135;

       R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed)*Azimuthvalue div 45)-((SrcRGB2.rgbtRed)*(45-Azimuthvalue) div 45)+78;

       G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen)*Azimuthvalue div 45)-((SrcRGB2.rgbtGreen)*(45-Azimuthvalue) div 45)+78;

       B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue)*Azimuthvalue div 45)-((SrcRGB2.rgbtBlue)*(45-Azimuthvalue) div 45)+78;

     end;

     R:=Min(R,255);

     R:=Max(R,0);

     G:=Min(G,255);

     G:=Max(G,0);

     B:=Min(B,255);

     B:=Max(B,0);

     Gray := (R shr 2) + (R shr 4) + (G shr 1) + (G shr 4) + (B shr 3);

     DestRGB.rgbtRed:=Gray;

     DestRGB.rgbtGreen:=Gray;

     DestRGB.rgbtBlue:=Gray;

     if (j<SrcBmp.Width - 1) or not (((AzimuthChange>=-180) and (AzimuthChange<-135)) or ((AzimuthChange>=90) and (AzimuthChange<=180))) then

     begin

       Inc(SrcRGB1);

     end;

     if (j<SrcBmp.Width - 1) or not (((AzimuthChange>=135) and (AzimuthChange<180)) or ((AzimuthChange>=-180) and (AzimuthChange<=-90))) then

     begin

       Inc(SrcRGB2);

     end;

     Inc(SrcRGB);

     Inc(DestRGB);

   end;

 end;

end;

procedure Emboss(Bmp:TBitmap;AzimuthChange:integer;ElevationChange:integer;WeightChange:integer);overload;

var

 DestBmp:TBitmap;

begin

  DestBmp:=TBitmap.Create;

  DestBmp.Assign(Bmp);

  Emboss(Bmp,DestBmp,AzimuthChange,ElevationChange,WeightChange);

  Bmp.Assign(DestBmp);

end;

 

//反色

procedure Negative(Bmp:TBitmap);

var

 i, j: Integer;

 PRGB: pRGBTriple;

begin

 Bmp.PixelFormat:=pf24Bit;

 for i := 0 to Bmp.Height - 1 do

 begin

   PRGB := Bmp.ScanLine[i];

   for j := 0 to Bmp.Width - 1 do

   begin

     PRGB^.rgbtRed :=not PRGB^.rgbtRed ;

     PRGB^.rgbtGreen :=not PRGB^.rgbtGreen;

     PRGB^.rgbtBlue :=not PRGB^.rgbtBlue;

     Inc(PRGB);

   end;

 end;

end;

//曝光

procedure Exposure(Bmp:TBitmap);

var

 i, j: integer;

 PRGB: pRGBTriple;

begin

 Bmp.PixelFormat:=pf24Bit;

 for i := 0 to Bmp.Height - 1 do

 begin

   PRGB := Bmp.ScanLine[i];

   for j := 0 to Bmp.Width - 1 do

   begin

     if PRGB^.rgbtRed<128 then

       PRGB^.rgbtRed :=not PRGB^.rgbtRed ;

     if PRGB^.rgbtGreen<128 then

       PRGB^.rgbtGreen :=not PRGB^.rgbtGreen;

     if PRGB^.rgbtBlue<128 then

       PRGB^.rgbtBlue :=not PRGB^.rgbtBlue;

     Inc(PRGB);

   end;

 end;

end;

//模糊

procedure Blur(SrcBmp:TBitmap);

var

 i, j:Integer;

 SrcRGB:pRGBTriple;

 SrcNextRGB:pRGBTriple;

 SrcPreRGB:pRGBTriple;

 Value:Integer;

 procedure IncRGB;

 begin

   Inc(SrcPreRGB);

   Inc(SrcRGB);

   Inc(SrcNextRGB);

 end;

 procedure DecRGB;

 begin

   Inc(SrcPreRGB,-1);

   Inc(SrcRGB,-1);

   Inc(SrcNextRGB,-1);

 end;

begin

 SrcBmp.PixelFormat:=pf24Bit;

 for i := 0 to SrcBmp.Height - 1 do

 begin

   if i > 0 then

     SrcPreRGB:=SrcBmp.ScanLine[i-1]

   else

     SrcPreRGB := SrcBmp.ScanLine[i];

   SrcRGB := SrcBmp.ScanLine[i];

   if i < SrcBmp.Height - 1 then

     SrcNextRGB:=SrcBmp.ScanLine[i+1]

   else

     SrcNextRGB:=SrcBmp.ScanLine[i];

   for j := 0 to SrcBmp.Width - 1 do

   begin

     if j > 0 then DecRGB;

     Value:=SrcPreRGB.rgbtRed+SrcRGB.rgbtRed+SrcNextRGB.rgbtRed;

     if j > 0 then IncRGB;

     Value:=Value+SrcPreRGB.rgbtRed+SrcRGB.rgbtRed+SrcNextRGB.rgbtRed;

     if j < SrcBmp.Width - 1 then IncRGB;

     Value:=(Value+SrcPreRGB.rgbtRed+SrcRGB.rgbtRed+SrcNextRGB.rgbtRed) div 9;

     DecRGB;

     SrcRGB.rgbtRed:=value;

     if j > 0 then DecRGB;

     Value:=SrcPreRGB.rgbtGreen+SrcRGB.rgbtGreen+SrcNextRGB.rgbtGreen;

     if j > 0 then IncRGB;

     Value:=Value+SrcPreRGB.rgbtGreen+SrcRGB.rgbtGreen+SrcNextRGB.rgbtGreen;

     if j < SrcBmp.Width - 1 then IncRGB;

     Value:=(Value+SrcPreRGB.rgbtGreen+SrcRGB.rgbtGreen+SrcNextRGB.rgbtGreen) div 9;

     DecRGB;

     SrcRGB.rgbtGreen:=value;

     if j > 0 then DecRGB;

     Value:=SrcPreRGB.rgbtBlue+SrcRGB.rgbtBlue+SrcNextRGB.rgbtBlue;

     if j > 0 then IncRGB;

     Value:=Value+SrcPreRGB.rgbtBlue+SrcRGB.rgbtBlue+SrcNextRGB.rgbtBlue;

     if j < SrcBmp.Width - 1 then IncRGB;

     Value:=(Value+SrcPreRGB.rgbtBlue+SrcRGB.rgbtBlue+SrcNextRGB.rgbtBlue) div 9;

     DecRGB;

     SrcRGB.rgbtBlue:=value;

     IncRGB;

   end;

 end;

end;

//锐化

procedure Sharpen(SrcBmp:TBitmap);

var

 i, j: integer;

 SrcRGB: pRGBTriple;

 SrcPreRGB: pRGBTriple;

 Value: integer;

begin

 SrcBmp.PixelFormat:=pf24Bit;

 for i := 0 to SrcBmp.Height - 1 do

 begin

   SrcRGB := SrcBmp.ScanLine[i];

   if i > 0 then

     SrcPreRGB:=SrcBmp.ScanLine[i-1]

   else

     SrcPreRGB:=SrcBmp.ScanLine[i];

   for j := 0 to SrcBmp.Width - 1 do

   begin

     if j = 1 then Dec(SrcPreRGB);

     Value:=SrcRGB.rgbtRed+(SrcRGB.rgbtRed-SrcPreRGB.rgbtRed) div 2;

     Value:=Max(0,Value);

     Value:=Min(255,Value);

     SrcRGB.rgbtRed:=value;

     Value:=SrcRGB.rgbtGreen+(SrcRGB.rgbtGreen-SrcPreRGB.rgbtGreen) div 2;

     Value:=Max(0,Value);

     Value:=Min(255,Value);

     SrcRGB.rgbtGreen:=value;

     Value:=SrcRGB.rgbtBlue+(SrcRGB.rgbtBlue-SrcPreRGB.rgbtBlue) div 2;

     Value:=Max(0,Value);

     Value:=Min(255,Value);

     SrcRGB.rgbtBlue:=value;

     Inc(SrcRGB);

     Inc(SrcPreRGB);

   end;

 end;

end;

由Delphi中的图像灰度化代码看基本图像处理~~~

http://expert.csdn.net/Expert/TopicView1.asp?id=1472467

   

模糊效果在处理指针移动时有些BUG,现贴出修正后的代码

//模糊

procedure Blur(SrcBmp:TBitmap);

var

 i, j:Integer;

 SrcRow:pRGBTriple;

 SrcNextRow:pRGBTriple;

 SrcPreRow:pRGBTriple;

 Value:Integer;

 procedure IncRow;

 begin

   Inc(SrcPreRow);

   Inc(SrcRow);

   Inc(SrcNextRow);

 end;

 procedure DecRow;

 begin

   Inc(SrcPreRow,-1);

   Inc(SrcRow,-1);

   Inc(SrcNextRow,-1);

 end;

begin

 SrcBmp.PixelFormat:=pf24Bit;

 for i := 0 to SrcBmp.Height - 1 do

 begin

   if i > 0 then

     SrcPreRow:=SrcBmp.ScanLine[i-1]

   else

     SrcPreRow := SrcBmp.ScanLine[i];

   SrcRow := SrcBmp.ScanLine[i];

   if i < SrcBmp.Height - 1 then

     SrcNextRow:=SrcBmp.ScanLine[i+1]

   else

     SrcNextRow:=SrcBmp.ScanLine[i];

   for j := 0 to SrcBmp.Width - 1 do

   begin

     if j > 0 then DecRow;

     Value:=SrcPreRow.rgbtRed+SrcRow.rgbtRed+SrcNextRow.rgbtRed;

     if j > 0 then IncRow;

     Value:=Value+SrcPreRow.rgbtRed+SrcRow.rgbtRed+SrcNextRow.rgbtRed;

     if j < SrcBmp.Width - 1 then IncRow;

     Value:=(Value+SrcPreRow.rgbtRed+SrcRow.rgbtRed+SrcNextRow.rgbtRed) div 9;

     if j < SrcBmp.Width - 1 then DecRow;

     SrcRow.rgbtRed:=value;

     if j > 0 then DecRow;

     Value:=SrcPreRow.rgbtGreen+SrcRow.rgbtGreen+SrcNextRow.rgbtGreen;

     if j > 0 then IncRow;

     Value:=Value+SrcPreRow.rgbtGreen+SrcRow.rgbtGreen+SrcNextRow.rgbtGreen;

     if j < SrcBmp.Width - 1 then IncRow;

     Value:=(Value+SrcPreRow.rgbtGreen+SrcRow.rgbtGreen+SrcNextRow.rgbtGreen) div 9;

     if j < SrcBmp.Width - 1 then DecRow;

     SrcRow.rgbtGreen:=value;

     if j > 0 then DecRow;

     Value:=SrcPreRow.rgbtBlue+SrcRow.rgbtBlue+SrcNextRow.rgbtBlue;

     if j > 0 then IncRow;

     Value:=Value+SrcPreRow.rgbtBlue+SrcRow.rgbtBlue+SrcNextRow.rgbtBlue;

     if j < SrcBmp.Width - 1 then IncRow;

     Value:=(Value+SrcPreRow.rgbtBlue+SrcRow.rgbtBlue+SrcNextRow.rgbtBlue) div 9;

     if j < SrcBmp.Width - 1 then DecRow;

     SrcRow.rgbtBlue:=value;

     IncRow;

   end;

 end;

end;

 

Windows provide two API "GetDeviceGammaRamp/SetDeviceGammaRamp" to perform gamma correction.  In fact we need to have an 3 dimension buffer of 256 WORD to manipulate gamma correction.  To change gamma it is necessary to change the RGB value of each color contained in the buffer by a float factor between 0.0 and 2.0.

上面的是系统支持的两个API(2000)

http://www.codeproject.com/useritems/gamma_manager.asp

回复人: ehom(?!) ( ) 信誉:128  2003-03-04 19:41:00  得分:0

 //修改后的对比度调整代码

procedure ContrastChange(const SrcBmp,DestBmp:TBitmap;ValueChange:integer);

var

 i, j: integer;

 SrcRow, DestRow: pRGBTriple;

begin

 for i := 0 to SrcBmp.Height - 1 do

 begin

   SrcRow := SrcBmp.ScanLine[i];

   DestRow := DestBmp.ScanLine[i];

   for j := 0 to SrcBmp.Width - 1 do

   begin

     if ValueChange>=0 then

     begin

     if SrcRow.rgbtRed >= 128 then

       DestRow.rgbtRed := Min(255, SrcRow.rgbtRed + (Abs(128 - SrcRow.rgbtRed) * ValueChange) div 128)

     else

       DestRow.rgbtRed := Max(0, SrcRow.rgbtRed - (Abs(128 - SrcRow.rgbtRed) * ValueChange) div 128);

     if SrcRow.rgbtGreen >= 128 then

       DestRow.rgbtGreen := Min(255, SrcRow.rgbtGreen + (Abs(128 - SrcRow.rgbtGreen) * ValueChange) div 128)

     else

       DestRow.rgbtGreen := Max(0, SrcRow.rgbtGreen - (Abs(128 - SrcRow.rgbtGreen) * ValueChange) div 128);

     if SrcRow.rgbtBlue >= 128 then

       DestRow.rgbtBlue := Min(255, SrcRow.rgbtBlue + (Abs(128 - SrcRow.rgbtBlue) * ValueChange) div 128)

     else

       DestRow.rgbtBlue := Max(0, SrcRow.rgbtBlue - (Abs(128 - SrcRow.rgbtBlue) * ValueChange) div 128);

     end

     else

     begin

     if SrcRow.rgbtRed >= 128 then

       DestRow.rgbtRed := Max(128, SrcRow.rgbtRed + (Abs(128 - SrcRow.rgbtRed) * ValueChange) div 128)

     else

       DestRow.rgbtRed := Min(128, SrcRow.rgbtRed - (Abs(128 - SrcRow.rgbtRed) * ValueChange) div 128);

     if SrcRow.rgbtGreen >= 128 then

       DestRow.rgbtGreen := Max(128, SrcRow.rgbtGreen + (Abs(128 - SrcRow.rgbtGreen) * ValueChange) div 128)

     else

       DestRow.rgbtGreen := Min(128, SrcRow.rgbtGreen - (Abs(128 - SrcRow.rgbtGreen) * ValueChange) div 128);

     if SrcRow.rgbtBlue >= 128 then

       DestRow.rgbtBlue := Max(128, SrcRow.rgbtBlue + (Abs(128 - SrcRow.rgbtBlue) * ValueChange) div 128)

     else

       DestRow.rgbtBlue := Min(128, SrcRow.rgbtBlue - (Abs(128 - SrcRow.rgbtBlue) * ValueChange) div 128);

     end;

     Inc(SrcRow);

     Inc(DestRow);

   end;

 end;

end;

 

Top