Zhang-Suen thinning algorithm: Difference between revisions

Content added Content deleted
(added Swift)
m (Added syntax highlighting (working from the back of the task list).)
Line 111: Line 111:
{{trans|Python}}
{{trans|Python}}


<lang 11l>V beforeTxt = |‘1100111
<syntaxhighlight lang=11l>V beforeTxt = |‘1100111
1100111
1100111
1100111
1100111
Line 216: Line 216:
print("\nFrom:\n#.".format(toTxt(image)))
print("\nFrom:\n#.".format(toTxt(image)))
V after = zhangSuen(&image)
V after = zhangSuen(&image)
print("\nTo thinned:\n#.".format(toTxt(after)))</lang>
print("\nTo thinned:\n#.".format(toTxt(after)))</syntaxhighlight>


{{out}}
{{out}}
Line 263: Line 263:


=={{header|Action!}}==
=={{header|Action!}}==
<lang Action!>PROC DrawImage(BYTE ARRAY image BYTE x,y,width,height)
<syntaxhighlight lang=Action!>PROC DrawImage(BYTE ARRAY image BYTE x,y,width,height)
BYTE i,j
BYTE i,j
BYTE POINTER ptr
BYTE POINTER ptr
Line 393: Line 393:
DO UNTIL CH#$FF OD
DO UNTIL CH#$FF OD
CH=$FF
CH=$FF
RETURN</lang>
RETURN</syntaxhighlight>
{{out}}
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Zhang-Suen_thinning_algorithm.png Screenshot from Atari 8-bit computer]
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Zhang-Suen_thinning_algorithm.png Screenshot from Atari 8-bit computer]


=={{header|AppleScript}}==
=={{header|AppleScript}}==
<lang applescript>-- Params:
<syntaxhighlight lang=applescript>-- Params:
-- List of lists (rows) of "pixel" values.
-- List of lists (rows) of "pixel" values.
-- Record indicating the values representing black and white.
-- Record indicating the values representing black and white.
Line 489: Line 489:
return join(matrix, linefeed)
return join(matrix, linefeed)
end demo
end demo
return demo()</lang>
return demo()</syntaxhighlight>


{{output}}
{{output}}
<lang applescript>"00000000000000000000000000000000
<pre>"00000000000000000000000000000000
00111111100000000011111100000000
00111111100000000011111100000000
00100000100000000110000000000000
00100000100000000110000000000000
Line 501: Line 501:
00000000100001000110000110001000
00000000100001000110000110001000
00000000010000000001111000000000
00000000010000000001111000000000
00000000000000000000000000000000"</lang>
00000000000000000000000000000000"</pre>
Alternative demo:
Alternative demo:
<lang applescript>on demo()
<syntaxhighlight lang=applescript>on demo()
set pattern to "
set pattern to "
################# #############
################# #############
Line 532: Line 532:
return join(matrix, linefeed)
return join(matrix, linefeed)
end demo
end demo
return demo()</lang>
return demo()</syntaxhighlight>


{{output}}
{{output}}
<lang applescript>"
<pre>
# ########## #######
# ########## #######
Line 551: Line 551:
# ############
# ############
### ###
### ###
</pre>
"</lang>


=={{header|AutoHotkey}}==
=={{header|AutoHotkey}}==
{{works with|AutoHotkey_L}}
{{works with|AutoHotkey_L}}
Reads input from a text file and writes output to a different text file (first creating the file, if necessary).
Reads input from a text file and writes output to a different text file (first creating the file, if necessary).
<lang AutoHotkey>FileIn := A_ScriptDir "\Zhang-Suen.txt"
<syntaxhighlight lang=AutoHotkey>FileIn := A_ScriptDir "\Zhang-Suen.txt"
FileOut := A_ScriptDir "\NewFile.txt"
FileOut := A_ScriptDir "\NewFile.txt"


Line 635: Line 634:
return 1
return 1
return Neighbors
return Neighbors
}</lang>
}</syntaxhighlight>
'''Output:'''
'''Output:'''
<pre>
<pre>
Line 656: Line 655:
</pre>
</pre>
The images before and after thinning are also printed on the console.
The images before and after thinning are also printed on the console.
<syntaxhighlight lang=C>
<lang C>
#include<stdlib.h>
#include<stdlib.h>
#include<stdio.h>
#include<stdio.h>
Line 817: Line 816:
return 0;
return 0;
}
}
</syntaxhighlight>
</lang>


Contents of input file : zhImage.txt
Contents of input file : zhImage.txt
Line 887: Line 886:
=={{header|C++}}==
=={{header|C++}}==
Compiled with --std=c++14
Compiled with --std=c++14
<lang CPP>#include <iostream>
<syntaxhighlight lang=CPP>#include <iostream>
#include <string>
#include <string>
#include <sstream>
#include <sstream>
Line 1,128: Line 1,127:
return 0;
return 0;
}
}
</syntaxhighlight>
</lang>


Output:
Output:
Line 1,202: Line 1,201:
=={{header|D}}==
=={{header|D}}==
This uses the module from the Bitmap Task. And it performs no heap allocations.
This uses the module from the Bitmap Task. And it performs no heap allocations.
<lang d>import std.stdio, std.algorithm, std.string, std.functional,
<syntaxhighlight lang=d>import std.stdio, std.algorithm, std.string, std.functional,
std.typecons, std.typetuple, bitmap;
std.typecons, std.typetuple, bitmap;


Line 1,329: Line 1,328:
writeln;
writeln;
}
}
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>From:
<pre>From:
Line 1,430: Line 1,429:
ELENA 5.0 :
ELENA 5.0 :
{{trans|Java}}
{{trans|Java}}
<lang elena>import system'collections;
<syntaxhighlight lang=elena>import system'collections;
import system'routines;
import system'routines;
import extensions;
import extensions;
Line 1,597: Line 1,596:
console.readChar()
console.readChar()
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,621: Line 1,620:
=={{header|Elixir}}==
=={{header|Elixir}}==
{{trans|Ruby}}
{{trans|Ruby}}
<lang elixir>defmodule ZhangSuen do
<syntaxhighlight lang=elixir>defmodule ZhangSuen do
@neighbours [{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}] # 8 neighbours
@neighbours [{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}] # 8 neighbours
Line 1,710: Line 1,709:
00000000000000000000000000000000
00000000000000000000000000000000
"""
"""
ZhangSuen.thinning(str, ?1)</lang>
ZhangSuen.thinning(str, ?1)</syntaxhighlight>


{{out}}
{{out}}
Line 1,773: Line 1,772:


=={{header|Fortran}}==
=={{header|Fortran}}==
With F90 came standardisation of a variety of array manipulation facilities. Since the image array is to be inspected as a whole then adjusted rather than adjusted step-by-step as it is inspected, the first thought was to employ the special facility of the FOR ALL statement, which is that in an expression such as <lang Fortarn>FOR ALL (i = 2:n - 1) A(i) = (A(i - 1) + A(i) + A(i + 1))/3</lang> all right-hand-side expressions will be evaluated with the original values of the array, while in the less special array assignment <lang Fortran>A(2:N - 1) = (A(1:N - 2) + A(2:N - 1) + A(3:N))/3</lang> as in the case of the equivalent DO-loop, the processing will be with a mixture of old and new values as the loop proceeds.
With F90 came standardisation of a variety of array manipulation facilities. Since the image array is to be inspected as a whole then adjusted rather than adjusted step-by-step as it is inspected, the first thought was to employ the special facility of the FOR ALL statement, which is that in an expression such as <syntaxhighlight lang=Fortarn>FOR ALL (i = 2:n - 1) A(i) = (A(i - 1) + A(i) + A(i + 1))/3</syntaxhighlight> all right-hand-side expressions will be evaluated with the original values of the array, while in the less special array assignment <syntaxhighlight lang=Fortran>A(2:N - 1) = (A(1:N - 2) + A(2:N - 1) + A(3:N))/3</syntaxhighlight> as in the case of the equivalent DO-loop, the processing will be with a mixture of old and new values as the loop proceeds.


So, that suggests something like <lang Fortran> FOR ALL (I = 2:N - 1, J = 2:M - 1)
So, that suggests something like <syntaxhighlight lang=Fortran> FOR ALL (I = 2:N - 1, J = 2:M - 1)
WHERE(DOT(I,J) .NE. 0) DOT(I,J) = ADJUST(DOT,I,J)</lang>
WHERE(DOT(I,J) .NE. 0) DOT(I,J) = ADJUST(DOT,I,J)</syntaxhighlight>
This requires function ADJUST to be a "pure" function, and they are not supposed to perpetrate side effects, such as one reporting that any adjustment was made. Nor is it clear that array DOT must be presented as a parameter either as the entire array or as element DOT(i,j), or if not, that it can be global to function ADJUST - which would also be an impurity - and for that matter, variables I and J could be global also...
This requires function ADJUST to be a "pure" function, and they are not supposed to perpetrate side effects, such as one reporting that any adjustment was made. Nor is it clear that array DOT must be presented as a parameter either as the entire array or as element DOT(i,j), or if not, that it can be global to function ADJUST - which would also be an impurity - and for that matter, variables I and J could be global also...


Instead, thought turned to more closely following the task specification, which involves producing a list of elements to be adjusted after an inspection pass. Given that array DOT is two-dimensional, it would be nice if an element could be indexed via an expression such as <code>DOT(INDEX)</code> where INDEX was an array of two elements with INDEX(1) = i, and INDEX(2) = j, so as to access DOT(i,j) If this were possible, then obviously one could hope that array INDEX could be extended so as to store the multiple elements of a list of such locations to access, with a view to <code>DOT(INDEX(1:n)) = 0</code> adjusting the image.
Instead, thought turned to more closely following the task specification, which involves producing a list of elements to be adjusted after an inspection pass. Given that array DOT is two-dimensional, it would be nice if an element could be indexed via an expression such as <code>DOT(INDEX)</code> where INDEX was an array of two elements with INDEX(1) = i, and INDEX(2) = j, so as to access DOT(i,j) If this were possible, then obviously one could hope that array INDEX could be extended so as to store the multiple elements of a list of such locations to access, with a view to <code>DOT(INDEX(1:n)) = 0</code> adjusting the image.


Alas, such a syntax form is not accommodated. However, F90 also introduced the ability to define and use compound data types, such as the type PLACE as used below. It is not possible to define a type of a special, recognised form, such as say "SUBSCRIPT LIST" that can be used as dreamt of above, so the components are just ordinary variables. Two ordinary arrays could be used, one for each of the two subscripts, or a compound type could be devised in a hint towards self-documentation. Thus, <lang Fortran> DOT(WHACK(1:WHACKCOUNT).I,WHACK(1:WHACKCOUNT).J) = 0</lang>
Alas, such a syntax form is not accommodated. However, F90 also introduced the ability to define and use compound data types, such as the type PLACE as used below. It is not possible to define a type of a special, recognised form, such as say "SUBSCRIPT LIST" that can be used as dreamt of above, so the components are just ordinary variables. Two ordinary arrays could be used, one for each of the two subscripts, or a compound type could be devised in a hint towards self-documentation. Thus, <syntaxhighlight lang=Fortran> DOT(WHACK(1:WHACKCOUNT).I,WHACK(1:WHACKCOUNT).J) = 0</syntaxhighlight>


But it doesn't work... After a fair amount of head scratching, not at all assisted by the woolly generalities and inane examples of the compiler's "help" collection, it became apparent that the expression did not work through a list of indices as anticipated, but instead, for ''each'' value of the first index, ''all'' the values of the second index were selected. Thus, instead of the first change being DOT(WHACK('''1''').I,WHACK('''1''').J) only, it was DOT(WHACK('''1''').I,WHACK('''1:WHACKCOUNT''').J) that were being cleared. Accordingly, the fancy syntax has to be abandoned in favour of a specific DO-loop.
But it doesn't work... After a fair amount of head scratching, not at all assisted by the woolly generalities and inane examples of the compiler's "help" collection, it became apparent that the expression did not work through a list of indices as anticipated, but instead, for ''each'' value of the first index, ''all'' the values of the second index were selected. Thus, instead of the first change being DOT(WHACK('''1''').I,WHACK('''1''').J) only, it was DOT(WHACK('''1''').I,WHACK('''1:WHACKCOUNT''').J) that were being cleared. Accordingly, the fancy syntax has to be abandoned in favour of a specific DO-loop.


<lang Fortran> MODULE ZhangSuenThinning !Image manipulation.
<syntaxhighlight lang=Fortran> MODULE ZhangSuenThinning !Image manipulation.
CONTAINS
CONTAINS
SUBROUTINE ZST(DOT) !Attempts to thin out thick lines.
SUBROUTINE ZST(DOT) !Attempts to thin out thick lines.
Line 1,890: Line 1,889:
CALL SHOW(IMAGE)
CALL SHOW(IMAGE)


END PROGRAM POKE </lang>
END PROGRAM POKE </syntaxhighlight>


Output:
Output:
Line 1,920: Line 1,919:


=={{header|FreeBASIC}}==
=={{header|FreeBASIC}}==
<lang freebasic>' version 08-10-2016
<syntaxhighlight lang=freebasic>' version 08-10-2016
' compile with: fbc -s console
' compile with: fbc -s console


Line 2,054: Line 2,053:
Print : Print "hit any key to end program"
Print : Print "hit any key to end program"
Sleep
Sleep
End</lang>
End</syntaxhighlight>
{{out}}
{{out}}
<pre>................................
<pre>................................
Line 2,080: Line 2,079:


=={{header|Go}}==
=={{header|Go}}==
<lang go>package main
<syntaxhighlight lang=go>package main


import (
import (
Line 2,268: Line 2,267:
}
}
}
}
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 2,284: Line 2,283:


=={{header|Groovy}}==
=={{header|Groovy}}==
<lang groovy>def zhangSuen(text) {
<syntaxhighlight lang=groovy>def zhangSuen(text) {
def image = text.split('\n').collect { line -> line.collect { it == '#' ? 1 : 0} }
def image = text.split('\n').collect { line -> line.collect { it == '#' ? 1 : 0} }
def p2, p3, p4, p5, p6, p7, p8, p9
def p2, p3, p4, p5, p6, p7, p8, p9
Line 2,308: Line 2,307:
while (reduce(step1) | reduce(step2));
while (reduce(step1) | reduce(step2));
image.collect { line -> line.collect { it ? '#' : '.' }.join('') }.join('\n')
image.collect { line -> line.collect { it ? '#' : '.' }.join('') }.join('\n')
}</lang>
}</syntaxhighlight>
Testing:
Testing:
<lang groovy>def small = """\
<syntaxhighlight lang=groovy>def small = """\
................................
................................
.#########.......########.......
.#########.......########.......
Line 2,348: Line 2,347:
println zhangSuen(it)
println zhangSuen(it)
println()
println()
}</lang>
}</syntaxhighlight>
Output:
Output:
<pre>From:
<pre>From:
Line 2,413: Line 2,412:


=={{header|Haskell}}==
=={{header|Haskell}}==
<lang Haskell>import Data.Array
<syntaxhighlight lang=Haskell>import Data.Array
import qualified Data.List as List
import qualified Data.List as List


Line 2,534: Line 2,533:


main :: IO ()
main :: IO ()
main = mapM_ (putStrLn . showBWArray . thin . toBWArray) [sampleExA, sampleExB]</lang>
main = mapM_ (putStrLn . showBWArray . thin . toBWArray) [sampleExA, sampleExB]</syntaxhighlight>
{{out}}
{{out}}
<pre> ####### ######
<pre> ####### ######
Line 2,565: Line 2,564:
=={{header|J}}==
=={{header|J}}==
'''Solution:'''
'''Solution:'''
<lang j>isBlackPx=: '1'&=;._2 NB. boolean array of black pixels
<syntaxhighlight lang=j>isBlackPx=: '1'&=;._2 NB. boolean array of black pixels
toImage=: [: , LF ,.~ '01' {~ ] NB. convert to original representation
toImage=: [: , LF ,.~ '01' {~ ] NB. convert to original representation
frameImg=: 0 ,. 0 , >:@$ {. ] NB. adds border of 0's to image
frameImg=: 0 ,. 0 , >:@$ {. ] NB. adds border of 0's to image
Line 2,589: Line 2,588:
step2=: whiten frameImg@(cond2 neighbrs)
step2=: whiten frameImg@(cond2 neighbrs)


zhangSuen=: [: toImage [: step2@step1^:_ isBlackPx</lang>
zhangSuen=: [: toImage [: step2@step1^:_ isBlackPx</syntaxhighlight>
'''Alternative, explicit representation of last verb above'''
'''Alternative, explicit representation of last verb above'''
<lang j>zhangSuenX=: verb define
<syntaxhighlight lang=j>zhangSuenX=: verb define
img=. isBlackPx y
img=. isBlackPx y
whilst. 0 < +/ , msk1 +.&-. msk2 do.
whilst. 0 < +/ , msk1 +.&-. msk2 do.
Line 2,600: Line 2,599:
end.
end.
toImage img
toImage img
)</lang>
)</syntaxhighlight>
'''Example Use:'''
'''Example Use:'''
<lang j>toASCII=: ' #' {~ '1'&=;._2 NB. convert to ASCII representation
<syntaxhighlight lang=j>toASCII=: ' #' {~ '1'&=;._2 NB. convert to ASCII representation


ExampleImg=: noun define
ExampleImg=: noun define
Line 2,627: Line 2,626:
# # ## ## #
# # ## ## #
# ####
# ####
</lang>
</syntaxhighlight>


=={{header|Java}}==
=={{header|Java}}==
{{works with|Java|7}}
{{works with|Java|7}}
<lang java>import java.awt.Point;
<syntaxhighlight lang=java>import java.awt.Point;
import java.util.*;
import java.util.*;


Line 2,747: Line 2,746:
System.out.println(row);
System.out.println(row);
}
}
}</lang>
}</syntaxhighlight>


Output:
Output:
Line 2,769: Line 2,768:
=={{header|JavaScript}}==
=={{header|JavaScript}}==
{{trans|Java}}
{{trans|Java}}
<lang javascript>function Point(x, y) {
<syntaxhighlight lang=javascript>function Point(x, y) {
this.x = x;
this.x = x;
this.y = y;
this.y = y;
Line 2,874: Line 2,873:
return ZhangSuen;
return ZhangSuen;
}());
}());
ZhangSuen.main(null);</lang>
ZhangSuen.main(null);</syntaxhighlight>


Output:
Output:
Line 2,895: Line 2,894:


=={{header|Julia}}==
=={{header|Julia}}==
<lang julia>
<syntaxhighlight lang=julia>
const pixelstring =
const pixelstring =
"00000000000000000000000000000000" *
"00000000000000000000000000000000" *
Line 2,972: Line 2,971:




asciiprint(zsthinning(pixels))</lang>
asciiprint(zsthinning(pixels))</syntaxhighlight>
{{output}}<pre>
{{output}}<pre>
loop number 1
loop number 1
Line 2,990: Line 2,989:
=={{header|Kotlin}}==
=={{header|Kotlin}}==
{{trans|Java}}
{{trans|Java}}
<lang scala>// version 1.1.2
<syntaxhighlight lang=scala>// version 1.1.2


class Point(val x: Int, val y: Int)
class Point(val x: Int, val y: Int)
Line 3,089: Line 3,088:
fun main(args: Array<String>) {
fun main(args: Array<String>) {
thinImage()
thinImage()
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 3,112: Line 3,111:


=={{header|Lua}}==
=={{header|Lua}}==
<lang lua>function zhangSuenThin(img)
<syntaxhighlight lang=lua>function zhangSuenThin(img)
local dirs={
local dirs={
{ 0,-1},
{ 0,-1},
Line 3,252: Line 3,251:


zhangSuenThin(image)
zhangSuenThin(image)
</syntaxhighlight>
</lang>


Output:
Output:
Line 3,271: Line 3,270:
Mathematica supports directly the Thinning methods "Morphological" and "MedialAxis".
Mathematica supports directly the Thinning methods "Morphological" and "MedialAxis".
The Zhang-Suen algorithm implementation could be done with:
The Zhang-Suen algorithm implementation could be done with:
<lang Mathematica>nB[mat_] := Delete[mat // Flatten, 5] // Total;
<syntaxhighlight lang=Mathematica>nB[mat_] := Delete[mat // Flatten, 5] // Total;


nA[mat_] := Module[{l},
nA[mat_] := Module[{l},
Line 3,308: Line 3,307:




FixedPoint[iter, dat]</lang>
FixedPoint[iter, dat]</syntaxhighlight>


Which results in:
Which results in:
Line 3,452: Line 3,451:


=={{header|Nim}}==
=={{header|Nim}}==
<lang Nim>import math, sequtils, strutils
<syntaxhighlight lang=Nim>import math, sequtils, strutils


type
type
Line 3,545: Line 3,544:
echo()
echo()
echo "Output image:"
echo "Output image:"
echo output</lang>
echo output</syntaxhighlight>


{{out}}
{{out}}
Line 3,575: Line 3,574:
=={{header|Perl}}==
=={{header|Perl}}==
{{trans|Raku}}
{{trans|Raku}}
<lang perl>use List::Util qw(sum min);
<syntaxhighlight lang=perl>use List::Util qw(sum min);


$source = <<'END';
$source = <<'END';
Line 3,637: Line 3,636:
while (@black) { push @thinned, join '', qw<. #>[splice(@black,0,$h)] }
while (@black) { push @thinned, join '', qw<. #>[splice(@black,0,$h)] }


print join "\n", @thinned;</lang>
print join "\n", @thinned;</syntaxhighlight>
{{out}}
{{out}}
<pre>............................................................
<pre>............................................................
Line 3,659: Line 3,658:


=={{header|Phix}}==
=={{header|Phix}}==
<!--<lang Phix>(phixonline)-->
<!--<syntaxhighlight lang=Phix>(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}};</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}};</span>
Line 3,726: Line 3,725:
................................"""</span>
................................"""</span>
<span style="color: #000000;">Zhang_Suen</span><span style="color: #0000FF;">(</span><span style="color: #000000;">small_rc</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">Zhang_Suen</span><span style="color: #0000FF;">(</span><span style="color: #000000;">small_rc</span><span style="color: #0000FF;">)</span>
<!--</lang>-->
<!--</syntaxhighlight>-->
{{out}}
{{out}}
<pre>
<pre>
Line 3,742: Line 3,741:


=={{header|PL/I}}==
=={{header|PL/I}}==
<lang>zhang: procedure options (main); /* 8 July 2014 */
<syntaxhighlight lang=PL/I>zhang: procedure options (main); /* 8 July 2014 */


declare pic(10) bit(32) initial (
declare pic(10) bit(32) initial (
Line 3,864: Line 3,863:
end B;
end B;


end zhang;</lang>
end zhang;</syntaxhighlight>
<pre>
<pre>
[Initial configuration:]
[Initial configuration:]
Line 3,955: Line 3,954:
=={{header|Python}}==
=={{header|Python}}==
Several input images are converted.
Several input images are converted.
<lang python># -*- coding: utf-8 -*-
<syntaxhighlight lang=python># -*- coding: utf-8 -*-


# Example from [http://nayefreza.wordpress.com/2013/05/11/zhang-suen-thinning-algorithm-java-implementation/ this blog post].
# Example from [http://nayefreza.wordpress.com/2013/05/11/zhang-suen-thinning-algorithm-java-implementation/ this blog post].
Line 4,072: Line 4,071:
print('\nFrom:\n%s' % toTxt(image))
print('\nFrom:\n%s' % toTxt(image))
after = zhangSuen(image)
after = zhangSuen(image)
print('\nTo thinned:\n%s' % toTxt(after))</lang>
print('\nTo thinned:\n%s' % toTxt(after))</syntaxhighlight>


{{out}}
{{out}}
Line 4,102: Line 4,101:
=={{header|Racket}}==
=={{header|Racket}}==


<lang racket>#lang racket
<syntaxhighlight lang=racket>#lang racket
(define (img-01string->vector str)
(define (img-01string->vector str)
(define lines (regexp-split "\n" str))
(define lines (regexp-split "\n" str))
Line 4,215: Line 4,214:
; (read-display-thin-display-image e.g.-image/2)
; (read-display-thin-display-image e.g.-image/2)
; (newline)
; (newline)
(read-display-thin-display-image e.g.-image))</lang>
(read-display-thin-display-image e.g.-image))</syntaxhighlight>


{{out}}
{{out}}
Line 4,245: Line 4,244:
(formerly Perl 6)
(formerly Perl 6)
Source image may be based on any characters whose low bits are 0 or 1 (which conveniently includes . and #).
Source image may be based on any characters whose low bits are 0 or 1 (which conveniently includes . and #).
<lang perl6>my $source = qq:to/EOD/;
<syntaxhighlight lang=perl6>my $source = qq:to/EOD/;
................................
................................
.#########.......########.......
.#########.......########.......
Line 4,295: Line 4,294:
}
}


say @black.splice(0,h).join.trans('01' => '.#') while @black;</lang>
say @black.splice(0,h).join.trans('01' => '.#') while @black;</syntaxhighlight>
{{out}}
{{out}}
<pre>Ping: 66 remaining after removing 33 41 49 56 67 71 74 80 83 86 89 99 106 114 119 120 121 131 135 138 146 169 178 195 197 210 215 217 227 230 233 236 238 240 243 246 249 251 253 257 258 259 263 264 266 268 269 270 273 274 279 280 283 284 285
<pre>Ping: 66 remaining after removing 33 41 49 56 67 71 74 80 83 86 89 99 106 114 119 120 121 131 135 138 146 169 178 195 197 210 215 217 227 230 233 236 238 240 243 246 249 251 253 257 258 259 263 264 266 268 269 270 273 274 279 280 283 284 285
Line 4,315: Line 4,314:


=={{header|REXX}}==
=={{header|REXX}}==
<lang rexx>/*REXX program thins a NxM character grid using the Zhang-Suen thinning algorithm.*/
<syntaxhighlight lang=rexx>/*REXX program thins a NxM character grid using the Zhang-Suen thinning algorithm.*/
parse arg iFID .; if iFID=='' then iFID='ZHANG_SUEN.DAT'
parse arg iFID .; if iFID=='' then iFID='ZHANG_SUEN.DAT'
white=' '; @.=white /* [↓] read the input character grid. */
white=' '; @.=white /* [↓] read the input character grid. */
Line 4,355: Line 4,354:
Ps: rm=r-1; rp=r+1; cm=c-1; cp=c+1 /*calculate some shortcuts.*/
Ps: rm=r-1; rp=r+1; cm=c-1; cp=c+1 /*calculate some shortcuts.*/
p2=@.rm.c\==white; p3=@.rm.cp\==white; p4=@.r.cp\==white; p5=@.rp.cp\==white
p2=@.rm.c\==white; p3=@.rm.cp\==white; p4=@.r.cp\==white; p5=@.rp.cp\==white
p6=@.rp.c\==white; p7=@.rp.cm\==white; p8=@.r.cm\==white; p9=@.rm.cm\==white; return</lang>
p6=@.rp.c\==white; p7=@.rp.cm\==white; p8=@.r.cm\==white; p9=@.rm.cm\==white; return</syntaxhighlight>
'''output''' &nbsp; when using the default input:
'''output''' &nbsp; when using the default input:
<pre>
<pre>
Line 4,429: Line 4,428:
First I define a function zs which given a point and its eight neighbours returns 1 if the point may be culled, 0 otherwise. g indicates if this is step 1 or step 2 in the task description. zs may be changed to remember the step independently if the reader does not wish to explore the algorithm.
First I define a function zs which given a point and its eight neighbours returns 1 if the point may be culled, 0 otherwise. g indicates if this is step 1 or step 2 in the task description. zs may be changed to remember the step independently if the reader does not wish to explore the algorithm.


<lang ruby>class ZhangSuen
<syntaxhighlight lang=ruby>class ZhangSuen
NEIGHBOUR8 = [[-1,0],[-1,1],[0,1],[1,1],[1,0],[1,-1],[0,-1],[-1,-1]] # 8 neighbors
NEIGHBOUR8 = [[-1,0],[-1,1],[0,1],[1,1],[1,0],[1,-1],[0,-1],[-1,-1]] # 8 neighbors
CIRCULARS = NEIGHBOUR8 + [NEIGHBOUR8.first] # P2, ... P9, P2
CIRCULARS = NEIGHBOUR8 + [NEIGHBOUR8.first] # P2, ... P9, P2
Line 4,496: Line 4,495:
EOS
EOS


ZhangSuen.new(task_example, "1")</lang>
ZhangSuen.new(task_example, "1")</syntaxhighlight>


{{out}}
{{out}}
Line 4,514: Line 4,513:
=={{header|Sidef}}==
=={{header|Sidef}}==
{{trans|Ruby}}
{{trans|Ruby}}
<lang ruby>class ZhangSuen(str, black="1") {
<syntaxhighlight lang=ruby>class ZhangSuen(str, black="1") {
const NEIGHBOURS = [[-1,0],[-1,1],[0,1],[1,1],[1,0],[1,-1],[0,-1],[-1,-1]] # 8 neighbors
const NEIGHBOURS = [[-1,0],[-1,1],[0,1],[1,1],[1,0],[1,-1],[0,-1],[-1,-1]] # 8 neighbors
const CIRCULARS = (NEIGHBOURS + [NEIGHBOURS.first]) # P2, ... P9, P2
const CIRCULARS = (NEIGHBOURS + [NEIGHBOURS.first]) # P2, ... P9, P2
Line 4,570: Line 4,569:
EOS
EOS


ZhangSuen.new(text, black: "1").display</lang>
ZhangSuen.new(text, black: "1").display</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 4,588: Line 4,587:
{{trans|Python}}
{{trans|Python}}


<lang>import UIKit
<syntaxhighlight lang=swift>import UIKit


// testing examples
// testing examples
Line 4,758: Line 4,757:
// print the result
// print the result
print("\nTo thinned:\n\(toTxt(intmatrix: after))")
print("\nTo thinned:\n\(toTxt(intmatrix: after))")
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 4,863: Line 4,862:
=={{header|Tcl}}==
=={{header|Tcl}}==
Only the single image is converted.
Only the single image is converted.
<lang tcl># -*- coding: utf-8 -*-
<syntaxhighlight lang=tcl># -*- coding: utf-8 -*-


set data {
set data {
Line 4,940: Line 4,939:
return $data
return $data
}
}
puts [string map {1 @ 0 .} [join [zhang-suen $data] \n]]</lang>
puts [string map {1 @ 0 .} [join [zhang-suen $data] \n]]</syntaxhighlight>


{{out}}
{{out}}
Line 4,958: Line 4,957:
=={{header|VBA}}==
=={{header|VBA}}==
{{trans|Phix}}
{{trans|Phix}}
<lang vb>Public n As Variant
<syntaxhighlight lang=vb>Public n As Variant
Private Sub init()
Private Sub init()
n = [{-1,0;-1,1;0,1;1,1;1,0;1,-1;0,-1;-1,-1;-1,0}]
n = [{-1,0;-1,1;0,1;1,1;1,0;1,-1;0,-1;-1,-1;-1,0}]
Line 5,040: Line 5,039:
Small_rc(9) = "................................"
Small_rc(9) = "................................"
Zhang_Suen (Small_rc)
Zhang_Suen (Small_rc)
End Sub</lang>{{out}}
End Sub</syntaxhighlight>{{out}}
<pre>................................
<pre>................................
...######.........######........
...######.........######........
Line 5,054: Line 5,053:
=={{header|Wren}}==
=={{header|Wren}}==
{{trans|Kotlin}}
{{trans|Kotlin}}
<lang ecmascript>class Point {
<syntaxhighlight lang=ecmascript>class Point {
construct new(x, y) {
construct new(x, y) {
_x = x
_x = x
Line 5,161: Line 5,160:
}
}


thinImage.call()</lang>
thinImage.call()</syntaxhighlight>


{{out}}
{{out}}