unit filterDistancesMap;
(* ***** 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 ***** *)
{
edurand (filters@edurand.com)
eburgel (filters@burgel.com)
}
interface
uses
filter, fparameters, image;
type
TFilterDistancesMap = class(TFilter)
public
constructor Create; override;
procedure Run(); override;
private
parameterImageIn, parameterImageOut : TParameterImage;
parameterPreProcessInvert : TParameterBoolean ;
parameterMaxEDM : TParameterInteger ;
parameterPostProcessScale : TParameterInteger ;
imgIn, imgOut : PBitmap32 ;
procedure _run();
procedure setValue (offset, rowsize : Integer; image16:PColor32Array) ;
procedure setEdgeValue (offset, rowsize : Integer; image16:PColor32Array ; x, y, xmax, ymax : Integer) ;
end;
implementation
//uses
//imageIO;
Const
one = 41;
sqrt2 = 58; // ~ 41 * sqrt(2)
sqrt5 = 92; // ~ 41 * sqrt(5)
constructor TFilterDistancesMap.Create;
begin
inherited;
parameterImageIn:=addParameterImage('inImage', 'input image to invert');
parameterImageOut:=addParameterImage('outImage', 'result image of invertion');
parameterPreProcessInvert := addParameterBoolean('preprocessInvert', 'invertion of image before processing', false) ; ;
parameterMaxEDM :=addOutputParameterInteger('maxEDM', 'Maximum EDM in this image');
parameterPostProcessScale := addParameterInteger('scale', 'scale', 1, 40, 1) ;
end;
procedure TFilterDistancesMap.run () ;
begin
imgIn := parameterImageIn.Image ;
imgOut := parameterImageOut.Image ;
if (imgIn<>nil) and (imgOut<>nil) then begin
_run();
end;
end;
procedure TFilterDistancesMap._run () ;
Var
x, y, width, height : Integer ;
xmax, ymax : Integer ;
offset, rowsize : Integer ;
pSrc, image16 : PColor32Array;
rounded : cardinal ;
scale : cardinal ;
v : integer ;
outColor : TColor32 ;
maxEDM : integer ;
preInvert : Boolean ;
Begin
// showStatus("Generating EDM")
preInvert := parameterPreProcessInvert.Value ;
scale := parameterPostProcessScale.Value ;
width := scanWidth(imgIn);
height := scanHeight(imgIn) ;
rowsize := width;
xmax := scanWidth(imgIn)-1 ;
ymax := scanHeight(imgIn)-1 ;
for y:=0 to ymax do begin
pSrc := scanLine(imgIn, y) ;
image16 := scanLine(imgOut, y) ;
if (preInvert) then Begin
for x:=0 to xmax do begin
//image16^[0] := (pSrc^[0] and $FF) * one;
image16^[0] := ($FF - Intensity(pSrc^[0])) * one;
inc(image16) ;
inc(pSrc) ;
end ;
end else Begin
for x:=0 to xmax do begin
//image16^[0] := (pSrc^[0] and $FF) * one;
image16^[0] := Intensity(pSrc^[0]) * one;
inc(image16) ;
inc(pSrc) ;
end ;
end ;
end ;
xmax := width - 3;
ymax := height - 3;
image16 := scanLine(imgOut, 0) ;
for y:=0 to height-1 do Begin
for x:=0 to width-1 do Begin
offset := x + y * rowsize;
if (image16[offset] > 0) Then Begin
if ((x<2) or (x>xmax) or (y<2) or (y>ymax)) Then
setEdgeValue(offset, rowsize, image16, x, y, xmax, ymax)
else
setValue(offset, rowsize, image16);
end ;
end ;
end ;
for y := height-1 downto 0 do Begin
for x := width-1 downto 0 do Begin
offset := x + y * rowsize;
if (image16[offset] > 0) Then Begin
if ((x<2) or (x>xmax) or (y<2) or (y>ymax)) then
setEdgeValue (offset, rowsize, image16, x, y, xmax, ymax)
else
setValue (offset, rowsize, image16);
end ;
end ;
end ;
// Back to 8 bits images
rounded := one div 2;
maxEDM := 0;
for y:=0 to height-1 do Begin
for x:=0 to width-1 do Begin
offset := x + y * width;
v := (image16[offset] + rounded) div one * scale ;
if (v > 255) then Begin
outColor := clRed32 ;
v := 255;
end else
outColor := v*$10101 ;
if (v>maxEDM) then maxEDM := v;
image16[offset] := outColor;
end ;
end ;
setOutputParameterInteger('maxEDM',maxEDM);
end ; // run)
procedure TFilterDistancesMap.setValue(offset, rowsize : Integer; image16:PColor32Array) ;
Const
one = 41;
sqrt2 = 58; // ~ 41 * sqrt(2)
sqrt5 = 92; // ~ 41 * sqrt(5)
Var
v: Integer ;
r1, r2, r3, r4, r5 : Integer ;
min : Integer ;
Begin
r1 := offset - rowsize - rowsize - 2;
r2 := r1 + rowsize;
r3 := r2 + rowsize;
r4 := r3 + rowsize;
r5 := r4 + rowsize;
min := 32767;
v := image16[r2 + 2] + one;
if (v < min) then min := v;
v := image16[r3 + 1] + one;
if (v < min) then min := v;
v := image16[r3 + 3] + one;
if (v < min) then min := v;
v := image16[r4 + 2] + one;
if (v < min) then min := v;
v := image16[r2 + 1] + sqrt2;
if (v < min) then min := v;
v := image16[r2 + 3] + sqrt2;
if (v < min) then min := v;
v := image16[r4 + 1] + sqrt2;
if (v < min)then min := v;
v := image16[r4 + 3] + sqrt2;
if (v < min)then min := v;
v := image16[r1 + 1] + sqrt5;
if (v < min) then min := v;
v := image16[r1 + 3] + sqrt5;
if (v < min) then min := v;
v := image16[r2 + 4] + sqrt5;
if (v < min) then min := v;
v := image16[r4 + 4] + sqrt5;
if (v < min) then min := v;
v := image16[r5 + 3] + sqrt5;
if (v < min) then min := v;
v := image16[r5 + 1] + sqrt5;
if (v < min) then min := v;
v := image16[r4] + sqrt5;
if (v < min) then min := v;
v := image16[r2] + sqrt5;
if (v < min) then min := v;
image16[offset] := min;
end ; // setValue()
procedure TFilterDistancesMap.setEdgeValue (offset, rowsize : Integer; image16:PColor32Array ; x, y, xmax, ymax : Integer) ;
Const
one = 41;
sqrt2 = 58; // ~ 41 * sqrt(2)
sqrt5 = 92; // ~ 41 * sqrt(5)
Var
v: Integer ;
r1, r2, r3, r4, r5 : Integer ;
min : Integer ;
offimage : Integer ;
Begin
r1 := offset - rowsize - rowsize - 2;
r2 := r1 + rowsize;
r3 := r2 + rowsize;
r4 := r3 + rowsize;
r5 := r4 + rowsize;
min := 32767;
offimage := image16[r3 + 2];
if (y<2) then
v := offimage + one
else
v := image16[r2 + 2] + one;
if (v < min) then min := v;
if (x<2) then
v := offimage + one
else
v := image16[r3 + 1] + one;
if (v < min) then min := v;
if (x>xmax) then
v := offimage + one
else
v := image16[r3 + 3] + one;
if (v < min) then min := v;
if (y>ymax) then
v := offimage + one
else
v := image16[r4 + 2] + one;
if (v < min) then min := v;
if ((x<2) or (y<2)) then
v := offimage + sqrt2
else
v := image16[r2 + 1] + sqrt2;
if (v < min) then min := v;
if ((x>xmax) or (y<2)) then
v := offimage + sqrt2
else
v := image16[r2 + 3] + sqrt2;
if (v < min) then min := v;
if ((x<2) or (y>ymax)) then
v := offimage + sqrt2
else
v := image16[r4 + 1] + sqrt2;
if (v < min) then min := v;
if ((x>xmax) or (y>ymax)) then
v := offimage + sqrt2
else
v := image16[r4 + 3] + sqrt2;
if (v < min) then min := v;
if ((x<2) or (y<2)) then
v := offimage + sqrt5
else
v := image16[r1 + 1] + sqrt5;
if (v < min) then min := v;
if ((x>xmax) or (y<2)) then
v := offimage + sqrt5
else
v := image16[r1 + 3] + sqrt5;
if (v < min) then min := v;
if ((x>xmax) or (y<2)) then
v := offimage + sqrt5
else
v := image16[r2 + 4] + sqrt5;
if (v < min) then min := v;
if ((x>xmax) or (y>ymax)) then
v := offimage + sqrt5
else
v := image16[r4 + 4] + sqrt5;
if (v < min) then min := v;
if ((x>xmax) or (y>ymax)) then
v := offimage + sqrt5
else
v := image16[r5 + 3] + sqrt5;
if (v < min) then min := v;
if ((x<2) or (y>ymax)) then
v := offimage + sqrt5
else
v := image16[r5 + 1] + sqrt5;
if (v < min) then min := v;
if ((x<2) or (y>ymax)) then
v := offimage + sqrt5
else
v := image16[r4] + sqrt5;
if (v < min) then min := v;
if ((x<2) or (y<2)) then
v := offimage + sqrt5
else
v := image16[r2] + sqrt5;
if (v < min) then min := v;
image16[offset] := min;
end ;
end.