图像效果问题-看来是有点难度了。。。(200分)

  • 主题发起人 主题发起人 dfw1001
  • 开始时间 开始时间
D

dfw1001

Unregistered / Unconfirmed
GUEST, unregistred user!
先看个图片 http://www.onnow.cn/temp.bmp
要实现的效果是:

程序在用image控件读入这个图片后,可以任意修改这个图片的颜色,但是效果不变。
也就是页面的颜色会变,但是纸张的效果不变。

恳请赐教,最好附带上关键代码,谢谢。
 
我的想法是这样的,首先获取图片的一个点的RGB值,然后计算所有像素点与这个点的区别,然后用设定的颜色按比例填充。谁能帮帮忙把代码写出来呢?[:)]
 
直接修改内存的RGB值?学习..
 
最简单的做法:
procedure TForm1.BitBtn1Click(Sender: TObject);
var
i, j : integer ;
begin
for i:=0 to Image1.Height-1 do
for j:=0 to Image1.Width-1 do
Image1.Picture.Bitmap.Canvas.Pixels[j,i] := Image1.Picture.Bitmap.Canvas.Pixels[j,i]+60 ;
Image1.Refresh ;
end;
最好的做法是做RGB-HSI-RGB转换
 
to pascal!:(谢谢你的代码)
虽然实现了页面的渐变效果,实际的纸张效果还是没有出来。
我最想要的是http://www.onnow.cn/temp.bmp 这个图片的纸张效果,请问怎么改进可以做到呢?
 
to pascal!: 你的方法我试了,有个问题是,如果图片很大处理起来很慢
还有,如何用指定的颜色替换图片中现有的灰色呢?
 
下面方法可满足你的要求,
将image1的图片加上某种颜色后画在Image2上

procedure TForm1.Button3Click(Sender: TObject);
var
udtBlender: TBlendFunction;
begin
if ColorDialog1.Execute then
Image2.Canvas.Brush.Color := ColorDialog1.Color;

Image2.Canvas.FillRect(Rect(0, 0, Image2.Width, Image2.Height));

Refresh;
with udtBlender do
begin
BlendOp := AC_SRC_OVER;
BlendFlags := 0;
SourceConstantAlpha := 80; //设置透明度,可以根据效果需要来调整
AlphaFormat := 0;
end;

Windows.AlphaBlend(Image2.Canvas.Handle,0, 0,
Image2.Width, Image2.Height,
Image1.Canvas.Handle,0, 0,
Image1.Width, Image1.Height, udtBlender);
Image2.Refresh;
end;
 
那两个Refresh语句是不必要的,影响速度,可以去掉,尤其是中间那个
 
tonmy:

你可能没有明白我的意思,请先个图片http://www.onnow.cn/temp.bmp
我要的效果是,image控件先读入这张图片,然后用指定的颜色替换图片中的灰色,保留纸张的效果。

pascal!的方法有点意思了,不过怎么和亮度结合就可以了。
 
type
cl= record
r,g,b : byte ;
end ;

a = array [0..$FFFF] of cl ;

procedure TForm1.BitBtn1Click(Sender: TObject);
var
l : ^a ;
i,j : integer ;
begin
for i:=0 to image1.Height-1 do
begin
l := image1.Picture.Bitmap.ScanLine ; //用ScanLine比用Pixels[j,i]+快得多
for j:=0 to image1.Width-1 do l^[j].r := 255 ; //这个r,g,b自己改其中的一个,由0~255随意

end ;
image1.Refresh ;
end;
前面的做法是一样的,但没这个精确
 
to pascal!:(非常非常感谢[:)])
上面的代码效率明显要好的多了,不过还省一个最关键的地方,就是如何按指定的颜色取替换图像的颜色,光修改RGB中的一个效果是有了,但无法设定指定颜色,怎么才能解决呢,谢谢。
 
type
TForm1 = class(TForm)
Image1: TImage;
BitBtn1: TBitBtn;
Image2: TImage;
ColorBox1: TColorBox;
procedure BitBtn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;



type
cl= record
b,g,r : byte ;
end ;

a = array [0..$FFFF] of cl ;
procedure RGBtoHSV(const R,G,B:byte;var H,S,V:integer) ;
var
M, D : integer ;
begin
V := Max(R, Max(G, B)) ;
M := Min(R, Min(G, B)) ;
D := V-M ;
if V=0
then begin
S := 0 ;
H := 0 ;
end
else begin
S := Round(255*D/V) ;
if S=0
then H := 0
else begin
if R=V
then H := Round(60*(G-B)/D)
else if G=V
then H := Round(60*((B-R)/D+2))
else H := Round(60*((R-G)/D+4)) ;
H := (H+360) mod 360 ;
end ;
end ;
end ;

procedure HSVtoRGB(const H, S, V:integer;var R, G, B:byte) ;
var
p, q, t : integer ;
f : double ;
begin
if S=0
then begin
R := V ;
G := V ;
B := V ;
end
else begin
f := Frac(H/60) ;
p := Round(V*(1-S/255)) ;
q := Round(V*(1-S/255*f)) ;
t := Round(V*(1-S/255*(1-f))) ;
case Round(H/60) of
0 : begin
R := V ;
G := t ;
B := p ;
end ;
1 : begin
R := q ;
G := v ;
B := p ;
end ;
2 : begin
R := p ;
G := v ;
B := t ;
end ;
3 : begin
R := p ;
G := q ;
B := v ;
end ;
4 : begin
R := t ;
G := p ;
B := v ;
end ;
5 : begin
R := V ;
G := p ;
B := q ;
end ;
end ;
end ;
end ;

procedure TForm1.BitBtn1Click(Sender: TObject);
var
l,t : ^a ;
i,j, H,S,V, c, p, q : integer ;
begin
c := ColorBox1.Selected ; //c:tcolor
RGBtoHSV(c and $FF, (c shr 8) and $FF, c shr 16, p, q, V) ;
for i:=0 to image1.Height-1 do
begin
l := image1.Picture.Bitmap.ScanLine ; //ÓÃScanLine±ÈÓÃPixels[j,i]¿ìµÃ¶à
t := image2.Picture.Bitmap.ScanLine ;
for j:=0 to image1.Width-1 do
begin
RGBtoHSV(l^[j].r, l^[j].g, l^[j].b, H, S, V) ;
S := q ;
H := p ;
HSVtoRGB(H, S, V, t^[j].r, t^[j].g, t^[j].b) ;
end ;
end ;
image2.Refresh ;
end;
 
也许你并没有试我给你的代码,它实现的效果就是将Image1的图片改变了颜色后显示在Image2中,Image2保持了Image1图片的效果.
实现原理是:将一个效果图片半透明地与一个单一颜色的图片叠加,实现改变效果图片颜色的目的;
需要注意一点是:Image2中不要事先加载图片,保持空白就可以了!

我试了pascal!的最后给的方法,操作复杂一些,效果也不错,而且颜色相对鲜艳一些
 
tonmy的方法的确可以实现我想要的效果,抱歉开始的时候一直没有试下,原来这么简单就能做到。

再次感谢tonmy和pascal!的热心耐心解答![:)]
 
后退
顶部