黑白图像的缩小灰度级显示算法的编写
2006-02-04 14:00:07 来源:WEB开发网 闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鐐劤缂嶅﹪寮婚悢鍏尖拻閻庨潧澹婂Σ顔剧磼閹冣挃闁硅櫕鎹囬垾鏃堝礃椤忎礁浜鹃柨婵嗙凹缁ㄧ粯銇勯幒瀣仾闁靛洤瀚伴獮鍥敍濮f寧鎹囬弻鐔哥瑹閸喖顬堝銈庡亝缁挸鐣烽崡鐐嶆棃鍩€椤掑嫮宓佸┑鐘插绾句粙鏌涚仦鎹愬闁逞屽墰閹虫捇锝炲┑瀣╅柍杞拌兌閻ゅ懐绱撴担鍓插剱妞ゆ垶鐟╁畷銉р偓锝庡枟閻撴洘銇勯幇闈涗簼缂佽埖姘ㄧ槐鎾诲礃閳哄倻顦板┑顔硷工椤嘲鐣烽幒鎴旀瀻闁规惌鍘借ⅵ濠电姷鏁告慨顓㈠磻閹剧粯鈷戞い鎺嗗亾缂佸鏁婚獮鍡涙倷閸濆嫮顔愬┑鐑囩秵閸撴瑦淇婇懖鈺冪<闁归偊鍙庡▓婊堟煛鐏炵硶鍋撻幇浣告倯闁硅偐琛ラ埀顒冨皺閺佹牕鈹戦悙鏉戠仸闁圭ǹ鎽滅划鏃堟偨缁嬭锕傛煕閺囥劌鐏犻柛鎰ㄥ亾婵$偑鍊栭崝锕€顭块埀顒佺箾瀹€濠侀偗婵﹨娅g槐鎺懳熺拠鑼舵暱闂備胶枪濞寸兘寮拠宸殨濠电姵纰嶉弲鎻掝熆鐠虹尨宸ョ€规挸妫濆铏圭磼濡搫顫嶇紓浣风劍閹稿啿鐣烽幋锕€绠婚悹鍥у级瀹撳秴顪冮妶鍡樺鞍缂佸鍨剁粋宥夋倷椤掍礁寮垮┑鈽嗗灣閸樠勭妤e啯鍊垫慨妯煎亾鐎氾拷

大家都知道,黑白图像是0,1二值的,缩小显示的时候由于n个点转化成1个点会导致图像局部细节信息丢失,比如一条宽度一个象素的细线由于缩小可能就会没有显示,而使用灰度级显示正是能解决这个缩小显示的问题,Windows自带的Eastman Software提供的的图像处理可以在你缩小黑白图片的时候使用灰度级来显示,下面我们就来深入研究一下这个算法是如何实现的吧。
基本约定:
1. 灰度级缩小显示只正对黑白或者灰度影像,经过算法变换可用于彩色影像
2. 只有在显示<100%的时候灰度级显示才生效
3. 灰度级缩小算法是基于原始图像来运算
具体算法:
1. 缩小算法
按照与原图比例1:n来对原图nXn个点生成1个点(n可以是浮点数),考虑到效率可以使用灰度级变换,从0-255 取中间点127大于该值显示白小于改值显示黑色。
2. 灰度级显示算法
结合缩小算法nXn个点生成一个点的原则,在原图上按照每个点的权值和颜色相乘再除以n来得到生成点的颜色值。
例如:
a1 a2 a3 a4 a5 a6 a7 a8 a9 a10
|-----|---*-|-----|-*---|-----|*----|-----*-----|-----|-----|
|---------|---------|----------|----------|----------|---------|--
b1 b2 b3 b4 b5 b6
经过变换后
b1 = (1.0*a1+0.8*a2)/1.8
b2 = (0.2*a2+a3+0.6*a3)/1.8
……
这是一维坐标,扩展到二维空间算法相同。
具体实现方法:
1. 计算出缩小后的位图点阵大小(nXm)
比如原图100X100,缩放90%之后就是90X90点阵
2. 循环点阵,为每个点的颜色赋值
赋值方法取相关点颜色乘以相应权值累加除以权值和
原图
缩放为66.6%
计算每点值
Delphi代码如下
var
i,j:integer;
tmpColorR,tmpColorG,tmpColorB:dWord;
x,y:integer;
ScaleRate,ScaleRateX,ScaleRateY:real;
begin
//combobox1.text为缩放%
ScaleRate:=100/strtoFloatDef(combobox1.text,100);
//循环生成图像的点阵
for i:=0 to trunc(image1.Picture.Width/ScaleRate) do
for j:=0 to trunc(image1.Picture.height/ScaleRate) do
begin
tmpColorR:=0;
tmpColorG:=0;
tmpColorB:=0;
//为每个点累加相关节点的颜色
for x:=trunc(i*ScaleRate) to ceil(((i+1)*ScaleRate)-1) do
begin
for y:=trunc(j*ScaleRate) to ceil(((j+1)*ScaleRate)-1) do
begin
ScaleRateX:=Min(x+1,(i+1)*ScaleRate) - Max(x,i*ScaleRate);
ScaleRateY:=Min(y+1,(j+1)*ScaleRate) - Max(y,j*ScaleRate);
//取每个点的RGB值(如果是黑白或者灰度,只需要取得一位)
tmpColorR:=tmpColorR+trunc(ScaleRateX*ScaleRateY*(GetRValue(Image1.Canvas.Pixels[x,y])));
tmpColorG:=tmpColorG+trunc(ScaleRateX*ScaleRateY*(GetGValue(Image1.Canvas.Pixels[x,y])));
tmpColorB:=tmpColorB+trunc(ScaleRateX*ScaleRateY*(GetBValue(Image1.Canvas.Pixels[x,y])));
end;
end;
//为点赋值颜色
image2.Canvas.Pixels[i,j]:=RGB(trunc(tmpColorR/(ScaleRate*ScaleRate)),trunc(tmpColorG/(ScaleRate*ScaleRate)),trunc(tmpColorB/(ScaleRate*ScaleRate)));
end;
这个算法是我写的第一版本,还有很多优化余地,比如如果是黑白图像就不需要计算R G B,因为256级灰度全部是相同的
另外for循环中的表达式可能影像速度,还有用整数运算会比浮点快,等等。
赞助商链接