📜 ⬆️ ⬇️

Context Free: language for generating images



This picture is generated by the Context Free program according to the following description:

startshape T // FLIGIZ background{b -1} tile {s 2.5} rule T {3*{r 120 hue 30}S{x .3}} rule S 3{CIRCLE{hue 30}4*{r 20 b.007 sat .1}S[s.3.7y.9]} rule S {CIRCLE{hue 15}9*{r 20 b.05 hue -3}S[s.3.7y.9]} rule S {S{flip 90}} 

To describe images, Context Free uses the context-free grammar programming language CFD , created specifically for generating images. Roughly speaking, this is a set of basic rules with only two terminals CIRCLE and SQUARE. Rendering is performed using the Maxim Shemanarev Anti-Grain Geometry library.
')
Here are some other paintings from the Context Free Art gallery . All works in the gallery are published under the Creative Commons license (click on the link to the original).


Code
  startshape START rule START { CIRCLE{} RAINBOW_SPLIT{hue 0 sat 0 b 0} RAINBOW_SPLIT{r 180 hue 120 sat 0} } rule RAINBOW_SPLIT{ RAINBOW{} } rule RAINBOW_SPLIT{ RAINBOW_MINI{alpha -.9 y -.4 s .2 flip 1 b -1} RAINBOW{} } rule RAINBOW{ SHADOW{} CIRCLE{} HIGHLIGHT{} RAINBOW_SPLIT{hue 1.5 sat .1 s .99 b .001 x .09 r 2.8 } } rule RAINBOW_MINI{ SHADOW{} CIRCLE{} HIGHLIGHT{} RAINBOW_MINI{alpha .1 hue 2 s .98 x .3 r 2.8 } } rule RAINBOW_MINI .04{ SHADOW{} CIRCLE{} HIGHLIGHT{} RAINBOW_MINI{flip 1 alpha .1 hue 5 s .99 x .3 r 2.8 } } rule SHADOW { CIRCLE{hue 3 b -1 sat -.6 s 1.1 y .04 alpha -.7} } rule HIGHLIGHT { CIRCLE{ hue 3 b .7 sat -.3 s .98 y .05} CIRCLE{ hue 3 b 2 sat -.7 s .9 y .01} } 



Code
 /* Ancient Scripts by Leaf Garland */ background { hue 40 sat 0.2 b -0.2} startshape LINES rule LINES { 20 * {y -90} NEWLINE {hue 90 sat 0.7 b 0.2 a -0.5} } rule NEWLINE { LINE {y 0} } rule NEWLINE { LINE {y 20} } rule NEWLINE { LINE {y 30} } rule LINE { 50 * {x 36} CHAR {} } rule CHAR 0.3 { // space } rule CHAR { 2 * {x 20 flip 180} STROKE {r 90} 2 * {y 20 flip 180} STROKE {} } rule CHAR { 4 * {r 60} STROKE {} } rule CHAR { STROKE {r 90} 3 * {y 10 flip 180} STROKE {} } rule STROKE { B {} } rule STROKE { B {flip 90} } rule B 30 { MARK {} B {x .6 r 10} } rule B 30 { MARK {} B {x .6 r 3} } rule B 250 { MARK {} B {x .9} } rule B 10 { MARK {} B {flip 90} } rule B 10 { } rule MARK 3 { CIRCLE {} } rule MARK { CIRCLE {s 2} } rule MARK { SQUARE {s 3} } rule MARK { CIRCLE {s 4} } rule MARK 0.01 { CIRCLE {s 7} } 



Code
 background{b -1} startshape init rule init{time{z 0 r -90 sat .5 |h 220}} //CONTROL rule time 40 {draw{} time{r 1 s .9991 b .1| a .1|}} rule time {slow{|b -1 |a 1 |sat 1}} rule time {slow{|b 1 |a -1 |sat 1}} rule slow 20 {draw{} slow{ r 1 s .9991 b .03| a .03| h -1}} rule slow {time{|sat -1}} //IMAGING rule draw{ SQUARE[z 0 x 1 s .27 .018 x -.5 a 1 h 1|] stars{z 1 x .91} cloud[z 2 x .83 s .17 x .5 h .7| a 1 sat .3|] ground[z 3 x .73 s .1 x .5] } rule ground{ SQUARE[s 1 .18 a 1 b -.5] highlight{s 1 .14} stuff{z 1} } rule stuff 5 {block[z 79 x .5 s .7225 .2 x -.5 a 1]} rule stuff {bush[z 86 x -.5 s 1.62 r -90 b -.7| a 1]} rule stuff {} rule block 2 {block{b -.1|}} rule block 3 {block[z -4 x .5 s .7225 x -.5 b .4|]} rule block 1 {block2{} block[z -4 x .5 s .64 x -.5 b .4|]} rule block2 {block3[x -.5 s .5 x .5 h 12]} rule block2 {block3[x -.5 s .5 x .5 h -12]} rule block3{SQUARE{} gleam{}} rule gleam{} rule gleam 2 {highlight{a 1}} rule highlight{SQUARE[z 50 x .5 s .02 1 x -.5 b 1]} rule bush 2 {bush[z -2 y .617 s .85 y -.617 b .3|]} rule bush {tree{h 180 sat -.4 b -.7}} rule tree { SQUARE{y .08 s .064 .16} fork{y .155} fork{y .155 f 90} } rule branch{tree{}} rule branch 3 { SQUARE{y .192 s .064 .384} fork{y .38} fork{y .38 f 90} } rule fork{branch{r 22 s .7}} rule fork{branch{r 33 s .7}} rule fork 0.2 {} rule stars {} rule stars 6 {star1{sat -1 h .99|} stars{}} rule star1 {star1{sat .12}} rule star1 6 {star1{r 139}} rule star1 {star2{}} rule star2 {star3{x .05 s .8}} rule star2 {star3{}} rule star3 9 {star3{s .8}} rule star3 {CIRCLE{x .03 s .007 b 1 h -.55|}} rule cloud 25 {} rule cloud{puff[ x -.6 s .25 .6 x .5 a -.95 h 170 sat .2]} rule puff 7 {TRIANGLE{} puff{x .5 r 20 s .91}} rule puff { TRIANGLE{} puff{x .5 f 0 s .91}} rule puff 5 {puff{x .5 r 20 s .9} puff{z 1 s .9 sat -.2 b .02}} 



Code
 //CKL startshape MAIN CF::Background = [hue 0 sat 0.84 b -0.9] CF::MinimumSize = 1 // how far to move each tree part in the local Y axis GTreePartMove = 0.02 // how much to scale each successive tree part GTreePartScale = 0.990 // Min and max length for the size of the trunk MaxTrunkDepth() = randint(10,40) // Min and max length for a branch coming off the trunk MaxTrunkBranchDepth() = randint(20,90) // Min and max length for a leaf branch MaxLeafBranchDepth() = randint(50,200) // returns a random int between (-High,-Low) and (Low,High) RandRange(Low,High) = select( randint(), -1, 1 ) * randint(Low,High) // Returns a rotation angle for a new branch NewBranchRotation() = randint(25,50) // Returns a random scale for a new branch NewBranchScale() = rand(0.6,0.9) NewStemRotation() = RandRange(30,50) NewSteamScale() = rand(0.4,0.6) LeafScale(Depth) = Depth / 250 // returns a random rotaiton amount of a single branch, to give them a less rigid shape BranchTwistSmall() = randint(10) - 5 BranchTwistLarge() = RandRange(10,25) shape MAIN rule 1 { SKY [ z -2 s 100 ] SUN [ z -1 s 400 ] TREE [ x -0.1 y -0.75 ] GRASS [ x -1 y -1 ] } shape SKY rule 1 { CIRCLE [ s rand(0.02,0.04) rand(0.01,0.03) sat 1 a -0.02 ] SKY [ s 0.9990 b 0.0005 hue 0.018 a -0.001 ] } shape SUN rule 1 { CIRCLE [ s rand(0.001,0.002) sat 0.84 b 1 a -0.95 ] SUN [[ r 40 s 0.9990 y 0.0001 hue (0.02,48) ]] } shape GRASS rule 1 { loop 20 [ y 0.01 ] loop 200 [ x 0.01 ] GRASSBLADE [ x rand(0.02) y rand(0.1) ] } shape GRASSBLADE rule 1 { CIRCLE [ s 0.02 a -0.9 ] GRASSBLADE [ y 0.01 s 0.95 r BranchTwistSmall() ] } shape TREE rule 1 { TRUNK( 0, MaxTrunkDepth() ) [ r ( randint(20) - 10 ) ] } shape TRUNK( natural Depth, natural EndDepth ) rule 20 { TreePart[] if ( Depth > EndDepth ) { TRUNKSPLIT(Depth) [] } else { TRUNK( Depth + 1, EndDepth ) [ y GTreePartMove s GTreePartScale] } } rule 5 { TRUNK( Depth + 1, EndDepth ) [ r BranchTwistSmall() ] } shape TRUNKSPLIT( natural Depth ) rule 1 { // split right TRUNKBRANCH( Depth, Depth + MaxTrunkBranchDepth() ) [ r NewBranchRotation() s NewBranchScale() ] TRUNKBRANCH( Depth, Depth + MaxTrunkBranchDepth() ) [ r randint(-20,0) s NewBranchScale() ] } rule 1 { // split left TRUNKBRANCH( Depth, Depth + MaxTrunkBranchDepth() ) [ r -NewBranchRotation() s NewBranchScale() ] TRUNKBRANCH( Depth, Depth + MaxTrunkBranchDepth() ) [ r -randint(-20,0) s NewBranchScale() ] } shape TRUNKBRANCH( natural Depth, natural EndDepth ) rule 1000 { TreePart[] if ( Depth > EndDepth ) { TRUNKBRANCHSPLIT(Depth) [] } else { TRUNKBRANCH( Depth + 1, EndDepth ) [ y GTreePartMove s GTreePartScale] } } rule 200 { TRUNKBRANCH( Depth + 1, EndDepth ) [ r BranchTwistSmall() ] } rule 50 { TRUNKBRANCH( Depth + 1, EndDepth ) [ r BranchTwistLarge() ] } rule 1 { TRUNKBRANCH( Depth + 1, EndDepth ) [ ] LEAFBUNCH( Depth ) [ r NewBranchRotation() ] } rule 1 { TRUNKBRANCH( Depth + 1, EndDepth ) [ ] LEAFBUNCH( Depth ) [ r -NewBranchRotation() ] } shape TRUNKBRANCHSPLIT( natural Depth ) rule 1 { // split right LEAFBRANCH( Depth, Depth + MaxLeafBranchDepth() ) [ r NewBranchRotation() s NewBranchScale() ] LEAFBRANCH( Depth, Depth + MaxLeafBranchDepth() ) [ r randint(-20,0) s NewBranchScale() ] } rule 1 { // split left LEAFBRANCH( Depth, Depth + MaxLeafBranchDepth() ) [ r -NewBranchRotation() s NewBranchScale() ] LEAFBRANCH( Depth, Depth + MaxLeafBranchDepth() ) [ r -randint(-20,0) s NewBranchScale() ] } shape LEAFBRANCH( natural Depth, natural EndDepth ) rule 50 { TreePart[] if ( Depth > EndDepth ) { //TRUNKBRANCHSPLIT(Depth) [] } else { LEAFBRANCH( Depth + 1, EndDepth ) [ y GTreePartMove s GTreePartScale] } } rule 50 { LEAFBRANCH( Depth + 1, EndDepth ) [ r BranchTwistSmall() ] } rule 5 { LEAFBUNCH( Depth ) [] } //rule 1 { // TRUNKBRANCHSPLIT(Depth) [] //} shape LEAFBUNCH( natural Depth ) rule 100 { TreePart [ ] LEAFBUNCH( Depth + 1 ) [ y GTreePartMove s GTreePartScale a -0.01 r BranchTwistSmall() ] } rule 25 { LEAFSTEM( Depth ) [ r NewStemRotation() s NewSteamScale() ] LEAFBUNCH( Depth ) [] } rule 1 { // split right LEAFBUNCH( Depth ) [ r NewBranchRotation() s NewBranchScale() ] LEAFBUNCH( Depth ) [ r randint(-20,0) s NewBranchScale() ] } rule 1 { // split left LEAFBUNCH( Depth ) [ r -NewBranchRotation() s NewBranchScale() ] LEAFBUNCH( Depth ) [ r -randint(-20,0) s NewBranchScale() ] } shape LEAFSTEM( natural Depth ) rule 100 { TreePart [] LEAFSTEM( Depth + 1 ) [ y GTreePartMove s 0.98 a -0.05 ] } rule 25 { LEAFSTEM( Depth + 1 ) [ r BranchTwistSmall() ] } rule 25 { LEAF(Depth) [ r BranchTwistSmall() ] LEAFSTEM(Depth) [] } shape LEAF( natural Depth ) rule 1 { LEAFSTAMP [[ s LeafScale(Depth) y 0.5 ]] } shape LEAFSTAMP rule 1 { CIRCLE [ a -0.1 s rand(0.1,0.8) 1 ] } shape TreePart rule 1 { CIRCLE [ s 0.1 ] CIRCLE [ s 0.1 x +0.005 a -0.9 ] CIRCLE [ s 0.1 x -0.005 a -0.9 ] CIRCLE [ s 0.1 x +0.0075 a -0.9 ] CIRCLE [ s 0.1 x -0.0075 a -0.9 ] CIRCLE [ s 0.1 x +0.0125 a -0.9 ] CIRCLE [ s 0.1 x -0.0125 a -0.9 ] } 


The Context Free program is distributed under the GPL license, you can download it here (Win / Mac / Linux), documentation .

We add that this is not the only initiative to create a convenient grammar for image generation. For example, here is the open source project Structure Synth for 3D graphics.

UPD. It turns out that they wrote about Context Free on Habré already in 2008 ! Thank you Imposeren for the link.

Source: https://habr.com/ru/post/137264/


All Articles