unit filterConvolution;
(* ***** BEGIN LICENSE BLOCK *****
* Copyright (C) 2004 Durand Emmanuel
* Copyright (C) 2004 Burgel Eric
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact :
* filters@edurand.com
* filters@burgel.com
*
* ***** END LICENSE BLOCK ***** *)
{
eburgel (filters@burgel.com)
}
interface
uses
filter, fparameters, image;
Type
TConvolutionEnum = (convNone, convLaplace, convHipass, convFindEdges, convSharpen, convEdgeEnhance, convEmboss, convSoften, convBlur, convSobelHorizontal, convSobelVertical) ;
const
TConvolutionEnumStr : Array[convNone..convSobelVertical] of String = ('None', 'Laplace', 'Hipass', 'FindEdges', 'Sharpen', 'EdgeEnhance', 'Emboss', 'Soften', 'Blur', 'SobelHorizontal', 'SobelVertical') ;
Type
TFilterConvolution = class(TFilter)
public
constructor Create; override;
procedure Run(); override;
procedure setConvType(aConvType: TConvolutionEnum);
procedure setParameterString( const aName, aValue:String ); override;
private
paramImageIn, paramImageOut : TParameterImage;
paramImageConvolution : TParameterImage;
paramConvType : TParameterString ;
paramZ : TParameterInteger ;
convType : TConvolutionEnum ;
procedure _run();
end;
implementation
Type
PIntArray = ^IntArray;
IntArray = array[0..0] of Integer;
function Set255(Clr : integer) : integer;
asm
MOV EAX,Clr // store value in EAX register (32-bit register)
CMP EAX,254 // compare it to 254
JG @SETHI // if greater than 254 then go set to 255 (max value)
CMP EAX,1 // if less than 255, compare to 1
JL @SETLO // if less than 1 go set to 0 (min value)
RET // otherwise it doesn't change, just exit
@SETHI: // Set value to 255
MOV EAX,255 // Move 255 into the EAX register
RET // Exit (result value is the EAX register value)
@SETLO: // Set value to 0
MOV EAX,0 // Move 0 into EAX register
end; // Result is in EAX
procedure TFilterConvolution.setParameterString( const aName, aValue:String );
begin
inherited;
if(aName='convType') then begin
if paramConvType.Value = 'None' Then setconvType(convNone)
else if paramConvType.Value = 'Laplace' Then setconvType(convLaplace)
else if paramConvType.Value = 'Hipass' Then setconvType(convHipass)
else if paramConvType.Value = 'FindEdges' Then setconvType(convFindEdges)
else if paramConvType.Value = 'Sharpen' Then setconvType(convSharpen)
else if paramConvType.Value = 'EdgeEnhance' Then setconvType(convEdgeEnhance)
else if paramConvType.Value = 'Emboss' Then setconvType(convEmboss)
else if paramConvType.Value = 'Soften' Then setconvType(convSoften)
else if paramConvType.Value = 'Blur' Then setconvType(convBlur)
else if paramConvType.Value = 'SobelHorizontal' Then setconvType(convSobelHorizontal)
else if paramConvType.Value = 'SobelVertical' Then setconvType(convSobelVertical) ;
end;
end;
constructor TFilterConvolution.Create;
begin
inherited;
paramImageIn := addParameterImage('inImage','Image to be filtered');
paramImageOut := addParameterImage('outImage','Filtered image');
paramConvType := addParameterString('convType', 'Convolution type', 'None');
paramImageConvolution := addParameterImage('imageConv','BW image for convolution weigth');
paramZ := addParameterInteger('z','global divisor',1, $10000, 128);
end;
procedure TFilterConvolution.Run;
begin
if (paramImageIn.Image<>nil) and (paramImageOut.Image<>nil) then begin
_run();
end;
end;
procedure TFilterConvolution._run;
var
pSrc, pLoopSrc, PDest, pConv, pLoopConv : PColor32Array;
pLoopDest : PIntArray ;
w,h : Word ;
x,y, max, maxX : Cardinal ;
convX, convY : word ;
maxConvX, maxConvY : word ;
weight : Integer ;
value : Integer ;
z : Integer ;
begin
{inherited;}
pSrc:=paramImageIn.Image.Bits;
pDest:=paramImageOut.Image.Bits;
h:=paramImageIn.Image.Height ;
w:=paramImageIn.Image.Width ;
max := h*w ;
maxX := w-2 ;
pConv := paramImageConvolution.Image.Bits ;
maxConvX := paramImageConvolution.Image.Width ;
maxConvY := paramImageConvolution.Image.Height ;
FillChar(pDest^, (max-1)*4, 0);
pLoopConv := pConv ;
for convY := 0 to maxConvY-1 do Begin
for convX := 0 to maxConvX -1 do Begin
weight := (Byte(pLoopConv[0]) and $FF) - 128;
if weight <> 0 Then Begin
for y:= 1 to h-2 do Begin
pLoopSrc := pSrc ;
inc (pLoopSrc, convY*w+convX) ;
inc (pLoopSrc, (y-1)*w);
pLoopDest := PIntArray(pDest) ;
inc(pLoopDest, y*w+1) ;
for x:= 1 to maxX do Begin
inc(pLoopDest[0], (Intensity(pLoopSrc[0]))*weight) ;
inc(pLoopSrc) ;
inc(pLoopDest) ;
End ;
End ;
End ;
inc(pLoopConv) ;
End ;
End ;
// normalization
z := paramZ.Value ;
pLoopDest := PIntArray(pDest) ;
for x:=0 to max-1 do Begin
value := (pLoopDest^[0]) * z;
value := value div 128;
value := Set255(value) ;
PColor32Array(pLoopDest)^[0] := value*$10101 ;
inc(pLoopDest) ;
End ;
end;
procedure TFilterConvolution.setConvType(aConvType: TConvolutionEnum);
Var img : PBitmap32 ;
Begin
if paramImageConvolution <> nil Then Begin
//freeBitmap(paramImageConvolution.Image);
//img := createBitmap(3, 3) ;
img := paramImageConvolution.Image ;
convType := aConvType ;
Case aConvType of
convNone : begin
setWeight(img, 0, 0, 0) ;
setWeight(img, 1, 0, 0) ;
setWeight(img, 2, 0, 0) ;
setWeight(img, 0, 1, 0) ;
setWeight(img, 1, 1, 16) ;
setWeight(img, 2, 1, 0) ;
setWeight(img, 0, 2, 0) ;
setWeight(img, 1, 2, 0) ;
setWeight(img, 2, 2, 0) ;
paramZ.Value := 8;
End ;
convLaplace : begin
setWeight(img, 0, 0, -16) ;
setWeight(img, 1, 0, -16) ;
setWeight(img, 2, 0, -16) ;
setWeight(img, 0, 1, -16) ;
setWeight(img, 1, 1, 127) ;
setWeight(img, 2, 1, -16) ;
setWeight(img, 0, 2, -16) ;
setWeight(img, 1, 2, -16) ;
setWeight(img, 2, 2, -16) ;
paramZ.Value := $80;
End ;
convHipass : Begin
setWeight(img, 0, 0, -16) ;
setWeight(img, 1, 0, -16) ;
setWeight(img, 2, 0, -16) ;
setWeight(img, 0, 1, -16) ;
setWeight(img, 1, 1, 127) ;
setWeight(img, 2, 1, -16) ;
setWeight(img, 0, 2, -16) ;
setWeight(img, 1, 2, -16) ;
setWeight(img, 2, 2, -15) ;
paramZ.Value := $80;
End ;
convfindEdges : Begin // Find Edges (top down)
setWeight(img, 0, 0, 64) ;
setWeight(img, 1, 0, 64) ;
setWeight(img, 2, 0, 64) ;
setWeight(img, 0, 1, 64) ;
setWeight(img, 1, 1, -128) ;
setWeight(img, 2, 1, 64) ;
setWeight(img, 0, 2, -64) ;
setWeight(img, 1, 2, -64) ;
setWeight(img, 2, 2, -64) ;
paramZ.Value := $20;
End ;
convSharpen : begin // Sharpen
setWeight(img, 0, 0, -4) ;
setWeight(img, 1, 0, -4) ;
setWeight(img, 2, 0, -4) ;
setWeight(img, 0, 1, -4) ;
setWeight(img, 1, 1, 64) ;
setWeight(img, 2, 1, -4) ;
setWeight(img, 0, 2, -4) ;
setWeight(img, 1, 2, -4) ;
setWeight(img, 2, 2, -4) ;
paramZ.Value := $4;
end;
convEdgeEnhance: Begin // Edge Enhance
//ray[0] := 0; ray[1] := -1; ray[2] := 0;
//ray[3] := -1; ray[4] := 5; ray[5] := -1;
//ray[6] := 0; ray[7] := -1; ray[8] := 0;
//z := 1;
setWeight(img, 0, 0, 0) ;
setWeight(img, 1, 0, -16) ;
setWeight(img, 2, 0, 0) ;
setWeight(img, 0, 1, 0) ;
setWeight(img, 1, 1, 80) ;
setWeight(img, 2, 1, -16) ;
setWeight(img, 0, 2, 0) ;
setWeight(img, 1, 2, -16) ;
setWeight(img, 2, 2, 0) ;
paramZ.Value := $4;
end;
convEmboss : begin // Emboss (Sorta)
//ray[0] := 1; ray[1] := 0; ray[2] := 1;
//ray[3] := 0; ray[4] := 0; ray[5] := 0;
//ray[6] := 1; ray[7] := 0; ray[8] := -2;
//z := 1;
setWeight(img, 0, 0, 1) ;
setWeight(img, 1, 0, 0) ;
setWeight(img, 2, 0, 1) ;
setWeight(img, 0, 1, 0) ;
setWeight(img, 1, 1, 0) ;
setWeight(img, 2, 1, 0) ;
setWeight(img, 0, 2, 1) ;
setWeight(img, 1, 2, 0) ;
setWeight(img, 2, 2, -2) ;
paramZ.Value := $80;
end;
convSoften : begin // Soften
//ray[0] := 2; ray[1] := 2; ray[2] := 2;
//ray[3] := 2; ray[4] := 0; ray[5] := 2;
//ray[6] := 2; ray[7] := 2; ray[8] := 2;
//z := 16;
setWeight(img, 0, 0, 2) ;
setWeight(img, 1, 0, 2) ;
setWeight(img, 2, 0, 2) ;
setWeight(img, 0, 1, 2) ;
setWeight(img, 1, 1, 0) ;
setWeight(img, 2, 1, 2) ;
setWeight(img, 0, 2, 2) ;
setWeight(img, 1, 2, 2) ;
setWeight(img, 2, 2, 2) ;
paramZ.Value := $8;
end;
convBlur : begin // Blur
//ray[0] := 3; ray[1] := 3; ray[2] := 3;
//ray[3] := 3; ray[4] := 8; ray[5] := 3;
//ray[6] := 3; ray[7] := 3; ray[8] := 3;
//z := 32;
setWeight(img, 0, 0, 3) ;
setWeight(img, 1, 0, 3) ;
setWeight(img, 2, 0, 3) ;
setWeight(img, 0, 1, 3) ;
setWeight(img, 1, 1, 8) ;
setWeight(img, 2, 1, 3) ;
setWeight(img, 0, 2, 3) ;
setWeight(img, 1, 2, 3) ;
setWeight(img, 2, 2, 3) ;
paramZ.Value := $4;
end;
// Gy
convSobelVertical : begin
setWeight(img, 0, 0, 1*16) ;
setWeight(img, 1, 0, 2*16) ;
setWeight(img, 2, 0, 1*16) ;
setWeight(img, 0, 1, 0*16) ;
setWeight(img, 1, 1, 0*16) ;
setWeight(img, 2, 1, 0*16) ;
setWeight(img, 0, 2, -1*16) ;
setWeight(img, 1, 2, -2*16) ;
setWeight(img, 2, 2, -1*16) ;
paramZ.Value := 8;
end;
// Gx
convSobelHorizontal : begin
setWeight(img, 0, 0, 1*16) ;
setWeight(img, 1, 0, 0*16) ;
setWeight(img, 2, 0, -1*16) ;
setWeight(img, 0, 1, 2*16) ;
setWeight(img, 1, 1, 0*16) ;
setWeight(img, 2, 1, -2*16) ;
setWeight(img, 0, 2, 1*16) ;
setWeight(img, 1, 2, 0*16) ;
setWeight(img, 2, 2, -1*16) ;
paramZ.Value := 8;
end;
(*
8 : begin // LAP1
ray[0] := 0; ray[1] := 1; ray[2] := 0;
ray[3] := 1; ray[4] := -4; ray[5] := 1;
ray[6] := 0; ray[7] := 1; ray[8] := 0;
z := 1;
end;
9 : begin // LAP4
ray[0] := 1; ray[1] := -2; ray[2] := 1;
ray[3] := -2; ray[4] := 4; ray[5] := -2;
ray[6] := 1; ray[7] := -2; ray[8] := 1;
z := 1;
end;
10 : begin // HP3
ray[0] := 1; ray[1] := -2; ray[2] := 1;
ray[3] := -2; ray[4] := 5; ray[5] := -2;
ray[6] := 1; ray[7] := -2; ray[8] := 1;
z := 1;
end;
11 : begin // Find Edges (Bottom top )
ray[0] := -1; ray[1] := -1; ray[2] := -1;
ray[3] := 1; ray[4] := -2; ray[5] := 1;
ray[6] := 1; ray[7] := 1; ray[8] := 1;
z := 1;
end;
12 : begin // Sobel hor
ray[0] := 1; ray[1] := 2; ray[2] := 1;
ray[3] := 0; ray[4] := 0; ray[5] := 0;
ray[6] := -1; ray[7] := -2; ray[8] := -1;
z := 1;
end;
13 : begin // Sobel vert
ray[0] := 1; ray[1] := 0; ray[2] := -1;
ray[3] := 2; ray[4] := 0; ray[5] := -2;
ray[6] := 1; ray[7] := 0; ray[8] := -1;
z := 1;
end;
14 : begin // Previt hor
ray[0] := 1; ray[1] := 1; ray[2] := 1;
ray[3] := 0; ray[4] := 0; ray[5] := 0;
ray[6] := -1; ray[7] := -1; ray[8] := -1;
z := 1;
end;
15 : begin // Previt vert
ray[0] := 1; ray[1] := 0; ray[2] := -1;
ray[3] := 1; ray[4] := 0; ray[5] := -1;
ray[6] := 1; ray[7] := 0; ray[8] := -1;
z := 1;
end;
16 : begin // Laplace - Origin
ray[0] := -1; ray[1] := -1; ray[2] := -1;
ray[3] := -1; ray[4] := 7; ray[5] := -1;
ray[6] := -1; ray[7] := -1; ray[8] := -1;
z := 1;
end;
17 : begin //Gaussian Blure
ray[0] := 1; ray[1] := 2; ray[2] := 1;
ray[3] := 2; ray[4] := 4; ray[5] := 2;
ray[6] := 1; ray[7] := 2; ray[8] := 1;
z := 16;
end;
*)
End ;
paramImageConvolution.Image := img ;
End
End ;
end.