Zhang-Suen thinning algorithm: Difference between revisions

m
→‎{{header|Wren}}: Changed to Wren S/H
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(14 intermediate revisions by 11 users not shown)
Line 111:
{{trans|Python}}
 
<langsyntaxhighlight lang="11l">V beforeTxt = |‘1100111
1100111
‘1100111
1100111
1100111
1100110
1100111
1100110
1100110
1100110
1100110
1100110
1100110
1100110
1111110
1100110
0000000’
1111110
0000000’
 
V smallrc01 =
|‘00000000000000000000000000000000
01111111110000000111111110000000
01110001111000001111001111000000
01110000111000001110000111000000
01110001111000001110000000000000
01111111110000001110000000000000
01110111100000001110000111000000
01110011110011101111001111011100
01110001111011100111111110011100
00000000000000000000000000000000’
 
V rc01 =
|‘00000000000000000000000000000000000000000000000000000000000
01111111111111111100000000000000000001111111111111000000000
01111111111111111110000000000000001111111111111111000000000
01111111111111111111000000000000111111111111111111000000000
01111111100000111111100000000001111111111111111111000000000
00011111100000111111100000000011111110000000111111000000000
00011111100000111111100000000111111100000000000000000000000
00011111111111111111000000000111111100000000000000000000000
00011111111111111110000000000111111100000000000000000000000
00011111111111111111000000000111111100000000000000000000000
00011111100000111111100000000111111100000000000000000000000
00011111100000111111100000000111111100000000000000000000000
00011111100000111111100000000011111110000000111111000000000
01111111100000111111100000000001111111111111111111000000000
01111111100000111111101111110000111111111111111111011111100
01111111100000111111101111110000001111111111111111011111100
01111111100000111111101111110000000001111111111111011111100
00000000000000000000000000000000000000000000000000000000000’
 
F intarray(binstring)
Line 171 ⟶ 170:
R intmatrix.map(row -> row.map(p -> (I p {‘#’} E ‘.’)).join(‘’)).join("\n")
 
F neighbours_arrneighbours_array(x, y, image)
‘Return 8-neighbours of point p1 of picture, in order’
V i = image
Line 196 ⟶ 195:
L(y) 1 .< image.len - 1
L(x) 1 .< image[0].len - 1
V n = neighbours_arrneighbours_array(x, y, image)
V (P2, P3, P4, P5, P6, P7, P8, P9) = neighbours_tuple(x, y, image)
I (image[y][x] == 1 & P4 * P6 * P8 == 0 & P2 * P4 * P6 == 0 & transitions(n) == 1 & sum(n) C 2..6)
Line 205 ⟶ 204:
L(y) 1 .< image.len - 1
L(x) 1 .< image[0].len - 1
V n = neighbours_arrneighbours_array(x, y, image)
V (P2, P3, P4, P5, P6, P7, P8, P9) = neighbours_tuple(x, y, image)
I (image[y][x] == 1 & P2 * P6 * P8 == 0 & P2 * P4 * P8 == 0 & transitions(n) == 1 & sum(n) C 2..6)
Line 217 ⟶ 216:
print("\nFrom:\n#.".format(toTxt(image)))
V after = zhangSuen(&image)
print("\nTo thinned:\n#.".format(toTxt(after)))</langsyntaxhighlight>
 
{{out}}
Line 261 ⟶ 260:
...........................................................
...........................................................
</pre>
 
=={{header|Action!}}==
<syntaxhighlight lang="action!">PROC DrawImage(BYTE ARRAY image BYTE x,y,width,height)
BYTE i,j
BYTE POINTER ptr
 
Color=2
FOR j=0 TO height-1
DO
Plot(x,j+y) DrawTo(x+width-1,j+y)
OD
Color=1
ptr=image
FOR j=0 TO height-1
DO
FOR i=0 TO width-1
DO
IF ptr^ THEN
Plot(i+x,j+y)
FI
ptr==+1
OD
OD
RETURN
 
PROC Thinning(BYTE ARRAY image BYTE width,height)
DEFINE PTR="CARD"
DEFINE MAX="200"
PTR ARRAY change(MAX)
BYTE POINTER p1,p2,p3,p4,p5,p6,p7,p8,p9,p68,p24
INT count,i
BYTE x,y,sum,step1
 
step1=1
DO
count=0
p1=image p8=p1-1 p4=p1+1
p2=p1-width p6=p1+width
p9=p2-1 p3=p2+1
p7=p6-1 p5=p6+1
 
FOR y=0 TO height-1
DO
FOR x=0 TO width-1
DO
IF p1^=1 AND x>0 AND y>0 AND x<width-1 AND y<height-1 THEN
sum=p2^+p3^+p4^+p5^+p6^+p7^+p8^+p9^
IF sum>=2 AND sum<=6 THEN
sum=0
IF p3^>p2^ THEN sum==+1 FI
IF p4^>p3^ THEN sum==+1 FI
IF p5^>p4^ THEN sum==+1 FI
IF p6^>p5^ THEN sum==+1 FI
IF p7^>p6^ THEN sum==+1 FI
IF p8^>p7^ THEN sum==+1 FI
IF p9^>p8^ THEN sum==+1 FI
IF p2^>p9^ THEN sum==+1 FI
IF sum=1 THEN
IF step1 THEN
p24=p4 p68=p6
ELSE
p24=p2 p68=p8
FI
IF p2^+p4^+p68^<3 AND p24^+p6^+p8^<3 THEN
change(count)=p1 count==+1
FI
FI
FI
FI
p1==+1 p2==+1 p3==+1 p4==+1 p5==+1
p6==+1 p7==+1 p8==+1 p9==+1
OD
OD
step1=1-step1
FOR i=0 TO count-1
DO
p1=change(i) p1^=0
OD
UNTIL count=0
OD
RETURN
 
PROC Main()
BYTE ARRAY image1=[
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0
0 1 1 1 0 0 0 1 1 1 1 0 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 0 0 0 0 0
0 1 1 1 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 1 1 1 0 0 0 0 0 0
0 1 1 1 0 0 0 1 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 0 1 1 1 1 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 1 1 0 0 0 0 0 0
0 1 1 1 0 0 1 1 1 1 0 0 1 1 1 0 1 1 1 1 0 0 1 1 1 1 0 1 1 1 0 0
0 1 1 1 0 0 0 1 1 1 1 0 1 1 1 0 0 1 1 1 1 1 1 1 1 0 0 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
BYTE ARRAY image2=[
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 0 0
0 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 0 0
0 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
BYTE width1=[32],height1=[10],width2=[59],height2=[18]
BYTE CH=$02FC
 
Graphics(7+16)
Color=1
SetColor(0,0,$00)
SetColor(4,0,$04)
SetColor(1,0,$0C)
 
DrawImage(image1,0,0,width1,height1)
Thinning(image1,width1,height1)
DrawImage(image1,width1+10,0,width1,height1)
 
DrawImage(image2,0,height1+10,width2,height2)
Thinning(image2,width2,height2)
DrawImage(image2,width2+10,height1+10,width2,height2)
 
DO UNTIL CH#$FF OD
CH=$FF
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Zhang-Suen_thinning_algorithm.png Screenshot from Atari 8-bit computer]
 
=={{header|AppleScript}}==
<syntaxhighlight lang="applescript">-- Params:
-- List of lists (rows) of "pixel" values.
-- Record indicating the values representing black and white.
on ZhangSuen(matrix, {black:black, white:white})
script o
property matrix : missing value
property changePixels : missing value
on A(neighbours) -- Count transitions from white to black.
set sum to 0
repeat with i from 1 to 8
if ((neighbours's item i is white) and (neighbours's item (i mod 8 + 1) is black)) then set sum to sum + 1
end repeat
return sum
end A
on B(neighbours) -- Count neighbouring black pixels.
set sum to 0
repeat with p in neighbours
if (p's contents is black) then set sum to sum + 1
end repeat
return sum
end B
end script
set o's matrix to matrix
set rowCount to (count o's matrix)
set columnCount to (count o's matrix's beginning) -- Assumed to be the same for every row.
repeat until (o's changePixels is {})
repeat with step from 1 to 2
set o's changePixels to {}
repeat with r from 2 to (rowCount - 1)
repeat with c from 2 to (columnCount - 1)
if (o's matrix's item r's item c is black) then
tell (a reference to o's matrix) to ¬
set neighbours to {item (r - 1)'s item c, item (r - 1)'s item (c + 1), ¬
item r's item (c + 1), item (r + 1)'s item (c + 1), item (r + 1)'s item c, ¬
item (r + 1)'s item (c - 1), item r's item (c - 1), item (r - 1)'s item (c - 1)}
set blackCount to o's B(neighbours)
if ((blackCount > 1) and (blackCount < 7) and (o's A(neighbours) is 1)) then
set {P2, x, P4, x, P6, x, P8} to neighbours
if (step is 1) then
set toChange to ((P4 is white) or (P6 is white) or ((P2 is white) and (P8 is white)))
else
set toChange to ((P2 is white) or (P8 is white) or ((P4 is white) and (P6 is white)))
end if
if (toChange) then set end of o's changePixels to {r, c}
end if
end if
end repeat
end repeat
if (o's changePixels is {}) then exit repeat
repeat with pixel in o's changePixels
set {r, c} to pixel
set o's matrix's item r's item c to white
end repeat
end repeat
end repeat
return o's matrix -- or: return matrix -- The input has been edited in place.
end ZhangSuen
 
on join(lst, delim)
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to delim
set txt to lst as text
set AppleScript's text item delimiters to astid
return txt
end join
 
on demo()
set pattern to "00000000000000000000000000000000
01111111110000000111111110000000
01110001111000001111001111000000
01110000111000001110000111000000
01110001111000001110000000000000
01111111110000001110000000000000
01110111100000001110000111000000
01110011110011101111001111011100
01110001111011100111111110011100
00000000000000000000000000000000"
set matrix to pattern's paragraphs
repeat with thisRow in matrix
set thisRow's contents to thisRow's characters
end repeat
ZhangSuen(matrix, {black:"1", white:"0"})
repeat with thisRow in matrix
set thisRow's contents to join(thisRow, "")
end repeat
return join(matrix, linefeed)
end demo
return demo()</syntaxhighlight>
 
{{output}}
<pre>"00000000000000000000000000000000
00111111100000000011111100000000
00100000100000000110000000000000
00100000010000000100000000000000
00100000100000000100000000000000
00111110100000000100000000000000
00000001100000000100000000000000
00000000100001000110000110001000
00000000010000000001111000000000
00000000000000000000000000000000"</pre>
Alternative demo:
<syntaxhighlight lang="applescript">on demo()
set pattern to "
################# #############
################## ################
################### ##################
######## ####### ###################
###### ####### ####### ######
###### ####### #######
################# #######
################ #######
################# #######
###### ####### #######
###### ####### #######
###### ####### ####### ######
######## ####### ###################
######## ####### ###### ################## ######
######## ####### ###### ################ ######
######## ####### ###### ############# ######
"
set matrix to pattern's paragraphs
repeat with thisRow in matrix
set thisRow's contents to thisRow's characters
end repeat
ZhangSuen(matrix, {black:"#", white:space})
repeat with thisRow in matrix
set thisRow's contents to join(thisRow, "")
end repeat
return join(matrix, linefeed)
end demo
return demo()</syntaxhighlight>
 
{{output}}
<pre>
# ########## #######
## # #### #
# # ##
# # #
# # #
# # #
############ #
# # #
# # #
# # #
# # #
# ##
# ############
### ###
</pre>
 
Line 266 ⟶ 556:
{{works with|AutoHotkey_L}}
Reads input from a text file and writes output to a different text file (first creating the file, if necessary).
<langsyntaxhighlight AutoHotkeylang="autohotkey">FileIn := A_ScriptDir "\Zhang-Suen.txt"
FileOut := A_ScriptDir "\NewFile.txt"
 
Line 344 ⟶ 634:
return 1
return Neighbors
}</langsyntaxhighlight>
'''Output:'''
<pre>
Line 356 ⟶ 646:
# ####
</pre>
 
=={{header|BASIC}}==
==={{header|FreeBASIC}}===
<syntaxhighlight lang="freebasic">' version 08-10-2016
' compile with: fbc -s console
 
Data "00000000000000000000000000000000"
Data "01111111110000000111111110000000"
Data "01110001111000001111001111000000"
Data "01110000111000001110000111000000"
Data "01110001111000001110000000000000"
Data "01111111110000001110000000000000"
Data "01110111100000001110000111000000"
Data "01110011110011101111001111011100"
Data "01110001111011100111111110011100"
Data "00000000000000000000000000000000"
Data "END"
 
' ------=< MAIN >=------
 
Dim As UInteger x, y, m, n
Dim As String input_str
 
Do ' find out how big it is
Read input_str
If input_str = "END" Then Exit Do
If x < Len(input_str) Then x = Len(input_str)
y = y + 1
Loop
 
m = x -1 : n = y -1
ReDim As UByte old(m, n), new_(m, n)
 
y = 0
Restore ' restore data pointer
Do ' put data in array
Read input_str
If input_str="END" Then Exit Do
For x = 0 To Len(input_str) -1
old(x,y) = input_str[x] - Asc("0")
' print image
If old(x, y) = 0 Then Print "."; Else Print "#";
Next
Print
y = y + 1
Loop
 
'corners and sides do not change
For x = 0 To m
new_(x, 0) = old(x, 0)
new_(x, n) = old(x, n)
Next
 
For y = 0 To n
new_(0, y) = old(0, y)
new_(m, y) = old(m, y)
Next
 
Dim As UInteger tmp, change, stage = 1
Do
change = 0
For y = 1 To n -1
For x = 1 To m -1
' -1-
If old(x,y) = 0 Then ' first condition, p1 must be black
new_(x,y) = 0
Continue For
End If
' -2-
tmp = old(x, y -1) + old(x +1, y -1)
tmp = tmp + old(x +1, y) + old(x +1, y +1) + old(x, y +1)
tmp = tmp + old(x -1, y +1) + old(x -1, y) + old(x -1, y -1)
If tmp < 2 OrElse tmp > 6 Then ' 2 <= B(p1) <= 6
new_(x, y) = 1
Continue For
End If
' -3-
tmp = 0
If old(x , y ) = 0 And old(x , y -1) = 1 Then tmp += 1 ' p1 > p2
If old(x , y -1) = 0 And old(x +1, y -1) = 1 Then tmp += 1 ' p2 > p3
If old(x +1, y -1) = 0 And old(x +1, y ) = 1 Then tmp += 1 ' p3 > p4
If old(x +1, y ) = 0 And old(x +1, y +1) = 1 Then tmp += 1 ' p4 > p5
If old(x +1, y +1) = 0 And old(x , y +1) = 1 Then tmp += 1 ' p5 > p6
If old(x , y +1) = 0 And old(x -1, y +1) = 1 Then tmp += 1 ' p6 > p7
If old(x -1, y +1) = 0 And old(x -1, y ) = 1 Then tmp += 1 ' p7 > p8
If old(x -1, y ) = 0 And old(x -1, y -1) = 1 Then tmp += 1 ' p8 > p9
If old(x -1, y -1) = 0 And old(x , y -1) = 1 Then tmp += 1 ' p9 > p2
' tmp = 1 ==> A(P1) = 1
If tmp <> 1 Then
new_(x, y) = 1
Continue For
End If
If (stage And 1) = 1 Then
' step 1 -4- -5-
If (old(x, y -1) + old(x +1, y) + old(x, y +1)) = 3 OrElse _
(old(x +1, y) + old(x, y +1) + old(x -1, y)) = 3 Then
new_(x, y) = 1
Continue For
End If
Else
' step 2 -4- -5-
If (old(x, y -1) + old(x +1, y) + old(x -1, y)) = 3 OrElse _
(old(x, y -1) + old(x, y +1) + old(x -1, y)) = 3 Then
new_(x, y) = 1
Continue For
End If
End If
' all condition are met, make p1 white (0)
new_(x, y) = 0
change = 1 ' flag change
Next
Next
 
' copy new_() into old()
For y = 0 To n
For x = 0 To m
old(x, y) = new_(x, y)
Next
Next
 
stage += 1
Loop Until change = 0 ' stop when there are no changes made
 
Print ' print result
Print "End result"
For y = 0 To n
For x = 0 To m
If old(x, y) = 0 Then Print "."; Else Print "#";
Next
Print
Next
 
 
' empty keyboard buffer
While Inkey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End</syntaxhighlight>
{{out}}
<pre>................................
.#########.......########.......
.###...####.....####..####......
.###....###.....###....###......
.###...####.....###.............
.#########......###.............
.###.####.......###....###......
.###..####..###.####..####.###..
.###...####.###..########..###..
................................
 
End result
................................
..#######.........######........
..#.....#........##.............
..#......#.......#..............
..#.....#........#..............
..#####.#........#..............
.......##........#..............
........#....#...##....##...#...
.........#.........####.........
................................</pre>
 
==={{header|VBA}}===
{{trans|Phix}}
<syntaxhighlight lang="vb">Public n As Variant
Private Sub init()
n = [{-1,0;-1,1;0,1;1,1;1,0;1,-1;0,-1;-1,-1;-1,0}]
End Sub
 
Private Function AB(text As Variant, y As Integer, x As Integer, step As Integer) As Variant
Dim wtb As Integer
Dim bn As Integer
Dim prev As String: prev = "#"
Dim next_ As String
Dim p2468 As String
For i = 1 To UBound(n)
next_ = Mid(text(y + n(i, 1)), x + n(i, 2), 1)
wtb = wtb - (prev = "." And next_ <= "#")
bn = bn - (i > 1 And next_ <= "#")
If (i And 1) = 0 Then p2468 = p2468 & prev
prev = next_
Next i
If step = 2 Then '-- make it p6842
p2468 = Mid(p2468, 3, 2) & Mid(p2468, 1, 2)
'p2468 = p2468(3..4)&p2468(1..2)
End If
Dim ret(2) As Variant
ret(0) = wtb
ret(1) = bn
ret(2) = p2468
AB = ret
End Function
Private Sub Zhang_Suen(text As Variant)
Dim wtb As Integer
Dim bn As Integer
Dim changed As Boolean, changes As Boolean
Dim p2468 As String '-- (p6842 for step 2)
Dim x As Integer, y As Integer, step As Integer
Do While True
changed = False
For step = 1 To 2
changes = False
For y = 1 To UBound(text) - 1
For x = 2 To Len(text(y)) - 1
If Mid(text(y), x, 1) = "#" Then
ret = AB(text, y, x, step)
wtb = ret(0)
bn = ret(1)
p2468 = ret(2)
If wtb = 1 _
And bn >= 2 And bn <= 6 _
And InStr(1, Mid(p2468, 1, 3), ".") _
And InStr(1, Mid(p2468, 2, 3), ".") Then
changes = True
text(y) = Left(text(y), x - 1) & "!" & Right(text(y), Len(text(y)) - x)
End If
End If
Next x
Next y
If changes Then
For y = 1 To UBound(text) - 1
text(y) = Replace(text(y), "!", ".")
Next y
changed = True
End If
Next step
If Not changed Then Exit Do
Loop
Debug.Print Join(text, vbCrLf)
End Sub
 
Public Sub main()
init
Dim Small_rc(9) As String
Small_rc(0) = "................................"
Small_rc(1) = ".#########.......########......."
Small_rc(2) = ".###...####.....####..####......"
Small_rc(3) = ".###....###.....###....###......"
Small_rc(4) = ".###...####.....###............."
Small_rc(5) = ".#########......###............."
Small_rc(6) = ".###.####.......###....###......"
Small_rc(7) = ".###..####..###.####..####.###.."
Small_rc(8) = ".###...####.###..########..###.."
Small_rc(9) = "................................"
Zhang_Suen (Small_rc)
End Sub</syntaxhighlight>{{out}}
<pre>................................
...######.........######........
...#....#.........#....##.......
...#....#.........#......#......
...#....#.........#.............
...####.#.........#.............
.......##.........#.............
........#....#....#....##...#...
.........#....#....####......#..
................................</pre>
 
=={{header|C}}==
Line 365 ⟶ 912:
</pre>
The images before and after thinning are also printed on the console.
<syntaxhighlight lang="c">
<lang C>
#include<stdlib.h>
#include<stdio.h>
Line 526 ⟶ 1,073:
return 0;
}
</syntaxhighlight>
</lang>
 
Contents of input file : zhImage.txt
Line 596 ⟶ 1,143:
=={{header|C++}}==
Compiled with --std=c++14
<langsyntaxhighlight CPPlang="cpp">#include <iostream>
#include <string>
#include <sstream>
Line 837 ⟶ 1,384:
return 0;
}
</syntaxhighlight>
</lang>
 
Output:
Line 911 ⟶ 1,458:
=={{header|D}}==
This uses the module from the Bitmap Task. And it performs no heap allocations.
<langsyntaxhighlight lang="d">import std.stdio, std.algorithm, std.string, std.functional,
std.typecons, std.typetuple, bitmap;
 
Line 1,038 ⟶ 1,585:
writeln;
}
}</langsyntaxhighlight>
{{out}}
<pre>From:
Line 1,137 ⟶ 1,684:
 
=={{header|Elena}}==
ELENA 56.0x :
{{trans|Java}}
<langsyntaxhighlight lang="elena">import system'collections;
import system'routines;
import extensions;
Line 1,164 ⟶ 1,711:
" "};
 
static int[][] nbrs = new int[][]
{
new int[]{0, -1}, new int[]{1, -1}, new int[]{1, 0}, new int[]{1, 1}, new int[]{0, 1},
Line 1,170 ⟶ 1,717:
};
 
static int[][][] nbrGroups = new int[][][]
{
new int[][]{new int[]{0, 2, 4}, new int[]{2, 4, 6}},
Line 1,203 ⟶ 1,750:
int count := 0;
for (int i := 0,; i < nbrs.Length, - 1; i += 1)
{
if (self[r + nbrs[i][1]][c + nbrs[i + 1][0]] == $35)
{ count += 1 }
};
Line 1,216 ⟶ 1,763:
int count := 0;
for (int i := 0,; i < nbrs.Length, - 1; i += 1)
{
if (self[r + nbrs[i][1]][c + nbrs[i][0]] == $32)
Line 1,234 ⟶ 1,781:
int count := 0;
var group := nbrGroups[step];
for(int i := 0,; i < 3,2; i += 1)
{
for(int j := 0,; j < group[i].Length,; j += 1)
{
var nbr := nbrs[group[i][j]];
if (self[r + nbr[1]][c + nbr[0]] == $32)
{ count := count + 1; ^ true$break; };
^ false
}
};
Line 1,261 ⟶ 1,806:
firstStep := firstStep.Inverted;
for(int r := 1,; r < self.Rows, - 1; r += 1)
{
for(int c := 1,; c < self.Columns, - 1; c += 1)
{
if(self.proceed(r,c,toWhite,firstStep))
Line 1,270 ⟶ 1,815:
};
toWhite.forEach::(p){ self[p.y][p.x] := $32 };
toWhite.clear()
}
Line 1,279 ⟶ 1,824:
var it := self.enumerator();
it.forEach::(ch){ console.print(ch," ") };
while (it.next())
{
console.writeLine();
 
it.forEach::(ch){ console.print(ch," ") }
}
}
Line 1,306 ⟶ 1,851:
console.readChar()
}</langsyntaxhighlight>
{{out}}
<pre>
# # # # # # # # # # # # # # # # # # # #
# # # # # # # # #
# # # #
# # #
# # #
# # # # #
# # # # # # # # # # # #
# # # # # # # # # # # # #
# # #
# # #
# # #
# # #
# # #
# # # # # # # # # # # # #
# # # # # #
Line 1,330 ⟶ 1,875:
=={{header|Elixir}}==
{{trans|Ruby}}
<langsyntaxhighlight lang="elixir">defmodule ZhangSuen do
@neighbours [{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}] # 8 neighbours
Line 1,419 ⟶ 1,964:
00000000000000000000000000000000
"""
ZhangSuen.thinning(str, ?1)</langsyntaxhighlight>
 
{{out}}
Line 1,482 ⟶ 2,027:
 
=={{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 <langsyntaxhighlight Fortarnlang="fortarn">FOR ALL (i = 2:n - 1) A(i) = (A(i - 1) + A(i) + A(i + 1))/3</langsyntaxhighlight> all right-hand-side expressions will be evaluated with the original values of the array, while in the less special array assignment <langsyntaxhighlight Fortranlang="fortran">A(2:N - 1) = (A(1:N - 2) + A(2:N - 1) + A(3:N))/3</langsyntaxhighlight> 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 <langsyntaxhighlight Fortranlang="fortran"> FOR ALL (I = 2:N - 1, J = 2:M - 1)
WHERE(DOT(I,J) .NE. 0) DOT(I,J) = ADJUST(DOT,I,J)</langsyntaxhighlight>
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.
 
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, <langsyntaxhighlight Fortranlang="fortran"> DOT(WHACK(1:WHACKCOUNT).I,WHACK(1:WHACKCOUNT).J) = 0</langsyntaxhighlight>
 
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.
 
<langsyntaxhighlight Fortranlang="fortran"> MODULE ZhangSuenThinning !Image manipulation.
CONTAINS
SUBROUTINE ZST(DOT) !Attempts to thin out thick lines.
Line 1,599 ⟶ 2,144:
CALL SHOW(IMAGE)
 
END PROGRAM POKE </langsyntaxhighlight>
 
Output:
Line 1,627 ⟶ 2,172:
................................
</pre>
 
=={{header|FreeBASIC}}==
<lang freebasic>' version 08-10-2016
' compile with: fbc -s console
 
Data "00000000000000000000000000000000"
Data "01111111110000000111111110000000"
Data "01110001111000001111001111000000"
Data "01110000111000001110000111000000"
Data "01110001111000001110000000000000"
Data "01111111110000001110000000000000"
Data "01110111100000001110000111000000"
Data "01110011110011101111001111011100"
Data "01110001111011100111111110011100"
Data "00000000000000000000000000000000"
Data "END"
 
' ------=< MAIN >=------
 
Dim As UInteger x, y, m, n
Dim As String input_str
 
Do ' find out how big it is
Read input_str
If input_str = "END" Then Exit Do
If x < Len(input_str) Then x = Len(input_str)
y = y + 1
Loop
 
m = x -1 : n = y -1
ReDim As UByte old(m, n), new_(m, n)
 
y = 0
Restore ' restore data pointer
Do ' put data in array
Read input_str
If input_str="END" Then Exit Do
For x = 0 To Len(input_str) -1
old(x,y) = input_str[x] - Asc("0")
' print image
If old(x, y) = 0 Then Print "."; Else Print "#";
Next
Print
y = y + 1
Loop
 
'corners and sides do not change
For x = 0 To m
new_(x, 0) = old(x, 0)
new_(x, n) = old(x, n)
Next
 
For y = 0 To n
new_(0, y) = old(0, y)
new_(m, y) = old(m, y)
Next
 
Dim As UInteger tmp, change, stage = 1
Do
change = 0
For y = 1 To n -1
For x = 1 To m -1
' -1-
If old(x,y) = 0 Then ' first condition, p1 must be black
new_(x,y) = 0
Continue For
End If
' -2-
tmp = old(x, y -1) + old(x +1, y -1)
tmp = tmp + old(x +1, y) + old(x +1, y +1) + old(x, y +1)
tmp = tmp + old(x -1, y +1) + old(x -1, y) + old(x -1, y -1)
If tmp < 2 OrElse tmp > 6 Then ' 2 <= B(p1) <= 6
new_(x, y) = 1
Continue For
End If
' -3-
tmp = 0
If old(x , y ) = 0 And old(x , y -1) = 1 Then tmp += 1 ' p1 > p2
If old(x , y -1) = 0 And old(x +1, y -1) = 1 Then tmp += 1 ' p2 > p3
If old(x +1, y -1) = 0 And old(x +1, y ) = 1 Then tmp += 1 ' p3 > p4
If old(x +1, y ) = 0 And old(x +1, y +1) = 1 Then tmp += 1 ' p4 > p5
If old(x +1, y +1) = 0 And old(x , y +1) = 1 Then tmp += 1 ' p5 > p6
If old(x , y +1) = 0 And old(x -1, y +1) = 1 Then tmp += 1 ' p6 > p7
If old(x -1, y +1) = 0 And old(x -1, y ) = 1 Then tmp += 1 ' p7 > p8
If old(x -1, y ) = 0 And old(x -1, y -1) = 1 Then tmp += 1 ' p8 > p9
If old(x -1, y -1) = 0 And old(x , y -1) = 1 Then tmp += 1 ' p9 > p2
' tmp = 1 ==> A(P1) = 1
If tmp <> 1 Then
new_(x, y) = 1
Continue For
End If
If (stage And 1) = 1 Then
' step 1 -4- -5-
If (old(x, y -1) + old(x +1, y) + old(x, y +1)) = 3 OrElse _
(old(x +1, y) + old(x, y +1) + old(x -1, y)) = 3 Then
new_(x, y) = 1
Continue For
End If
Else
' step 2 -4- -5-
If (old(x, y -1) + old(x +1, y) + old(x -1, y)) = 3 OrElse _
(old(x, y -1) + old(x, y +1) + old(x -1, y)) = 3 Then
new_(x, y) = 1
Continue For
End If
End If
' all condition are met, make p1 white (0)
new_(x, y) = 0
change = 1 ' flag change
Next
Next
 
' copy new_() into old()
For y = 0 To n
For x = 0 To m
old(x, y) = new_(x, y)
Next
Next
 
stage += 1
Loop Until change = 0 ' stop when there are no changes made
 
Print ' print result
Print "End result"
For y = 0 To n
For x = 0 To m
If old(x, y) = 0 Then Print "."; Else Print "#";
Next
Print
Next
 
 
' empty keyboard buffer
While Inkey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End</lang>
{{out}}
<pre>................................
.#########.......########.......
.###...####.....####..####......
.###....###.....###....###......
.###...####.....###.............
.#########......###.............
.###.####.......###....###......
.###..####..###.####..####.###..
.###...####.###..########..###..
................................
 
End result
................................
..#######.........######........
..#.....#........##.............
..#......#.......#..............
..#.....#........#..............
..#####.#........#..............
.......##........#..............
........#....#...##....##...#...
.........#.........####.........
................................</pre>
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,977 ⟶ 2,362:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,993 ⟶ 2,378:
 
=={{header|Groovy}}==
<langsyntaxhighlight lang="groovy">def zhangSuen(text) {
def image = text.split('\n').collect { line -> line.collect { it == '#' ? 1 : 0} }
def p2, p3, p4, p5, p6, p7, p8, p9
Line 2,017 ⟶ 2,402:
while (reduce(step1) | reduce(step2));
image.collect { line -> line.collect { it ? '#' : '.' }.join('') }.join('\n')
}</langsyntaxhighlight>
Testing:
<langsyntaxhighlight lang="groovy">def small = """\
................................
.#########.......########.......
Line 2,057 ⟶ 2,442:
println zhangSuen(it)
println()
}</langsyntaxhighlight>
Output:
<pre>From:
Line 2,122 ⟶ 2,507:
 
=={{header|Haskell}}==
<langsyntaxhighlight Haskelllang="haskell">import Data.Array
import qualified Data.List as List
 
Line 2,243 ⟶ 2,628:
 
main :: IO ()
main = mapM_ (putStrLn . showBWArray . thin . toBWArray) [sampleExA, sampleExB]</langsyntaxhighlight>
{{out}}
<pre> ####### ######
Line 2,274 ⟶ 2,659:
=={{header|J}}==
'''Solution:'''
<langsyntaxhighlight lang="j">isBlackPx=: '1'&=;._2 NB. boolean array of black pixels
toImage=: [: , LF ,.~ '01' {~ ] NB. convert to original representation
frameImg=: 0 ,. 0 , >:@$ {. ] NB. adds border of 0's to image
Line 2,298 ⟶ 2,683:
step2=: whiten frameImg@(cond2 neighbrs)
 
zhangSuen=: [: toImage [: step2@step1^:_ isBlackPx</langsyntaxhighlight>
'''Alternative, explicit representation of last verb above'''
<langsyntaxhighlight lang="j">zhangSuenX=: verb define
img=. isBlackPx y
whilst. 0 < +/ , msk1 +.&-. msk2 do.
Line 2,309 ⟶ 2,694:
end.
toImage img
)</langsyntaxhighlight>
'''Example Use:'''
<langsyntaxhighlight lang="j">toASCII=: ' #' {~ '1'&=;._2 NB. convert to ASCII representation
 
ExampleImg=: noun define
Line 2,336 ⟶ 2,721:
# # ## ## #
# ####
</langsyntaxhighlight>
 
=={{header|Java}}==
{{works with|Java|7}}
<langsyntaxhighlight lang="java">import java.awt.Point;
import java.util.*;
 
Line 2,456 ⟶ 2,841:
System.out.println(row);
}
}</langsyntaxhighlight>
 
Output:
Line 2,478 ⟶ 2,863:
=={{header|JavaScript}}==
{{trans|Java}}
<langsyntaxhighlight lang="javascript">function Point(x, y) {
this.x = x;
this.y = y;
Line 2,583 ⟶ 2,968:
return ZhangSuen;
}());
ZhangSuen.main(null);</langsyntaxhighlight>
 
Output:
Line 2,604 ⟶ 2,989:
 
=={{header|Julia}}==
<langsyntaxhighlight lang="julia">
const pixelstring =
"00000000000000000000000000000000" *
Line 2,681 ⟶ 3,066:
 
 
asciiprint(zsthinning(pixels))</langsyntaxhighlight>
{{output}}<pre>
loop number 1
Line 2,699 ⟶ 3,084:
=={{header|Kotlin}}==
{{trans|Java}}
<langsyntaxhighlight lang="scala">// version 1.1.2
 
class Point(val x: Int, val y: Int)
Line 2,798 ⟶ 3,183:
fun main(args: Array<String>) {
thinImage()
}</langsyntaxhighlight>
 
{{out}}
Line 2,821 ⟶ 3,206:
 
=={{header|Lua}}==
<langsyntaxhighlight lang="lua">function zhangSuenThin(img)
local dirs={
{ 0,-1},
Line 2,961 ⟶ 3,346:
 
zhangSuenThin(image)
</syntaxhighlight>
</lang>
 
Output:
Line 2,977 ⟶ 3,362:
</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
 
Mathematica supports directly the Thinning methods "Morphological" and "MedialAxis".
The Zhang-Suen algorithm implementation could be done with:
<langsyntaxhighlight Mathematicalang="mathematica">nB[mat_] := Delete[mat // Flatten, 5] // Total;
 
nA[mat_] := Module[{l},
Line 3,018 ⟶ 3,402:
 
 
FixedPoint[iter, dat]</langsyntaxhighlight>
 
Which results in:
Line 3,162 ⟶ 3,546:
 
=={{header|Nim}}==
<langsyntaxhighlight Nimlang="nim">import math, sequtils, strutils
 
type
Line 3,255 ⟶ 3,639:
echo()
echo "Output image:"
echo output</langsyntaxhighlight>
 
{{out}}
Line 3,285 ⟶ 3,669:
=={{header|Perl}}==
{{trans|Raku}}
<syntaxhighlight lang ="perl">use List::Util qw(sum min)v5.36.0;
no warnings 'uninitialized';
use List::Util qw(sum min);
 
$source = <<'END';
Line 3,323 ⟶ 3,709:
 
do {
sub seewhite ($w1,$w2) {
my($w1,$w2) = @_results;
sub cycles (@neighbors) { my $c; $c += $neighbors[$_] < $neighbors[($_+1)%8] for 0..$#neighbors; $c }
my(@results);
sub cyclesblacks { my(@neighbors)=@_; my{ $c;sum $c += $@neighbors[$_] < $neighbors[($_+1)%8] for 0..$#neighbors; return $c }
sub blacks { my(@neighbors)=@_; sum @neighbors }
 
@prior = @cand; @cand = ();
for $p (@prior) {
Line 3,338 ⟶ 3,722:
}
}
return @results;
}
 
@goners1 = seewhite [0,2,4], [2,4,6]; @black[@goners1] = 0 x @goners1;
@goners2 = seewhite [0,2,6], [0,4,6]; @black[@goners2] = 0 x @goners2;
} untilwhile @goners1 == 0 andor @goners2 == 0;
 
while (@black) { push @thinned, join '', qw<. #>[splice(@black,0,$h)] }
 
printsay join "\n", @thinned;</langsyntaxhighlight>
{{out}}
<pre>............................................................
Line 3,369 ⟶ 3,753:
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>constant n = {{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0}};
<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>
function AB(sequence text, integer y, x, step)
integer wtb = 0, bn = 0
<span style="color: #008080;">function</span> <span style="color: #000000;">AB</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">text</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">step</span><span style="color: #0000FF;">)</span>
integer prev = '#', next
<span style="color: #004080;">integer</span> <span style="color: #000000;">wtb</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">bn</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
string p2468 = ""
<span style="color: #004080;">integer</span> <span style="color: #000000;">prev</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'#'</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">next</span>
for i=1 to length(n) do
<span style="color: #004080;">string</span> <span style="color: #000000;">p2468</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
next = text[y+n[i][1]][x+n[i][2]]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
wtb += (prev='.' and next<='#')
<span style="color: #000000;">next</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">text</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">+</span><span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]][</span><span style="color: #000000;">x</span><span style="color: #0000FF;">+</span><span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]]</span>
bn += (i>1 and next<='#')
<span style="color: #000000;">wtb</span> <span style="color: #0000FF;">+=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">prev</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'.'</span> <span style="color: #008080;">and</span> <span style="color: #000000;">next</span><span style="color: #0000FF;"><=</span><span style="color: #008000;">'#'</span><span style="color: #0000FF;">)</span>
if and_bits(i,1)=0 then p2468 = append(p2468,prev) end if
<span style="color: #000000;">bn</span> <span style="color: #0000FF;">+=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">></span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">next</span><span style="color: #0000FF;"><=</span><span style="color: #008000;">'#'</span><span style="color: #0000FF;">)</span>
prev = next
<span style="color: #008080;">if</span> <span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</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: #008080;">then</span> <span style="color: #000000;">p2468</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p2468</span><span style="color: #0000FF;">,</span><span style="color: #000000;">prev</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #000000;">prev</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">next</span>
if step=2 then -- make it p6842
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
p2468 = p2468[3..4]&p2468[1..2]
<span style="color: #008080;">if</span> <span style="color: #000000;">step</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- make it p6842</span>
end if
<span style="color: #000000;">p2468</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">p2468</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">..</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]&</span><span style="color: #000000;">p2468</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span>
return {wtb,bn,p2468}
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">wtb</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p2468</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
procedure Zhang_Suen(sequence text)
integer wtb, bn, changed, changes
<span style="color: #008080;">procedure</span> <span style="color: #000000;">Zhang_Suen</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">text</span><span style="color: #0000FF;">)</span>
string p2468 -- (p6842 for step 2)
<span style="color: #004080;">integer</span> <span style="color: #000000;">wtb</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">bn</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">changed</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">changes</span>
text = split(text,'\n')
<span style="color: #004080;">string</span> <span style="color: #000000;">p2468</span> <span style="color: #000080;font-style:italic;">-- (p6842 for step 2)</span>
while 1 do
<span style="color: #000000;">text</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">text</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\n'</span><span style="color: #0000FF;">)</span>
changed = 0
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
for step=1 to 2 do
<span style="color: #000000;">changed</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
changes = 0
<span style="color: #008080;">for</span> <span style="color: #000000;">step</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">2</span> <span style="color: #008080;">do</span>
for y=2 to length(text)-1 do
<span style="color: #000000;">changes</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
for x=2 to length(text[y])-1 do
<span style="color: #008080;">for</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">text</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
if text[y][x]='#' then
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">text</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">])-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
{wtb,bn,p2468} = AB(text,y,x,step)
<span style="color: #008080;">if</span> <span style="color: #000000;">text</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">][</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'#'</span> <span style="color: #008080;">then</span>
if wtb=1
<span style="color: #0000FF;">{</span><span style="color: #000000;">wtb</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p2468</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">AB</span><span style="color: #0000FF;">(</span><span style="color: #000000;">text</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">step</span><span style="color: #0000FF;">)</span>
and bn>=2 and bn<=6
<span style="color: #008080;">if</span> <span style="color: #000000;">wtb</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span>
and find('.',p2468[1..3])
<span style="color: #008080;">and</span> <span style="color: #000000;">bn</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">2</span> <span style="color: #008080;">and</span> <span style="color: #000000;">bn</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">6</span>
and find('.',p2468[2..4])then
<span style="color: #008080;">and</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'.'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p2468</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">3</span><span style="color: #0000FF;">])</span>
changes = 1
<span style="color: #008080;">and</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'.'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p2468</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..</span><span style="color: #000000;">4</span><span style="color: #0000FF;">])</span><span style="color: #008080;">then</span>
text[y][x] = '!' -- (logically still black)
<span style="color: #000000;">changes</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
end if
<span style="color: #000000;">text</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">][</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'!'</span> <span style="color: #000080;font-style:italic;">-- (logically still black)</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
if changes then
<span style="color: #008080;">end</span> for<span ystyle=2"color: to length(text)-1 do#008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">changes</span> <span style="color: #008080;">then</span>
text[y] = substitute(text[y],"!",".")
<span style="color: #008080;">for</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">text</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000000;">text</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">text</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">],</span><span style="color: #008000;">"!"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"."</span><span style="color: #0000FF;">)</span>
changed = 1
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end if
<span style="color: #000000;">changed</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if not changed then exit end if
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end while
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">changed</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
puts(1,join(text,"\n"))
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
end procedure
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">text</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">))</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
string small_rc = """
................................
<span style="color: #004080;">string</span> <span style="color: #000000;">small_rc</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"""
.#########.......########.......
................###...####.....####..####......
.###....######.......###....#####.......
.###...####.....####.......####......
.######....###......###.......###......
.###...####.......###....###.........
.###..####..###.####..####...###.............
.###...####.###..#####....###....###......
.###..####..###.####..####.###..
................................"""
.###...####.###..########..###..
Zhang_Suen(small_rc)</lang>
................................"""</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>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 3,449 ⟶ 3,836:
 
=={{header|PL/I}}==
<syntaxhighlight lang="pl/i">zhang: procedure options (main); /* 8 July 2014 */
 
declare pic(10) bit(32) initial (
Line 3,571 ⟶ 3,958:
end B;
 
end zhang;</langsyntaxhighlight>
<pre>
[Initial configuration:]
Line 3,662 ⟶ 4,049:
=={{header|Python}}==
Several input images are converted.
<langsyntaxhighlight lang="python"># -*- coding: utf-8 -*-
 
# Example from [http://nayefreza.wordpress.com/2013/05/11/zhang-suen-thinning-algorithm-java-implementation/ this blog post].
Line 3,779 ⟶ 4,166:
print('\nFrom:\n%s' % toTxt(image))
after = zhangSuen(image)
print('\nTo thinned:\n%s' % toTxt(after))</langsyntaxhighlight>
 
{{out}}
Line 3,809 ⟶ 4,196:
=={{header|Racket}}==
 
<langsyntaxhighlight lang="racket">#lang racket
(define (img-01string->vector str)
(define lines (regexp-split "\n" str))
Line 3,922 ⟶ 4,309:
; (read-display-thin-display-image e.g.-image/2)
; (newline)
(read-display-thin-display-image e.g.-image))</langsyntaxhighlight>
 
{{out}}
Line 3,952 ⟶ 4,339:
(formerly Perl 6)
Source image may be based on any characters whose low bits are 0 or 1 (which conveniently includes . and #).
<syntaxhighlight lang="raku" perl6line>my $source = qq:to/EOD/;
................................
.#########.......########.......
Line 4,002 ⟶ 4,389:
}
 
say @black.splice(0,h).join.trans('01' => '.#') while @black;</langsyntaxhighlight>
{{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
Line 4,022 ⟶ 4,409:
 
=={{header|REXX}}==
<langsyntaxhighlight 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'
white=' '; @.=white /* [↓] read the input character grid. */
Line 4,062 ⟶ 4,449:
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
p6=@.rp.c\==white; p7=@.rp.cm\==white; p8=@.r.cm\==white; p9=@.rm.cm\==white; return</langsyntaxhighlight>
'''output''' &nbsp; when using the default input:
<pre>
Line 4,136 ⟶ 4,523:
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.
 
<langsyntaxhighlight lang="ruby">class ZhangSuen
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
Line 4,203 ⟶ 4,590:
EOS
 
ZhangSuen.new(task_example, "1")</langsyntaxhighlight>
 
{{out}}
Line 4,221 ⟶ 4,608:
=={{header|Sidef}}==
{{trans|Ruby}}
<langsyntaxhighlight 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 CIRCULARS = (NEIGHBOURS + [NEIGHBOURS.first]) # P2, ... P9, P2
Line 4,277 ⟶ 4,664:
EOS
 
ZhangSuen.new(text, black: "1").display</langsyntaxhighlight>
{{out}}
<pre>
Line 4,291 ⟶ 4,678:
</pre>
 
=={{header|Swift}}==
{{trans|Python}}
 
<syntaxhighlight lang="swift">import UIKit
 
// testing examples
let beforeTxt = """
1100111
1100111
1100111
1100111
1100110
1100110
1100110
1100110
1100110
1100110
1100110
1100110
1111110
0000000
"""
 
let smallrc01 = """
00000000000000000000000000000000
01111111110000000111111110000000
01110001111000001111001111000000
01110000111000001110000111000000
01110001111000001110000000000000
01111111110000001110000000000000
01110111100000001110000111000000
01110011110011101111001111011100
01110001111011100111111110011100
00000000000000000000000000000000
"""
let rc01 = """
00000000000000000000000000000000000000000000000000000000000
01111111111111111100000000000000000001111111111111000000000
01111111111111111110000000000000001111111111111111000000000
01111111111111111111000000000000111111111111111111000000000
01111111100000111111100000000001111111111111111111000000000
00011111100000111111100000000011111110000000111111000000000
00011111100000111111100000000111111100000000000000000000000
00011111111111111111000000000111111100000000000000000000000
00011111111111111110000000000111111100000000000000000000000
00011111111111111111000000000111111100000000000000000000000
00011111100000111111100000000111111100000000000000000000000
00011111100000111111100000000111111100000000000000000000000
00011111100000111111100000000011111110000000111111000000000
01111111100000111111100000000001111111111111111111000000000
01111111100000111111101111110000111111111111111111011111100
01111111100000111111101111110000001111111111111111011111100
01111111100000111111101111110000000001111111111111011111100
00000000000000000000000000000000000000000000000000000000000
"""
 
// Zhang-Suen thinning algorithm in Swift
/// function to thin the image
func zhangSuen(image: inout [[Int]]) -> [[Int]] {
// array of x, y position where need to changed to be white
var changing1, changing2: [(Int, Int)]
repeat {
// set to empty array
changing1 = []
changing2 = []
// Step 1
// loop through row of image
for y in 1..<image.count-1 {
// loop through column of image
for x in 1..<image[0].count-1 {
// get neighbours of P1
var nb = neighbours(x: x, y: y, image: image)
// set P2, P4, P6, P8 from neighbours
let P2 = nb[0], P4 = nb[2], P6 = nb[4], P8 = nb[6]
// reference: https://www.hackingwithswift.com/example-code/language/how-to-sum-an-array-of-numbers-using-reduce
// reference: https://www.hackingwithswift.com/articles/90/how-to-check-whether-a-value-is-inside-a-range
if (image[y][x] == 1 && // Condision 0
(2...6).contains(nb.reduce(0, +)) && // Condision 1
transitions(neighbours: &nb) == 1 && // Condision 2
P2 * P4 * P6 == 0 && // Condision 3
P4 * P6 * P8 == 0 // Condision 4
) {
// add to step1 changing1 list
changing1.append((x,y))
}
}
}
// loop through step1 changing1 list and change to white
for (x, y) in changing1 {
image[y][x] = 0
}
// Step 2
// loop through row of image
for y in 1..<image.count-1 {
// loop through column of image
for x in 1..<image[0].count-1 {
// get neighbours of P1
var nb = neighbours(x: x, y: y, image: image)
// set P2, P4, P6, P8 from neighbours
let P2 = nb[0], P4 = nb[2], P6 = nb[4], P8 = nb[6]
if (image[y][x] == 1 && // Condision 0
(2...6).contains(nb.reduce(0, +)) && // Condision 1
transitions(neighbours: &nb) == 1 && // Condision 2
P2 * P4 * P8 == 0 && // Condision 3
P2 * P6 * P8 == 0 // Condision 4
) {
// add to step2 changing2 list
changing2.append((x,y))
}
}
}
// loop through step2 changing2 list and change to white
for (x, y) in changing2 {
image[y][x] = 0
}
// finish loop when there's no more place to change to white, when changing1, changing2 are empty
} while !changing1.isEmpty && !changing2.isEmpty
// return updated image
return image
}
 
/// function to convert multiline string of 1/0 into 2D Int array
func intarray(binstring: String) -> [[Int]] {
// reference: https://stackoverflow.com/questions/28611336/how-to-convert-a-string-numeric-in-a-int-array-in-swift
// map through each char of input String to convert to Int
return binstring.split(separator: "\n").map {$0.compactMap{$0.wholeNumberValue}}
}
 
/// function to convert 2D Int array of 1/0 into multiline String of ‘#’ and ‘.’
func toTxt(intmatrix: [[Int]]) -> String {
// map through each array of parent array and
// map through element of child array and convert to '#' when 1 and to '.' when 0
return intmatrix.map {$0.map { $0 == 1 ? "#" : "."}.joined(separator: "")}.joined(separator: "\n")
}
 
/// function to get neighbours of P1 = [P2,P3,P4,P5,P6,P7,P8,P9]
func neighbours(x: Int, y: Int, image: [[Int]]) -> [Int] {
let i = image
// set x, y positions of P1 neighbours
let x1 = x+1, y1 = y-1, x_1 = x-1, y_1 = y+1
// return neighbours of P1
return [i[y1][x], i[y1][x1], i[y][x1], i[y_1][x1], // P2,P3,P4,P5
i[y_1][x], i[y_1][x_1], i[y][x_1], i[y1][x_1]] // P6,P7,P8,P9
}
 
/// function to get the number of transitions from white to black, (0 -> 1) in the sequence P2,P3,P4,P5,P6,P7,P8,P9,P2.
func transitions(neighbours: inout [Int]) -> Int {
// add P2 at the end of neighbours array
let n = neighbours + [neighbours[0]]
var result = 0
// reference: https://www.marcosantadev.com/arrayslice-in-swift/
// compare between each element of neightbour and next element of the element to check if the transition is 0 -> 1
for (n1, n2) in zip(n, n.suffix(n.count - 1)) {
// if the pattern matches, increament result to 1
if (n1, n2) == (0, 1) { result += 1 }
}
// return number of transitions from 0 to 1
return result
}
 
// run testing
// array of test examples
let testCases: [String] = [beforeTxt, smallrc01, rc01]
for picture in testCases {
// convert string to 2D Int array
var image = intarray(binstring: picture)
// print the result
print("\nFrom:\n\(toTxt(intmatrix: image))")
// run through Zhang-Suen thinning algorithm
let after = zhangSuen(image: &image)
// print the result
print("\nTo thinned:\n\(toTxt(intmatrix: after))")
}</syntaxhighlight>
 
{{out}}
 
<pre>
From:
##..###
##..###
##..###
##..###
##..##.
##..##.
##..##.
##..##.
##..##.
##..##.
##..##.
##..##.
######.
.......
 
To thinned:
##..###
#.....#
#.....#
#...###
#...#..
#...#..
#...#..
#...#..
#...#..
#...#..
#...#..
#...#..
#####..
.......
 
From:
................................
.#########.......########.......
.###...####.....####..####......
.###....###.....###....###......
.###...####.....###.............
.#########......###.............
.###.####.......###....###......
.###..####..###.####..####.###..
.###...####.###..########..###..
................................
 
To thinned:
................................
..#######.........######........
..#.....#........##.............
..#......#.......#..............
..#.....#........#..............
..#####.#........#..............
.......##........#..............
........#....#...##....##...#...
.........#.........####.........
................................
 
From:
...........................................................
.#################...................#############.........
.##################...............################.........
.###################............##################.........
.########.....#######..........###################.........
...######.....#######.........#######.......######.........
...######.....#######........#######.......................
...#################.........#######.......................
...################..........#######.......................
...#################.........#######.......................
...######.....#######........#######.......................
...######.....#######........#######.......................
...######.....#######.........#######.......######.........
.########.....#######..........###################.........
.########.....#######.######....##################.######..
.########.....#######.######......################.######..
.########.....#######.######.........#############.######..
...........................................................
 
To thinned:
...........................................................
...........................................................
....#.##########.......................#######.............
.....##........#...................####.......#............
.....#..........#.................##.......................
.....#..........#................#.........................
.....#..........#................#.........................
.....#..........#................#.........................
.....############...............#..........................
.....#..........#...............#..........................
.....#..........#................#.........................
.....#..........#................#.........................
.....#..........#................#.........................
.....#............................##.......................
.....#.............................############............
.......................###..........................###....
...........................................................
...........................................................
</pre>
 
 
=={{header|Tcl}}==
Only the single image is converted.
<langsyntaxhighlight lang="tcl"># -*- coding: utf-8 -*-
 
set data {
Line 4,371 ⟶ 5,034:
return $data
}
puts [string map {1 @ 0 .} [join [zhang-suen $data] \n]]</langsyntaxhighlight>
 
{{out}}
Line 4,386 ⟶ 5,049:
................................
</pre>
 
=={{header|VBA}}==
{{trans|Phix}}
<lang vb>Public n As Variant
Private Sub init()
n = [{-1,0;-1,1;0,1;1,1;1,0;1,-1;0,-1;-1,-1;-1,0}]
End Sub
 
Private Function AB(text As Variant, y As Integer, x As Integer, step As Integer) As Variant
Dim wtb As Integer
Dim bn As Integer
Dim prev As String: prev = "#"
Dim next_ As String
Dim p2468 As String
For i = 1 To UBound(n)
next_ = Mid(text(y + n(i, 1)), x + n(i, 2), 1)
wtb = wtb - (prev = "." And next_ <= "#")
bn = bn - (i > 1 And next_ <= "#")
If (i And 1) = 0 Then p2468 = p2468 & prev
prev = next_
Next i
If step = 2 Then '-- make it p6842
p2468 = Mid(p2468, 3, 2) & Mid(p2468, 1, 2)
'p2468 = p2468(3..4)&p2468(1..2)
End If
Dim ret(2) As Variant
ret(0) = wtb
ret(1) = bn
ret(2) = p2468
AB = ret
End Function
Private Sub Zhang_Suen(text As Variant)
Dim wtb As Integer
Dim bn As Integer
Dim changed As Boolean, changes As Boolean
Dim p2468 As String '-- (p6842 for step 2)
Dim x As Integer, y As Integer, step As Integer
Do While True
changed = False
For step = 1 To 2
changes = False
For y = 1 To UBound(text) - 1
For x = 2 To Len(text(y)) - 1
If Mid(text(y), x, 1) = "#" Then
ret = AB(text, y, x, step)
wtb = ret(0)
bn = ret(1)
p2468 = ret(2)
If wtb = 1 _
And bn >= 2 And bn <= 6 _
And InStr(1, Mid(p2468, 1, 3), ".") _
And InStr(1, Mid(p2468, 2, 3), ".") Then
changes = True
text(y) = Left(text(y), x - 1) & "!" & Right(text(y), Len(text(y)) - x)
End If
End If
Next x
Next y
If changes Then
For y = 1 To UBound(text) - 1
text(y) = Replace(text(y), "!", ".")
Next y
changed = True
End If
Next step
If Not changed Then Exit Do
Loop
Debug.Print Join(text, vbCrLf)
End Sub
 
Public Sub main()
init
Dim Small_rc(9) As String
Small_rc(0) = "................................"
Small_rc(1) = ".#########.......########......."
Small_rc(2) = ".###...####.....####..####......"
Small_rc(3) = ".###....###.....###....###......"
Small_rc(4) = ".###...####.....###............."
Small_rc(5) = ".#########......###............."
Small_rc(6) = ".###.####.......###....###......"
Small_rc(7) = ".###..####..###.####..####.###.."
Small_rc(8) = ".###...####.###..########..###.."
Small_rc(9) = "................................"
Zhang_Suen (Small_rc)
End Sub</lang>{{out}}
<pre>................................
...######.........######........
...#....#.........#....##.......
...#....#.........#......#......
...#....#.........#.............
...####.#.........#.............
.......##.........#.............
........#....#....#....##...#...
.........#....#....####......#..
................................</pre>
 
=={{header|Wren}}==
{{trans|Kotlin}}
<langsyntaxhighlight ecmascriptlang="wren">class Point {
construct new(x, y) {
_x = x
Line 4,592 ⟶ 5,159:
}
 
thinImage.call()</langsyntaxhighlight>
 
{{out}}
9,476

edits