技术标签: Delphi图像处理 Delphi
阅读提示:
《Delphi图像处理》系列以效率为侧重点,一般代码为PASCAL,核心代码采用BASM。
《C++图像处理》系列以代码清晰,可读性为主,全部使用C++代码。
尽可能保持二者内容一致,可相互对照。
本文代码必须包括文章《Delphi图像处理 -- 数据类型及公用过程》中的ImageData.pas单元。
最近一段时间,在整理以前的文章,前几天刚刚将《Delphi图像处理 -- 色相/饱和度调整》一文修改整理完毕,可昨天不知怎么突然想到其实《Delphi图像处理 -- 色相/饱和度调整》中的代码还有优化的余地,因为在我的几篇关于图像色相/饱和度调整的文章里,一直是按照SHL为基础写的代码,事实上Photoshop的色相/饱和度调整功能也确实是以SHL为基础的,但是毕竟Photoshop的色相/饱和度调整并不是SHL调整,无论是明度、色相还是饱和度都有着很大独立性,它们之间的关系是松散性的,并非象SHL那样,三者联系得很紧,在《Delphi图像处理 -- 色相/饱和度调整》一文中,明度部分已经是独立调整的,但色相和饱和度部分还有着一些联系,主要是共用像素的S、L部分,但事实上,用SHL调整色相是很麻烦的,如果采用SHV来调整色相则会简单得多(当然,这只是指我采用的SSE代码,如果不是SSE代码,就很难说了,因为在《Delphi图像处理 -- 色相/饱和度调整》。一文的色相调整代码中,只计算了中间值,最大值和最小值保留原来的,这样本身就节省了不少代码)。改进代码写完后,本想覆盖更新《Delphi图像处理 -- 色相/饱和度调整》中的代码,但又觉得以前的代码还是保留为好,因此,把这改进后的代码作为续篇,以便二者之间对照比较:
procedure GetBrightTable(Bright: Integer; var Table: TGrayTable);
asm
push ebx
cmp eax, -255
jge @@1
mov eax, -255
jmp @@2
@@1:
cmp eax, 255
jle @@2
mov eax, 255
@@2:
push eax
mov ebx, 255
fild dword ptr[esp]
fwait
mov [esp], ebx
fidiv dword ptr[esp]// Bright / 255
fwait
xor ecx, ecx
test eax, eax
jg @@Loop
xor ebx, ebx // mask = Bright > 0? 255 : 0
@@Loop:
mov [esp], ecx
xor [esp], ebx
fild dword ptr[esp]
fmul st(0), st(1)
fistp dword ptr[esp]
fwait
mov eax, [esp]
add eax, ecx
mov [edx], al // Table[i] = (i ^ mask) * Bright / 255
inc edx
inc ecx
cmp ecx, 256
jb @@Loop
ffree st
pop eax
pop ebx
end;
procedure HSBSetBright(var Data: TImageData; const Table: TGrayTable);
asm
push ebp
push esi
push edi
push ebx
mov esi, edx
call _SetDataRegs
mov ebp, edx
@@yLoop:
push ecx
@@xLoop:
movzx eax, [edi].TARGBQuad.Blue
movzx edx, [edi].TARGBQuad.Green
mov al, [esi+eax]
mov dl, [esi+edx]
mov [edi].TARGBQuad.Blue, al
mov [edi].TARGBQuad.Green, dl
movzx eax, [edi].TARGBQuad.Red
mov al, [esi+eax]
mov [edi].TARGBQuad.Red, al
add edi, 4
loop @@xLoop
pop ecx
add edi, ebx
dec ebp
jnz @@yLoop
pop ebx
pop edi
pop esi
pop ebp
end;
procedure HSBSetHueAndSaturation(var Data: TImageData; Hv, Sv: Integer);
const
_fc2: Single = 2.0;
_fc4: Single = 4.0;
_fc6: Single = 6.0;
_fc128: Single = 128.0;
var
Hv0: Integer;
fHv: Single;
width, height, datOffset: Integer;
asm
push esi
push edi
push ebx
push ecx
mov Hv0, edx
call _SetDataRegs
mov width, ecx
mov height, edx
mov datOffset, ebx
pop ebx // Sv
pxor xmm7, xmm7
pxor xmm3, xmm3 // xmm3清零,便于色相处理时的或运算
mov eax, 1
cvtsi2ss xmm6, eax
mov eax, 60
cvtsi2ss xmm5, Hv0
cvtsi2ss xmm4, eax
divss xmm5, xmm4
movss fHv, xmm5 // fHv = Hv / 60
mov eax, 255
cvtsi2ss xmm5, ebx
cvtsi2ss xmm4, eax
divss xmm5, xmm4
movss xmm4, xmm5 // xmm4 = xmm5 = Sv / 255
test ebx, ebx
jle @@1
movaps xmm5, xmm6 // if (Sv > 0)
subss xmm5, xmm4 // xmm5 = 1 / (1 - xmm4) - 1
rcpss xmm5, xmm5
subss xmm5, xmm6
@@1:
pshufd xmm5, xmm5, 0
@@yLoop:
push width
@@xLoop:
movzx ecx, [edi].TARGBQuad.Blue
movzx edx, [edi].TARGBQuad.Green
movzx eax, [edi].TARGBQuad.Red
cmp ecx, edx // ecx = rgbMax
jge @@3 // edx = rgbMin
xchg ecx, edx
@@3:
cmp ecx, eax
jge @@4
xchg ecx, eax
@@4:
cmp edx, eax
cmova edx, eax
mov eax, ecx
sub eax, edx
jz @@next // if (delta == 0) continue
cvtsi2ss xmm3, eax // xmm3 = delta = rgbMax - rgbmin
cmp Hv0, 0
jne @@6
movd xmm0, [edi]
punpcklbw xmm0, xmm7
punpcklwd xmm0, xmm7
cvtdq2ps xmm0, xmm0
jmp @@20
@@6:
// 按HSV调整色相,比HSL快40%
movss xmm2, fHv // add = fHv
cmp cl, [edi].TARGBQuad.Red
jne @@8 // if (R == rgbMax) eax = G - B
movzx eax, [edi].TARGBQuad.Green
movzx esi, [edi].TARGBQuad.Blue
jmp @@10
@@8:
cmp cl, [edi].TARGBQuad.Green
jne @@9
movzx eax, [edi].TARGBQuad.Blue
movzx esi, [edi].TARGBQuad.Red
addss xmm2, _fc2 // if (G == rgbMax) eax = B - R; add += 2
jmp @@10
@@9:
movzx eax, [edi].TARGBQuad.Red
movzx esi, [edi].TARGBQuad.Green
addss xmm2, _fc4 // if (B == rgbMax) eax = R - G; add += 4
@@10:
sub eax, esi
cvtsi2ss xmm1, eax
divss xmm1, xmm3
addss xmm1, xmm2 // H = eax / delta + add
comiss xmm1, xmm7
jae @@11
addss xmm1, _fc6 // if (H < 0) H += 6
jmp @@12
@@11:
comiss xmm1, _fc6
jb @@12
subss xmm1, _fc6 // else if (H >= 6) H -= 6
@@12:
cvtss2si esi, xmm1 // index = Round(H)
cvtsi2ss xmm2, esi
subss xmm1, xmm2 // extra = H - index
comiss xmm1, xmm7 // if (extra < 0) // 如果index发生五入
jae @@13 // {
dec esi // index --
addss xmm1, xmm6 // extra ++
@@13: // }
test esi, 1
jnz @@14
movaps xmm2, xmm1
movss xmm1, xmm6
subss xmm1, xmm2 // if ((index & 1) == 0) extra = 1 - extra
@@14:
mulss xmm1, xmm3 // xmm1 = delta * extra
pslldq xmm1, 4
orps xmm1, xmm3
movlhps xmm1, xmm7 // xmm1 = 0 0 delta*extra delta
cvtsi2ss xmm0, ecx // xmm0 = V = rgbMax
pshufd xmm0, xmm0, 0 // xmm0 = V V V V
subps xmm0, xmm1 // xmm0 - xmm1 = NAN V T P
jmp @@jmpTable[esi*4].Pointer
@@jmpTable: dd offset @@H60
dd offset @@H120
dd offset @@H180
dd offset @@H240
dd offset @@H300
dd offset @@H360
dd offset @@H60// 当H=6.0时,SSE判断误差导致index=6,实际应为0
@@H360: // 300 - 359 (V, P, T)
pshufd xmm0, xmm0, 11100001b
jmp @@H60
@@H300: // 240 - 299 (T, P, V)
pshufd xmm0, xmm0, 11010010b
jmp @@H60
@@H240: // 180 - 239 (P, T, V)
pshufd xmm0, xmm0, 11000110b
jmp @@H60
@@H180: // 120 - 179 (P, V, T)
pshufd xmm0, xmm0, 11001001b
jmp @@H60
@@H120: // 60 - 119 (T, V, P)
pshufd xmm0, xmm0, 11011000b
@@H60: // 0 - 59 (V, T, P)
test ebx, ebx
je @@25
@@20:
// 调整饱和度。先按HSL计算亮度
add ecx, edx // ecx = rgbMar + rgbMin
cvtsi2ss xmm2, ecx
divss xmm2, _fc2 // xmm3 = L = ecx / 2
pshufd xmm2, xmm2, 0
movaps xmm1, xmm0
subps xmm0, xmm2 // rgb0 = rgb - L
test ebx, ebx
jle @@23
// 如果饱和度增量为正,按SHL计算饱和度以控制新的饱和度上限
comiss xmm2, _fc128 // if (Sv > 0)
jb @@21 // {
neg ecx
add ecx, 510 // if (L >= 128) ecx = 510 - ecx
@@21:
cvtsi2ss xmm2, ecx
divss xmm3, xmm2 // S = delta / ecx
addss xmm3, xmm4
comiss xmm3, xmm6
jb @@23
subss xmm3, xmm4 // if ((xmm4 + S) >= 1)
rcpss xmm2, xmm3 // rgb0 = rgb0 * (1 / S - 1)
subss xmm2, xmm6 // else
pshufd xmm2, xmm2, 0 // // 事先已经计算好存放在xmm5中
mulps xmm0, xmm2 // rgb0 = rgb0 * (1 / (1 - xmm4) - 1)
jmp @@24 // }
@@23: // else
mulps xmm0, xmm5 // rgb0 = rgb0 * fSv
@@24:
addps xmm0, xmm1 // rgb += rgb0
@@25:
cvtps2dq xmm0, xmm0
packssdw xmm0, xmm7
packuswb xmm0, xmm7
mov al, [edi].TARGBQuad.Alpha
movd [edi], xmm0
mov [edi].TARGBQuad.Alpha, al
@@next:
add edi, 4
dec width
jnz @@xLoop
add edi, datOffset
pop width
dec height
jnz @@yLoop
pop ebx
pop edi
pop esi
end;
procedure ImageHSBAdjustment(var Data: TImageData; hValue, sValue, bValue: Integer);
var
BrightTab: TGrayTable;
begin
if hValue > 180 then hValue := 180
else if hValue < -180 then hValue := -180;
if sValue > 255 then sValue := 255
else if sValue < -255 then sValue := -255;
if bValue <> 0 then GetBrightTable(bValue, BrightTab);
if (sValue > 0) and (bValue <> 0) then
HSBSetBright(Data, BrightTab);
if (hValue <> 0) or (sValue <> 0) then
begin
HSBSetHueAndSaturation(Data, hValue, sValue);
end;
if (sValue <= 0) and (bValue <> 0) then
HSBSetBright(Data, BrightTab);
end;
从上面的代码结构看,色相、饱和度和明度三者基本“独立”了,明度不用说,早独立了,色相和饱和度之间共享的部分仅仅是像素RGB值的最大值和差值(HSBSetHueAndSaturation过程中的ecx和xmm3)。经过简单测试,改进的代码速度提升不少,色相、饱和度和明度三者全部调整的时间只相当于《Delphi图像处理 -- 色相/饱和度调整》中的色相部分的调整时间。
最后鄙视一下CSDN,近来一直整理修改以前的文章,每一篇文章都重新加了4 - 5个标签,可是没过几天,文章的标签没了,我以为是我没设置好,又重新加了一遍,几天后,又没了!不带这么玩人的,再次鄙视CSDN。
《Delphi图像处理》系列使用GDI+单元下载地址和说明见文章《GDI+ for VCL基础 -- GDI+ 与 VCL》。
因水平有限,错误在所难免,欢迎指正和指导。邮箱地址:[email protected]
这里可访问《Delphi图像处理 -- 文章索引》。
本文是一些比较基础的shellcode开发技巧,有些技巧可能已经过时了。所有内容均摘自《0day安全软件漏洞分析技术 第二版》关于exploit和shellcode的区别:植入代码前需要大量调试,如,弄清程序有几个输入点,这些输入将最终会当做哪几个函数的第几个参数读入到内存的哪一个区域,哪一个输入会造成栈溢出,在复制到栈区的时候对这些数据有没有额外的限制等。调试之后,还要计算函数...
这两个选项分别用来设置socket接收数据和发送数据的超时时间,因此仅对于数据接收和发送相关的socket专用系统调用有效,,这些系统调用包括 send,sendmsg,recv,recvmsg ,accept 和connect.在程序中,我们可以根据系统调用的返回值和errno来判断超时时间是否已到,进而觉得是否开始定时任务.#include &lt;sys/types.h&gt;#inclu...
一、String 转 DateString ds=new String("2022-02-14"); Date sd=df.parse(ds);二、Date 转 StringDate d=new Date();SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");String ds=df.format(d);
原文链接地址:http://blog.csdn.net/tx3344/article/details/81065451.openmax 简介http://www.khronos.org/openmax/OpenMax是一个多媒体应用程序的框架标准,由NVIDIA公司和Khronos在2006年推出。OpenMAX分为3层:第一层:OpenMax DL(Devel
赋值语句= “=”符号跟数学上的“等于”是不同的 a=a+5 数学上是不成立的,意思是将变量a+5的值赋值给a =作用是把等号右边的值或者表达式的值赋给左边的变量输入输出语句:cin,cout: cin从键盘上输入变量值,格式:cin&gt;&gt;变量1&gt;&gt;变量2&gt;&gt;变量n;可一次读入多个不同类型的变量,...
一、网络与网络流给一个有向图(V,E),在V中指定一点,称为源点(记为vs),和另一点,称为汇点(记为vt),其余的点叫做中间点。对于E中每条弧(vi,vj)都对应一个正整数c(vi,vj)&gt;=0(或简写为cij),称为f的容量,则赋权有向图N=(V,E,c,vs,vt)称为一个网络。所谓网络上的流,是指定义在弧集E上的一个函数f=f{f{vi,vj}},并称f(vi,vj)为弧(vi,...
我随便谢谢,你随便看看!
C++之string长度(1)采用string的成员方法length()获取字符串长度(2)采用string的成员方法size()获取字符串长度(3)用strlen获取字符串长度(4)函数实现获取字符串长度的功能int GetStringWords( string strWord ){ int nWor...
上篇文章我们给出了用paddlepaddle来做手写数字识别的示例,并对网络结构进行到了调整,提高了识别的精度。有的同学表示不是很理解原理,为什么传统的机器学习算法,简单的神经网络(如多层感知机)都可以识别手写数字,我们要采用卷积神经网络CNN来进行别呢?CNN到底是怎么识别的?用CNN有哪些优势呢?我们下面就来简单分析一下。在讲CNN之前,为避免完全零基础的人看不懂后面的讲解,我们先简单回顾一下传统的神经网络的基本知识。神经网络的预备知识为什么要用神经网络?特征提取的高效性。大家可能会疑惑,对于同
流在生活中十分常见,例如交通系统中的人流、车流、物流,供水管网中的水流,金融系统中的现金流,网络中的信息流。网络流优化问题是基本的网络优化问题,应用非常广泛。网络流优化问题最重要的指标是边的成本和容量限制,既要考虑成本最低,又要满足容量限制,由此产生了网络最大流问题、最小费用流问题、最小费用最大流问题。本文基于 NetworkX 工具包,通过例程详细介绍网络最大流问题、最小费用流问题、最小费用最大流问题的建模和编程。
一、基本权限UGO一个文件或一个目录1、权限对象U 属主 G属组 O其他人 a(u+g+o)所有人2、权限类型 r=4 读权限 w=2写权限 x=1 执行权限3、查看权限(1)查看文件详细权限信息Ls -l 文件(2)查看目录详细权限信息Ls -l -d 目录例如:[[email protected] ~]#ls -l /root/1.txt- rw- r-- r-- .
前言现在刷抖音经常可以看到一些老外街坊,问他们最想把什么带回自己的国家,我听过很多的回答都是:淘宝,支付宝,美食,微信,外卖,高铁等等。确实如此,随着国家的快速发展吸引了不少国际上羡慕的目光,更让中国的新四大发明走向世界。说到这些,都离不开背后庞大的互联网体系的支撑,阿里作为国内最顶级的互联网企业必然也聚集了行业内顶级的IT人才。众所周知,阿里巴巴的主要开发语言就是Java,而对于Java开发者来说,最重要的就是学习Spring框架了。现在,我想跟大家分享出这份老外看外都不禁赞叹的《阿里技术官Spri