Delphi 汇编学习(八)--- 图像水平镜像垂直镜像的极致优化
一:水平镜像/翻转
将一幅图像水平镜像/翻转,代码很简单,就一行代码:
procedure HorizMirror(bmp: TBitmap);
beginbmp.Canvas.CopyRect(bmp.Canvas.ClipRect, bmp.Canvas, Rect(bmp.Width, 0, 0, bmp.Height));
end;
简单不。看一看 CopyRect 源码,
procedure TCanvas.CopyRect(const Dest: TRect; Canvas: TCanvas; const Source: TRect);
beginChanging;RequiredState([csHandleValid, csFontValid, csBrushValid]);Canvas.RequiredState([csHandleValid, csBrushValid]);StretchBlt(FHandle, Dest.Left, Dest.Top, Dest.Right - Dest.Left,Dest.Bottom - Dest.Top, Canvas.FHandle, Source.Left, Source.Top,Source.Right - Source.Left, Source.Bottom - Source.Top, CopyMode);Changed;
end;
Changing / RequireState / Changed 肯定影响效率。真正起作用的是 StrectchBlt 函数。
虽然说这个 StrectchBlt 效率已经不错了。4096x4096x32 的图片,在我的机器上耗时 100 毫秒左右。
有没有可以在优化的地方呢,如果我们自己来写该如何呢?
自己写当然是用 Scanline 方法了(简单)。按中间位置,左右水平像素对调,再加上多核并行:
{ 水平翻转 并行模式,需要脱离 IDE 执行 }
procedure HorizMirror(bmp: TBitmap);
varStartScanLine: Integer;bmpWidthBytes: Integer;
beginStartScanLine := Integer(bmp.ScanLine[0]);bmpWidthBytes := Integer(bmp.ScanLine[1]) - Integer(bmp.ScanLine[0]);TParallel.For(0, bmp.Height - 1,procedure(Y: Integer)varX: Integer;swapColor: DWORD;pColor01: PDWORD;pColor02: PDWORD;beginpColor01 := PDWORD(StartScanLine + Y * bmpWidthBytes);pColor02 := PDWORD(StartScanLine + Y * bmpWidthBytes);Inc(pColor02, bmp.Width - 1);for X := 0 to bmp.Width div 2 - 1 dobeginswapColor := pColor02^;pColor02^ := pColor01^;pColor01^ := swapColor;Inc(pColor01);Dec(pColor02);end;end);
end;
这段代码,在我的机器上,4096X4096X32 的图片,只需要 5 毫秒左右的时间,非常的理想了,无需进行 SSE 优化了。
二:垂直镜像/翻转
垂直镜像/翻转,同样也只需要一行代码:
{ 垂直翻转 }
procedure VertiMirror(bmp: TBitmap);
beginbmp.Canvas.CopyRect(bmp.Canvas.ClipRect, bmp.Canvas, Rect(0, bmp.Height, bmp.Width, 0));
end;
在我的机器上,4096X4096X32 的图片,耗时 100 毫秒左右。
想一想,垂直镜像,就是上下行对调。整行内存交换呀。自己写的话,效率应该比 StrectchBlt 好。来试试:
{ 垂直镜像/翻转 }
procedure VertiMirror(bmp: TBitmap);
varCount, Y: Integer;pColor01: PByte;pColor02: PByte;tmpColor: PByte;
beginCount := Integer(bmp.ScanLine[0]) - Integer(bmp.ScanLine[1]);tmpColor := AllocMem(Count);tryfor Y := 0 to bmp.Height div 2 - 1 dobeginpColor01 := bmp.ScanLine[Y];pColor02 := bmp.ScanLine[bmp.Height - Y - 1];Move(pColor01^, tmpColor^, Count);Move(pColor02^, pColor01^, Count);Move(tmpColor^, pColor02^, Count);end;finallyFreeMem(tmpColor);end;
end;
这段代码,没有使用多核并行,也没有使用 SSE 优化。就是内存的交换。
在我的机器上耗时 15 毫秒左右。效率提高很明显呀。6倍之多!
印证了那句话:相信指令,相信编译器,不如相信自己。自己动手,丰衣足食!
当看到 AllocMem、Move,你想到了什么?
内存管理。Delphi 优化内存的有:FastMM4、FastMM5、FastMM4-AVX、FastCode、FastMove。
对。引入试试。
在工程单元文件中,第一行,添加引用:FastMove。函数不用做任何修改。再编译一下程序。
运行看看效果。在我的机器上耗时降到了 10 毫秒左右。呵呵。不错不错。
少了 5 毫秒的时间。如何少的,看看 FastMove 源码就知道了。留作课后作业了。
三:转置
即水平翻转+垂直翻转。
{ 转置翻转 并行模式,需要脱离 IDE 执行 }
procedure HAndVMirror(bmp: TBitmap);
beginHorizMirror(bmp);VertiMirror(bmp);
end;
详细代码:https://github.com/dbyoung720/ImageGray.git
qq交流群:101611228
Delphi 汇编学习(八)--- 图像水平镜像垂直镜像的极致优化相关推荐
- Delphi 汇编学习(十)--- 内存复制的极致优化
在 汇编学习(八)--- 图像水平镜像垂直镜像的极致优化 中,我们使用了 FastMove,来提高内存复制速度. 但 FastMove 不支持 x64.而且很多年没有更新了.我们自己动手来写吧.由简到 ...
- OpenCV与图像处理学习八——图像边缘提取(Canny检测代码)
OpenCV与图像处理学习八--图像边缘提取(Canny检测代码) 一.图像梯度 1.1 梯度 1.2 图像梯度 二.梯度图与梯度算子 2.1模板卷积 2.2 梯度图 2.3 梯度算子 2.3.1 R ...
- 41、labelme数据集转dota、rolabelimg以及rolabelimg转dota、labelme和labelimg数据集旋转水平镜像 垂直镜像 和水平垂直镜像
基本思想:为了给BBAVectors-Oriented-Object-Detection 提供数据,所以记录一下操作,搞了旋转,但是旋转影响图片大小,所以先写个镜像方法,进行训练和使扩充数据集 一.l ...
- MATLAB:图像水平、垂直、水平垂直镜像、转置、旋转变换
1.原图像经水平.垂直.水平垂直镜像设置通过mirror函数实现: close all; %关闭当前所有图形窗口,清空工作空间变量,清除工作空间所有变量 clear all; clc; I=imrea ...
- c语言如何实现水平和垂直镜像_如何用C语言实现OOP
点击上方蓝字关注我们 我们知道面向对象的三大特性分别是:封装.继承.多态.很多语言例如:C++和Java等都是面向对象的编程语言,而我们通常说C是面向过程的语言,那么是否可以用C实现简单的面向对象呢? ...
- PyTorch框架学习五——图像预处理transforms(一)
PyTorch框架学习五--图像预处理transforms(一) 一.transforms运行机制 二.transforms的具体方法 1.裁剪 (1)随机裁剪:transforms.RandomCr ...
- 图像几何变换C++实现--镜像,平移,旋转,错切,缩放
一.图像几何变换介绍 图像的几何空间变换是图像处理中的最基础的算法,是指对原始图像按需要改变其大小.形状和位置的变化,原始图像与目标函数之间的坐标变换函数为线性函数.二维图像的基本几何变换主要包括镜像 ...
- 数据标注:图像镜像(水平镜像;垂直镜像;对角镜像)
1 介绍 在训练卷积神经网络的时候,常常需要将原有图像数据集进行一定程度上的扩充,采用的手段主要是图像镜像等方法.本文主要实现了图像的批量水平镜像,垂直镜像,对角镜像功能,希望对你有所帮助! 2 源代 ...
- opencv学习---计算图像的水平积分投影和垂直积分投影
opencv学习---计算图像的水平积分投影和垂直积分投影 标签: opencv水平积分投影垂直积分投影 2016-12-07 18:48 1806人阅读 评论(1) 收藏 举报 分类: opencv ...
最新文章
- 基于SSH实现的学生成绩管理系统
- Python实现固定效应回归模型实现因果关系推断
- 我的技术回顾因ABP框架触发DevOps云原生之路-2020年
- jdeveloper_适用于JDeveloper 11gR2的Glassfish插件
- android pdu 编码规则,[转载]PDU编码规则
- 遗传算法求函数最大值实验_小知识:什么是遗传算法
- 【Python】我的第一个EXE程序
- 京东开通数字人民币“硬件钱包”线上消费功能
- [链表]同时遍历两个链表
- BTC 重现“自由落体”式暴跌,原来是受这几个因素影响?
- 微信到底做没做精准广告投放? | 技术头条
- 实战攻防比赛中作为防守方需要做哪些工作
- HTML5 第003篇 area标签
- 基于Python的股票红利预测
- 操作系统同步互斥问题
- r55600h和i511320h哪个好
- 华硕笔记本全硬盘恢复原厂状态 实机操作,MYASUS IN WINRE恢复,ASUS RECOVERY恢复
- Linux系统下计算机C语言的编程技巧
- 技术思维VS管理思维
- 关于split的用法与注意事项