图像灰暗度的调节(100分)

  • 主题发起人 主题发起人 hrm
  • 开始时间 开始时间
灰暗度?你是不是指亮度?
 
对象素的R,G,B做相同的放缩就可以了
 
有有关的公式!
 
Y:=0.30R+0.59G+0.11B;
 
// 说明:用于处理的BITMAP必须是24bit的,如果不是则需要先转为24BIT
// 这是从我正在开发的眼科影像处理系统中直接取出来的,尚未进行优化,
// 但是肯定能正常工作,且效率高(你可以将这段代码放在一个滚动条
// 的 OnChange 事件中,你可以看到随着滚动条的移动图象的变化)

procedure bmpbright(mybitmap: tbitmap; // 用来处理的BITMAP,要求24BIT
brightness: integer; // 亮度,范围:0-255
contrast: integer; // 对比度,范围:0-255
displayingray: boolean; // 是否显示为灰度,TRUE为灰度
reversedisplay: boolean; // 是否显示负片效果,TRUE为负片
colorfilter: byte; // 颜色过滤:1=滤赤色,2=荧光色
x1,y1,x2,y2: integer); // 处理区域
var
thew,theh: integer;
i,j: integer;
p: pbytearray;
colorlevel: int64;
sty,stx,eny,enx: integer;
bripos,conpos: integer;
sum1,sum2,sum3: int64;
ave1,ave2,ave3: integer;
times: integer;
rlevel,glevel,blevel: integer;
maxnum,minnum: integer;
begin
conpos:=contrast+100;
times:=conpos;
if conpos>100 then times:=conpos*conpos div 100;
with mybitmap do
begin
thew:=width;
theh:=height;
if (x1=x2) or (y1=y2) then
begin
x1:=1;
y1:=1;
x2:=thew-1;
y2:=theh-1;
end
else
begin
minnum:=min(y1,y2);
maxnum:=max(y1,y2);
y1:=minnum;
y2:=maxnum;
minnum:=min(x1,x2);
maxnum:=max(x1,x2);
x1:=minnum;
x2:=maxnum;
end;
if x1<1 then x1:=1;
if y1<1 then y1:=1;
if x2>thew-1 then x2:=thew-1;
if y2>theh-1 then y2:=theh-1;
sum1:=0;
sum2:=0;
sum3:=0;
for i:=y1 to y2 do
begin
p:=scanline;
for j:=x1 to x2 do
begin
sum1:=sum1+p[j*3+2];
sum2:=sum2+p[j*3+1];
sum3:=sum3+p[j*3];
end;
end;
ave1:=sum1 div ((y2-y1+1)*(x2-x1+1));
ave2:=sum2 div ((y2-y1+1)*(x2-x1+1));
ave3:=sum3 div ((y2-y1+1)*(x2-x1+1));
for i:=y1 to y2 do
begin
p:=scanline;
for j:=x1 to x2 do
begin
colorlevel:=((p[j*3+2]-ave1)*times div 100)+ave1+brightness;
if colorlevel>255 then colorlevel:=255;
if colorlevel<0 then colorlevel:=0;
p[j*3+2]:=colorlevel;
colorlevel:=((p[j*3+1]-ave2)*times div 100)+ave2+brightness;
if colorlevel>255 then colorlevel:=255;
if colorlevel<0 then colorlevel:=0;
p[j*3+1]:=colorlevel;
colorlevel:=((p[j*3]-ave3)*times div 100)+ave3+brightness;
if colorlevel>255 then colorlevel:=255;
if colorlevel<0 then colorlevel:=0;
p[j*3]:=colorlevel;
if colorfilter=1 then
p[j*3+2]:=0;
if colorfilter=2 then
begin
p[j*3+2]:=0;
p[j*3]:=0;
end;
if displayingray then
begin
rlevel:=p[j*3+2];
glevel:=p[j*3+1];
blevel:=p[j*3];
colorlevel:=rlevel*rlevel+glevel*glevel+blevel*blevel;
colorlevel:=colorlevel div (rlevel+glevel+blevel+1);
p[j*3]:=colorlevel;
p[j*3+1]:=colorlevel;
p[j*3+2]:=colorlevel;
end;
if reversedisplay then
begin
p[j*3]:=$ff-p[j*3];
p[j*3+1]:=$ff-p[j*3+1];
p[j*3+2]:=$ff-p[j*3+2];
end;
end;
end;
end;
end;
 
pengyt似乎写得太复杂了。下面是我的程序。

function Scale(c:Byte):Byte;
const
Ratio=0.8; //缩放系数
var
t:Real;
begin
t:=1.0*c*Ratio;
if t>255 then Result:=255
else Result:=Round(t);
end;

...

var
Bmp1,Bmp2:TBitmap;
i,j:Integer;
P1,P2:PByteArray;
begin
Bmp1:=TBitmap.Create;
Bmp2:=TBitmap.Create;
try
Bmp1.LoadFromFile(InputFileName);
Bmp1.PixelFormat:=pf24Bit;
Bmp2.Width:=Bmp1.Width;
Bmp2.Height:=Bmp1.Height;
Bmp2.PixelFormat:=pf24Bit;
for i:=0 to Bmp1.Height-1 do begin
P1:=Bmp1.ScanLine;
P2:=Bmp2.ScanLine;
for j:=0 to Bmp1.Width*3-1 do
P2[j]:=Scale(P1[j]);
end;
Bmp2.SaveToFile(OutputFileName);
finally
Bmp2.Free;
Bmp1.Free;
end;
end;
 
请参考DELPHI/HELP/EXAMPLES/JPEG.
我想你会满意的.
 
to wjiachun:
>> Y:=0.30R+0.59G+0.11B;
这个算式是用来把彩图转换成灰度图的一种较好的方法.
 
pengyt:您提供的这段代码的确很有效。但是在运行过程中发现有一个问题,那就是改变了
亮度或对比度的图像无法回到原始状态,很多图像的细节被丢失了!!!请问原因何在?
 
当然了,因为在运行之后原来的图象信息都已经被修改了,而这段代码并
没有去保存它们。所以你如果需要不停调整的话,你需要先将原图保存
在另一个bitmap中,如otherbitmap,然后在你的滚动条的onchange事件
中这样写:
bitmap.assign(otherbitmap); // 假设bitmap是你正在处理的图象
bmpbright(......);
 
接受答案了.
 
后退
顶部