Обработка изображений с использованием расширения процессора
12. (по выбору пункта «операции - сохранить» на вкладке «результат») данные результативного изображения сохраняются в файл.
Листинг программы
const
MaxKernelSize = 64;
delay_names = 'миллисекунд';
//for image
PRGBTriple = ^TPxlC;
TPxlC = record//TPxlC
b:byte;
g:byte;
r:byte;
end;
PRow = ^TRow; //массив картинки
TRow = array[0 1000000] o
f TPxlC;
PPRows = ^TPRows; //массив строки пикселей
TPRows = array[0 1000000] of PRow;
TKernelSize = 1 MaxKernelSize;
TKernel = record //зерно
Size: TKernelSize; //размер зерна
Weights: array[-(MaxKernelSize-1) MaxKernelSize] of single;
end;
TXMMSingle = array[0 3] of Single;//массив для SSE
TXMMArrByte = array[0 15] of byte;//массив пикселей
TXMMRsByte = record
item:TXMMArrByte;
end;
TSSERegLines = array[0 5] of TXMMRsByte;
//основная процелура размытия
procedure GBlur(theBitmap: TBitmap; radius: double; withSSE:boolean);
var
frm_img: Tfrm_img;
implementation
uses DateUtils, optscopyimg, optsblurimg;
{$R *.dfm}
const
MAX_imageSize = 65535;
//построение зерна (списка весов) размытия (без SSE)
//MakeGaussianKernel noSSE-----------------------------------------------------
procedure MakeGaussianKernel(var K: TKernel; radius: double;
MaxData, DataGranularity: double);
//Делаем K (гауссово зерно) со среднеквадратичным отклонением = radius.
//Для текущего приложения мы устанавливаем переменные MaxData = 255,
//DataGranularity = 1. Теперь в процедуре установим значение
//K.Size так, что при использовании K мы будем игнорировать Weights (вес)
//с наименее возможными значениями. (Малый размер нам на пользу,
//поскольку время выполнения напрямую зависит от
//значения K.Size.)
var
j: integer;
temp, delta: double;
KernelSize: TKernelSize;
a,b:smallint;
begin
//получили строку весов (зерна)
for j:=Low(K.Weights) to High(K.Weights) do begin
temp := j / radius;
K.Weights[j] := exp(-(temp * temp) / 2);
end;
//делаем так, чтобы sum(Weights) = 1:
temp:=0;
for j := Low(K.Weights) to High(K.Weights) do
temp := temp + K.Weights[j];//все сумировали
for j := Low(K.Weights) to High(K.Weights) do
K.Weights[j] := K.Weights[j] / temp;//делим каждое на сумму (нормирование)
//теперь отбрасываем (или делаем отметку "игнорировать"
//для переменной Size) данные, имеющие относительно небольшое значение -
//это важно, в противном случае смазавание происходим с малым радиусом и
//той области, которая "захватывается" большим радиусом .
KernelSize := MaxKernelSize;
delta := DataGranularity / (2 * MaxData);
temp := 0;
while (temp < delta) and (KernelSize > 1) do
begin
temp := temp + 2 * K.Weights[KernelSize];
dec(KernelSize);
end;//выравнивание
K.Size := KernelSize;
//теперь для корректности возвращаемого результата проводим ту же
//операцию с K.Size, так, чтобы сумма всех данных была равна единице:
temp := 0;
for j := -K.Size to K.Size do
temp := temp + K.Weights[j];//
for j := -K.Size to K.Size do
K.Weights[j] := K.Weights[j] / temp;//
end;
//построение зерна (списка весов) размытия с SSE
//MakeGaussianKernel SSE-------------------------------------------------------
procedure MakeGaussianKernelSSE(var K: TKernel; radius: double;
MaxData, DataGranularity: double);
//Делаем K (гауссово зерно) со среднеквадратичным отклонением = radius.
//Для текущего приложения мы устанавливаем переменные MaxData = 255,
//DataGranularity = 1. Теперь в процедуре установим значение
//K.Size так, что при использовании K мы будем игнорировать Weights (вес)
//с наименее возможными значениями. (Малый размер нам на пользу,
//поскольку время выполнения напрямую зависит от
//значения K.Size.)
const
nmax=3;
var
j: integer;
temp, delta: double;
KernelSize: TKernelSize;
xmm_n,xmm_r,xmm_a:TXMMSingle;
_low,_high,na:smallint;
begin
_low:=Low(K.Weights);
_high:=High(K.Weights);
j:=_low;
for na:=0 to nmax do xmm_a[na]:=2;//константа 2
for na:=0 to nmax do xmm_r[na]:=radius;//радиус
asm
push eax
push ebx
push ecx
push edx
movups xmm0,xmm_a//2 в SSE
movups xmm1,xmm_r//радиус в SSE
end;
while (j<=_high) do begin
for na:=0 to nmax do
if ((j+na)<=_high) then
xmm_n[na]:=j+na
else break;
//копирование простое и передача не дает оптимизации в SSE
asm
movups xmm2,xmm_n //j
divps xmm2,xmm1 //j/radius
movups xmm_n,xmm2
mulps xmm2,xmm2 //temp^2
movups xmm_n,xmm2
divps xmm2,xmm0 //temp*temp/2
movups xmm_n,xmm2
end;//asm
for na:=0 to nmax do begin
if (j<=_high) then
K.Weights[j]:=exp(-xmm_n[na])
else break;
inc(j);
end;//for
end;//while
//получили строку весов (зерна)
//делаем так, чтобы sum(Weights) = 1:
temp:=0;
for j := Low(K.Weights) to High(K.Weights) do
temp := temp + K.Weights[j];//все сумировали
for j := Low(K.Weights) to High(K.Weights) do
K.Weights[j] := K.Weights[j] / temp;//делим каждое на сумму (нормирование)
for na:=0 to nmax do xmm_n[na]:=temp;
asm
movups xmm0,xmm_n;
end;
j:=_low;
while (j<=_high) do begin
for na:=0 to nmax do begin
if ((j+na)<=_high) then
xmm_n[na]:=K.Weights[j+na]
else break;
end;//for
asm
movups xmm1,xmm_n
divps xmm1,xmm0//K.Weights[j]/temp
movups xmm_n,xmm1
end;
for na:=0 to nmax do begin
if (j<=_high) then
K.Weights[j]:=xmm_n[na]
else break;
inc(j);
end;
end;//while
//отбрасываем (или делаем отметку "игнорировать"
//для переменной Size) данные, имеющие относительно небольшое значение -
//это важно, в противном случае смазавание происходим с малым радиусом и
//той области, которая "захватывается" большим радиусом .
KernelSize := MaxKernelSize;
delta := DataGranularity / (2 * MaxData);
temp := 0;
while (temp < delta) and (KernelSize > 1) do
begin
temp := temp + 2 * K.Weights[KernelSize];
dec(KernelSize);
end;//выравнивание
K.Size := KernelSize;
//для корректности возвращаемого результата проводим ту же
//операцию с K.Size, так, чтобы сумма всех данных была равна единице:
temp := 0;
for j := -K.Size to K.Size do
temp := temp + K.Weights[j];
for na:=0 to nmax do xmm_n[na]:=temp;
asm
movups xmm0,xmm_n;
end;
j:=_low;
while (j<=_high) do begin
for na:=0 to nmax do begin
if ((j+na)<=_high) then
xmm_n[na]:=K.Weights[j+na]
else break;
end;//for
asm
movups xmm1,xmm_n
divps xmm1,xmm0//K.Weights[j]/temp
movups xmm_n,xmm1
end;
for na:=0 to nmax do begin
if (j<=_high) then
K.Weights[j]:=xmm_n[na]
else break;
Другие рефераты на тему «Программирование, компьютеры и кибернетика»:
Поиск рефератов
Последние рефераты раздела
- Основные этапы объектно-ориентированного проектирования
- Основные структуры языка Java
- Основные принципы разработки графического пользовательского интерфейса
- Основы дискретной математики
- Программное обеспечение системы принятия решений адаптивного робота
- Программное обеспечение
- Проблемы сохранности информации в процессе предпринимательской деятельности