一:水平镜像/翻转
       将一幅图像水平镜像/翻转,代码很简单,就一行代码:

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 汇编学习(八)--- 图像水平镜像垂直镜像的极致优化相关推荐

  1. Delphi 汇编学习(十)--- 内存复制的极致优化

    在 汇编学习(八)--- 图像水平镜像垂直镜像的极致优化 中,我们使用了 FastMove,来提高内存复制速度. 但 FastMove 不支持 x64.而且很多年没有更新了.我们自己动手来写吧.由简到 ...

  2. OpenCV与图像处理学习八——图像边缘提取(Canny检测代码)

    OpenCV与图像处理学习八--图像边缘提取(Canny检测代码) 一.图像梯度 1.1 梯度 1.2 图像梯度 二.梯度图与梯度算子 2.1模板卷积 2.2 梯度图 2.3 梯度算子 2.3.1 R ...

  3. 41、labelme数据集转dota、rolabelimg以及rolabelimg转dota、labelme和labelimg数据集旋转水平镜像 垂直镜像 和水平垂直镜像

    基本思想:为了给BBAVectors-Oriented-Object-Detection 提供数据,所以记录一下操作,搞了旋转,但是旋转影响图片大小,所以先写个镜像方法,进行训练和使扩充数据集 一.l ...

  4. MATLAB:图像水平、垂直、水平垂直镜像、转置、旋转变换

    1.原图像经水平.垂直.水平垂直镜像设置通过mirror函数实现: close all; %关闭当前所有图形窗口,清空工作空间变量,清除工作空间所有变量 clear all; clc; I=imrea ...

  5. c语言如何实现水平和垂直镜像_如何用C语言实现OOP

    点击上方蓝字关注我们 我们知道面向对象的三大特性分别是:封装.继承.多态.很多语言例如:C++和Java等都是面向对象的编程语言,而我们通常说C是面向过程的语言,那么是否可以用C实现简单的面向对象呢? ...

  6. PyTorch框架学习五——图像预处理transforms(一)

    PyTorch框架学习五--图像预处理transforms(一) 一.transforms运行机制 二.transforms的具体方法 1.裁剪 (1)随机裁剪:transforms.RandomCr ...

  7. 图像几何变换C++实现--镜像,平移,旋转,错切,缩放

    一.图像几何变换介绍 图像的几何空间变换是图像处理中的最基础的算法,是指对原始图像按需要改变其大小.形状和位置的变化,原始图像与目标函数之间的坐标变换函数为线性函数.二维图像的基本几何变换主要包括镜像 ...

  8. 数据标注:图像镜像(水平镜像;垂直镜像;对角镜像)

    1 介绍 在训练卷积神经网络的时候,常常需要将原有图像数据集进行一定程度上的扩充,采用的手段主要是图像镜像等方法.本文主要实现了图像的批量水平镜像,垂直镜像,对角镜像功能,希望对你有所帮助! 2 源代 ...

  9. opencv学习---计算图像的水平积分投影和垂直积分投影

    opencv学习---计算图像的水平积分投影和垂直积分投影 标签: opencv水平积分投影垂直积分投影 2016-12-07 18:48 1806人阅读 评论(1) 收藏 举报 分类: opencv ...

最新文章

  1. 基于SSH实现的学生成绩管理系统
  2. Python实现固定效应回归模型实现因果关系推断
  3. 我的技术回顾因ABP框架触发DevOps云原生之路-2020年
  4. jdeveloper_适用于JDeveloper 11gR2的Glassfish插件
  5. android pdu 编码规则,[转载]PDU编码规则
  6. 遗传算法求函数最大值实验_小知识:什么是遗传算法
  7. 【Python】我的第一个EXE程序
  8. 京东开通数字人民币“硬件钱包”线上消费功能
  9. [链表]同时遍历两个链表
  10. BTC 重现“自由落体”式暴跌,原来是受这几个因素影响?
  11. 微信到底做没做精准广告投放? | 技术头条
  12. 实战攻防比赛中作为防守方需要做哪些工作
  13. HTML5 第003篇 area标签
  14. 基于Python的股票红利预测
  15. 操作系统同步互斥问题
  16. r55600h和i511320h哪个好
  17. 华硕笔记本全硬盘恢复原厂状态 实机操作,MYASUS IN WINRE恢复,ASUS RECOVERY恢复
  18. Linux系统下计算机C语言的编程技巧
  19. 技术思维VS管理思维
  20. 关于split的用法与注意事项

热门文章

  1. Java时间轮算法的实现
  2. python在abaqus中的应用光盘文件下载_python语言在abaqus中的应用随书光盘.rar-讲义文档类资源...
  3. QGIS官网安装包下载与安装
  4. 【python学习笔记】关于python Flask前后端分离跨域问题
  5. 王者荣耀科技守护者密码答案是什么?最新科技守护者密码分享
  6. Excel中按多个符号进行分列
  7. Centos 7分辨率调整成适应虚拟机屏幕大小
  8. 如何让安卓手机访问内网服务器?
  9. Linux学习-文件操作和属性
  10. 2019最应该投资什么?是你明年的北大核心