又有新瓶装旧酒——使用Delphi实现图片界面换肤色 [原创] (2004-8)[2]

[入库:2005年8月18日] [更新:2007年3月24日]

本文简介:选择自 islet8 的 blog

                              255 - (255 - g) * (255 - 0) div 255,   // 计算 g 值
                              255 - (255 - b) * (255 - 0) div 255);  // 计算 b 值
    end;
  end;

  rect.left := 448;
  rect.top := 152;
  rect.right := rect.left + png.width;
  rect.bottom := rect.top + png.height;

  png.draw(canvas, rect);

  t2 := gettickcount - t1;
  showmessage(inttostr(t2));

  png.free;
end;

颜色转换后的效果如图3。
图3

目标看似达到了,不过看看这粗糙的算法吧,二重循环遍历每个象素一定是很慢的,测试了一下转换这张200*200(象素)的图片在p4 2.4的cpu下耗时平均94ms(上面我用了一个rgbtemp临时变量来保存当前像素的rgb值,要不然在计算r、g、b时分别去直接读png.pixels[i,j]的话时间基本要再翻倍)。天!这个耗时很可观哪!后来我把代码改成把图片的scanline属性复制到一个指针数组,大大提高了运算速度:

{ 定义指针数组类型 }
const
  maxpixelcount = 65536;

type
  prgbarray = ^trgbarray;
  trgbarray = array [0..maxpixelcount - 1] of trgbtriple;

procedure tform1.button3click(sender: tobject);
var
  i, j: integer;
  row: prgbarray;
  png: tpngobject;
  rect: trect;
begin
  png := tpngobject.create;
  png.loadfromfile('2.png');

  for i := 0 to png.height - 1 do
  begin
    row := png.scanline[i];  // 复制scanline属性到row指针数组
    for j := 0 to png.width - 1 do
    begin
      row[j].rgbtred := 255 - (255 - row[j].rgbtred) * (255 - 153) div 255;
      row[j].rgbtgreen := 255 - (255 - row[j].rgbtgreen) * (255 - 0) div 255;
      row[j].rgbtblue := 255 - (255 - row[j].rgbtblue) * (255 - 0) div 255;
    end;
  end;
{ ... }
{ 后面的画图片代码相同 }

经过这个算法优化,运行时间缩短到几乎为0ms了(偶尔出现16ms)!

< 收工 >

    总算写完了^^。以上算法是我自己琢磨出来的,网上也没找到什么相关资料,哪位朋友如果有更好的方法,请多多指点,也希望能和我联系(islet8@yahoo.com.cn)。希望这篇文章能给各位朋友起到抛砖引玉的作用!
    以上代码在winxp + delphi7下调试通过。

本文关键:又有新瓶装旧酒——使用Delphi实现图片界面换肤色 [原创] (2004-8)
  相关方案
Google
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top