Обработка изображений с использованием расширения процессора

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;

Страница:  1  2  3  4  5  6  7 


Другие рефераты на тему «Программирование, компьютеры и кибернетика»:

Поиск рефератов

Последние рефераты раздела

Copyright © 2010-2024 - www.refsru.com - рефераты, курсовые и дипломные работы