如何将图像缩放的速度提高到photoshop那样快(100分)

  • 主题发起人 主题发起人 hitman007260
  • 开始时间 开始时间
H

hitman007260

Unregistered / Unconfirmed
GUEST, unregistred user!
如何将图像缩放的速度提高到photoshop那样快??
 
千堆雪 好像这方面很厉害。
 
呼唤千堆雪 救苦救难的大侠帮帮小弟
 
以前出来了个叫做干堆雪的,不仔细看看不出来分别
 
这也有伪劣产品?
 
小波变换了了,代码,我只有VC的...
 
小波变换?
太菜不懂啊
 
呼唤各路大侠
 
lofa (2003-02-13 14:52:00)
我现在正在看一个GraphicEx的库,里面有图像缩小的算法,速度很快,比Acdsee也慢不
了多少,你去Google里面找这个词,下面是缩放代码:
不过滤镜的函数没有给你拷,他那都有,是有源代码的。
procedure DoStretch(Filter: TFilterFunction; Radius: Single; Source, Target: TBitmap);

// This is the actual scaling routine. Target must be allocated already with sufficient size. Source must
// contain valid data, Radius must not be 0 and Filter must not be nil.

var
ScaleX,
ScaleY: Single; // Zoom scale factors
I, J,
K, N: Integer; // Loop variables
Center: Single; // Filter calculation variables
Width: Single;
Weight: Integer; // Filter calculation variables
Left,
Right: Integer; // Filter calculation variables
Work: TBitmap;
ContributorList: TContributorList;
SourceLine,
DestLine: PPixelArray;
DestPixel: PBGR;
Delta,
DestDelta: Integer;
SourceHeight,
SourceWidth,
TargetHeight,
TargetWidth: Integer;

begin
// shortcut variables
SourceHeight := Source.Height;
SourceWidth := Source.Width;
TargetHeight := Target.Height;
TargetWidth := Target.Width;

if (SourceHeight = 0) or (SourceWidth = 0) or
(TargetHeight = 0) or (TargetWidth = 0) then Exit;

// create intermediate image to hold horizontal zoom
Work := TBitmap.Create;
try
Work.PixelFormat := pf24Bit;
Work.Height := SourceHeight;
Work.Width := TargetWidth;
if SourceWidth = 1 then ScaleX := TargetWidth / SourceWidth
else ScaleX := (TargetWidth - 1) / (SourceWidth - 1);
if (SourceHeight = 1) or (TargetHeight = 1) then ScaleY := TargetHeight / SourceHeight
else ScaleY := (TargetHeight - 1) / (SourceHeight - 1);

// pre-calculate filter contributions for a row
SetLength(ContributorList, TargetWidth);
// horizontal sub-sampling
if ScaleX < 1 then
begin
// scales from bigger to smaller Width
Width := Radius / ScaleX;
for I := 0 to TargetWidth - 1 do
begin
ContributorList.N := 0;
SetLength(ContributorList.Contributors, Trunc(2 * Width + 1));
Center := I / ScaleX;
Left := Floor(Center - Width);
Right := Ceil(Center + Width);
for J := Left to Right do
begin
Weight := Round(Filter((Center - J) * ScaleX) * ScaleX * 256);
if Weight <> 0 then
begin
if J < 0 then N := -J
else
if J >= SourceWidth then N := SourceWidth - J + SourceWidth - 1
else N := J;
K := ContributorList.N;
Inc(ContributorList.N);
ContributorList.Contributors[K].Pixel := N;
ContributorList.Contributors[K].Weight := Weight;
end;
end;
end;
end
else
begin
// horizontal super-sampling
// scales from smaller to bigger Width
for I := 0 to TargetWidth - 1 do
begin
ContributorList.N := 0;
SetLength(ContributorList.Contributors, Trunc(2 * Radius + 1));
Center := I / ScaleX;
Left := Floor(Center - Radius);
Right := Ceil(Center + Radius);
for J := Left to Right do
begin
Weight := Round(Filter(Center - J) * 256);
if Weight <> 0 then
begin
if J < 0 then N := -J
else
if J >= SourceWidth then N := SourceWidth - J + SourceWidth - 1
else N := J;
K := ContributorList.N;
Inc(ContributorList.N);
ContributorList.Contributors[K].Pixel := N;
ContributorList.Contributors[K].Weight := Weight;
end;
end;
end;
end;

// now apply filter to sample horizontally from Src to Work
SetLength(CurrentLineR, SourceWidth);
SetLength(CurrentLineG, SourceWidth);
SetLength(CurrentLineB, SourceWidth);
for K := 0 to SourceHeight - 1 do
begin
SourceLine := Source.ScanLine[K];
FillLineChache(SourceWidth, 3, SourceLine);
DestPixel := Work.ScanLine[K];
for I := 0 to TargetWidth - 1 do
with ContributorList do
begin
DestPixel^ := ApplyContributors(N, ContributorList.Contributors);
// move on to next column
Inc(DestPixel);
end;
end;

// free the memory allocated for horizontal filter weights, since we need the stucture again
for I := 0 to TargetWidth - 1 do ContributorList.Contributors := nil;
ContributorList := nil;

// pre-calculate filter contributions for a column
SetLength(ContributorList, TargetHeight);
// vertical sub-sampling
if ScaleY < 1 then
begin
// scales from bigger to smaller height
Width := Radius / ScaleY;
for I := 0 to TargetHeight - 1 do
begin
ContributorList.N := 0;
SetLength(ContributorList.Contributors, Trunc(2 * Width + 1));
Center := I / ScaleY;
Left := Floor(Center - Width);
Right := Ceil(Center + Width);
for J := Left to Right do
begin
Weight := Round(Filter((Center - J) * ScaleY) * ScaleY * 256);
if Weight <> 0 then
begin
if J < 0 then N := -J
else
if J >= SourceHeight then N := SourceHeight - J + SourceHeight - 1
else N := J;
K := ContributorList.N;
Inc(ContributorList.N);
ContributorList.Contributors[K].Pixel := N;
ContributorList.Contributors[K].Weight := Weight;
end;
end;
end
end
else
begin
// vertical super-sampling
// scales from smaller to bigger height
for I := 0 to TargetHeight - 1 do
begin
ContributorList.N := 0;
SetLength(ContributorList.Contributors, Trunc(2 * Radius + 1));
Center := I / ScaleY;
Left := Floor(Center - Radius);
Right := Ceil(Center + Radius);
for J := Left to Right do
begin
Weight := Round(Filter(Center - J) * 256);
if Weight <> 0 then
begin
if J < 0 then N := -J
else
if J >= SourceHeight then N := SourceHeight - J + SourceHeight - 1
else N := J;
K := ContributorList.N;
Inc(ContributorList.N);
ContributorList.Contributors[K].Pixel := N;
ContributorList.Contributors[K].Weight := Weight;
end;
end;
end;
end;

// apply filter to sample vertically from Work to Target
SetLength(CurrentLineR, SourceHeight);
SetLength(CurrentLineG, SourceHeight);
SetLength(CurrentLineB, SourceHeight);


SourceLine := Work.ScanLine[0];
Delta := Integer(Work.ScanLine[1]) - Integer(SourceLine);
DestLine := Target.ScanLine[0];
DestDelta := Integer(Target.ScanLine[1]) - Integer(DestLine);
for K := 0 to TargetWidth - 1 do
begin
DestPixel := Pointer(DestLine);
FillLineChache(SourceHeight, Delta, SourceLine);
for I := 0 to TargetHeight - 1 do
with ContributorList do
begin
DestPixel^ := ApplyContributors(N, ContributorList.Contributors);
Inc(Integer(DestPixel), DestDelta);
end;
Inc(SourceLine);
Inc(DestLine);
end;

// free the memory allocated for vertical filter weights
for I := 0 to TargetHeight - 1 do ContributorList.Contributors := nil;
// this one is done automatically on exit, but is here for completeness
ContributorList := nil;

finally
Work.Free;
CurrentLineR := nil;
CurrentLineG := nil;
CurrentLineB := nil;
end;
end;
 
关键是他们用MMX,SSE,3dNow指令来优化图形计算性能,这些指令集支持48,64位的寄存器运算,对于RGB这样的变化每次都可以同时几个像素点,同样的算法减少到原来的1/2甚至1/9的时间。
 
有谁知道如何优化??
或者查什么资料??
 
用GDI+实现,速度应该非常快!
 
http://www.whowait.com/2.rar
这是我用MMX指令作的一个小软件,速度还是非常快的。
 
楼上的,如何用mmx指令?
能给我你的源代码看看吗??
有关于mmx得。
 
问题: 如何缩放图片??? ( 积分: 50 )
分类: 图形图象

来自: comindex, 时间: 2005-01-07 21:50:00, ID: 2956789
不裁减图片,在原来的图片基础上。缩一下。。。
有代码实例吗?各位朋友小弟很急!!!
我做的一个,会裁减图片。。。原先图片很长。现在要求不裁减图片缩成方形!


来自: 啊啊啊啊啊, 时间: 2005-01-08 22:08:11, ID: 2957596
不剪裁,不粘贴
image导入bmp图片后,设置:
image1.AutoSize:=false;
image1.Stretch:=true;
image1.Height:=trunc(image1.Height * 放大缩小系数)) ;
image1.Width:=trunc(image1.Width * 放大缩小系数));


来自: weiliu, 时间: 2005-01-08 22:11:37, ID: 2957599
实现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;


来自: weiliu, 时间: 2005-01-08 22:14:46, ID: 2957603
有没有好的图象缩放的例子,或者好用的控件也可以.我做的老是图象失真. (78分)
分类:图形图象 liuyang (2002-11-06 14:51:00)
有没有好的图象缩放的例子,或者好用的控件也可以.我做的老是图象失真.
谢谢各位了.

vine (2002-11-06 15:16:00)
我有两个
来自:千堆雪
留下mail

liuyang (2002-11-06 15:55:00)
谢谢拉.
liuyang@mail.taiji.com.cn
lyshrine@163.com

ydy (2002-11-06 15:57:00)
我也要,谢谢拉!
ydystory@sina.com

vine (2002-11-06 16:14:00)
已发

王公子 (2002-11-06 16:20:00)
我也在找这方面的东东,能否给我发一下,多谢!

huasoft (2002-11-07 2:24:00)
hth@huasoft.net

Another_eYes (2002-11-07 2:57:00)
我写过一个函数就是干这个的。
SmoothTransBlt
支持平滑缩放。 而且支持透明背景。速度还可以, 500*300图片50%显示用时27ms, 1000%用时1秒半。
提一句:参数中的TransColor是RGBColor, 不是TColor, 请将TColor用ColorToRGB转换成RGB后调用(一个特例, 如果不想透明的话直接传入TColor的clNone值即可)

type
TRGB = packed record
b, g, r: Byte;
end;
PRGB = ^TRGB;

TDIBBmp = record
hBmp: HBITMAP;
w, h: Integer;
gap, Lbytes: Integer;
Bits: PRGB;
end;

function NewDIBBmp(w, h: Integer; var bits: PRGB; var gap, retw: Integer): HBITMAP; overload;
function NewDIBBmp(var bmp: TDIBBmp): HBITMAP; overload;
procedure DestroyDIBBmp(var Bmp: TDIBBmp);

procedure SmoothTransBlt(DestDC: HDC; dx, dy, dw, dh: Integer;
Bmp24: TBitmap; sx, sy, sw, sh: Integer;
TransColor: Cardinal); overload;
procedure SmoothTransBlt(Dest: TDIBBmp; Bmp24: TBitmap; sx, sy, sw, sh: Integer;
TransColor: Cardinal); overload;
procedure SmoothBlt(DestDC: HDC; x, y: Integer; Bmp24: TBitmap; TransColor: Cardinal; Percent: Integer= 100);

implementation

function NewDIBBmp(var bmp: TDIBBmp): HBITMAP; overload;
begin
bmp.hbmp := newdibbmp(bmp.w, bmp.h, bmp.bits, bmp.gap, bmp.lbytes);
result := bmp.hbmp;
end;

function NewDIBBmp(w, h: Integer; var bits: PRGB; var gap, retw: Integer): HBITMAP; overload;
var
bmInfo: TBitmapInfo;
begin
bmInfo.bmiHeader.biSize:=SizeOf(TBitmapInfoHeader);
bmInfo.bmiHeader.biPlanes:=1;
bmInfo.bmiHeader.biBitCount:=24;
bmInfo.bmiHeader.biCompression:=BI_RGB;
bmInfo.bmiHeader.biWidth:=W;
bmInfo.bmiHeader.biHeight:=-H;
result := createDIBSection(0, bminfo, DIB_RGB_COLORS, pointer(bits), 0, 0);
retw := ((W*24+31)shr 5)shl 2;
gap := w mod 4;
end;

procedure SmoothTransBlt(DestDC: HDC; dx, dy, dw, dh: Integer;
Bmp24: TBitmap; sx, sy, sw, sh: Integer;
TransColor: Cardinal); overload;
var
tmpdc: HDC;
tmp: TDIBBmp;
begin
if bmp24.PixelFormat <> pf24Bit then
bmp24.PixelFormat := pf24Bit;
tmp.w := dw;
tmp.h := dh;
newdibbmp(tmp);
tmpdc := createcompatibledc(0);
deleteobject(selectobject(tmpdc, tmp.hbmp));
bitblt(tmpdc, 0, 0, dw, dh, destdc, dx, dy, SRCCOPY);
smoothtransblt(tmp, bmp24, sx, sy, sw, sh, transcolor);
bitblt(destdc, dx, dy, dw, dh, tmpdc, 0, 0, SRCCOPY);
deletedc(tmpdc);
destroydibbmp(tmp);
end;

procedure SmoothTransBlt(Dest: TDIBBmp; Bmp24: TBitmap; sx, sy, sw, sh: Integer;
TransColor: Cardinal); overload;
var
srcw: Integer;
x,y,xP,yP,
yP2,xP2: Integer;
Read,Read2: PRGB;
t,z,z2,iz2: Integer;
pc:PRGB;
w1,w2,w3,w4: Integer;
Col1,Col2,
Col3, Col4: PRGB;
begin
srcw := ((bmp24.width*24+31)shr 5)shl 2;
xP2:=((sw-1)shl 15)div dest.w;
yP2:=((sh-1)shl 15)div dest.h;
yP:=0;
pc := dest.bits;
for y:=0 to dest.h-1 do
begin
xP:=0;
Read:=pointer(bmp24.scanline[yp shr 15 + sy]);
if yP shr 16<sh-1 then
Read2:=pointer(integer(read)-srcw)
else
Read2:=read;
z2:=yP and $7FFF;
iz2:=$8000-z2;
for x:=0 to dest.w-1 do
begin
t:=(xP shr 15)+sx;
Col1:=pointer(integer(read)+t*3);
if xp shr 15 < sw-1 then
col3 := pointer(integer(col1) +3)
else
col3 := col1;
if (integer(transcolor) <> clNone) and
(col1^.r=PRGB(@TransColor)^.b) and
(col1^.g=PRGB(@transcolor)^.g) and
(col1^.b=PRGB(@transcolor)^.r) then
col1 := pc;
if (col3^.r=PRGB(@transcolor)^.b) and
(col3^.g=PRGB(@transcolor)^.g) and
(col3^.b=PRGB(@transcolor)^.r) then
col3 := pc;
Col2:=pointer(integer(read2)+t*3);
col4 := pointer(integer(col2)+3);
if (col2^.r=PRGB(@transcolor)^.b) and
(col2^.g=PRGB(@transcolor)^.g) and
(col2^.b=PRGB(@transcolor)^.r) then
col2 := pc;
if (col4^.r=PRGB(@transcolor)^.b) and
(col4^.g=PRGB(@transcolor)^.g) and
(col4^.b=PRGB(@transcolor)^.r) then
col4 := pc;
z:=xP and $7FFF;
w2:=(z*iz2)shr 15;
w1:=iz2-w2;
w4:=(z*z2)shr 15;
w3:=z2-w4;
pc.b:=
(Col1^.b*w1+col3^.b*w2+
Col2^.b*w3+col4^.b*w4)shr 15;
pc.g:=
(Col1^.g*w1+col3^.g*w2+
Col2^.g*w3+col4^.g*w4)shr 15;
pc.r:=
(Col1^.r*w1+col3^.r*w2+
Col2^.r*w3+col4^.r*w4)shr 15;
Inc(pc);
Inc(xP,xP2);
end;
Inc(yP,yP2);
pc := pointer(integer(pc)+dest.gap);
end;
end;

procedure SmoothBlt(DestDC: HDC; x, y: Integer; Bmp24: TBitmap; TransColor: Cardinal; Percent: integer= 100);
var
w, h: Integer;
begin
w := round(bmp24.width * percent / 100);
h := round(bmp24.height * percent / 100);
smoothtransblt(destdc, x, y, w, h, bmp24, 0, 0, bmp24.width, bmp24.height, transcolor);
end;

procedure DestroyDIBBmp(var Bmp: TDIBBmp);
begin
if bmp.hBmp <> 0 then
begin
deleteobject(bmp.hbmp);
bmp.hbmp := 0;
bmp.w := 0;
bmp.h := 0;
bmp.gap := 0;
bmp.Lbytes := 0;
bmp.Bits := nil;
end;
end;


liuyang (2002-11-07 8:32:00)
谢谢各位了.我今天看看,然后就给分

liuyang (2002-11-07 10:16:00)
to vine
谢谢你发的例子.两个文件分别是两个控件吧,有没有具体的例子.我不知道怎么用.
方法什么的不知道怎么用.ZOOMSLZ的那个文件是例子吗?要新建一个项目把.pas加入进去?
可我在程序中加了一个图片运行时总时显示不出来.

vine (2002-11-07 10:22:00)
两个都是控件
你要先安装
ZoomImage可以直接显示图片,自己设置Zoomvalue
另一个有Zoomer1.ShowImage();的方法的
不过我也没有show出来

liuyang (2002-11-07 13:47:00)
to vine
我按你说的做了.用ZoomImage控件,可编译的时候总提示
&quot;file not found zoom.dcu&quot; 不知道怎么解决,能否做个例子给我?麻烦了.

liuyang (2002-11-07 14:03:00)
to vine
可以了,那个ZoomImage控件,工程必须存一下然后把zoom.dcu考到工程目录下就可以了.
是不是只是BMP图象的处理?


hug (2002-11-12 14:05:00)
Img.AutoSize:=False;
Img.Width:=Img div ZoomRate;
Img.Height:=Img div ZoomRate;
ImgF.Stretch:=True;
这个可以!

GGCAT (2002-11-13 12:51:00)
[:D][:D]
采用SSE指令和优化算法可以在PIII667上实现32bit双线性平滑缩放
的速度可以达到 12M目标pixel/S 以上
也就是说 目标在 200x300 可以在5ms内 目标在1000x1000 是 90ms
目标是4000x3000则是1s

zhoufujin (2002-11-25 20:13:00)
我也要,谢谢拉!
gswzhoufujin@163.com

sthsm (2002-11-25 21:00:00)
我要,谢谢!~

commonwu (2002-11-27 13:44:00)
我想要,
common1@netease.com

juc (2002-11-27 14:47:00)
谢谢,也给我一份
ysxsunny@sina.com


jsxjd (2002-11-29 10:25:00)
位图图片的缩放

一些程序可以缩放图片,也就是说,这些程序可以显示缩放的图片。例如,一个应用程序可以提供可以提供一个可以缩放的图片以便查看和编辑没一个像素。其实缩放图片是调用了StretchBlt这个函数。象BitBlt函数,StretchBlt函数都可以把位图从一个DC拷贝到另外一个DC上。但是,与BitBlt这个函数不同的是,StretchBlt函数可以通过指定图象的尺寸来缩放图片,如果源位图的尺寸大于目标位图的尺寸,则目标图片就是缩小了的,反之目标图片就是放大了的。

如果目标位图尺寸小于源位图的尺寸,StretchBlt函数按照下面表格列出的缩放模式 去除颜色数据。

缩放模式:
BLACKONWHITE
对消除的像素和保留的像素执行逻辑AND 操作
WHITEONBLACK
对消除的像素和保留的像素执行逻辑OR 操作
COLORONCOLOR
直接去处颜色数据
HALFTONE
在目标位图中尽量保持源位图的色彩数据

可以通过调用SetStretchBltMode来缩放位图。

下面的例子取自一个应用程序,这个程序演示了如何显示一个原始的和放大一倍的位图(在这个程序中使用的是缺省的缩放模式)。

以下似乎是C语言

hdcScaled = CreateCompatibleDC(hdcScreen);
hbmScaled = CreateCompatibleBitmap(hdcScreen,
GetDeviceCaps(hdcScreen, HORZRES) * 2,
GetDeviceCaps(hdcScreen, VERTRES) * 2);

if (hbmScaled == 0)
errhandler(&quot;hbmScaled&quot;, hwnd);

// Select the bitmaps into the compatible DC.

if (!SelectObject(hdcScaled, hbmScaled))
errhandler(&quot;Scaled Bitmap Selection&quot;, hwnd);

case WM_COMMAND:
// message: command from application menu
switch(wParam)
{
case IDM_SCALEX1:
if (fBlt)
{
fScaled = FALSE;
hdcWin = GetDC(hwnd);
BitBlt(hdcWin,0,0,bmp.bmWidth, bmp.bmHeight,
hdcCompatible,0,0,SRCCOPY);
ReleaseDC(hwnd, hdcWin);
}
break;
case IDM_SCALEX2:
if (fBlt)
{
fScaled = TRUE;
StretchBlt(hdcScaled,0,0,
bmp.bmWidth * 2, bmp.bmHeight * 2,
hdcCompatible,0,0,
bmp.bmWidth, bmp.bmHeight,SRCCOPY);
hdcWin = GetDC(hwnd);
BitBlt(hdcWin,0,0,
bmp.bmWidth, bmp.bmHeight,
hdcScaled,0,0,SRCCOPY);
ReleaseDC(hwnd, hdcWin);
}
break;



调色板对图像的影响

当系统使用调色板时,显示图形必须正确设置调色板,否则图形会失真。

以下为对TImage设置调色板的情况
var
Bitmap: TBitmap;
begin
Bitmap:=TBitmap.Create;
Bitmap.LoadfromFile({'Whatever.bmp'});
With Image2.Picture.bitmap do
Begin
Width:=Bitmap.Width;
height:=Bitmap.Height;
Palette:=Bitmap.Palette;
Canvas.draw(0,0,bitmap);
Refresh;
end;
end;

以下为在Form上画图设置调色板的情况
Canvas.Draw(0,0,Bitmap);
SelectPalette(Form1.Canvas.handle,Bitmap.Palette,True);
RealizePalette(Form1.Canvas.Handle);




使资源中的Bitmap不失去调色板

在内存中构造BMP文件


HResInfo: THandle;
BMF: TBitmapFileHeader;
MemHandle: THandle;
Stream: TMemoryStream;
ResPtr: PByte;
ResSize: Longint;
null:array [0..8] of char;

begin
strpcopy (null, naam);
HResInfo := FindResource(HInstance, null, RT_Bitmap);
ResSize := SizeofResource(HInstance, HResInfo);
MemHandle := LoadResource(HInstance, HResInfo);
ResPtr := LockResource(MemHandle);

Stream := TMemoryStream.Create;
try
Stream.SetSize(ResSize + SizeOf(BMF));
BMF.bfType := $4D42;
Stream.Write(BMF, SizeOf(BMF));
Stream.Write(ResPtr^, ResSize);
Stream.Seek(0, 0);

Bitmap:=tbitmap.create;
Bitmap.LoadFromStream(Stream);
finally
Stream.Free;
end;
FreeResource(MemHandle);
end;



cjg325 (2002-12-12 20:59:00)
我也要cjg325@sina.com

jingzux (2002-12-20 13:16:00)
我也要fwcf@163.net,谢谢!

liuyang (2002-12-23 13:33:00)
多人接受答案了。

1028_zww1980 (2002-12-30 14:43:00)
我也要 zww@caascose.net.cn


Another_eYes-25,jsxjd-25,vine-28,的回答最终被接受。


问题讨论没有结束 ...
 
想知道如何采用SSE指令和优化算法
 
那位大侠能帮我翻译一下下面的c++代码?


const int __idecimal = 4096;
inline int AverageResize32VergeLine(BYTE * p_out,BYTE * p_in1,BYTE * p_in2,int x_verge,int x_in2,int x_delta)
{
//ebx : x_in2
//ecx : x_out
//edi : p_out
//esi : p_in1
//edx : p_in2
__asm
{
xor ecx,ecx
cmp ecx,x_verge
ja __end

mov edi,p_out
mov esi,p_in1
mov edx,p_in2
mov ebx,x_in2
__loop:
mov eax,ebx
shr eax,12
movd mm0,dword ptr [esi + eax * 4 + 0]
movd mm3,dword ptr [edx + eax * 4 + 0]

punpcklbw mm0,mm0
punpcklbw mm3,mm3
psrlw mm0,8
psrlw mm3,8
paddw mm0,mm3
psrlw mm0,1
packuswb mm0,mm0

movd dword ptr[edi + ecx * 4 + 0],mm0
add ebx,x_delta

inc ecx
cmp ecx,x_verge
jbe __loop
__end:
mov x_in2,ebx
}
return x_in2;
}

void AverageResize32Line(BYTE * p_out,BYTE * p_in1,BYTE * p_in2,int x_verge,int out_width,int x_in2,int x_delta)
{
//ebx : x_in2
//ecx : x_out
//edi : p_out
//esi : p_in1
//edx : p_in2
__asm
{
mov ecx,x_verge
cmp ecx,out_width
jae __end

mov edi,p_out
mov esi,p_in1
mov edx,p_in2
mov ebx,x_in2
__loop:
#if DOUBLE_AVERAGE
mov eax,ebx
sub eax,x_delta
shr eax,12
movd mm0,dword ptr [esi + eax * 4 + 0]
movd mm1,dword ptr [edx + eax * 4 + 0]

mov eax,ebx
shr eax,12
movd mm2,dword ptr [esi + eax * 4 + 0]
movd mm3,dword ptr [edx + eax * 4 + 0]

punpcklbw mm0,mm0
punpcklbw mm1,mm1
punpcklbw mm2,mm2
punpcklbw mm3,mm3
psrlw mm0,8
psrlw mm1,8
psrlw mm2,8
psrlw mm3,8
paddw mm2,mm3
paddw mm0,mm1
paddw mm0,mm2
psrlw mm0,2
packuswb mm0,mm0
#else
mov eax,ebx
sub eax,x_delta
shr eax,12
movd mm0,dword ptr [esi + eax * 4 + 0]

mov eax,ebx
shr eax,12
movd mm3,dword ptr [edx + eax * 4 + 0]

punpcklbw mm0,mm0
punpcklbw mm3,mm3
psrlw mm0,8
psrlw mm3,8
paddw mm0,mm3
psrlw mm0,1
packuswb mm0,mm0
#endif
movd dword ptr[edi + ecx * 4 + 0],mm0
add ebx,x_delta

inc ecx
cmp ecx,out_width
jb __loop
__end:
}
}

unsigned int AverageResize32(void * out,int out_width,int out_height,int out_pitch,
const void * in,int in_width,int in_height,int in_pitch)
{
//边界值
int y_delta = __idecimal * in_height / out_height;
int x_delta = __idecimal * in_width / out_width;
int y_verge = in_height / out_height / 2;
int x_verge = in_width / out_width / 2;

BYTE * p_out = (BYTE *)out;

int y_in2 = y_delta / 2;

//y边界条件
BYTE * p_in1 = (BYTE *)in;
BYTE * p_in2 = (BYTE *)((int)in + in_pitch * (y_in2 / __idecimal));
for(int y_out=0; y_out<y_verge; ++y_out)
{
//y,x边界条件
int x_in2 = x_delta / 2;
x_in2 = AverageResize32VergeLine(p_out,p_in1,p_in2,x_verge,x_in2,x_delta);
AverageResize32Line(p_out,p_in1,p_in2,x_verge,out_width,x_in2,x_delta);

p_out = (BYTE *)((int)p_out + out_pitch);

y_in2 += y_delta;
p_in2 = (BYTE *)((int)p_in2 + in_pitch * (y_in2 / __idecimal));
y_in2 %= __idecimal;
}

p_in1 = (BYTE *)((int)in + in_pitch * ((y_delta * y_out - y_delta / 2) / __idecimal));
p_in2 = (BYTE *)((int)in + in_pitch * ((y_delta * y_out + y_delta / 2) / __idecimal));
for(; y_out<out_height; ++y_out)
{
//x边界条件
int x_in2 = x_delta / 2;
x_in2 = AverageResize32VergeLine(p_out,p_in1,p_in2,x_verge,x_in2,x_delta);
AverageResize32Line(p_out,p_in1,p_in2,x_verge,out_width,x_in2,x_delta);

p_out = (BYTE *)((int)p_out + out_pitch);

y_in2 += y_delta;
p_in1 = p_in2;
//p_in1 = (BYTE *)((int)p_in1 + in_pitch * (y_in2 / __idecimal));
p_in2 = (BYTE *)((int)p_in2 + in_pitch * (y_in2 / __idecimal));
y_in2 %= __idecimal;
}

__asm emms;

return 0;
}
 

Similar threads

后退
顶部