G'MIC Challenge: Create image from photographs with a single line

Tiger : https://www.ghostscript.com/doc/examples/tiger.eps


Thanks to @grosgood for his answer, here is the result of his advice :


resize 1024,{{h}/{w}*1024}
samj_Masques_Noir_Et_Blanc_Preview 3,50
to_gray
negate
dilate 10
   +r2dx. 25%,5
   pointcloud. 3
   channels. 0,1
   f. c==0?i*4.1:i*3.9
   tsp. ,
   permute. cyzx
   nm. points
   i 1024,1024,1,1
   nm. canvas
   eval {V=crop(#$points);polygon(#$canvas,-size(V)/2,V,1,0xffffffff,255)}
   keep[0,-1]
rm[0]
autocrop

Stairs/Escaliers

resize 1024,{{h}/{w}*1024}
samj_Masques_Noir_Et_Blanc_Preview 3,50
to_gray
negate
dilate 10
jeje_strip 45,50,0,2,0
   +r2dx. 25%,5
   pointcloud. 3
   channels. 0,1
   *. 4
   tsp. ,
   permute. cyzx
   nm. points
   i 1024,1024,1,1
   nm. canvas
   eval {V=crop(#$points);polygon(#$canvas,-size(V)/2,V,1,0xffffffff,255)}
   keep[0,-1]
rm[0]

You donā€™t need to wrap around w, and h. It works.

C:\Windows\System32>gmic 5,10 echo {w/h} rm
[gmic]-0./ Start G'MIC interpreter.
[gmic]-0./ Input black image at position 0 (1 image 5x10x1x1).
[gmic]-1./ 0.5
[gmic]-1./ Remove image [0] (0 images left).
[gmic]-0./ End G'MIC interpreter.

@Reptorian

Thatā€™s right. I simply use the beginning of another project to activate the ā€˜tspā€™ script :o)

Thatā€™s cool, Gary. Just sharing some insights I discovered with voronoi stippler over the years. Another one is to invert the target, then after running, invert that result to get white on black (similar results to what you got with yours). :slight_smile:

@lylejk
Thank you : The Traveling Salesman problem. ā€¢ GIMP Chat

I always have fun with the scripts of @David_Tschumperle and @grosgood

A black line on a white background :

if {w}>{h}
resize 1000,{{h}/{w}*1000}
else
resize {{w}/{h}*1000},1000
fi
samj_Masques_Noir_Et_Blanc_Preview 3,50
to_gray
negate
dilate 10
pointcloud. 3
channels. 0,1
resize. 2%,1
add. 12
tsp. 200
1024,1024,1,1
repeat {0,w}
 line. {0,boundary=2;[I[$>],I[$>+1]]},1,255
done
rm[-2]
dilate 2
negate
1 Like

I like this last one. Black line on white canvas. It still has a laser beam coming out of the eye of the tiger. :rotating_light: :joy_cat:

Going back to Repā€™s original, I sort of like the meandering single line (i.e, no picking up the pin) result. Again, I would want this ability in the plugin, since, well, Iā€™m a GIMPer. Not opposed to CLI or scripts (hence TSP), but like to be able to keep withing an editing environment. Maybe David or someone can figure out how to do this within the Gā€™MIC plugin. While Iā€™m asking, would like the Hilbert (and other type) of variable density single line fill render abilities as well (doesnā€™t hurt to ask). lol

:slight_smile:

Well, the main difference of @Reptorianā€™s sample and the rest of yours is that the line can cross itself! Although it is different, I recall this:

Somehow, instead of having the edges of the image or shape as direction change points, we could have the edges and textures of the imageā€¦ and instead of straight lines, we have splines, etc.

Some remarks follows to my tests :

I did some testing with splines but itā€™s very, very slow.

@lylejk
Make a GMIC-Gimp plug-in is difficult because the rendering is very, very slow.
It could be sequential, for example :

  • At first visualize the completed areas.
  • Then validate the final overview.

The stability of the plug-in during the time of treatment must be taken into consideration.

Just brainstorming. We donā€™t have to implement all the ideas. I think it would still work with straight lines, we just have to decide when to change directions and how many times.

The thing is Gā€™MIC is probably the wrong program to do this because of the slowness but who knows: you are all geniuses. :nerd_face:

Appreciate the followup, samj. I guess Iā€™m still wanting Gā€™MIC to be the do all of do alls. lololololool

Still, my Dad always told me thereā€™s always more than one way to skin a cat. lol

:slight_smile:

Thatā€™s why I attempted to recreate/convert many Paint.NET plugin to Gā€™MIC.

Appreciate your efforts, Rep since coder Iā€™m not. So many great coders that have made me happy over the years, you included, Rep. :slight_smile:

1 Like

I had fun exporting to SVG in the directory where is ā€˜update310.gmicā€™
I join the code I activate in GIMP and the file ā€˜list_points_tsp.svgā€™ created by the script.
I will realize a plug-in by separating the rendering and the SVG backup.


CRLF="\\r\\n"
Liste="<?xml version=\\"1.0\\" encoding=\\"utf-8\\"?>"$CRLF
Liste=$Liste"<svg xmlns=\\"http://www.w3.org/2000/svg\\" version=\\"1.1\\" width=\\"1024\\" height=\\"1024\\">"$CRLF
Liste=$Liste"<title>Test GMIC SVG</title>"$CRLF
Liste=$Liste"<desc>Points et Segments</desc>"$CRLF
if {w}>{h}
resize 1000,{{h}/{w}*1000}
else
resize {{w}/{h}*1000},1000
fi
samj_Masques_Noir_Et_Blanc_Preview 3,50
to_gray
negate
dilate 10
pointcloud. 3
channels. 0,1
resize. 2%,1
add. 12
tsp. 200
+crop 0,0,1,0
Xend={i0}
Yend={i1}
rm[-1]
repeat {{w}-1}
Index=$>
 +crop $Index,0,{$Index+1},0
 Xa={i0}
 Ya={i1}
 rm[-1]
 +crop {$Index+1},0,{$Index+2},0
 Xb={i0}
 Yb={i1}
 rm[-1]
 Liste=$Liste"<line x1=\\""$Xa
 Liste=$Liste"\\" y1=\\""$Ya
 Liste=$Liste"\\" x2=\\""$Xb
 Liste=$Liste"\\" y2=\\""$Yb
 Liste=$Liste"\\" stroke=\\"black\\" />"$CRLF
done
Liste=$Liste"<line x1=\\""$Xb
Liste=$Liste"\\" y1=\\""$Yb
Liste=$Liste"\\" x2=\\""$Xend
Liste=$Liste"\\" y2=\\""$Yend
Liste=$Liste"\\" stroke=\\"black\\" />"$CRLF
Liste=$Liste"</svg>"$CRLF
('$Liste')
output_text.  $_path_rc/Liste_Points_TSP.svg
# SVG validƩ sur https://validator.w3.org/
rm.
1024,1024,1,1
repeat {0,w}
 line. {0,boundary=2;[I[$>],I[$>+1]]},1,255
done
rm[-2]

Liste_Points_TSP

1 Like

@samj: For Liste, you could do:

str=initial_string
str.=" appended string"

echo $str

You can do ..= which appends the other way.

Having fun with Gmicky in GIMP/GMIC 3.1.0_pre for getting an SVG image (1 line) :

Liste_Points_TSP


## Supprimer les 2 lignes pour obtenir un SVG sur une autre image ##
rm
fx_gmicky 0
####################################################################
Param1Masque1=1.25
Param2Masque1=42
Param1Masque2=0
Param2Masque2=32.5
CRLF="\\r\\n"
Liste="<?xml version=\\"1.0\\" encoding=\\"utf-8\\"?>"$CRLF
Liste.="<svg xmlns=\\"http://www.w3.org/2000/svg\\" version=\\"1.1\\" width=\\"1024\\" height=\\"1024\\">"$CRLF
Liste.="<title>Test GMIC SVG</title>"$CRLF
Liste.="<desc>Points et Segments</desc>"$CRLF
Liste.="<polyline points=\\""
if w>h
resize 1000,{h/w*1000}
else
resize {w/h*1000},1000
fi
+samj_Masques_Noir_Et_Blanc_Preview $Param1Masque1,$Param2Masque1
to_gray.
negate.
dilate. 10
pointcloud. 3
channels. 0,1
resize. 1%,1
add. 12
tsp. 200
+crop. 0,0,1,0
Xend={i0}
Yend={i1}
rm.
repeat w
 Index=$>
 +crop. $Index,0,{$Index+1},0
 Xa={i0}
 Ya={i1}
 rm.
 Liste.=$Xa" "
 Liste.=$Ya" "
done
rm.
# ligne 2
samj_Masques_Noir_Et_Blanc_Preview $Param1Masque2,$Param2Masque2
to_gray.
negate.
dilate. 10
pointcloud. 3
channels. 0,1
resize. 1%,1
add. 12
tsp. 200
repeat w
 Index=$>
 +crop. $Index,0,{$Index+1},0
 Xa={i0}
 Ya={i1}
 rm.
 Liste.=$Xa" "
 Liste.=$Ya" "
done
Liste.=$Xend" "
Liste.=$Yend" "
# Liste.="\\" stroke=\\"blue\\" fill=\\"transparent\\" stroke-width=\\"2\\"/>"$CRLF
Liste.="\\" stroke=\\"blue\\" fill=\\"transparent\\" stroke-width=\\"2\\" mask=\\"none\\" style=\\"fill:#000000;fill-opacity:0\\"/>"$CRLF
Liste.="</svg>"$CRLF
('$Liste')
output_text.  $_path_rc/Liste_Points_TSP.svg
# SVG validƩ sur https://validator.w3.org/
rm
1500,100,1,3
fill_color. 255,255,255
text. "SVG disponible sur :",20,20,20,1,255,0,0
if '$_os'=='windows'
 text. $_path_rc"\\Liste_Points_TSP.svg",20,50,20,1,255,0,0
else
 text. $_path_rc"/Liste_Points_TSP.svg",20,50,20,1,255,0,0
fi
autocrop
3 Likes

@samj This is wonderful. Much closer to @Reptorianā€™s and @lylejkā€™s examples. SVG too.

@afre

Thank you :o)
The next step will replace the right segments with curves.
I have to find a formula to create a smoothed and beautiful rendering (not easy to do for me).

I use smooth pathā€™s plugin in GIMP (not sure when/where I got this plugin). Also can simplify in Inkscape since itā€™s a vector, but Inkscape tends to smooth too much. :slight_smile:

(Edit) Here is a version with which uses SVG BĆ©zier curves to get curved lines.

I join the code for GIMP GMIC 3.1.0_pre (this code is not optimized).

I will wait for the GMIC ā€˜execā€™ command to work properly to continue.

Liste_Points_TSP


## Supprimer les 2 lignes pour obtenir un SVG sur une autre image ##
rm
fx_gmicky 0
####################################################################
Param1Masque1=1.25
Param2Masque1=42
Param1Masque2=0
Param2Masque2=32.5
Echelle=1
CRLF="\\r\\n"
Liste="<?xml version=\\"1.0\\" encoding=\\"utf-8\\"?>"$CRLF
Liste.="<svg xmlns=\\"http://www.w3.org/2000/svg\\" version=\\"1.1\\" width=\\"1024\\" height=\\"1024\\">"$CRLF
Liste.="<title>Test GMIC SVG</title>"$CRLF
Liste.="<desc>Points et Splines</desc>"$CRLF
if w>h
resize 1000,{h/w*1000}
else
resize {w/h*1000},1000
fi
+samj_Masques_Noir_Et_Blanc_Preview $Param1Masque1,$Param2Masque1
to_gray.
negate.
dilate. 10
pointcloud. 3
channels. 0,1
WWe={round(w/100*$Echelle)}
if {$WWe%2}==0 resize. $WWe,1 else resize. {$WWe-1},1 fi
add. 12
tsp. 200
+crop. 0,0,1,0
Xo={i0}
Yo={i1}
rm[-1]
+crop. 1,0,2,0
Xs={i0}
Ys={i1}
rm[-1]
+crop. 2,0,3,0
Xt={i0}
Yt={i1}
rm[-1]
+crop. 3,0,4,0
Xq={i0}
Yq={i1}
rm[-1]
Liste.="<path d=\\"M"
Liste.=$Xo" "
Liste.=$Yo" C"
Liste.=$Xs" "
Liste.=$Ys" "
Liste.=$Xt" "
Liste.=$Yt" "
Liste.=$Xq" "
Liste.=$Yq" "
Liste.="\\" stroke=\\"blue\\" fill=\\"transparent\\" stroke-width=\\"2\\" mask=\\"none\\"  style=\\"fill:#000000;fill-opacity:0\\"/>"$CRLF
Index=2
repeat {{w/2}-1}
 Xu=$Xq
 Yu=$Yq
 Xd=$Xt
 Yd=$Yt
 +crop {$Index},0,{$Index+1},0
 Xt={i0}
 Yt={i1}
 rm[-1]
 rm[-1]
 +crop {$Index+1},0,{$Index+2},0
 Xq={i0}
 Yq={i1}
 rm[-1]
 rm[-1]
 Xs={$Xu+$Xu-$Xd}
 if $Xs<0 Xs=0 fi
 if $Xs>1023 Xs=1023 fi
 Ys={$Yu+$Yu-$Yd}
 if $Ys<0 Ys=0 fi
 if $Ys>1023 Ys=1023 fi
 Liste.="<path d=\\"M"
 Liste.=$Xu" "
 Liste.=$Yu" C"
 Liste.=$Xs" "
 Liste.=$Ys" "
 Liste.=$Xt" "
 Liste.=$Yt" "
 Liste.=$Xq" "
 Liste.=$Yq" "
 Liste.="\\" stroke=\\"blue\\" fill=\\"transparent\\" stroke-width=\\"2\\" mask=\\"none\\"  style=\\"fill:#000000;fill-opacity:0\\"/>"$CRLF
 Index={$Index+2}
done
rm.
########## ligne 2
samj_Masques_Noir_Et_Blanc_Preview $Param1Masque2,$Param2Masque2
to_gray.
negate.
dilate. 10
pointcloud. 3
channels. 0,1
WWe={round(w/100*$Echelle)}
if {$WWe%2}==0 resize. $WWe,1 else resize. {$WWe-1},1 fi
add. 12
tsp. 200
+crop. 1,0,2,0
Xs={i0}
Ys={i1}
rm[-1]
+crop. 2,0,3,0
Xt={i0}
Yt={i1}
rm[-1]
+crop. 3,0,4,0
Xq={i0}
Yq={i1}
rm[-1]
Liste.="<path d=\\"M"
Liste.=$Xo" "
Liste.=$Yo" C"
Liste.=$Xs" "
Liste.=$Ys" "
Liste.=$Xt" "
Liste.=$Yt" "
Liste.=$Xq" "
Liste.=$Yq" "
Liste.="\\" stroke=\\"blue\\" fill=\\"transparent\\" stroke-width=\\"2\\" mask=\\"none\\"  style=\\"fill:#000000;fill-opacity:0\\"/>"$CRLF
Index=2
repeat {{w/2}-1}
 Xu=$Xq
 Yu=$Yq
 Xd=$Xt
 Yd=$Yt
 +crop {$Index},0,{$Index+1},0
 Xt={i0}
 Yt={i1}
 rm[-1]
 +crop {$Index+1},0,{$Index+2},0
 Xq={i0}
 Yq={i1}
 rm[-1]
 Xs={$Xu+$Xu-$Xd}
 if $Xs<0 Xs=0 fi
 if $Xs>1023 Xs=1023 fi
 Ys={$Yu+$Yu-$Yd}
 if $Ys<0 Ys=0 fi
 if $Ys>1023 Ys=1023 fi
 Liste.="<path d=\\"M"
 Liste.=$Xu" "
 Liste.=$Yu" C"
 Liste.=$Xs" "
 Liste.=$Ys" "
 Liste.=$Xt" "
 Liste.=$Yt" "
 Liste.=$Xq" "
 Liste.=$Yq" "
 Liste.="\\" stroke=\\"blue\\" fill=\\"transparent\\" stroke-width=\\"2\\" mask=\\"none\\"  style=\\"fill:#000000;fill-opacity:0\\"/>"$CRLF
 Index={$Index+2}
done
Liste.="</svg>"$CRLF
('$Liste')
output_text.  $_path_rc/Liste_Points_TSP.svg
# SVG validƩ sur https://validator.w3.org/
rm
1500,100,1,3
fill_color. 255,255,255
text. "SVG disponible sur :",20,20,20,1,255,0,0
if '$_os'=='windows'
 text. $_path_rc"\\Liste_Points_TSP.svg",20,50,20,1,255,0,0
else
 text. $_path_rc"/Liste_Points_TSP.svg",20,50,20,1,255,0,0
fi
autocrop
3 Likes