图片旋转90度用什么方法比较快?

ooolinux 2020-03-10 12:13:44
图片是jpg格式,我需要加载到TBitmap对象,并旋转90度,不改变原图。
利用TBitmap的Canvas的Pixels[x][y]来旋转图片速度很慢。
...全文
1427 32 打赏 收藏 转发到动态 举报
写回复
用AI写文章
32 条回复
切换为时间正序
请发表友善的回复…
发表回复
ooolinux 2020-06-10
  • 打赏
  • 举报
回复
引用 33 楼 武稀松 的回复:
scanline纯内存操作,就很快。
ok
武稀松 2020-06-09
  • 打赏
  • 举报
回复
scanline纯内存操作,就很快。
ooolinux 2020-06-09
  • 打赏
  • 举报
回复
引用 31 楼 Y.A.K.E 的回复:
脖子一歪!谁都不爱. ................ firemonkey 图像或者组件可以直接旋转.
我用的VCL。
Y.A.K.E 2020-06-09
  • 打赏
  • 举报
回复
脖子一歪!谁都不爱.

................

firemonkey 图像或者组件可以直接旋转.
m0_46901103 2020-05-25
  • 打赏
  • 举报
回复
我是有一个图不停的旋转,取数据费点时间,然后旋转,在主线程定时画图,20帧左右
ooolinux 2020-04-28
  • 打赏
  • 举报
回复
引用 28 楼 m0_46901103的回复:
我是把图像数据取出,放到线程里旋转
同时旋转多个图对应用多个线程才有用。
m0_46901103 2020-04-28
  • 打赏
  • 举报
回复
我是把图像数据取出,放到线程里旋转
ooolinux 2020-03-14
  • 打赏
  • 举报
回复
引用 25 楼 早打大打打核战争 的回复:
windows bitmap的每行数据对齐到4字节边界,所以每行末尾可能有填充
如果旋转90度,把scanline数据从行变换为列,这个增加了一点复杂性。 帮我看看这个: https://bbs.csdn.net/topics/396123023
  • 打赏
  • 举报
回复
windows bitmap的每行数据对齐到4字节边界,所以每行末尾可能有填充
ooolinux 2020-03-13
  • 打赏
  • 举报
回复
引用 16 楼 早打大打打核战争 的回复:
可以给TBitmap写个Helper,补上一些方法来实现,我有空研究一下
不过如果研究出来也是很有用的。
ooolinux 2020-03-13
  • 打赏
  • 举报
回复
引用 17 楼 哦吼? 的回复:
openCV就可以了呀。如果是图像太大 可以先缩放 再旋转 再回复原来分辨率。如果担心图像经过缩放后变模糊了 可以通过拉普拉斯金字塔重建高分辨率图像 就得到旋转过后的清晰图像了。
这个厉害了,假如给你10块钱,能否拉普拉斯变成100块,买100块钱的东西回来?
ooolinux 2020-03-13
  • 打赏
  • 举报
回复
引用 16 楼 早打大打打核战争 的回复:
可以给TBitmap写个Helper,补上一些方法来实现,我有空研究一下
ok。我那个旋转慢了点尚且可以接受,小程序不怎么打算再整了。
邱小兵 2020-03-13
  • 打赏
  • 举报
回复
openCV就可以了呀。如果是图像太大 可以先缩放 再旋转 再回复原来分辨率。如果担心图像经过缩放后变模糊了 可以通过拉普拉斯金字塔重建高分辨率图像 就得到旋转过后的清晰图像了。
  • 打赏
  • 举报
回复
可以给TBitmap写个Helper,补上一些方法来实现,我有空研究一下
ooolinux 2020-03-13
  • 打赏
  • 举报
回复
引用 23 楼 wdonghai 的回复:

uses jpeg;

代码看不是很懂,你这个是在同一个bmp内挪动scanline的RGB数据吗? 不知道每一行的scanline是不是就是精确的RGB RGB RGB……这样三个字节的重复,不多(末尾)也不少?
wdonghai 2020-03-13
  • 打赏
  • 举报
回复

uses jpeg;

function RotateJPG90(AJPG:TJPEGImage):TBitmap;//顺时针90
var
bmp:TBitmap;
p,pBuf:PChar;
w,h,y,x,LineSize,nOfs:Integer;
begin
bmp:=TBitmap.Create;
bmp.PixelFormat:=pf24bit;
bmp.Assign(AJPG);
w:=bmp.Width;
h:=bmp.Height;
LineSize:=w*3;
GetMem(pBuf,LineSize*h);
try
for y:=0 to bmp.Height-1 do
begin
p:=bmp.ScanLine[y];
for x:=0 to bmp.Width-1 do
begin
nOfs:=(x*h+h-y-1)*3;
Move(p^,pBuf[nOfs],3);
Inc(p,3);
end;
end;
bmp.Width:=h;
bmp.Height:=w;
LineSize:=h*3;
for y:=0 to bmp.Height-1 do
begin
nOfs:=y*LineSize;
Move(pBuf[nOfs],bmp.scanline[y]^,LineSize);
end;
result:=bmp;
finally
FreeMem(pBuf);
end;
end;

function RotateJPG270(AJPG:TJPEGImage):TBitmap;//顺时针270
var
bmp:TBitmap;
p,pBuf:PChar;
w,h,y,x,LineSize,nOfs:Integer;
begin
bmp:=TBitmap.Create;
bmp.PixelFormat:=pf24bit;
bmp.Assign(AJPG);
w:=bmp.Width;
h:=bmp.Height;
LineSize:=w*3;
GetMem(pBuf,LineSize*h);
try
for y:=0 to bmp.Height-1 do
begin
p:=bmp.ScanLine[h-y-1];
for x:= bmp.Width-1 downto 0 do
begin
nOfs:=(x*h+h-y-1)*3;
Move(p^,pBuf[nOfs],3);
Inc(p,3);
end;
end;
bmp.Width:=h;
bmp.Height:=w;
LineSize:=h*3;
for y:=0 to bmp.Height-1 do
begin
nOfs:=y*LineSize;
Move(pBuf[nOfs],bmp.scanline[y]^,LineSize);
end;
result:=bmp;
finally
FreeMem(pBuf);
end;
end;

function RotateJPG180(AJPG:TJPEGImage):TBitmap;//顺时针180
var
bmp:TBitmap;
p1,p2:PChar;
h,y,x:Integer;
begin
bmp:=TBitmap.Create;
try
bmp.PixelFormat:=pf24bit;
bmp.Assign(AJPG);
result:=TBitmap.Create;
Result.PixelFormat:=pf24bit;
Result.Width:=bmp.Width;
Result.Height:=bmp.Height;
h:=bmp.Height;
for y:=0 to bmp.Height-1 do
begin
p1:=result.ScanLine[y];
p2:=PChar(Integer(bmp.ScanLine[h-1-y])+bmp.Width*3);
for x:=0 to bmp.Width-1 do
begin
Move(p2^,p1^,3);
inc(p1,3);
Dec(p2,3);
end;
end;
finally
bmp.Free;
end;
end;

function FlipVertical(AJPG:TJPEGImage):TBitmap;//水平镜像
var
bmp:TBitmap;
p1,p2:PChar;
h,y,LineSize:Integer;
begin
bmp:=TBitmap.Create;
try
bmp.PixelFormat:=pf24bit;
bmp.Assign(AJPG);
Result:=TBitmap.Create;
Result.PixelFormat:=pf24bit;
Result.Width:=bmp.Width;
Result.Height:=bmp.Height;
LineSize:=bmp.Width*3;
h:=bmp.Height;
for y:=0 to bmp.Height-1 do
begin
p1:=result.ScanLine[y];
p2:=bmp.ScanLine[h-1-y];
Move(p2^,p1^,LineSize);
end;
finally
bmp.Free;
end;
end;

function FlipHorizontal(AJPG:TJPEGImage):TBitmap;//垂直镜像
var
bmp:TBitmap;
p1,p2:PChar;
y,x:Integer;
begin
bmp:=TBitmap.Create;
try
bmp.PixelFormat:=pf24bit;
bmp.Assign(AJPG);
Result:=TBitmap.Create;
Result.PixelFormat:=pf24bit;
Result.Width:=bmp.Width;
Result.Height:=bmp.Height;
for y:=0 to bmp.Height-1 do
begin
p1:=result.ScanLine[y];
p2:=PChar(Integer(bmp.ScanLine[y])+bmp.Width*3);
for x:=0 to bmp.Width-1 do
begin
Move(p2^,p1^,3);
inc(p1,3);
Dec(p2,3);
end;
end;
finally
bmp.Free;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
jpg:TJPEGImage;
bmp:TBitmap;
begin
bmp:=nil;
jpg:=TJPEGImage.Create;
try
jpg.LoadFromFile('c:\1.jpg');
bmp:=RotateJPG90(jpg);//顺时针90
// bmp:=RotateJPG180(jpg);//顺时针180
// bmp:=RotateJPG270(jpg);//顺时针270
// bmp:=FlipHorizontal(jpg);//垂直镜像
// bmp:=FlipVertical(jpg);//水平镜像
Image1.Picture.Assign(bmp);
finally
bmp.Free;
jpg.Free;
end;
end;
邱小兵 2020-03-13
  • 打赏
  • 举报
回复
引用 19 楼 ooolinux的回复:
[quote=引用 17 楼 哦吼? 的回复:] openCV就可以了呀。如果是图像太大 可以先缩放 再旋转 再回复原来分辨率。如果担心图像经过缩放后变模糊了 可以通过拉普拉斯金字塔重建高分辨率图像 就得到旋转过后的清晰图像了。
这个厉害了,假如给你10块钱,能否拉普拉斯变成100块,买100块钱的东西回来?[/quote] 什么叫10块钱变100块钱。。。。直接去把10x10的图像放大到100x100就要进行插值,插值后细节就和原来的图像不一致了。但是它的分辨率实实在在是变大了。
邱小兵 2020-03-13
  • 打赏
  • 举报
回复
引用 19 楼 ooolinux的回复:
[quote=引用 17 楼 哦吼? 的回复:] openCV就可以了呀。如果是图像太大 可以先缩放 再旋转 再回复原来分辨率。如果担心图像经过缩放后变模糊了 可以通过拉普拉斯金字塔重建高分辨率图像 就得到旋转过后的清晰图像了。
这个厉害了,假如给你10块钱,能否拉普拉斯变成100块,买100块钱的东西回来?[/quote] 。。这两回事。。 我的意思是将原来的高清的图像建立拉普拉斯金字塔将它的细节保存起来,然后将图像缩小后旋转,然后通过低分辨率图像加上保存的细节部分放大到原尺寸,这样就可以减少细节损失。如果你对细节无要求,那直接缩小旋转后再放大到原尺寸就可以。如果你的图像本来就是正常尺寸,那直接用openCV的API去旋转就可以。
wdonghai 2020-03-12
  • 打赏
  • 举报
回复

uses jpeg;

function RotateJPG90(AJPG:TJPEGImage):TBitmap;
var
bmp:TBitmap;
p,pBuf:PChar;
w,h,y,x,LineSize,nOfs:Integer;
begin
bmp:=TBitmap.Create;
bmp.PixelFormat:=pf24bit;
bmp.Assign(AJPG);
w:=bmp.Width;
h:=bmp.Height;
LineSize:=w*3;
GetMem(pBuf,LineSize*h);
try
for y:=0 to bmp.Height-1 do
begin
p:=bmp.ScanLine[y];
for x:=0 to bmp.Width-1 do
begin
nOfs:=((x+1)*h-y-1)*3;
Move(p^,pBuf[nOfs],3);
Inc(p,3);
end;
end;
bmp.Width:=h;
bmp.Height:=w;
LineSize:=h*3;
for y:=0 to bmp.Height-1 do
begin
nOfs:=y*LineSize;
Move(pBuf[nOfs],bmp.scanline[y]^,LineSize);
end;
result:=bmp;
finally
FreeMem(pBuf);
end;
end;
加载更多回复(12)

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi GAME,图形处理/多媒体
社区管理员
  • GAME,图形处理/多媒体社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧