低失真的图像缩放和24bit->8bit转换(100分)

  • 主题发起人 主题发起人 GoogolLee
  • 开始时间 开始时间
G

GoogolLee

Unregistered / Unconfirmed
GUEST, unregistred user!
如何在Delphi中实现ACDSee低失真的图像缩放和24bit->8bit转换?有这种控件么?
 
有,当然有,上网找一找。
要保持低失真,必须利用抖动技术。
对于放大,可以通过插值增加点。例如在两点p1、p2之间增加一个点q,
那么可以让q=(p1+p2)/2。当然,这个例子比较简单,复杂的情况下,可能会通过
多个点,用更复杂的公式来计算新增加点的颜色。
对于缩小,原理差不多,例如原来的两个点减少为一个点,那么可以用这两个点颜色
的平均值作为这个点的颜色。
对于颜色,也举个简化的例子:假设只有两种颜色0、1,那么利用这两种颜色
如何表示更多的颜色呢?很简单,通过牺牲空间分辨率来提高颜色分辨率,即利用4个
点的组合表示不同的颜色,它们是
0 0 1 0 1 0 1 1 1 1
0 0, 0 0,0 1,1 0,1 1。当然,同样的,抖动技术可以做得更复杂,
效果更好,但原理是一样的。
其他关于保持低失真的技术,还有利用人眼特点,进行各种变换的方法,如果真
感兴趣,可以找《计算机图形学》和《数字图像处理》之类的书籍阅读。如果,只
是为了应用,建议还是上网找些控件直接使用。例如delphi深度历险
http://delphi.twart.com/DELPHIGB/就有不少。




 
还是找吧!
自己做太麻烦了。
抖动有事也会有锯齿出现
 
能推荐几个效果好的控件吗?
 
我做过一个24->8的变换的例子,因为追求的是效果,所以在当时的奔腾133上跑的
奇慢。所以就没做玩。

具体方法是这样:
首先,扫描所有的像素,(faint,光这一步就很费时了)。讲在同一个很小的
颜色空间里的像素归在一处,最后的到一个调色板。这个调色板可能很大,也不
准确,然后就在次处理。注意,这一步要保存每个调色板项在图片里出现的次数。
这个次数可以看做每个调色板项的权值。

第二次,扫描调色板项,利用权值进行加权分类,去掉一些使用很少的调色板项,
再次融合一些相近的项。但是要保证在一定的色彩空间里必须有一定数目的调色
版项。这个过程里可以手动干预,根据实际图像的色调设置一些比较重要的色彩
空间,让调色板项的分配集中在对图像整个色调最重要的色彩空间里。

然后就是重复第二步,直到选出在256色左右的调色板项。

最后在确定大概的调色版项后,有几种选择。
1。直接使用这些调色板项。这样的效果不是很好。
2。再扫描一次图像,对调色版项进行修正。这样的效果好一些。
3。在第2步的基础上,加上抖动等特殊效果。这样再优化以后的图像效果就比较
让人满意了。

这是我n年前读初三时写的程序里的想法了,很不成熟,当时就觉得效率很低。应
该可以优化一下性能的。
希望本文可以抛砖引玉,如果大家有更好的办法不要忘了通知我。







 
图像缩放现在一般是反向求解的,就是判断缩放后的图像的i点应该是对应到源图像的那个
点,当出现第10.8个点这样的情况时,在源图像的第10,11点间做线性插值(当然你也可
以用9,10,11,12做二次插值等,这时的问题变成在计算环境不变时,用什么插值方法,选
几个、哪些基点的效率,保真最好的问题)
 
请问我如果要把单色(12*12左右)的图缩小成9*12的(其实是一些字符),该怎么办才能不失真?
 
edisons:失真是必然的,只能减少失真,特别是线条的图像,简单的缩放,效果会很差

 
实现acdsee的缩放效果的 我这儿有程序
贴给你

//缩----------------------------------------------
procedure TForm1.sp_sClick(Sender: TObject);
begin
if not((image1.width<18)or(image1.Height<18)) then
begin
Where_the_Form;

image1.Visible :=false;
suoxiao;
show_picture_window_size_II;
where_show_picture;
image1.Visible :=true;
end;
end;

//放-----------------------------------------------
procedure TForm1.sp_usClick(Sender: TObject);
begin
Where_the_Form;

image1.Visible :=true;
fangda;
where_show_picture;
show_picture_window_size;
image1.Visible :=true;
end;

//合适----------------------------------------------
procedure TForm1.sp_fitClick(Sender: TObject);
begin
show_picture_fit_size;
where_show_picture;
end;
-------------------------------自定义过程-----------
----------------------------------------------------
//将商取整,返回值为integer 型
function TForm1.int_from_div(aNum:real):integer;
var aa1:string;
begin
aa1 :=floattostr(int(aNum)); //div 是整数除,
result :=strtoint(aa1); //mod 是整数余
end;

//将加载图片的尺寸赋给 image1
procedure TForm1.load_picture_size;
begin
image1.Height :=image1.Picture.Height;
image1.Width :=image1.Picture.Width;
end;

//显示图片的位置(左上点坐标)
//.. 要调用int_from_div()
procedure TForm1.where_show_picture;
begin
if image1.width<Panel2.Width then
image1.Left :=int_from_div((panel2.Width-image1.Width)div 2)
else
image1.Left :=4;

if image1.Height<panel2.Height then
image1.Top :=int_from_div(int((panel2.Height-image1.Height)div 2))
else
image1.Top :=4;
end;

//以合适的尺寸显示整个图片
procedure TForm1.show_picture_fit_size;
var
aa01,aa02:integer;
pp01,pp02:integer;
begin
aa01 := image1.Picture.Height;
aa02 := image1.Picture.Width;
pp01 := screen.Height - 100; //去除窗口边框的高度
pp02 := screen.Width - 16; //去除窗口边框的宽度
if aa01 * pp02 / aa02 / pp01 - 1 > 0 then
if aa01 > pp01 then //图片高度较大
begin
image1.Height := pp01;
image1.Width := int_from_div(aa02 * pp01 div aa01);

form1.Left := 0;
form1.Top := 0;
form1.Height := screen.Height;// image1.Height + 100;
form1.Width := screen.Width;//image1.Width + 16;

rule_1 := pp01;
rule_2 := aa01;
end else begin
load_picture_size;
end;

if aa01 * pp02 / aa02 / pp01 - 1 < 0 then
if aa02 >pp02 then
begin
image1.Width := pp02;
image1.Height := int_from_div(aa01 * pp02 div aa02);
form1.Left := 0;
form1.Top := 0;
form1.Height := image1.Height + 100;
form1.Width := image1.Width + 16;

rule_1 := pp02;
rule_2 := aa02;
end else begin
load_picture_size;
end;

if aa01 / aa02 = pp01 / pp02 then
begin
if aa01 > pp01 then
begin
image1.Height := pp01;
image1.Width := pp02;
form1.Left := 0;
form1.Top := 0;
form1.Height := screen.Height;//image1.Height + 100;
form1.Width := screen.Width;//image1.Width + 16;

rule_1 := pp01;
rule_2 := aa01;
end else begin
load_picture_size;
form1.Height := image1.Height + 100;
form1.Width := image1.Width + 16;

rule_1 := 1;
rule_2 := 1;
end;
end;
end;

//窗口适应图片的大小 (窗口 < 图片时) 图片在窗口上的位置
procedure TForm1.show_picture_window_size;
begin
if not(image1.width+ 8< panel2.Width) then
Form1.Width :=image1.Width +16; //image 到 form 边框宽-象素
if not(image1.Height+ 8< panel2.Height) then
Form1.Height :=image1.Height +100; //image 到 form 边框高-象素
end;

//窗口适应图片的大小 (窗口 >> 图片时) 图片在窗口上的位置
procedure TForm1.show_picture_window_size_II;
begin
if (form1.width>449)and(form1.Height>276) then
begin
form1.Width :=image1.Width+16; //image 到 form 边框宽-象素
form1.Height :=image1.Height+100; //image 到 form 边框高-象素
end;
if (form1.width>449)and(not(form1.Height>276)) then
form1.Width :=image1.Width+16;
if (not(form1.width>449))and(form1.Height>276) then
form1.Height :=image1.Height+100;
end;

//窗口在屏幕上的位置
procedure TForm1.Where_the_Form;
begin
end;

//缩小显示的图象
procedure TForm1.suoxiao;
begin
image1.Width := int_from_div((image1.Width div 3)*2);
image1.Height := int_from_div((image1.Height div 3)*2);

rule_1 := rule_1 * 2; //比例尺-分子
rule_2 := rule_2 * 3; //比例尺-分母
end;

//放大显示图象
procedure TForm1.fangda;
begin
image1.width :=int_from_div((image1.Width div 2)*3);
image1.Height :=int_from_div((image1.Height div 2)*3);

rule_1 := rule_1 * 3; //比例尺-分子
rule_2 := rule_2 * 2; //比例尺-分母
end;

========================================================
这是我应试的作品,属私有财产,
如果你觉得阅读不便,发mail告诉我
我把元程序整个发给你
(cat..yy@263.net)
 
>> 24bit->8bit转换
TBitmap.PixelFormat 不行吗
 
to cat.yy
您的方法不是不可以,但效果太差呀。
 
GoogolLee:如果还想接着讨论请定期提前自己的帖子,如果不想继续讨论请结束帖子。
 
24bit->8bit转换,我以前写DOS程序时做过。用的是C++,算法是参考
某本书的。当时我在一些图像处理的书上很容易找到这个算法,不知现在......
 
多人接受答案了。
 
后退
顶部