Delphi中改变图片(bitmap)的亮度、对比度、饱和度

最近在做视频处理相关的工作,遇到一些图片处理的问题,从别处找到解决的代码。 

其中对比度调节的代码处理结果看起来不太舒服,暂时没时间仔细研究,先放在这里。

// 改亮度
function ChangeBrightness(bmp: TBitmap; s: Integer): Boolean;
var
  p: PByteArray;
  x, y: Integer;
begin
  try
    //24位真彩色
    Bmp.PixelFormat   :=   pf24Bit;

    bmp.Canvas.Lock;
    for y := 0 to Bmp.Height - 1 do
    begin
      p := Bmp.scanline[y];
      for x := 0 to Bmp.Width - 1 do
      begin
        //每个象素点的R、G、B分量进行调节
        begin
          if s > 0 then
          begin
            p[x * 3] := Min(255, p[x * 3] + s); //不能越界,限制在0~255
            p[x * 3 + 1] := Min(255, p[x * 3 + 1] + s);
            p[x * 3 + 2] := Min(255, p[x * 3 + 2] + s);
          end
          else
          begin
            p[x * 3] := max(0, p[x * 3] + s); //不能越界,限制在-255~0
            p[x * 3 + 1] := max(0, p[x * 3 + 1] + s);
            p[x * 3 + 2] := max(0, p[x * 3 + 2] + s);
          end;
        end;
      end;
    end;
    bmp.Canvas.Unlock;

    Result := true;
  except
    Result := false;
  end;

end;
// 改对比度
function ChangeContrast(bmp: TBitmap; s: Integer): Boolean;
const
  CMid = 128;
  CMin = 10;
  CMax = 246;
var
  p: PByteArray;
  x, y: Integer; 
begin
  try
    //24位真彩色
    Bmp.PixelFormat   :=   pf24Bit;

    bmp.Canvas.Lock;
    for y := 0 to Bmp.Height - 1 do
    begin
      p := Bmp.ScanLine[y];
      for x := 0 to Bmp.Width - 1 do
      begin
        //确定阀值为128 
        if (p[x*3] > CMid) and (p[x*3] <= CMax)
          and (p[x*3+1] > CMid) and (p[x*3+1] <= CMax)
          and (p[x*3+2] > CMid) and (p[x*3+2] <= CMax) then
        begin
          p[x*3]  := Min(255, p[x*3]  + s * p[x*3]   div (p[x*3]+p[x*3+1]+p[x*3+2]));
          p[x*3+1]:= Min(255, p[x*3+1]+ s * p[x*3+1] div (p[x*3]+p[x*3+1]+p[x*3+2]));
          p[x*3+2]:= Min(255, p[x*3+2]+ s * p[x*3+2] div (p[x*3]+p[x*3+1]+p[x*3+2]));
        end;
        if (p[x*3] > CMin) and (p[x*3] <= CMid)
          and (p[x*3+1] > CMin) and (p[x*3+1] <= CMid)
          and (p[x*3+2] > CMin) and (p[x*3+2] <= CMid) then
        begin
          p[x*3]  := Max(0, p[x*3]  - s * p[x*3]   div (p[x*3]+p[x*3+1]+p[x*3+2]));
          p[x*3+1]:= Max(0, p[x*3+1]- s * p[x*3+1] div (p[x*3]+p[x*3+1]+p[x*3+2]));
          p[x*3+2]:= Max(0, p[x*3+2]- s * p[x*3+2] div (p[x*3]+p[x*3+1]+p[x*3+2]));
        end;
      end;
    end;
    bmp.Canvas.Unlock;

    Result := true;
  except
    Result := false;
  end;
end;
// 改饱和度
function ChangeSaturation(bmp: TBitmap; ValueChange: Integer): Boolean;
const
  CMax = 255;
var
  Grays: array[0..767] of Integer;
  Alpha: array[0..255] of Word;
  Gray, x, y: Integer;
  SrcRGB: PRGBTriple;
  i: Byte;
begin
  ValueChange := ValueChange + 255;
  for i := 0 to CMax do
  begin
    Alpha[i] := (i * ValueChange) shr 8;
  end;
  x := 0;
  for i := 0 to CMax 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 bmp.Height - 1 do
  begin
    SrcRGB := bmp.ScanLine[y];
    for x := 0 to bmp.Width - 1 do
    begin
      Gray := Grays[SrcRGB.rgbtRed + SrcRGB.rgbtBlue + SrcRGB.rgbtGreen];
      if Gray + Alpha[SrcRGB.rgbtRed] > 0 then
        SrcRGB.rgbtRed := Min(CMax, Gray + Alpha[SrcRGB.rgbtRed])
      else
        SrcRGB.rgbtRed := 0;

      if Gray + Alpha[SrcRGB.rgbtGreen] > 0 then
        SrcRGB.rgbtGreen := Min(CMax, Gray + Alpha[SrcRGB.rgbtGreen])
      else
        SrcRGB.rgbtGreen := 0;

      if Gray + Alpha[SrcRGB.rgbtBlue] > 0 then
        SrcRGB.rgbtBlue := Min(CMax, Gray + Alpha[SrcRGB.rgbtBlue])
      else
        SrcRGB.rgbtBlue := 0;

      Inc(SrcRGB);
    end;
  end;
end;
posted @ 2010-11-17 14:23  XuXn  阅读(3570)  评论(1编辑  收藏  举报