Barnsley fern

From Rosetta Code
Task
Barnsley fern
You are encouraged to solve this task according to the task description, using any language you may know.

A Barnsley fern is a fractal named after British mathematician Michael Barnsley and can be created using an iterated function system (IFS).


Task

Create this fractal fern, using the following transformations:

  • ƒ1   (chosen 1% of the time)
        xn + 1 = 0
        yn + 1 = 0.16 yn
  • ƒ2   (chosen 85% of the time)
        xn + 1 = 0.85 xn + 0.04 yn
        yn + 1 = −0.04 xn + 0.85 yn + 1.6
  • ƒ3   (chosen 7% of the time)
        xn + 1 = 0.2 xn − 0.26 yn
        yn + 1 = 0.23 xn + 0.22 yn + 1.6
  • ƒ4   (chosen 7% of the time)
        xn + 1 = −0.15 xn + 0.28 yn
        yn + 1 = 0.26 xn + 0.24 yn + 0.44.

Starting position: x = 0, y = 0

Action!

<lang Action!>INCLUDE "H6:REALMATH.ACT"

BYTE CH=$02FC,COLOR1=$02C5,COLOR2=$02C6 REAL r0,r4,r15,r16,r20,r22,r23,r24,r26,r28,r44,r85,r160

PROC Init()

 ValR("0",r0)
 ValR("0.04",r4)
 ValR("0.15",r16)
 ValR("0.16",r16)
 ValR("0.2",r20)
 ValR("0.22",r22)
 ValR("0.23",r23)
 ValR("0.24",r24)
 ValR("0.26",r26)
 ValR("0.28",r28)
 ValR("0.44",r44)
 ValR("0.85",r85)
 ValR("1.6",r160)

RETURN

PROC Fern(REAL POINTER scale)

 BYTE r
 REAL x,y,xp,yp,tmp1,tmp2
 INT i,ix,iy
 RealAssign(r0,x)
 RealAssign(r0,y)
 DO
   RealMult(x,scale,tmp1)
   RealMult(y,scale,tmp2)
   ix=Round(tmp2) ;fern is rotated to fit the screen size
   iy=Round(tmp1)+85
   IF (ix>=0) AND (ix<=319) AND (iy>=0) AND (iy<=191) THEN
     Plot(ix,iy)
   FI
   r=Rand(100)
   RealAssign(x,xp) ;xp=x
   RealAssign(y,yp) ;yp=y
   IF r<1 THEN
     RealAssign(r0,x)   ;x=0
     RealMult(r16,yp,y) ;y=0.16*yp
   ELSEIF r<86 THEN
     RealMult(r85,xp,tmp1) ;tmp1=0.85*xp
     RealMult(r4,yp,tmp2)  ;tmp2=0.4*yp
     RealAdd(tmp1,tmp2,x)  ;x=0.85*xp+0.4*yp
     RealMult(r4,xp,tmp1)    ;tmp1=0.04*xp
     RealSub(r160,tmp1,tmp2) ;tmp2=-0.04*xp+1.6
     RealMult(r85,yp,tmp1)   ;tmp1=0.85*yp
     RealAdd(tmp1,tmp2,y)    ;y=-0.04*xp+0.85*yp+1.6
   ELSEIF r<93 THEN
     RealMult(r20,xp,tmp1) ;tmp1=0.2*xp
     RealMult(r26,yp,tmp2) ;tmp2=0.26*yp
     RealSub(tmp1,tmp2,x)  ;x=0.2*xp-0.26*yp
     RealMult(r23,xp,tmp1)   ;tmp1=0.23*xp
     RealAdd(r160,tmp1,tmp2) ;tmp2=0.23*xp+1.6
     RealMult(r22,yp,tmp1)   ;tmp1=0.22*yp
     RealAdd(tmp1,tmp2,y)    ;y=0.23*xp+0.22*yp+1.6
   ELSE
     RealMult(r15,xp,tmp1) ;tmp1=0.15*xp
     RealMult(r28,yp,tmp2) ;tmp2=0.28*yp
     RealSub(tmp2,tmp1,x)  ;x=-0.15*xp+0.28*yp
     RealMult(r26,xp,tmp1)  ;tmp1=0.26*xp
     RealAdd(r44,tmp1,tmp2) ;tmp2=0.26*xp+0.44
     RealMult(r24,yp,tmp1)  ;tmp1=0.24*yp
     RealAdd(tmp1,tmp2,y)   ;y=0.26*xp+0.44*yp+0.44
   FI
   Poke(77,0) ;turn off the attract mode
 UNTIL CH#$FF ;until key pressed
 OD
 CH=$FF

RETURN

PROC Main()

 REAL scale
 Graphics(8+16)
 Color=1
 COLOR1=$BA
 COLOR2=$B2
 Init()
 ValR("30",scale)
 Fern(scale)

RETURN</lang>

Output:

Screenshot from Atari 8-bit computer

Ada

Library: SDLAda

<lang Ada>with Ada.Numerics.Discrete_Random;

with SDL.Video.Windows.Makers; with SDL.Video.Renderers.Makers; with SDL.Events.Events;

procedure Barnsley_Fern is

  Iterations : constant := 1_000_000;
  Width      : constant := 500;
  Height     : constant := 750;
  Scale      : constant := 70.0;
  type Percentage is range 1 .. 100;
  package Random_Percentages is
     new Ada.Numerics.Discrete_Random (Percentage);
  Gen      : Random_Percentages.Generator;
  Window   : SDL.Video.Windows.Window;
  Renderer : SDL.Video.Renderers.Renderer;
  Event    : SDL.Events.Events.Events;
  procedure Draw_Barnsley_Fern is
     use type SDL.C.int;
     subtype F1_Range is Percentage range Percentage'First  .. Percentage'First;
     subtype F2_Range is Percentage range F1_Range'Last + 1 .. F1_Range'Last + 85;
     subtype F3_Range is Percentage range F2_Range'Last + 1 .. F2_Range'Last + 7;
     subtype F4_Range is Percentage range F3_Range'Last + 1 .. F3_Range'Last + 7;
     X0, Y0 : Float := 0.00;
     X1, Y1 : Float;
  begin
     for I in 1 .. Iterations loop
        case Random_Percentages.Random (Gen) is
           when F1_Range =>
              X1 := 0.00;
              Y1 := 0.16 * Y0;
           when F2_Range =>
              X1 :=  0.85 * X0 + 0.04 * Y0;
              Y1 := -0.04 * X0 + 0.85 * Y0 + 1.60;
           when F3_Range =>
              X1 := 0.20 * X0 - 0.26 * Y0;
              Y1 := 0.23 * X0 + 0.22 * Y0 + 1.60;
           when F4_Range =>
              X1 := -0.15 * X0 + 0.28 * Y0;
              Y1 :=  0.26 * X0 + 0.24 * Y0 + 0.44;
        end case;
        Renderer.Draw (Point => (X => Width / 2 + SDL.C.int (Scale * X1),
                                 Y => Height    - SDL.C.int (Scale * Y1)));
        X0 := X1; Y0 := Y1;
     end loop;
  end Draw_Barnsley_Fern;
  procedure Wait is
     use type SDL.Events.Event_Types;
  begin
     loop
        while SDL.Events.Events.Poll (Event) loop
           if Event.Common.Event_Type = SDL.Events.Quit then
              return;
           end if;
        end loop;
     end loop;
  end Wait;

begin

  if not SDL.Initialise (Flags => SDL.Enable_Screen) then
     return;
  end if;
  SDL.Video.Windows.Makers.Create (Win      => Window,
                                   Title    => "Barnsley Fern",
                                   Position => SDL.Natural_Coordinates'(X => 10, Y => 10),
                                   Size     => SDL.Positive_Sizes'(Width, Height),
                                   Flags    => 0);
  SDL.Video.Renderers.Makers.Create  (Renderer, Window.Get_Surface);
  Renderer.Set_Draw_Colour ((0, 0, 0, 255));
  Renderer.Fill (Rectangle => (0, 0, Width, Height));
  Renderer.Set_Draw_Colour ((0, 220, 0, 255));
  Random_Percentages.Reset (Gen);
  Draw_Barnsley_Fern;
  Window.Update_Surface;
  Wait;
  Window.Finalize;
  SDL.Finalise;

end Barnsley_Fern;</lang>

ALGOL 68

Works with: ALGOL 68G version any with non-standard establish routine

This program generates a PBM file. <lang algol68> BEGIN

 INT iterations = 300000;
 LONG REAL scale x = 40, scale y = 40;
 [0:400,-200:200]CHAR canvas;
 LONG REAL x := 0, y := 0;
 FOR i FROM 1 LWB canvas TO 1 UPB canvas DO
   FOR j FROM 2 LWB canvas TO 2 UPB canvas DO
     canvas[i,j] := "0"
 OD OD;
 canvas[0, 0] := "1";
 TO iterations DO
   REAL choice := random;
   LONG REAL xn = x, yn = y;
   IF choice < 0.01 THEN
     x := 0;
     y := 0.16 * yn
   ELIF (choice -:= 0.01) < 0.85 THEN
     x :=  0.85 * xn + 0.04 * yn;
     y := -0.04 * xn + 0.85 * yn + 1.6
   ELIF (choice -:= 0.85) < 0.07 THEN
     x := 0.2  * xn - 0.26 * yn;
     y := 0.23 * xn + 0.22 * yn + 1.6
   ELSE
     x := -0.15 * xn + 0.28 * yn;
     y :=  0.26 * xn + 0.24 * yn + 0.44
   FI;
   INT px = SHORTEN ROUND (x * scale x),
       py = SHORTEN ROUND (y * scale y);
   IF px < 2 LWB canvas OR px > 2 UPB canvas OR
      py < 1 LWB canvas OR py > 1 UPB canvas
   THEN
     print(("resize canvas. px=", px, ", py=", py, new line));
     leave
   FI;
   canvas[py, px] := "1"
 OD;
 FILE f;
 IF establish(f, "fern.pbm", stand out channel) /= 0 THEN
   print("error creating file!"); leave
 FI;
 put(f, "P1"); new line(f);
 put(f, (whole((2 UPB canvas) - (2 LWB canvas) + 1, 0), " ",
         whole((1 UPB canvas) - (1 LWB canvas) + 1, 0), new line));
 FOR i FROM 1 UPB canvas BY -1 TO 1 LWB canvas DO
   put(f, canvas[i,]); new line(f)
 OD;
 close(f);
 leave: SKIP

END </lang>

Applesoft BASIC

<lang ApplesoftBasic> 100 LET YY(1) = .16

110  XX(2) =    .85:XY(2) = .04
120  YX(2) =  - .04:YY(2) = .85
130  LET Y(2) = 1.6
140  XX(3) = .20:XY(3) =  - .26
150  YX(3) = .23:YY(3) =    .22
160  LET Y(3) = 1.6
170  XX(4) =  - .15:XY(4) = .28
180  YX(4) =    .26:YY(4) = .24
190  LET Y(4) = .44
200  HGR :I =  PEEK (49234)
210  HCOLOR= 1
220  LET X = 0:Y = 0
230  FOR I = 1 TO 100000
240      R =  INT ( RND (1) * 100)
250      F = (R < 7) + (R < 14) + 2
260      F = F - (R = 99)
270      X = XX(F) * X + XY(F) * Y
280      Y = YX(F) * X + YY(F) * Y
290      Y = Y + Y(F)
300      X% = 62 + X * 27.9
320      Y% = 192 - Y * 19.1
330      HPLOT X% * 2 + 1,Y%
340  NEXT

</lang>

BBC BASIC

<lang bbcbasic> GCOL 2 : REM Green Graphics Color

     X=0 : Y=0
     FOR I%=1 TO 100000
       R%=RND(100)
       CASE TRUE OF
         WHEN R% == 1 NewX= 0                 : NewY= .16 * Y
         WHEN R% <  9 NewX= .20 * X - .26 * Y : NewY= .23 * X + .22 * Y + 1.6
         WHEN R% < 16 NewX=-.15 * X + .28 * Y : NewY= .26 * X + .24 * Y + .44
         OTHERWISE    NewX= .85 * X + .04 * Y : NewY=-.04 * X + .85 * Y + 1.6
       ENDCASE
       X=NewX : Y=NewY
       PLOT 1000 + X * 130 , Y * 130
     NEXT
     END</lang>

C

This implementation requires the WinBGIm library. Iteration starts from (0,0) as required by the task however before plotting the point is translated and scaled as negative co-ordinates are not supported by the graphics window, scaling is necessary as otherwise the fern is tiny even for large iterations ( > 1000000). <lang C>

  1. include<graphics.h>
  2. include<stdlib.h>
  3. include<stdio.h>
  4. include<time.h>

void barnsleyFern(int windowWidth, unsigned long iter){

double x0=0,y0=0,x1,y1; int diceThrow; time_t t; srand((unsigned)time(&t));

while(iter>0){ diceThrow = rand()%100;

if(diceThrow==0){ x1 = 0; y1 = 0.16*y0; }

else if(diceThrow>=1 && diceThrow<=7){ x1 = -0.15*x0 + 0.28*y0; y1 = 0.26*x0 + 0.24*y0 + 0.44; }

else if(diceThrow>=8 && diceThrow<=15){ x1 = 0.2*x0 - 0.26*y0; y1 = 0.23*x0 + 0.22*y0 + 1.6; }

else{ x1 = 0.85*x0 + 0.04*y0; y1 = -0.04*x0 + 0.85*y0 + 1.6; }

putpixel(30*x1 + windowWidth/2.0,30*y1,GREEN);

x0 = x1; y0 = y1;

iter--; }

}

int main() { unsigned long num;

printf("Enter number of iterations : "); scanf("%ld",&num);

initwindow(500,500,"Barnsley Fern");

barnsleyFern(500,num);

getch();

closegraph();

return 0; } </lang>

C#

<lang csharp>using System; using System.Diagnostics; using System.Drawing;

namespace RosettaBarnsleyFern {

   class Program
   {
       static void Main(string[] args)
       {
           const int w = 600;
           const int h = 600;
           var bm = new Bitmap(w, h);
           var r = new Random();
           double x = 0;
           double y = 0;
           for (int count = 0; count < 100000; count++)
           {
               bm.SetPixel((int)(300 + 58 * x), (int)(58 * y), Color.ForestGreen);
               int roll = r.Next(100);
               double xp = x;
               if (roll < 1)
               {
                   x = 0;
                   y = 0.16 * y;
               } else if (roll < 86)
               {
                   x = 0.85 * x + 0.04 * y;
                   y = -0.04 * xp + 0.85 * y + 1.6;
               } else if (roll < 93)
               {
                   x = 0.2 * x - 0.26 * y;
                   y = 0.23 * xp + 0.22 * y + 1.6;
               } else
               {
                   x = -0.15 * x + 0.28 * y;
                   y = 0.26 * xp + 0.24 * y + 0.44;
               }
           }
           const string filename = "Fern.png";
           bm.Save(filename);
           Process.Start(filename);
       }
   }

}</lang>

C++

<lang cpp>

  1. include <windows.h>
  2. include <ctime>
  3. include <string>

const int BMP_SIZE = 600, ITERATIONS = static_cast<int>( 15e5 );

class myBitmap { public:

   myBitmap() : pen( NULL ), brush( NULL ), clr( 0 ), wid( 1 ) {}
   ~myBitmap() {
       DeleteObject( pen ); DeleteObject( brush );
       DeleteDC( hdc ); DeleteObject( bmp );
   }
   bool create( int w, int h ) {
       BITMAPINFO bi;
       ZeroMemory( &bi, sizeof( bi ) );
       bi.bmiHeader.biSize        = sizeof( bi.bmiHeader );
       bi.bmiHeader.biBitCount    = sizeof( DWORD ) * 8;
       bi.bmiHeader.biCompression = BI_RGB;
       bi.bmiHeader.biPlanes      = 1;
       bi.bmiHeader.biWidth       =  w;
       bi.bmiHeader.biHeight      = -h;
       HDC dc = GetDC( GetConsoleWindow() );
       bmp = CreateDIBSection( dc, &bi, DIB_RGB_COLORS, &pBits, NULL, 0 );
       if( !bmp ) return false;
       hdc = CreateCompatibleDC( dc );
       SelectObject( hdc, bmp );
       ReleaseDC( GetConsoleWindow(), dc );
       width = w; height = h;
       return true;
   }
   void clear( BYTE clr = 0 ) {
       memset( pBits, clr, width * height * sizeof( DWORD ) );
   }
   void setBrushColor( DWORD bClr ) {
       if( brush ) DeleteObject( brush );
       brush = CreateSolidBrush( bClr );
       SelectObject( hdc, brush );
   }
   void setPenColor( DWORD c ) {
       clr = c; createPen();
   }
   void setPenWidth( int w ) {
       wid = w; createPen();
   }
   void saveBitmap( std::string path ) {
       BITMAPFILEHEADER fileheader;
       BITMAPINFO       infoheader;
       BITMAP           bitmap;
       DWORD            wb;
       GetObject( bmp, sizeof( bitmap ), &bitmap );
       DWORD* dwpBits = new DWORD[bitmap.bmWidth * bitmap.bmHeight];
       ZeroMemory( dwpBits, bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD ) );
       ZeroMemory( &infoheader, sizeof( BITMAPINFO ) );
       ZeroMemory( &fileheader, sizeof( BITMAPFILEHEADER ) );
       infoheader.bmiHeader.biBitCount = sizeof( DWORD ) * 8;
       infoheader.bmiHeader.biCompression = BI_RGB;
       infoheader.bmiHeader.biPlanes = 1;
       infoheader.bmiHeader.biSize = sizeof( infoheader.bmiHeader );
       infoheader.bmiHeader.biHeight = bitmap.bmHeight;
       infoheader.bmiHeader.biWidth = bitmap.bmWidth;
       infoheader.bmiHeader.biSizeImage = bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD );
       fileheader.bfType    = 0x4D42;
       fileheader.bfOffBits = sizeof( infoheader.bmiHeader ) + sizeof( BITMAPFILEHEADER );
       fileheader.bfSize    = fileheader.bfOffBits + infoheader.bmiHeader.biSizeImage;
       GetDIBits( hdc, bmp, 0, height, ( LPVOID )dwpBits, &infoheader, DIB_RGB_COLORS );
       HANDLE file = CreateFile( path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 
           FILE_ATTRIBUTE_NORMAL, NULL );
       WriteFile( file, &fileheader, sizeof( BITMAPFILEHEADER ), &wb, NULL );
       WriteFile( file, &infoheader.bmiHeader, sizeof( infoheader.bmiHeader ), &wb, NULL );
       WriteFile( file, dwpBits, bitmap.bmWidth * bitmap.bmHeight * 4, &wb, NULL );
       CloseHandle( file );
       delete [] dwpBits;
   }
   HDC getDC() const     { return hdc; }
   int getWidth() const  { return width; }
   int getHeight() const { return height; }

private:

   void createPen() {
       if( pen ) DeleteObject( pen );
       pen = CreatePen( PS_SOLID, wid, clr );
       SelectObject( hdc, pen );
   }
   HBITMAP bmp; HDC    hdc;
   HPEN    pen; HBRUSH brush;
   void    *pBits; int    width, height, wid;
   DWORD    clr;

}; class fern { public:

   void draw() {
       bmp.create( BMP_SIZE, BMP_SIZE );
       float x = 0, y = 0; HDC dc = bmp.getDC();
       int hs = BMP_SIZE >> 1;
       for( int f = 0; f < ITERATIONS; f++ ) {
           SetPixel( dc, hs + static_cast<int>( x * 55.f ), 
                     BMP_SIZE - 15 - static_cast<int>( y * 55.f ), 
                     RGB( static_cast<int>( rnd() * 80.f ) + 20, 
                          static_cast<int>( rnd() * 128.f ) + 128, 
                          static_cast<int>( rnd() * 80.f ) + 30 ) ); 
           getXY( x, y );
       }
       bmp.saveBitmap( "./bf.bmp" );
   }

private:

   void getXY( float& x, float& y ) {
       float g, xl, yl;
       g = rnd();
       if( g < .01f ) { xl = 0; yl = .16f * y; } 
       else if( g < .07f ) {
           xl = .2f * x - .26f * y;
           yl = .23f * x + .22f * y + 1.6f;
       } else if( g < .14f ) {
           xl = -.15f * x + .28f * y;
           yl = .26f * x + .24f * y + .44f;
       } else {
           xl = .85f * x + .04f * y;
           yl = -.04f * x + .85f * y + 1.6f;
       }
       x = xl; y = yl;
   }
   float rnd() {
       return static_cast<float>( rand() ) / static_cast<float>( RAND_MAX );
   }
   myBitmap bmp;

}; int main( int argc, char* argv[]) {

   srand( static_cast<unsigned>( time( 0 ) ) );
   fern f; f.draw(); return 0;    

} </lang>

Cross-Platform Alternative

Library: Qt

This version uses the QImage class from the Qt toolkit as an easy way to save an image in PNG format. It also uses the C++ 11 random number library. Built and tested on macOS 10.15.4 with Qt 5.12.5. <lang cpp>#include <iostream>

  1. include <random>
  2. include <vector>
  1. include <QImage>

bool barnsleyFern(const char* fileName, int width, int height) {

   constexpr int iterations = 1000000;
   int bytesPerLine = 4 * ((width + 3)/4);
   std::vector<uchar> imageData(bytesPerLine * height);
   std::random_device dev;
   std::mt19937 engine(dev());
   std::uniform_int_distribution<int> distribution(1, 100);
   double x = 0, y = 0;
   for (int i = 0; i < iterations; ++i) {
       int r = distribution(engine);
       double x1, y1;
       if (r == 1) {
           x1 = 0;
           y1 = 0.16 * y;
       } else if (r <= 86) {
           x1 = 0.85 * x + 0.04 * y;
           y1 = -0.04 * x + 0.85 * y + 1.6;
       } else if (r <= 93) {
           x1 = 0.2 * x - 0.26 * y;
           y1 = 0.23 * x + 0.22 * y + 1.6;
       } else {
           x1 = -0.15 * x + 0.28 * y;
           y1 = 0.26 * x + 0.24 * y + 0.44;
       }
       x = x1;
       y = y1;
       int row = height * (1 - y/11);
       int column = width * (0.5 + x/11);
       imageData[row * bytesPerLine + column] = 1;
   }
   QImage image(&imageData[0], width, height, bytesPerLine, QImage::Format_Indexed8);
   QVector<QRgb> colours(2);
   colours[0] = qRgb(255, 255, 255);
   colours[1] = qRgb(0, 160, 0);
   image.setColorTable(colours);
   return image.save(fileName);

}

int main(int argc, char *argv[]) {

   if (argc != 2) {
       std::cerr << "usage: " << argv[0] << " filename\n";
       return EXIT_FAILURE;
   }
   if (!barnsleyFern(argv[1], 600, 600)) {
       std::cerr << "image generation failed\n";
       return EXIT_FAILURE;
   }
   return EXIT_SUCCESS;

}</lang>

Output:

See: barnsley_fern.png (offsite PNG image)

Common Lisp

This code uses the opticl package for generating an image and saving it as a PNG file. <lang lisp>(defpackage #:barnsley-fern

 (:use #:cl
       #:opticl))

(in-package #:barnsley-fern)

(defparameter *width* 800) (defparameter *height* 800) (defparameter *factor* (/ *height* 13)) (defparameter *x-offset* (/ *width* 2)) (defparameter *y-offset* (/ *height* 10))

(defun f1 (x y)

 (declare (ignore x))
 (values 0 (* 0.16 y)))

(defun f2 (x y)

 (values (+ (*  0.85 x) (* 0.04 y))
         (+ (* -0.04 x) (* 0.85 y) 1.6)))

(defun f3 (x y)

 (values (+ (* 0.2  x) (* -0.26 y))
         (+ (* 0.23 x) (*  0.22 y) 1.6)))

(defun f4 (x y)

 (values (+ (* -0.15 x) (* 0.28 y))
         (+ (*  0.26 x) (* 0.24 y) 0.44)))

(defun choose-transform ()

 (let ((r (random 1.0)))
   (cond ((< r 0.01) #'f1)
         ((< r 0.86) #'f2)
         ((< r 0.93) #'f3)
         (t          #'f4))))

(defun set-pixel (image x y)

 (let ((%x (round (+ (* *factor* x) *x-offset*)))
       (%y (round (- *height* (* *factor* y) *y-offset*))))
   (setf (pixel image %y %x) (values 0 255 0))))

(defun fern (filespec &optional (iterations 10000000))

 (let ((image (make-8-bit-rgb-image *height* *width* :initial-element 0))
       (x 0)
       (y 0))
   (dotimes (i iterations)
     (set-pixel image x y)
     (multiple-value-setq (x y) (funcall (choose-transform) x y)))
   (write-png-file filespec image)))</lang>

D

Translation of: Raku
Library: dlib

<lang d>#!/usr/bin/env dub /+ dub.sdl: dependency "dlib" version="~>0.21.0" +/ import std.random;

import dlib.image;

void main() { enum WIDTH = 640; enum HEIGHT = 640; enum ITERATIONS = 2E6;

float x = 0.0f; float y = 0.0f;

auto rng = Random(unpredictableSeed); auto color = Color4f(0.0f, 1.0f, 0.0f); auto img = image(WIDTH, HEIGHT);

foreach (_; 0..ITERATIONS) { auto r = uniform(0, 101, rng);

if (r <= 1) { x = 0.0; y = 0.16 * y; } else { if (r <= 8) { x = 0.20 * x - 0.26 * y; y = 0.23 * x + 0.22 * y + 1.60; } else { if (r <= 15) { x = -0.15 * x + 0.28 * y; y = 0.26 * x + 0.24 * y + 0.44; } else { x = 0.85 * x + 0.04 * y; y = -0.04 * x + 0.85 * y + 1.6; } } } auto X = cast(int) (WIDTH / 2.0 + x * 60); auto Y = HEIGHT - cast(int)(y * 60); img[X, Y] = color; } img.saveImage(`barnsley_dlib.png`); }</lang>

Delphi

Translation of: Java

Hint: After putting a TPaintBox on the main form align it to alClient. Client width / height of the main form should be no less than 640 x 480. <lang delphi>unit Unit1;

interface

uses

 Windows, SysUtils, Graphics, Forms, Controls, Classes, ExtCtrls;

type

 TForm1 = class(TForm)
   PaintBox1: TPaintBox;
   procedure FormPaint(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var

 Form1: TForm1;

implementation

{$R *.dfm}

procedure CreateFern(const w, h: integer); var r, x, y: double;

   tmpx, tmpy: double;
   i: integer;

begin

   x := 0;
   y := 0;
   randomize();
   for i := 0 to 200000 do begin
       r := random(100000000) / 99999989;
       if r <= 0.01 then begin
           tmpx := 0;
           tmpy := 0.16 * y;
       end
       else if r <= 0.08 then begin
           tmpx := 0.2 * x - 0.26 * y;
           tmpy := 0.23 * x + 0.22 * y + 1.6;
       end
       else if r <= 0.15 then begin
           tmpx := -0.15 * x + 0.28 * y;
           tmpy := 0.26 * x + 0.24 * y + 0.44;
       end
       else begin
           tmpx := 0.85 * x + 0.04 * y;
           tmpy := -0.04 * x + 0.85 * y + 1.6;
       end;
       x := tmpx;
       y := tmpy;
       Form1.PaintBox1.Canvas.Pixels[round(w / 2 + x * w / 11), round(h - y * h / 11)] := clGreen;
   end;

end;

procedure TForm1.FormPaint(Sender: TObject); begin

   CreateFern(Form1.ClientWidth, Form1.ClientHeight);

end;

end.</lang>

EasyLang

Run it

<lang>color 060 for i range 200000

 r = randomf
 if r < 0.01
   nx = 0
   ny = 0.16 * y
 elif r < 0.08
   nx = 0.2 * x - 0.26 * y
   ny = 0.23 * x + 0.22 * y + 1.6
 elif r < 0.15
   nx = -0.15 * x + 0.28 * y
   ny = 0.26 * x + 0.24 * y + 0.44
 else
   nx = 0.85 * x + 0.04 * y
   ny = -0.04 * x + 0.85 * y + 1.6
 .
 x = nx
 y = ny
 move 50 + x * 15 100 - y * 10
 rect 0.3 0.3

.</lang>

F#

<lang fsharp> open System.Drawing

let (|F1|F2|F3|F4|) r =

   if r < 0.01 then F1
   else if r < 0.08 then F3
   else if r < 0.15 then F4
   else F2
   

let barnsleyFernFunction (x, y) = function

   | F1 -> (0.0, 0.16*y)
   | F2 -> ((0.85*x + 0.04*y), (-0.04*x + 0.85*y + 1.6))
   | F3 -> ((0.2*x - 0.26*y), (0.23*x + 0.22*y + 1.6))
   | F4 -> ((-0.15*x + 0.28*y), (0.26*x + 0.24*y + 0.44))
   

let barnsleyFern () =

   let rnd = System.Random()
   (0.0, 0.0)
   |> Seq.unfold (fun point -> Some (point, barnsleyFernFunction point (rnd.NextDouble())))
   

let run width height =

   let emptyBitmap = new Bitmap(int width,int height)
   let bitmap =
       barnsleyFern ()
       |> Seq.take 250000 // calculate points
       |> Seq.map (fun (x,y) -> (int (width/2.0+(width*x/11.0)), int (height-(height*y/11.0)))) // transform to pixels
       |> Seq.fold (fun (b:Bitmap) (x,y) -> b.SetPixel(x-1,y-1,Color.ForestGreen); b) emptyBitmap // add pixels to bitmap
   bitmap.Save("BFFsharp.png")

</lang>

Use:

<lang fsharp> BarnsleyFern.run 720 720 </lang>

Forth

Works with: gforth version 0.7.3
Library: SDL2

Fixed Point and Matrix solution

Traditionaly, Forth use Fixed-Point Arithmetic (here with a 1000 scale). For transformation function choice, a formula is used to pick coefficients in a matrix.

<lang forth> s" SDL2" add-lib \c #include <SDL2/SDL.h> c-function sdl-init SDL_Init n -- n c-function sdl-quit SDL_Quit -- void c-function sdl-createwindow SDL_CreateWindow a n n n n n -- a c-function sdl-createrenderer SDL_CreateRenderer a n n -- a c-function sdl-setdrawcolor SDL_SetRenderDrawColor a n n n n -- n c-function sdl-drawpoint SDL_RenderDrawPoint a n n -- n c-function sdl-renderpresent SDL_RenderPresent a -- void c-function sdl-delay SDL_Delay n -- void

require random.fs

0 value window 0 value renderer variable x variable y

initFern ( -- )
 $20 sdl-init drop
 s\" Rosetta Task : Barnsley fern\x0" drop 0 0 1000 1000 $0 sdl-createwindow to window
 window -1 $2 sdl-createrenderer to renderer
 renderer 0 255 0 255 sdl-setdrawcolor drop

create coefficients

            0 ,    0 ,   0 , 160 ,    0 ,    \  1% of the time - f1
          200 , -260 , 230 , 220 , 1600 ,    \  7% of the time - f3
         -150 ,  280 , 260 , 240 ,  440 ,    \  7% of the time - f4
          850 ,   40 , -40 , 850 , 1600 ,    \ 85% of the time - f2
nextcoeff ( n -- n+1 coeff ) coefficients over cells + @ swap 1+ swap ;
transformation ( n -- )
 nextcoeff x @ *   swap nextcoeff y @ *    rot + 1000 /   swap
 nextcoeff x @ *   swap nextcoeff y @ *    rot + 1000 /   swap nextcoeff rot +    y ! drop
 x !  \ x shall be modified after y calculation
randomchoice ( -- index )
 100 random
 dup 0 > swap
 dup 7 > swap
 dup 14 > swap drop
 + + negate 5 *
fern

initFern 20000 0 do

 randomchoice transformation
 renderer x @ 10 / 500 + y @ 10 / sdl-drawpoint drop

loop renderer sdl-renderpresent 5000 sdl-delay sdl-quit

fern</lang>

Floating Point and Multiple Functions solution

Forth may use a dedicated Floating Point Stack. For transformation, a pointer to one of the 4 functions is used to be be called at the end of the loop.

<lang forth> s" SDL2" add-lib \c #include <SDL2/SDL.h> c-function sdl-init SDL_Init n -- n c-function sdl-quit SDL_Quit -- void c-function sdl-createwindow SDL_CreateWindow a n n n n n -- a c-function sdl-createrenderer SDL_CreateRenderer a n n -- a c-function sdl-setdrawcolor SDL_SetRenderDrawColor a n n n n -- n c-function sdl-drawpoint SDL_RenderDrawPoint a n n -- n c-function sdl-renderpresent SDL_RenderPresent a -- void c-function sdl-delay SDL_Delay n -- void

require random.fs

0 value window 0 value renderer 0 value diceThrow fvariable x fvariable y variable transformation

initFern ( -- )
 $20 sdl-init drop
 s\" Rosetta Task : Barnsley fern\x0" drop 0 0 1000 1000 $0 sdl-createwindow to window
 window -1 $2 sdl-createrenderer to renderer
 renderer 0 255 0 255 sdl-setdrawcolor drop
closeFern sdl-quit ;
f1
 0e0 x f!
 y f@ 0.16e0 f* y f!
f2
 x f@  0.85e0 f* y f@ 0.040e0 f* f+
 x f@ -0.04e0 f* y f@ 0.850e0 f* f+ 1.600e0 f+   y f!
 x f!
f3
 x f@ 0.200e0 f* y f@ -0.260e0 f* f+
 x f@ 0.230e0 f* y f@  0.220e0 f* f+ 1.600e0 f+   y f!
 x f!
f4
 x f@ -0.150e0 f* y f@ 0.280e0 f* f+
 x f@  0.260e0 f* y f@ 0.240e0 f* f+  0.440e0 f+    y f!
 x f!
fern

initFern 0e0 x f! 0e0 y f! 20000 0 do

 renderer x f@ 50e0 f* f>s 500 + y f@ 50e0 f* f>s sdl-drawpoint drop
 100 random to diceThrow
 ['] f2 transformation !
 diceThrow 15 < if ['] f4 transformation ! then
 diceThrow 8 < if ['] f3 transformation ! then
 diceThrow 1 < if ['] f1 transformation ! then
 transformation @ execute

loop

 renderer sdl-renderpresent
 5000 sdl-delay

closeFern

fern</lang>


Fortran

<lang fortran> !Generates an output file "plot.dat" that contains the x and y coordinates !for a scatter plot that can be visualized with say, GNUPlot program BarnsleyFern implicit none

double precision :: p(4), a(4), b(4), c(4), d(4), e(4), f(4), trx, try, prob integer :: itermax, i

!The probabilites and coefficients can be modified to generate other !fractal ferns, e.g. http://www.home.aone.net.au/~byzantium/ferns/fractal.html !probabilities p(1) = 0.01; p(2) = 0.85; p(3) = 0.07; p(4) = 0.07

!coefficients a(1) = 0.00; a(2) = 0.85; a(3) = 0.20; a(4) = -0.15 b(1) = 0.00; b(2) = 0.04; b(3) = -0.26; b(4) = 0.28 c(1) = 0.00; c(2) = -0.04; c(3) = 0.23; c(4) = 0.26 d(1) = 0.16; d(2) = 0.85; d(3) = 0.22; d(4) = 0.24 e(1) = 0.00; e(2) = 0.00; e(3) = 0.00; e(4) = 0.00 f(1) = 0.00; f(2) = 1.60; f(3) = 1.60; f(4) = 0.44

itermax = 100000

trx = 0.0D0 try = 0.0D0

open(1, file="plot.dat") write(1,*) "#X #Y" write(1,'(2F10.5)') trx, try

do i = 1, itermax

 call random_number(prob)
 if (prob < p(1)) then
   trx = a(1) * trx + b(1) * try + e(1)
   try = c(1) * trx + d(1) * try + f(1)
 else if(prob < (p(1) + p(2))) then
   trx = a(2) * trx + b(2) * try + e(2)
   try = c(2) * trx + d(2) * try + f(2)
 else if ( prob < (p(1) + p(2) + p(3))) then
   trx = a(3) * trx + b(3) * try + e(3)
   try = c(3) * trx + d(3) * try + f(3)
 else
   trx = a(4) * trx + b(4) * try + e(4)
   try = c(4) * trx + d(4) * try + f(4)
 end if
 write(1,'(2F10.5)') trx, try

end do close(1) end program BarnsleyFern </lang>

FreeBASIC

<lang freebasic>' version 10-10-2016 ' compile with: fbc -s console

Sub barnsley(height As UInteger)

 Dim As Double x, y, xn, yn
 Dim As Double f = height / 10.6
 Dim As UInteger offset_x = height \ 4 - height \ 40
 Dim As UInteger n, r
 ScreenRes height \ 2, height, 32
 For n = 1 To height * 50
   r = Int(Rnd * 100)      ' f from 0 to 99
   Select Case As Const r
     Case 0 To 84
       xn  =  0.85 * x + 0.04 * y
       yn  = -0.04 * x + 0.85 * y + 1.6
     Case 85 To 91
       xn  = 0.2  * x - 0.26 * y
       yn  = 0.23 * x + 0.22 * y + 1.6
     Case 92 To 98
       xn  = -0.15 * x + 0.28 * y
       yn  =  0.26 * x + 0.24 * y + 0.44
     Case Else
       xn = 0
       yn = 0.16 * y
   End Select
   x = xn : y = yn
   PSet( offset_x + x * f, height - y * f), RGB(0, 255, 0)
 Next

' remove comment (') in next line to save window as .bmp file ' BSave "barnsley_fern_" + Str(height) + ".bmp", 0

End Sub


' ------=< MAIN >=------

' adjustable window height ' call the subroutine with the height you want ' it's possible to have a window that's large than your display

barnsley(800)


' empty keyboard buffer While Inkey <> "" : Wend Windowtitle "hit any key to end program" Sleep End</lang>

Frink

<lang Frink> g = new graphics g.backgroundColor[0,0,0] // black g.color[0,0.5,0] // green

x = 0 y = 0

for i = 1 to 100000 {

  g.fillEllipseCenter[x*10,y*-10,0.25,0.25]
  z = random[1, 100]
  if z == 1
  {
     xn = 0
     yn = 0.16 * y
  }
  if z >= 2 and z <= 86
  {
     xn = 0.85 * x + 0.04 * y
     yn = -0.04 * x + 0.85 * y + 1.6
  }
  if z >= 87 and z <= 93
  {
     xn = 0.2 * x - 0.26 * y
     yn = 0.23 * x + 0.22 * y + 1.6
  }
  if z >= 94 and z <= 100
  {
     xn = -0.15 * x + 0.28 * y
     yn = 0.26 * x + 0.24 * y + 0.44
  }
  x = xn
  y = yn

}

g.show[] </lang>

Fōrmulæ

Fōrmulæ programs are not textual, visualization/edition of programs is done showing/manipulating structures but not text. Moreover, there can be multiple visual representations of the same program. Even though it is possible to have textual representation —i.e. XML, JSON— they are intended for storage and transfer purposes more than visualization and edition.

Programs in Fōrmulæ are created/edited online in its website, However they run on execution servers. By default remote servers are used, but they are limited in memory and processing power, since they are intended for demonstration and casual use. A local server can be downloaded and installed, it has no limitations (it runs in your own computer). Because of that, example programs can be fully visualized and edited, but some of them will not run if they require a moderate or heavy computation/memory resources, and no local server is being used.

In this page you can see the program(s) related to this task and their results.

G'MIC

<lang c>

  1. Put this into a new file 'fern.gmic' and invoke it from the command line, like this:
  2. $ gmic fern.gmic -barnsley_fern

barnsley_fern :

 1024,2048
 -skip {"
     f1 = [ 0,0,0,0.16 ];           g1 = [ 0,0 ];
     f2 = [ 0.2,-0.26,0.23,0.22 ];  g2 = [ 0,1.6 ];
     f3 = [ -0.15,0.28,0.26,0.24 ]; g3 = [ 0,0.44 ];
     f4 = [ 0.85,0.04,-0.04,0.85 ]; g4 = [ 0,1.6 ];
     xy = [ 0,0 ];
     for (n = 0, n<2e6, ++n,
       r = u(100);
       xy = r<=1?((f1**xy)+=g1):
            r<=8?((f2**xy)+=g2):
            r<=15?((f3**xy)+=g3):
                  ((f4**xy)+=g4);
       uv = xy*200 + [ 480,0 ];
       uv[1] = h - uv[1];
       I(uv) = 0.7*I(uv) + 0.3*255;
     )"}
 -r 40%,40%,1,1,2

</lang>

gnuplot

Translation of: PARI/GP
Works with: gnuplot version 5.0 (patchlevel 3) and above
File:BarnsleyFernGnu.png
Output BarnsleyFernGnu.png

<lang gnuplot>

    1. Barnsley fern fractal 2/17/17 aev

reset fn="BarnsleyFernGnu"; clr='"green"'; ttl="Barnsley fern fractal" dfn=fn.".dat"; ofn=fn.".png"; set terminal png font arial 12 size 640,640 set print dfn append set output ofn unset border; unset xtics; unset ytics; unset key; set size square set title ttl font "Arial:Bold,12" n=100000; max=100; x=y=xw=yw=p=0; randgp(top) = floor(rand(0)*top) do for [i=1:n] {

 p=randgp(max);
 if (p==1) {xw=0;yw=0.16*y;}
 if (1<p&&p<=8) {xw=0.2*x-0.26*y;yw=0.23*x+0.22*y+1.6;}
 if (8<p&&p<=15) {xw=-0.15*x+0.28*y;yw=0.26*x+0.24*y+0.44;}
 if (p>15) {xw=0.85*x+0.04*y;yw=-0.04*x+0.85*y+1.6;}
 x=xw;y=yw; print x," ",y;

} plot dfn using 1:2 with points pt 7 ps 0.5 lc @clr set output unset print </lang>

Output:
File: BarnsleyFernGnu.png
  (also BarnsleyFernGnu.dat)

Go

<lang go>package main

import (

   "image"
   "image/color"
   "image/draw"
   "image/png"
   "log"
   "math/rand"
   "os"

)

// values from WP const (

   xMin = -2.1820
   xMax = 2.6558
   yMin = 0.
   yMax = 9.9983

)

// parameters var (

   width = 200
   n     = int(1e6)
   c     = color.RGBA{34, 139, 34, 255} // forest green

)

func main() {

   dx := xMax - xMin
   dy := yMax - yMin
   fw := float64(width)
   fh := fw * dy / dx
   height := int(fh)
   r := image.Rect(0, 0, width, height)
   img := image.NewRGBA(r)
   draw.Draw(img, r, &image.Uniform{color.White}, image.ZP, draw.Src)
   var x, y float64
   plot := func() {
       // transform computed float x, y to integer image coordinates
       ix := int(fw * (x - xMin) / dx)
       iy := int(fh * (yMax - y) / dy)
       img.SetRGBA(ix, iy, c)
   }
   plot()
   for i := 0; i < n; i++ {
       switch s := rand.Intn(100); {
       case s < 85:
           x, y =
               .85*x+.04*y,
               -.04*x+.85*y+1.6
       case s < 85+7:
           x, y =
               .2*x-.26*y,
               .23*x+.22*y+1.6
       case s < 85+7+7:
           x, y =
               -.15*x+.28*y,
               .26*x+.24*y+.44
       default:
           x, y = 0, .16*y
       }
       plot()
   }
   // write img to png file
   f, err := os.Create("bf.png")
   if err != nil {
       log.Fatal(err)
   }
   if err := png.Encode(f, img); err != nil {
       log.Fatal(err)
   }

}</lang>

Groovy

Library: JavaFX

<lang Groovy>import javafx.animation.AnimationTimer import javafx.application.Application import javafx.scene.Group import javafx.scene.Scene import javafx.scene.image.ImageView import javafx.scene.image.WritableImage import javafx.scene.paint.Color import javafx.stage.Stage

class BarnsleyFern extends Application {

   @Override
   void start(Stage primaryStage) {
       primaryStage.title = 'Barnsley Fern'
       primaryStage.scene = getScene()
       primaryStage.show()
   }
   def getScene() {
       def root = new Group()
       def scene = new Scene(root, 640, 640)
       def imageWriter = new WritableImage(640, 640)
       def imageView = new ImageView(imageWriter)
       root.children.add imageView
       def pixelWriter = imageWriter.pixelWriter
       def x = 0, y = 0
       ({
           50.times {
               def r = Math.random()
               if (r <= 0.01) {
                   x = 0
                   y = 0.16 * y
               } else if (r <= 0.08) {
                   x = 0.2 * x - 0.26 * y
                   y = 0.23 * x + 0.22 * y + 1.6
               } else if (r <= 0.15) {
                   x = -0.15 * x + 0.28 * y
                   y = 0.26 * x + 0.24 * y + 0.44
               } else {
                   x = 0.85 * x + 0.04 * y
                   y = -0.04 * x + 0.85 * y + 1.6
               }
               pixelWriter.setColor(Math.round(640 / 2 + x * 640 / 11) as Integer, Math.round(640 - y * 640 / 11) as Integer, Color.GREEN)
           }
       } as AnimationTimer).start()
       scene
   }
   static void main(args) {
       launch(BarnsleyFern)
   }

} </lang>

Haskell

<lang haskell>import Data.List (scanl') import Diagrams.Backend.Rasterific.CmdLine import Diagrams.Prelude import System.Random

type Pt = (Double, Double)

-- Four affine transformations used to produce a Barnsley fern. f1, f2, f3, f4 :: Pt -> Pt f1 (x, y) = ( 0, 0.16 * y) f2 (x, y) = ( 0.85 * x + 0.04 * y , -0.04 * x + 0.85 * y + 1.60) f3 (x, y) = ( 0.20 * x - 0.26 * y , 0.23 * x + 0.22 * y + 1.60) f4 (x, y) = (-0.15 * x + 0.28 * y , 0.26 * x + 0.24 * y + 0.44)

-- Given a random number in [0, 1) transform an initial point by a randomly -- chosen function. func :: Pt -> Double -> Pt func p r | r < 0.01 = f1 p

        | r < 0.86  = f2 p
        | r < 0.93  = f3 p
        | otherwise = f4 p

-- Using a sequence of uniformly distributed random numbers in [0, 1) return -- the same number of points in the fern. fern :: [Double] -> [Pt] fern = scanl' func (0, 0)

-- Given a supply of random values and a count, generate a diagram of a fern -- composed of that number of points. drawFern :: [Double] -> Int -> Diagram B drawFern rs n = frame 0.5 . diagramFrom . take n $ fern rs

 where diagramFrom = flip atPoints (repeat dot) . map p2
       dot = circle 0.005 # lc green

-- To generate a PNG image of a fern, call this program like: -- -- fern -o fern.png -w 640 -h 640 50000 -- -- where the arguments specify the width, height and number of points in the -- image. main :: IO () main = do

 rand <- getStdGen
 mainWith $ drawFern (randomRs (0, 1) rand)</lang>

IS-BASIC

<lang IS-BASIC>100 PROGRAM "Fern.bas" 110 RANDOMIZE 120 SET VIDEO MODE 1:SET VIDEO COLOR 0:SET VIDEO X 40:SET VIDEO Y 27 130 OPEN #101:"video:" 140 DISPLAY #101:AT 1 FROM 1 TO 27 150 SET PALETTE BLACK,GREEN 160 LET MX=16000:LET X,Y=0 170 FOR N=1 TO MX 180 LET P=RND(100) 190 SELECT CASE P 200 CASE IS<=1 210 LET NX=0:LET NY=.16*Y 220 CASE IS<=8 230 LET NX=.2*X-.26*Y:LET NY=.23*X+.22*Y+1.6 240 CASE IS<=15 250 LET NX=-.15*X+.28*Y:LET NY=.26*X+.24*Y+.44 260 CASE ELSE 270 LET NX=.85*X+.04*Y:LET NY=-.04*X+.85*Y+1.6 280 END SELECT 290 LET X=NX:LET Y=NY 300 PLOT X*96+600,Y*96 310 NEXT</lang>

J

<lang j>require 'plot'

f=: |: 0 ". ];._2 noun define

 0     0     0    0.16   0 0      0.01
 0.85 -0.04  0.04 0.85   0 1.60   0.85
 0.20  0.23 -0.26 0.22   0 1.60   0.07
-0.15  0.26  0.28 0.24   0 0.44   0.07

)

fm=: {&(|: 2 2 $ f) fa=: {&(|: 4 5 { f) prob=: (+/\ 6 { f) I. ?@0:

ifs=: (fa@] + fm@] +/ .* [) prob getPoints=: ifs^:(<200000) plotFern=: 'dot;grids 0 0;tics 0 0;labels 0 0;color green' plot ;/@|:

  plotFern getPoints 0 0</lang>

Java

Works with: Java version 8

<lang java>import java.awt.*; import java.awt.image.BufferedImage; import javax.swing.*;

public class BarnsleyFern extends JPanel {

   BufferedImage img;
   public BarnsleyFern() {
       final int dim = 640;
       setPreferredSize(new Dimension(dim, dim));
       setBackground(Color.white);
       img = new BufferedImage(dim, dim, BufferedImage.TYPE_INT_ARGB);
       createFern(dim, dim);
   }
   void createFern(int w, int h) {
       double x = 0;
       double y = 0;
       for (int i = 0; i < 200_000; i++) {
           double tmpx, tmpy;
           double r = Math.random();
           if (r <= 0.01) {
               tmpx = 0;
               tmpy = 0.16 * y;
           } else if (r <= 0.08) {
               tmpx = 0.2 * x - 0.26 * y;
               tmpy = 0.23 * x + 0.22 * y + 1.6;
           } else if (r <= 0.15) {
               tmpx = -0.15 * x + 0.28 * y;
               tmpy = 0.26 * x + 0.24 * y + 0.44;
           } else {
               tmpx = 0.85 * x + 0.04 * y;
               tmpy = -0.04 * x + 0.85 * y + 1.6;
           }
           x = tmpx;
           y = tmpy;
           img.setRGB((int) Math.round(w / 2 + x * w / 11),
                   (int) Math.round(h - y * h / 11), 0xFF32CD32);
       }
   }
   @Override
   public void paintComponent(Graphics gg) {
       super.paintComponent(gg);
       Graphics2D g = (Graphics2D) gg;
       g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
               RenderingHints.VALUE_ANTIALIAS_ON);
       g.drawImage(img, 0, 0, null);
   }
   public static void main(String[] args) {
       SwingUtilities.invokeLater(() -> {
           JFrame f = new JFrame();
           f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
           f.setTitle("Barnsley Fern");
           f.setResizable(false);
           f.add(new BarnsleyFern(), BorderLayout.CENTER);
           f.pack();
           f.setLocationRelativeTo(null);
           f.setVisible(true);
       });
   }

}</lang>

JavaScript

Translation of: PARI/GP
File:BarnsleyFernjs.png
Output BarnsleyFernjs.png

<lang javascript>// Barnsley fern fractal //6/17/16 aev function pBarnsleyFern(canvasId, lim) {

   // DCLs
   var canvas = document.getElementById(canvasId);
   var ctx = canvas.getContext("2d");
   var w = canvas.width;
   var h = canvas.height;
   var x = 0.,
       y = 0.,
       xw = 0.,
       yw = 0.,
       r;
   // Like in PARI/GP: return random number 0..max-1
   function randgp(max) {
       return Math.floor(Math.random() * max)
   }
   // Clean canvas
   ctx.fillStyle = "white";
   ctx.fillRect(0, 0, w, h);
   // MAIN LOOP
   for (var i = 0; i < lim; i++) {
       r = randgp(100);
       if (r <= 1) {
           xw = 0;
           yw = 0.16 * y;
       } else if (r <= 8) {
           xw = 0.2 * x - 0.26 * y;
           yw = 0.23 * x + 0.22 * y + 1.6;
       } else if (r <= 15) {
           xw = -0.15 * x + 0.28 * y;
           yw = 0.26 * x + 0.24 * y + 0.44;
       } else {
           xw = 0.85 * x + 0.04 * y;
           yw = -0.04 * x + 0.85 * y + 1.6;
       }
       x = xw;
       y = yw;
       ctx.fillStyle = "green";
       ctx.fillRect(x * 50 + 260, -y * 50 + 540, 1, 1);
   } //fend i

}</lang> Executing: <lang html> <html>

<head><script src="BarnsleyFern.js"></script></head>
<body onload="pBarnsleyFern('canvas', 100000)">


Barnsley fern fractal

  <canvas id="canvas" width="540" height="540" style="border: 2px inset;"></canvas>
</body>

</html> </lang>

Output:
Page with BarnsleyFernjs.png

Julia

Works with: Julia version 0.6

<lang julia>function barnsleyfern(n::Integer)

   funs = (
       (x, y) -> (0, 0.16y),
       (x, y) -> (0.85x + 0.04y, -0.04x + 0.85y + 1.6),
       (x, y) -> (0.2x - 0.26y, 0.23x + 0.22y + 1.6),
       (x, y) -> (-0.15x + 0,28y, 0.26x + 0.24y + 0.44))
   rst = Matrix{Float64}(n, 2)
   rst[1, :] = 0.0
   for row in 2:n
       r = rand(0:99)
       if r < 1;      f = 1;
       elseif r < 86; f = 2;
       elseif r < 93; f = 3;
       else           f = 4; end
       rst[row, 1], rst[row, 2] = funs[f](rst[row-1, 1], rst[row-1, 2])
   end
   return rst

end</lang>

Kotlin

Translation of: Java

<lang scala>// version 1.1.0

import java.awt.* import java.awt.image.BufferedImage import javax.swing.*

class BarnsleyFern(private val dim: Int) : JPanel() {

   private val img: BufferedImage
   
   init {
       preferredSize = Dimension(dim, dim)
       background = Color.black
       img = BufferedImage(dim, dim, BufferedImage.TYPE_INT_ARGB)
       createFern(dim, dim)
   }
   private fun createFern(w: Int, h: Int) {
       var x = 0.0
       var y = 0.0
       for (i in 0 until 200_000) {
           var tmpx: Double
           var tmpy: Double
           val r = Math.random()
           if (r <= 0.01) {
               tmpx = 0.0
               tmpy = 0.16 * y
           }
           else if (r <= 0.86) {
               tmpx =  0.85 * x + 0.04 * y
               tmpy = -0.04 * x + 0.85 * y + 1.6
           }
           else if (r <= 0.93) {
               tmpx = 0.2  * x - 0.26 * y
               tmpy = 0.23 * x + 0.22 * y + 1.6
           } 
           else {
               tmpx = -0.15 * x + 0.28 * y
               tmpy =  0.26 * x + 0.24 * y + 0.44
           }               
           x = tmpx
           y = tmpy
           img.setRGB(Math.round(w / 2.0 + x * w / 11.0).toInt(),
                      Math.round(h - y * h / 11.0).toInt(), 0xFF32CD32.toInt())
       }
   }
   override protected fun paintComponent(gg: Graphics) {
       super.paintComponent(gg)
       val g = gg as Graphics2D
       g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON) 
       g.drawImage(img, 0, 0, null)
   }   

}

fun main(args: Array<String>) {

   SwingUtilities.invokeLater {
       val f = JFrame()
       f.defaultCloseOperation = JFrame.EXIT_ON_CLOSE
       f.title = "Barnsley Fern"
       f.setResizable(false)
       f.add(BarnsleyFern(640), BorderLayout.CENTER)
       f.pack()
       f.setLocationRelativeTo(null)
       f.setVisible(true)
   }

}</lang>

Lambdatalk

<lang scheme> {def fern

{lambda {:size :sign}
 {if {> :size 2}
  then M:size
       T{* 70 :sign}
         {fern {* :size 0.5} {- :sign}}
       T{* {- 70} :sign}
       M:size
       T{* {- 70} :sign}
         {fern {* :size 0.5} :sign}
       T{* 70 :sign}
       T{* 7 :sign}
         {fern {- :size 1} :sign}
       T{* {- 7} :sign}
       M{* -:size 2}
  else }}}

{def F {fern 25 1}}

</lang> The output can be seen in http://lambdaway.free.fr/lambdawalks/?view=fern

Liberty BASIC

<lang lb>nomainwin WindowWidth=800 WindowHeight=600 open "Barnsley Fern" for graphics_nf_nsb as #1

  1. 1 "trapclose [q];down;fill black;flush;color green"

for n = 1 To WindowHeight * 50

   r = int(rnd(1)*100)
   Select Case
     Case (r>=0) and (r<=84)
       xn=0.85*x+0.04*y
       yn=-0.04*x+0.85*y+1.6
     Case (r>84) and (r<=91)
       xn=0.2*x-0.26*y
       yn=0.23*x+0.22*y+1.6
     Case (r>91) and (r<=98)
       xn=-0.15*x+0.28*y
       yn=0.26*x+0.24*y+0.44
     Case Else
       xn=0
       yn=0.16*y
   End Select
   x=xn
   y = yn
   #1 "set ";x*80+300;" ";WindowHeight/1.1-y*50
 next n
 #1 "flush"
 wait

[q] close #1 </lang>

Locomotive Basic

Translation of: ZX Spectrum Basic

<lang locobasic>10 mode 2:ink 0,0:ink 1,18:randomize time 20 scale=38 30 maxpoints=20000: x=0: y=0 40 for z=1 to maxpoints 50 p=rnd*100 60 if p<=1 then nx=0: ny=0.16*y: goto 100 70 if p<=8 then nx=0.2*x-0.26*y: ny=0.23*x+0.22*y+1.6: goto 100 80 if p<=15 then nx=-0.15*x+0.28*y: ny=0.26*x+0.24*y+0.44: goto 100 90 nx=0.85*x+0.04*y: ny=-0.04*x+0.85*y+1.6 100 x=nx: y=ny 110 plot scale*x+320,scale*y 120 next</lang>

Lua

Needs LÖVE 2D Engine <lang Lua> g = love.graphics wid, hei = g.getWidth(), g.getHeight()

function choose( i, j )

 local r = math.random()
 if r < .01 then return 0, .16 * j 
   elseif r < .07 then return .2 * i - .26 * j, .23 * i + .22 * j + 1.6
   elseif r < .14 then return -.15 * i + .28 * j, .26 * i + .24 * j + .44
   else return .85 * i + .04 * j, -.04 * i + .85 * j + 1.6
 end

end function createFern( iterations )

 local hw, x, y, scale = wid / 2, 0, 0, 45
 local pts = {}
 for k = 1, iterations do
   pts[1] = { hw + x * scale, hei - 15 - y * scale, 
              20 + math.random( 80 ), 
              128 + math.random( 128 ), 
              20 + math.random( 80 ), 150 }
   g.points( pts )
   x, y = choose( x, y )
 end

end function love.load()

 math.randomseed( os.time() )
 canvas = g.newCanvas( wid, hei )
 g.setCanvas( canvas )
 createFern( 15e4 )
 g.setCanvas()

end function love.draw()

 g.draw( canvas )

end </lang>

Mathematica / Wolfram Language

<lang Mathematica> BarnsleyFern[{x_, y_}] := Module[{},

  i = RandomInteger[{1, 100}];
  If[i <= 1, {xt = 0, yt = 0.16*y},
   If[i <= 8, {xt = 0.2*x - 0.26*y, yt = 0.23*x + 0.22*y + 1.6},
    If[i <= 15, {xt = -0.15*x + 0.28*y, yt = 0.26*x + 0.24*y + 0.44},
     {xt = 0.85*x + 0.04*y, yt = -0.04*x + 0.85*y + 1.6}]]];
  {xt, yt}];

points = NestList[BarnsleyFern, {0,0}, 100000]; Show[Graphics[{Hue[.35, 1, .7], PointSize[.001], Point[#] & /@ points}]] </lang>

MiniScript

Translation of: C#
Works with: Mini Micro

<lang MiniScript>clear x = 0 y = 0 for i in range(100000) gfx.setPixel 300 + 58 * x, 58 * y, color.green roll = rnd * 100 xp = x if roll < 1 then x = 0 y = 0.16 * y else if roll < 86 then x = 0.85 * x + 0.04 * y y = -0.04 * xp + 0.85 * y + 1.6 else if roll < 93 then x = 0.2 * x - 0.26 * y y = 0.23 * xp + 0.22 * y + 1.6 else x = -0.15 * x + 0.28 * y y = 0.26 * xp + 0.24 * y + 0.44 end if end for</lang>

Nim

<lang Nim> import nimPNG, random

randomize()

const

 width = 640
 height = 640
 minX = -2.1815
 maxX = 2.6556
 minY = 0.0
 maxY = 9.9982
 iterations = 1_000_000

var img: array[width * height * 3, char]

proc floatToPixel(x,y:float): tuple[a:int,b:int] =

 var px = abs(x - minX) / abs(maxX - minX)
 var py = abs(y - minY) / abs(maxY - minY)
 var a:int = (int)(width * px)
 var b:int = (int)(height * py)
 a = a.clamp(0, width-1)
 b = b.clamp(0, height-1)
 # flip the y axis
 (a:a,b:height-b-1)

proc pixelToOffset(a,b: int): int =

 b * width * 3 + a * 3

proc toString(a: openArray[char]): string =

 result = newStringOfCap(a.len)
 for ch in items(a):
   result.add(ch)

proc drawPixel(x,y:float) =

 var (a,b) = floatToPixel(x,y)
 var offset = pixelToOffset(a,b)
 #img[offset] = 0 # red channel
 img[offset+1] = char(250) # green channel
 #img[offset+2] = 0 # blue channel
  1. main

var x, y: float = 0.0

for i in 1..iterations:

 var r = random(101)
 var nx, ny: float
 if r <= 85:
   nx = 0.85 * x + 0.04 * y
   ny = -0.04 * x + 0.85 * y + 1.6
 elif r <= 85 + 7:
   nx = 0.2 * x - 0.26 * y
   ny = 0.23 * x + 0.22 * y + 1.6
 elif r <= 85 + 7 + 7:
   nx = -0.15 * x + 0.28 * y
   ny = 0.26 * x + 0.24 * y + 0.44
 else:
   nx = 0
   ny = 0.16 * y
 x = nx
 y = ny
 drawPixel(x,y)

discard savePNG24("fern.png",img.toString, width, height) </lang>

Oberon-2

File:Barnsleyfern-oberon2.png

<lang oberon2> MODULE BarnsleyFern; (** Oxford Oberon-2

    • )

IMPORT Random, XYplane;

VAR a1, b1, c1, d1, e1, f1, p1: REAL; a2, b2, c2, d2, e2, f2, p2: REAL; a3, b3, c3, d3, e3, f3, p3: REAL; a4, b4, c4, d4, e4, f4, p4: REAL; X, Y: REAL; x0, y0, e: INTEGER;

PROCEDURE Draw; VAR x, y: REAL; xi, eta: INTEGER; rn: REAL; BEGIN REPEAT rn := Random.Uniform(); IF rn < p1 THEN x := a1 * X + b1 * Y + e1; y := c1 * X + d1 * Y + f1 ELSIF rn < (p1 + p2) THEN x := a2 *X + b2 * Y + e2; y := c2 * X + d2 * Y + f2 ELSIF rn < (p1 + p2 + p3) THEN x := a3 * X + b3 * Y + e3; y := c3 * X + d3 * Y + f3 ELSE x := a4 * X + b4 * Y + e4; y := c4 * X + d4 * Y + f4 END; X := x; xi := x0 + SHORT(ENTIER(X * e)); Y := y; eta := y0 + SHORT(ENTIER(Y * e)); XYplane.Dot(xi, eta, XYplane.draw) UNTIL "s" = XYplane.Key() END Draw;

PROCEDURE Init; BEGIN X := 0; Y := 0; x0 := 120; y0 := 0; e := 25;

a1 := 0.00; a2 := 0.85; a3 := 0.20; a4 := -0.15; b1 := 0.00; b2 := 0.04; b3 := -0.26; b4 := 0.28; c1 := 0.00; c2 := -0.04; c3 := 0.23; c4 := 0.26; d1 := 0.16; d2 := 0.85; d3 := 0.22; d4 := 0.24; e1 := 0.00; e2 := 0.00; e3 := 0.00; e4 := 0.00; f1 := 0.00; f2 := 1.60; f3 := 1.60; f4 := 0.44; p1 := 0.01; p2 := 0.85; p3 := 0.07; p4 := 0.07; XYplane.Open; END Init;

BEGIN Init;Draw END BarnsleyFern. </lang>

PARI/GP

Translation of: zkl
Works with: PARI/GP version 2.7.4 and above
File:BarnsleyFern.png
Output BarnsleyFern.png

<lang parigp> \\ Barnsley fern fractal \\ 6/17/16 aev pBarnsleyFern(size,lim)={ my(X=List(),Y=X,x=y=xw=yw=0.0,r); print(" *** Barnsley Fern, size=",size," lim=",lim); plotinit(0); plotcolor(0,6); \\green plotscale(0, -3,3, 0,10); plotmove(0, 0,0); for(i=1, lim,

 r=random(100);
 if(r<=1, xw=0;yw=0.16*y,
   if(r<=8, xw=0.2*x-0.26*y;yw=0.23*x+0.22*y+1.6,
     if(r<=15, xw=-0.15*x+0.28*y;yw=0.26*x+0.24*y+0.44,
       xw=0.85*x+0.04*y;yw=-0.04*x+0.85*y+1.6)));
 x=xw;y=yw; listput(X,x); listput(Y,y);

);\\fend i plotpoints(0,Vec(X),Vec(Y)); plotdraw([0,-3,-0]); } {\\ Executing: pBarnsleyFern(530,100000); \\ BarnsleyFern.png } </lang>

Output:
> pBarnsleyFern(530,100000);  \\ BarnsleyFern.png
 *** Barnsley Fern, size=530 lim=100000

Perl

<lang perl>use Imager;

my $w = 640; my $h = 640;

my $img = Imager->new(xsize => $w, ysize => $h, channels => 3); my $green = Imager::Color->new('#00FF00');

my ($x, $y) = (0, 0);

foreach (1 .. 2e5) {

 my $r = rand(100);
 ($x, $y) = do {
   if    ($r <=  1) { ( 0.00 * $x - 0.00 * $y,  0.00 * $x + 0.16 * $y + 0.00) }
   elsif ($r <=  8) { ( 0.20 * $x - 0.26 * $y,  0.23 * $x + 0.22 * $y + 1.60) }
   elsif ($r <= 15) { (-0.15 * $x + 0.28 * $y,  0.26 * $x + 0.24 * $y + 0.44) }
   else             { ( 0.85 * $x + 0.04 * $y, -0.04 * $x + 0.85 * $y + 1.60) }
 };
 $img->setpixel(x => $w / 2 + $x * 60, y => $y * 60, color => $green);

}

$img->flip(dir => 'v'); $img->write(file => 'barnsleyFern.png');</lang>

Phix

Library: Phix/pGUI
Library: Phix/online

You can run this online here, or see the output on imgur

--
-- pwa\phix\BarnsleyFern.exw
-- =========================
--
with javascript_semantics
include pGUI.e

Ihandle dlg, canvas
cdCanvas cddbuffer, cdcanvas

function redraw_cb(Ihandle /*canvas*/, integer /*posx*/, integer /*posy*/)
    atom x = 0, y = 0
    integer {width, height} = IupGetIntInt(canvas, "DRAWSIZE")
    cdCanvasActivate(cddbuffer)
    for i=1 to 100000 do
        integer r = rand(100)
--      {x, y} = iff(r<=1? {             0,        0.16*y     } :
--               iff(r<=8? { 0.20*x-0.26*y, 0.23*x+0.22*y+1.60} :
--               iff(r<=15?{-0.15*x+0.28*y, 0.26*x+0.24*y+0.44} :
--                         { 0.85*x+0.04*y,-0.04*x+0.85*y+1.60})))
        if r<=1 then        {x, y} = {             0,        0.16*y     }
        elsif r<=8 then     {x, y} = { 0.20*x-0.26*y, 0.23*x+0.22*y+1.60}
        elsif r<=15 then    {x, y} = {-0.15*x+0.28*y, 0.26*x+0.24*y+0.44}
        else                {x, y} = { 0.85*x+0.04*y,-0.04*x+0.85*y+1.60}
        end if
        cdCanvasPixel(cddbuffer, width/2+x*50, y*50, CD_DARK_GREEN)
    end for
    cdCanvasFlush(cddbuffer)
    return IUP_DEFAULT
end function

IupOpen()

canvas = IupCanvas(Icallback("redraw_cb"),"RASTERSIZE=340x540")
dlg = IupDialog(canvas,`TITLE="Barnsley Fern"`)

IupMap(dlg)
cdcanvas = cdCreateCanvas(CD_IUP, canvas)
cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas)
IupSetAttribute(canvas, "RASTERSIZE", NULL) -- release the minimum limitation
IupShow(dlg)
if platform()!=JS then
    IupMainLoop()
    IupClose()
end if

PicoLisp

<lang PicoLisp>`(== 64 64) (seed (in "/dev/urandom" (rd 8))) (scl 20) (de gridX (X)

  (*/ (+ 320.0 (*/ X 58.18 1.0)) 1.0) )

(de gridY (Y)

  (*/ (- 640.0 (*/ Y 58.18 1.0)) 1.0) )

(de calc (R X Y)

  (cond
     ((< R 1) (list 0 (*/ Y 0.16 1.0)))
     ((< R 86)
        (list
           (+ (*/ 0.85 X 1.0) (*/ 0.04 Y 1.0))
           (+ (*/ -0.04 X 1.0) (*/ 0.85 Y 1.0) 1.6) ) )
     ((< R 93)
        (list
           (- (*/ 0.2 X 1.0) (*/ 0.26 Y 1.0))
           (+ (*/ 0.23 X 1.0) (*/ 0.22 Y 1.0) 1.6) ) ) 
     (T
        (list
           (+ (*/ -0.15 X 1.0) (*/ 0.28 Y 1.0))
           (+ (*/ 0.26 X 1.0) (*/ 0.24 Y 1.0) 0.44) ) ) ) )

(let

  (X 0
     Y 0 
     G (make (do 640 (link (need 640 0)))) )
  (do 100000
     (let ((A B) (calc (rand 0 99) X Y))
        (setq X A  Y B)
        (set (nth G (gridY Y) (gridX X)) 1) ) ) 
  (out "fern.pbm"
     (prinl "P1")
     (prinl 640 " " 640)
     (mapc prinl G) ) )</lang>

Processing

<lang java>void setup() {

 size(640, 640);
 background(0, 0, 0);

}

float x = 0; float y = 0;

void draw() {

 for (int i = 0; i < 100000; i++) {
   float xt = 0;
   float yt = 0;
   float r = random(100);
   if (r <= 1) {
     xt = 0;
     yt = 0.16*y;
   } else if (r <= 8) {
     xt = 0.20*x - 0.26*y;
     yt = 0.23*x + 0.22*y + 1.60;
   } else if (r <= 15) {
     xt = -0.15*x + 0.28*y;
     yt =  0.26*x + 0.24*y + 0.44;
   } else {
     xt =  0.85*x + 0.04*y;
     yt = -0.04*x + 0.85*y + 1.60;
   }
   x = xt;
   y = yt;
   int m = round(width/2 + 60*x);
   int n = height-round(60*y);
   set(m, n, #00ff00);
 }
 noLoop();

}</lang>

Processing Python mode

<lang python>size(640, 640) background(0)

x = 0 y = 0

for _ in range(100000):

   xt = 0
   yt = 0
   r = random(100)
   if r <= 1:
       xt = 0
       yt = 0.16 * y
   elif r <= 8:
       xt = 0.20 * x - 0.26 * y
       yt = 0.23 * x + 0.22 * y + 1.60
   elif r <= 15:
       xt = -0.15 * x + 0.28 * y
       yt = +0.26 * x + 0.24 * y + 0.44
   else:
       xt = +0.85 * x + 0.04 * y
       yt = -0.04 * x + 0.85 * y + 1.60

size(640, 640) background(0)

x = 0 y = 0

for _ in range(100000):

   xt = 0
   yt = 0
   r = random(100)
   
   if r <= 1:
       xt = 0
       yt = 0.16*y
   elif r <= 8:
       xt = 0.20*x - 0.26*y
       yt = 0.23*x + 0.22*y + 1.60
   elif r <= 15:
       xt = -0.15*x + 0.28*y
       yt =    0.26*x + 0.24*y + 0.44
   else:
       xt =    0.85*x + 0.04*y
       yt = -0.04*x + 0.85*y + 1.60
   
   x = xt
   y = yt
   m = round(width/2 + 60*x)
   n = height-round(60*y)
   set(m, n, "#00ff00")
   x = xt
   y = yt
   m = round(width / 2 + 60 * x)
   n = height - round(60 * y)
   set(m, n, "#00ff00")</lang>

PureBasic

<lang PureBasic>EnableExplicit DisableDebugger

DataSection

 R84:  : Data.d 0.85,0.04,-0.04,0.85,1.6
 R91:  : Data.d 0.2,-0.26,0.23,0.22,1.6
 R98:  : Data.d -0.15,0.28,0.26,0.24,0.44
 R100: : Data.d 0.0,0.0,0.0,0.16,0.0

EndDataSection

Procedure Barnsley(height.i)

 Define x.d, y.d, xn.d, yn.d, v1.d, v2.d, v3.d, v4.d, v5.d,
        f.d=height/10.6,
        offset.i=Int(height/4-height/40),
        n.i, r.i  
 For n=1 To height*50
   r=Random(99,0)
   Select r
     Case 0 To 84  : Restore R84
     Case 85 To 91 : Restore R91
     Case 92 To 98 : Restore R98
     Default       : Restore R100
   EndSelect
   Read.d v1 : Read.d v2 : Read.d v3 : Read.d v4 : Read.d v5
   xn=v1*x+v2*y : yn=v3*x+v4*y+v5    
   x=xn : y=yn
   Plot(offset+x*f,height-y*f,RGB(0,255,0))
 Next

EndProcedure

Define w1.i=400,

      h1.i=800

If OpenWindow(0,#PB_Ignore,#PB_Ignore,w1,h1,"Barnsley fern")

 If CreateImage(0,w1,h1,24,0) And StartDrawing(ImageOutput(0))        
   Barnsley(h1)
   StopDrawing()
 EndIf
 ImageGadget(0,0,0,0,0,ImageID(0))  
 Repeat : Until WaitWindowEvent(50)=#PB_Event_CloseWindow

EndIf End</lang>

Python

<lang Python>

import random from PIL import Image


class BarnsleyFern(object):

   def __init__(self, img_width, img_height, paint_color=(0, 150, 0),
                bg_color=(255, 255, 255)):
       self.img_width, self.img_height = img_width, img_height
       self.paint_color = paint_color
       self.x, self.y = 0, 0
       self.age = 0
       self.fern = Image.new('RGB', (img_width, img_height), bg_color)
       self.pix = self.fern.load()
       self.pix[self.scale(0, 0)] = paint_color
   def scale(self, x, y):
       h = (x + 2.182)*(self.img_width - 1)/4.8378
       k = (9.9983 - y)*(self.img_height - 1)/9.9983
       return h, k
   def transform(self, x, y):
       rand = random.uniform(0, 100)
       if rand < 1:
           return 0, 0.16*y
       elif 1 <= rand < 86:
           return 0.85*x + 0.04*y, -0.04*x + 0.85*y + 1.6
       elif 86 <= rand < 93:
           return 0.2*x - 0.26*y, 0.23*x + 0.22*y + 1.6
       else:
           return -0.15*x + 0.28*y, 0.26*x + 0.24*y + 0.44
   def iterate(self, iterations):
       for _ in range(iterations):
           self.x, self.y = self.transform(self.x, self.y)
           self.pix[self.scale(self.x, self.y)] = self.paint_color
       self.age += iterations

fern = BarnsleyFern(500, 500) fern.iterate(1000000) fern.fern.show()

</lang>

QB64

<lang qb64>_Title "Barnsley Fern" Dim As Integer sw, sh sw = 400: sh = 600 Screen _NewImage(sw, sh, 8)

Dim As Long i, ox, oy Dim As Single sRand Dim As Double x, y, x1, y1, sx, sy sx = 60: sy = 59 ox = 180: oy = 4 Randomize Timer

x = 0 y = 0 For i = 1 To 400000

   sRand = Rnd
   Select Case sRand
       Case Is < 0.01
           x1 = 0: y1 = 0.16 * y
       Case Is < 0.08
           x1 = 0.2 * x - 0.26 * y: y1 = 0.23 * x + 0.22 * y + 1.6
       Case Is < 0.15
           x1 = -0.15 * x + 0.28 * y: y1 = 0.26 * x + 0.24 * y + 0.44
       Case Else
           x1 = 0.85 * x + 0.04 * y: y1 = -0.04 * x + 0.85 * y + 1.6
   End Select
   x = x1
   y = y1
   PSet (x * sx + ox, sh - (y * sy) - oy), 10

Next

Sleep System</lang>


R

Matrix solution

Translation of: PARI/GP
File:BarnsleyFernR.png
Output BarnsleyFernR.png

<lang rsplus>## pBarnsleyFern(fn, n, clr, ttl, psz=600): Plot Barnsley fern fractal.

    1. Where: fn - file name; n - number of dots; clr - color; ttl - plot title;
    2. psz - picture size.
    3. 7/27/16 aev

pBarnsleyFern <- function(fn, n, clr, ttl, psz=600) {

 cat(" *** START:", date(), "n=", n, "clr=", clr, "psz=", psz, "\n");
 cat(" *** File name -", fn, "\n");
 pf = paste0(fn,".png"); # pf - plot file name
 A1 <- matrix(c(0,0,0,0.16,0.85,-0.04,0.04,0.85,0.2,0.23,-0.26,0.22,-0.15,0.26,0.28,0.24), ncol=4, nrow=4, byrow=TRUE);
 A2 <- matrix(c(0,0,0,1.6,0,1.6,0,0.44), ncol=2, nrow=4, byrow=TRUE);
 P <- c(.01,.85,.07,.07);
 # Creating matrices M1 and M2.
 M1=vector("list", 4); M2 = vector("list", 4);
 for (i in 1:4) {
   M1i <- matrix(c(A1[i,1:4]), nrow=2);
   M2i <- matrix(c(A2[i, 1:2]), nrow=2);
 }
 x <- numeric(n); y <- numeric(n);
 x[1] <- y[1] <- 0;
 for (i in 1:(n-1)) {
   k <- sample(1:4, prob=P, size=1);
   M <- as.matrix(M1k);
   z <- M%*%c(x[i],y[i]) + M2k; 
   x[i+1] <- z[1]; y[i+1] <- z[2];
 }
 plot(x, y, main=ttl, axes=FALSE, xlab="", ylab="", col=clr, cex=0.1);
 # Writing png-file
 dev.copy(png, filename=pf,width=psz,height=psz);
 # Cleaning 
 dev.off(); graphics.off();
 cat(" *** END:",date(),"\n");

}

    1. Executing:

pBarnsleyFern("BarnsleyFernR", 100000, "dark green", "Barnsley Fern Fractal", psz=600) </lang>

Output:
> pBarnsleyFern("BarnsleyFernR", 100000, "dark green", "Barnsley Fern Fractal", psz=600)
 *** START: Wed Jul 27 13:50:49 2016 n= 1e+05 clr= dark green psz= 600 
 *** File name - BarnsleyFernR 
 *** END: Wed Jul 27 13:50:56 2016 
+ BarnsleyFernR.png file

'Obvious' solution

The matrix solution above is a clever approach, but the following solution is more readable if you're unfamiliar with linear algebra. This is very much a blind "just do what the task says" solution. It's so simple that it probably runs unadapted in S. I suspect that there is room for an interesting use of R's ifelse function somewhere, but I couldn't find a clean way. <lang rsplus>fernOfNPoints <- function(n) {

 currentX <- currentY <- newX <- newY <- 0
 plot(0, 0, xlim = c(-2, 3), ylim = c(0, 10), xlab = "", ylab = "", pch = 20, col = "darkgreen", cex = 0.1)
 f1 <- function()#ran 1% of the time
 {
   newX <<- 0
   newY <<- 0.16 * currentY
 }
 f2 <- function()#ran 85% of the time
 {
   newX <<- 0.85 * newX + 0.04 * newY
   newY <<- -0.04 * newX + 0.85 * newY + 1.6
 }
 f3 <- function()#ran 7% of the time
 {
   newX <<- 0.2 * newX - 0.26 * newY
   newY <<- 0.23 * newX + 0.22 * newY + 1.6
 }
 f4 <- function()#ran 7% of the time
 {
   newX <<- -0.15 * newX + 0.28 * newY
   newY <<- 0.26 * newX + 0.24 * newY + 0.44
 }
 for(i in 2:n)#We've already plotted (0,0), so we can skip one run.
 {
   case <- runif(1)
   if(case <= 0.01) f1()
   else if(case <= 0.86) f2()
   else if(case <= 0.93) f3()
   else f4()
   points(newX, newY, pch = 20, col = "darkgreen", cex = 0.1)
 }
 return(invisible())

}

  1. To plot the fern, use:

fernOfNPoints(500000)

  1. It will look better if you use a bigger input, but the plot might take a while.
  2. I find that there's a large delay between RStudio saying that my code is finished running and the plot appearing.
  3. If your input is truly big, you may want to reduce the two cex parameters (to make the points smaller).</lang>

Racket

File:Racket-barnsley-fern.png : file uploading broken :-( <lang racket>#lang racket

(require racket/draw)

(define fern-green (make-color #x32 #xCD #x32 0.66))

(define (fern dc n-iterations w h)

 (for/fold ((x #i0) (y #i0))
           ((i n-iterations))
   (define-values (x′ y′)
     (let ((r (random)))
       (cond
         [(<= r 0.01) (values 0
                              (* y 16/100))]
         [(<= r 0.08) (values (+ (* x 20/100) (* y -26/100))
                              (+ (* x 23/100) (* y 22/100) 16/10))]
         [(<= r 0.15) (values (+ (* x -15/100) (* y 28/100))
                              (+ (* x 26/100) (* y 24/100) 44/100))]
         [else (values (+ (* x 85/100) (* y 4/100))
                       (+ (* x -4/100) (* y 85/100) 16/10))])))
   (define px (+ (/ w 2) (* x w 1/11)))
   (define py (- h (* y h 1/11)))
   (send dc set-pixel (exact-round px) (exact-round py) fern-green)                   
   (values x′ y′)))


(define bmp (make-object bitmap% 640 640 #f #t 2))

(fern (new bitmap-dc% [bitmap bmp]) 200000 640 640)

bmp (send bmp save-file "images/racket-barnsley-fern.png" 'png)</lang>

Raku

(formerly Perl 6)

Works with: Rakudo version 2016.03
Translation of: Perl

<lang perl6>use Image::PNG::Portable;

my ($w, $h) = (640, 640);

my $png = Image::PNG::Portable.new: :width($w), :height($h);

my ($x, $y) = (0, 0);

for ^2e5 {

   my $r = 100.rand;
   ($x, $y) = do given $r {
       when  $r <=  1 { (                     0,              0.16 * $y       ) }
       when  $r <=  8 { ( 0.20 * $x - 0.26 * $y,  0.23 * $x + 0.22 * $y + 1.60) }
       when  $r <= 15 { (-0.15 * $x + 0.28 * $y,  0.26 * $x + 0.24 * $y + 0.44) }
       default        { ( 0.85 * $x + 0.04 * $y, -0.04 * $x + 0.85 * $y + 1.60) }
   };
   $png.set(($w / 2 + $x * 60).Int, ($h - $y * 60).Int, 0, 255, 0);

}

$png.write: 'Barnsley-fern-perl6.png';</lang>

REXX

This REXX version is modeled after the   Fortran   entry;     it generates an output file   ("BARNSLEY.DAT")   that
contains the   X   and   Y   coördinates for a scatter plot that can be visualized with a plotting program. <lang rexx>/*REXX pgm gens X & Y coördinates for a scatter plot to be used to show a Barnsley fern.*/ parse arg N FID seed . /*obtain optional arguments from the CL*/ if N== | N=="," then N= 100000 /*Not specified? Then use the default*/ if FID== | FID=="," then FID= 'BARNSLEY.DAT' /* " " " " " " */ if datatype(seed,'W') then call random ,,seed /*if specified, then use random seed. */ call lineout FID, , 1 /*just set the file ptr to the 1st line*/ x=0 /*set the initial value for X coörd. */ y=0 /* " " " " " Y " */

   do #=1  for N                                /*generate   N   number of plot points.*/
   ?=random(, 100)                              /*generate a random number: 0 ≤ ? ≤ 100*/
      select
      when ?==0  then do;   xx=   0           ;    yy=            .16*y         ;     end
      when ?< 8  then do;   xx=  .2 *x - .26*y;    yy=  .23*x  +  .22*y  +  1.6 ;     end
      when ?<15  then do;   xx= -.15*x + .28*y;    yy=  .26*x  +  .24*y  +   .44;     end
      otherwise             xx=  .85*x + .04*y;    yy= -.04*x  +  .85*y  +  1.6
      end   /*select*/
                            x=xx;                     y=yy
   if #==1  then  do;    minx= x;  maxx= x;        miny= y;  maxy= y
                  end
                         minx= min(minx, x);       miny= min(miny, y)
                         maxx= max(maxx, x);       maxy= max(maxy, y)
   call lineout FID, x","y
   end      /*#*/                               /* [↓]  close the file (safe practice).*/

call lineout FID /*stick a fork in it, we're all done. */</lang>

output   is generated to an output file:   BARNSLEY.DAT   which contains the   X   and   Y   coördinates of a scatter plot.



Ring

<lang Ring>

Load "guilib.ring"

/*

+---------------------------------------------------------------------------
+        Program Name : Draw Barnsley Fern
+        Purpose      : Draw Fern using Quadratic Equation and Random Number
+---------------------------------------------------------------------------
  • /
      1. -------------------------------
      2. DRAW CHART size 400 x 500
      3. -------------------------------


New qapp { win1 = new qwidget() { ### Position and Size on Screen setwindowtitle("Drawing using QPainter") setgeometry( 10, 25, 400, 500)

### Draw within this Win Box label1 = new qlabel(win1) { ### Label Position and Size setgeometry(10, 10, 400, 500) settext(" ") }

buttonFern = new qpushbutton(win1) { ### Button DrawFern setgeometry(10, 10, 80, 20) settext("Draw Fern") setclickevent("DrawFern()") ### Call DRAW function }

show() } exec() }

      1. ------------------------
      2. FUNCTIONS
      3. ------------------------

Func DrawFern p1 = new qpicture()

colorGreen = new qcolor() { setrgb(0,255,0,255) } penGreen = new qpen() { setcolor(colorGreen) setwidth(1) }

new qpainter() { begin(p1) setpen(penGreen)

###------------------------------------- ### Quadratic equation matrix of arrays

a = [ 0, 0.85, 0.2, -0.15 ] b = [ 0, 0.04, -0.26, 0.28 ] c = [ 0, -0.04, 0.23, 0.26 ] d = [ 0.16, 0.85, 0.22, 0.24 ] e = [ 0, 0, 0, 0 ] f = [ 0, 1.6, 1.6, 0.44 ]

### Initialize x, y points

xf = 0.0 yf = 0.0

### Size of output screen

MaxX = 400 MaxY = 500 MaxIterations = MaxY * 200 Count = 0

###------------------------------------------------

while ( Count <= MaxIterations )

### NOTE *** RING *** starts at Index 1, ### Do NOT use Random K=0 result

k = random() % 100 k = k +1

### if (k = 0) k = 1 ok ### Do NOT use

if ((k > 0) and (k <= 85)) k = 2 ok if ((k > 85) and (k <= 92)) k = 3 ok if (k > 92) k = 4 ok

TempX = ( a[k] * xf ) + ( b[k] * yf ) + e[k] TempY = ( c[k] * xf ) + ( d[k] * yf ) + f[k]

xf = TempX yf = TempY

if( (Count >= MaxIterations) or (Count != 0) ) xPoint = (floor(xf * MaxY / 11) + floor(MaxX / 2)) yPoint = (floor(yf * -MaxY / 11) + MaxY ) drawpoint( xPoint , yPoint ) ok

Count++ end

###----------------------------------------------------

endpaint() }

label1 { setpicture(p1) show() } return

</lang>

Ruby

Library: RubyGems
Library: JRubyArt

<lang ruby> MAX_ITERATIONS = 200_000

def setup

 sketch_title 'Barnsley Fern'
 no_loop
 puts 'Be patient. This takes about 10 seconds to render.'

end

def draw

 background 0
 load_pixels
 x0 = 0.0
 y0 = 0.0
 x = 0.0
 y = 0.0
 MAX_ITERATIONS.times do
   r = rand(100)
   if r < 85
     x = 0.85 * x0 + 0.04 * y0
     y = -0.04 * x0 + 0.85 * y0 + 1.6
   elsif r < 92
     x = 0.2 * x0 - 0.26 * y0
     y = 0.23 * x0 + 0.22 * y0 + 1.6
   elsif r < 99
     x = -0.15 * x0 + 0.28 * y0
     y = 0.26 * x0 + 0.24 * y0 + 0.44
   else
     x = 0
     y = 0.16 * y
   end
   i = height - (y * 48).to_i
   j = width / 2 + (x * 48).to_i
   pixels[i * height + j] += 2_560
   x0 = x
   y0 = y
 end
 update_pixels

end

def settings

 size 500, 500

end </lang>

Run BASIC

<lang runbasic>'Barnsley Fern - Run BASIC

 'http://rosettacode.org/wiki/Barnsley_fern#Run_BASIC
 'copy code and run it at http://www.runbasic.com
 '
 ' -----------------------------------
 ' Barnsley Fern
 ' -----------------------------------maxpoints	= 20000

graphic #g, 200, 200

  1. g fill("blue")

FOR n = 1 TO maxpoints p = RND(0)*100 IF p <= 1 THEN nx = 0 ny = 0.16 * y else if p <= 8 THEN nx = 0.2 * x - 0.26 * y ny = 0.23 * x + 0.22 * y + 1.6 else if p <= 15 THEN nx = -0.15 * x + 0.28 * y ny = 0.26 * x + 0.24 * y + 0.44 else nx = 0.85 * x +0.04 * y ny = -0.04 * x +0.85 * y + 1.6 end if x = nx y = ny

  1. g "color green ; set "; x * 17 + 100; " "; y * 17

NEXT n render #g

  1. g "flush"</lang>

Rust

Translation of: Java
Library: rand

<lang rust>extern crate rand; extern crate raster;

use rand::Rng;

fn main() {

   let max_iterations = 200_000u32;
   let height = 640i32;
   let width = 640i32;
   let mut rng = rand::thread_rng();
   let mut image = raster::Image::blank(width, height);
   raster::editor::fill(&mut image, raster::Color::white()).unwrap();
   let mut x = 0.;
   let mut y = 0.;
   for _ in 0..max_iterations {
       let r = rng.gen::<f32>();
       let cx: f64;
       let cy: f64;
       if r <= 0.01 {
           cx = 0f64;
           cy = 0.16 * y as f64;
       } else if r <= 0.08 {
           cx = 0.2 * x as f64 - 0.26 * y as f64;
           cy = 0.23 * x as f64 + 0.22 * y as f64 + 1.6;
       } else if r <= 0.15 {
           cx = -0.15 * x as f64 + 0.28 * y as f64;
           cy = 0.26 * x as f64 + 0.26 * y as f64 + 0.44;
       } else {
           cx = 0.85 * x as f64 + 0.04 * y as f64;
           cy = -0.04 * x as f64 + 0.85 * y as f64 + 1.6;
       }
       x = cx;
       y = cy;
       let _ = image.set_pixel(
           ((width as f64) / 2. + x * (width as f64) / 11.).round() as i32,
           ((height as f64) - y * (height as f64) / 11.).round() as i32,
           raster::Color::rgb(50, 205, 50));
   }
   raster::save(&image, "fractal.png").unwrap();

}</lang>

Scala

Java Swing Interoperability

<lang Scala>import java.awt._ import java.awt.image.BufferedImage

import javax.swing._

object BarnsleyFern extends App {

 SwingUtilities.invokeLater(() =>
   new JFrame("Barnsley Fern") {
     private class BarnsleyFern extends JPanel {
       val dim = 640
       val img = new BufferedImage(dim, dim, BufferedImage.TYPE_INT_ARGB)
       private def createFern(w: Int, h: Int): Unit = {
         var x, y = 0.0
         for (i <- 0 until 200000) {
           var tmpx, tmpy = .0
           val r = math.random
           if (r <= 0.01) {
             tmpx = 0
             tmpy = 0.16 * y
           }
           else if (r <= 0.08) {
             tmpx = 0.2 * x - 0.26 * y
             tmpy = 0.23 * x + 0.22 * y + 1.6
           }
           else if (r <= 0.15) {
             tmpx = -0.15 * x + 0.28 * y
             tmpy = 0.26 * x + 0.24 * y + 0.44
           }
           else {
             tmpx = 0.85 * x + 0.04 * y
             tmpy = -0.04 * x + 0.85 * y + 1.6
           }
           x = tmpx
           y = tmpy
           img.setRGB((w / 2 + tmpx * w / 11).round.toInt,
             (h - tmpy * h / 11).round.toInt, 0xFF32CD32)
         }
       }
       override def paintComponent(gg: Graphics): Unit = {
         super.paintComponent(gg)
         val g = gg.asInstanceOf[Graphics2D]
         g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
         g.drawImage(img, 0, 0, null)
       }
       setBackground(Color.white)
       setPreferredSize(new Dimension(dim, dim))
       createFern(dim, dim)
     }
     add(new BarnsleyFern, BorderLayout.CENTER)
     pack()
     setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
     setLocationRelativeTo(null)
     setResizable(false)
     setVisible(true)
   })

}</lang>

Scheme

This version creates a list of points, defining the fern, which are then rescaled and output to an eps file. <lang scheme>(import (scheme base)

       (scheme cxr)
       (scheme file)
       (scheme inexact)
       (scheme write)
       (srfi 27))     ; for random numbers

(define (create-fern x y num-points)

 (define (new-point xn yn)
   (let ((r (* 100 (random-real))))
     (cond ((< r 1) ; f1
            (list 0 (* 0.16 yn)))
           ((< r 86) ; f2
            (list (+ (* 0.85 xn) (* 0.04 yn))
                  (+ (* -0.04 xn) (* 0.85 yn) 1.6)))
           ((< r 93) ; f3
            (list (- (* 0.2 xn) (* 0.26 yn))
                  (+ (* 0.23 xn) (* 0.22 yn) 1.6)))
           (else ; f4
             (list (+ (* -0.15 xn) (* 0.28 yn))
                   (+ (* 0.26 xn) (* 0.24 yn) 0.44))))))
 ;
 (random-source-randomize! default-random-source)
 (do ((i 0 (+ i 1))
      (pts (list (list x y)) (cons (new-point (caar pts) (cadar pts)) pts)))
   ((= i num-points) pts)))
output the fern to an eps file

(define (output-fern-as-eps filename fern)

 (when (file-exists? filename) (delete-file filename))
 (with-output-to-file
   filename
   (lambda ()
     (let* ((width 600)
            (height 800)
            (min-x (apply min (map car fern)))
            (max-x (apply max (map car fern)))
            (min-y (apply min (map cadr fern)))
            (max-y (apply max (map cadr fern)))
            (scale-x (/ (- width 50) (- max-x min-x)))
            (scale-y (/ (- height 50) (- max-y min-y)))
            (scale-points (lambda (point)
                            (list (truncate (+ 20 (* scale-x (- (car point) min-x))))
                                  (truncate (+ 20 (* scale-y (- (cadr point) min-y))))))))
       (display 
         (string-append "%!PS-Adobe-3.0 EPSF-3.0\n%%BoundingBox: 0 0 "
                        (number->string width) " " (number->string height) "\n"))
       ;; add each point in fern as an arc - sets linewidth based on depth in tree
       (for-each (lambda (point)
                   (display
                     (string-append (number->string (list-ref point 0))
                                    " "
                                    (number->string (list-ref point 1))
                                    " 0.1 0 360 arc\nstroke\n")))
                 (map scale-points fern))
       (display "\n%%EOF")))))

(output-fern-as-eps "barnsley.eps" (create-fern 0 0 50000))</lang>

Scilab

Works with: Scilab version 5.4.0 and above

This version creates a list of points, defining the fern, and shows them on a graphic window which can then be saved to a file via the GUI or the console by the user. <lang> iteractions=1.0d6;

XY=zeros(2,iteractions+1); x=0; y=0;

i=2; while i<iteractions+2

   random_numbers=rand();
   xp=x;
   if random_numbers(1) < 0.01 then
       x = 0;
       y = 0.16 * y;
   elseif random_numbers(1) >= 0.01 & random_numbers(1) < 0.01+0.85 then
       x = 0.85 * x + 0.04 * y;
       y = -0.04 * xp + 0.85 * y + 1.6;
   elseif random_numbers(1) >= 0.86 & random_numbers(1) < 0.86+0.07 then
       x = 0.2 * x - 0.26 * y;
       y = 0.23 * xp + 0.22 * y + 1.6;
   else
       x = -0.15 * x + 0.28 * y;
       y = 0.26 * xp + 0.24 * y + 0.44;
   end
   
   XY(1,i)=x;
   XY(2,i)=y;
   
   i=i+1;

end

scf(0); clf(); xname('Barnsley fern'); plot2d(XY(1,:),XY(2,:),-0) axes=gca(); axes.isoview="on"; axes.children.children.mark_foreground=13; </lang>

SequenceL

Tail-Recursive SequenceL Code:
<lang sequencel>import <Utilities/Math.sl>; import <Utilities/Random.sl>;

transform(p(1), rand) :=

   let
       x := p[1]; y := p[2];
   in
       [0.0, 0.16*y] when rand <= 0.01
   else
       [0.85*x + 0.04*y, -0.04*x + 0.85*y + 1.6] when rand <= 0.86
   else
       [0.2*x - 0.26*y, 0.23*x + 0.22*y + 1.6] when rand <= 0.93
   else
       [-0.15*x + 0.28*y, 0.26*x + 0.24*y + 0.44];
       

barnsleyFern(rand, count, result(2)) :=

   let
       nextRand := getRandom(rand);
       next := transform(result[size(result)], nextRand.value / 2147483647.0);
   in
       result when count <= 0
   else
       barnsleyFern(nextRand.generator, count - 1, result ++ [next]);

scale(p(1), width, height) := [round((p[1] + 2.182) * width / 4.8378),

                              round((9.9983 - p[2]) * height / 9.9983)];
       

entry(seed, count, width, height) :=

   let
       fern := barnsleyFern(seedRandom(seed), count, 0.0,0.0);
   in
       scale(fern, width, height);</lang>

C++ Driver Code:

Library: CImg

<lang c>#include "SL_Generated.h"

  1. include "CImg.h"

using namespace cimg_library;

int main(int argc, char** argv) {

   int threads = 0; if(argc > 1) threads = atoi(argv[1]);
   int width = 300; if(argc > 2) width = atoi(argv[2]);
   int height = 600; if(argc > 3) height = atoi(argv[3]);
   int steps = 10000; if(argc > 4) steps = atoi(argv[4]);
   int seed = 314159; if(argc > 5) seed = atoi(argv[5]);
   
   CImg<unsigned char> visu(width, height, 1, 3, 0);
   Sequence< Sequence<int> > result;
   sl_init(threads);
   sl_entry(seed, steps, width-1, height-1, threads, result);
   
   visu.fill(0);
   for(int i = 1; i <= result.size(); i++)
       visu(result[i][1], result[i][2],1) = 255;
   
   CImgDisplay draw_disp(visu);
   draw_disp.set_title("Barnsley Fern in SequenceL");
   visu.display(draw_disp);
   
   while(!draw_disp.is_closed()) draw_disp.wait();
   sl_done();
   return 0;

}</lang>

Output:

Output Screenshot

Sidef

<lang ruby>require('Imager')

var w = 640 var h = 640

var img = %O<Imager>.new(xsize => w, ysize => h, channels => 3) var green = %O<Imager::Color>.new('#00FF00')

var (x, y) = (0.float, 0.float)

1e5.times {

 var r = 100.rand
 (x, y) = (
   if    (r <=  1) { ( 0.00*x - 0.00*y,  0.00*x + 0.16*y + 0.00) }
   elsif (r <=  8) { ( 0.20*x - 0.26*y,  0.23*x + 0.22*y + 1.60) }
   elsif (r <= 15) { (-0.15*x + 0.28*y,  0.26*x + 0.24*y + 0.44) }
   else            { ( 0.85*x + 0.04*y, -0.04*x + 0.85*y + 1.60) }
 )
 img.setpixel(x => w/2 + 60*x, y => 60*y, color => green)

}

img.flip(dir => 'v') img.write(file => 'barnsleyFern.png')</lang> Output image: Barnsley fern

SPL

<lang spl>w,h = #.scrsize() x,y = 0 >

 r = #.rnd(100)
 ? r<85, x,y = f2(x,y)
 ? r!<85 & r<92, x,y = f3(x,y)
 ? r!<92 & r<99, x,y = f4(x,y)
 ? r!<99, x,y = f1(y)
 #.drawpoint(x/10*w+w/2,h-y/10*h,0,0.5,0,0.1)

< f1(y) <= 0, 0.16*y f2(x,y) <= 0.85*x+0.04*y, -0.04*x+0.85*y+1.6 f3(x,y) <= 0.2*x-0.26*y, 0.23*x+0.22*y+1.6 f4(x,y) <= -0.15*x+0.28*y, 0.26*x+0.24*y+0.44</lang>

Standard ML

Works with PolyML. Random generator copy from the Random_numbers#Standard_ML task. Window slimmed down from Animation#Standard_ML. <lang Standard ML>open XWindows ; open Motif ;

val uniformdeviate = fn seed =>

let
 val in31m = (Real.fromInt o Int32.toInt ) (getOpt (Int32.maxInt,0) );
 val in31 = in31m +1.0;
 val (s1,s2,v) = (41160.0 , 950665216.0 , Real.realFloor seed);
 val (val1,val2) = (v*s1, v*s2);
 val next1 = Real.fromLargeInt (Real.toLargeInt IEEEReal.TO_NEGINF (val1/in31)) ;
 val next2 = Real.rem(Real.realFloor(val2/in31) , in31m );
 val valt = val1+val2 - (next1+next2)*in31m;
 val nextt = Real.realFloor(valt/in31m);
 val valt = valt - nextt*in31m;
in
 (valt/in31m,valt)

end;


local

val sizeup = 60.0 ;
fun toI {x=x,y=y} = {x=Real.toInt  IEEEReal.TO_NEAREST (sizeup *x),y=Real.toInt  IEEEReal.TO_NEAREST (sizeup*y)}  ;
val next  = [  (fn {x=x,y=y} =>  {x= 0.0,           y= 0.16*y            })
             , (fn {x=x,y=y} =>  {x= 0.85*x+0.04*y, y= ~0.04*x+0.85*y+1.6})
             , (fn {x=x,y=y} =>  {x= 0.2*x-0.26*y,  y= 0.23*x+0.22*y+1.6 })
             , (fn {x=x,y=y} =>  {x= ~0.15*x+0.28*y,y= 0.26*x+0.24*y+0.44}) ] ;
val seed  = ref 100027.0 

in

fun putNext  1 win usegc coord =  XFlush (XtDisplay win) 
|   putNext  N win usegc coord =
 let
  val (i,ns) =  uniformdeviate ( !seed ) ;
  val _      =  seed := ns  ;
  val fi     =  List.nth (next, List.foldr (fn (a,b) => b + (if i>a then 1 else 0)) 0 [0.1,0.86,0.93,1.0] )  ;
  val nwp    =  fi coord 
 in
     (XDrawPoint (XtWindow win) usegc  ( AddPoint ((XPoint o toI) coord, XPoint {x=300,y=0}) )  ;
      putNext (N-1) win usegc nwp  )
 end
 

end;


val demoWindow = fn () => let

 val shell     =  XtAppInitialise      ""    "demo" "top" [] [ XmNwidth 600, XmNheight 700 ] ;
 val main      =  XmCreateMainWindow   shell    "main"       [ XmNmappedWhenManaged true ]  ;
 val canvas    =  XmCreateDrawingArea  main   "drawarea"     [ XmNwidth 600, XmNheight 700] ;
 val usegc     =  DefaultGC (XtDisplay canvas) ;
 val _         =  XSetForeground usegc 0x4a632d ;
 val drawall   =  fn (w,c,t)=> ( XClearWindow (XtWindow canvas ); putNext 1000000 canvas usegc {x=0.0,y=0.0} ; t )

in

 (
  XtSetCallbacks   canvas [ (XmNexposeCallback ,  drawall)  ] XmNarmCallback ;
  XtManageChild    canvas ;
  XtManageChild    main   ; 
  XtRealizeWidget  shell 
 )

end ; </lang> call

demoWindow () ;

Swift

Output is viewable in a playground.

<lang swift>import UIKit import CoreImage import PlaygroundSupport

let imageWH = 300 let context = CGContext(data: nil,

                       width: imageWH,
                       height: imageWH,
                       bitsPerComponent: 8,
                       bytesPerRow: 0,
                       space: CGColorSpace(name: CGColorSpace.sRGB)!,
                       bitmapInfo: CGImageAlphaInfo.premultipliedFirst.rawValue)!

var x0 = 0.0 var x1 = 0.0 var y0 = 0.0 var y1 = 0.0

context.setFillColor(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)) context.fill(CGRect(x: 0, y: 0, width: imageWH, height: imageWH)) context.setFillColor(#colorLiteral(red: 0.539716677, green: 1, blue: 0.265400682, alpha: 1))

for _ in 0..<100_000 {

   switch Int(arc4random()) % 100 {
   case 0:
       x1 = 0
       y1 = 0.16 * y0
   case 1...7:
       x1 = -0.15 * x0 + 0.28 * y0
       y1 = 0.26 * x0 + 0.24 * y0 + 0.44
   case 8...15:
       x1 = 0.2 * x0 - 0.26 * y0
       y1 = 0.23 * x0 + 0.22 * y0 + 1.6
   default:
       x1 = 0.85 * x0 + 0.04 * y0
       y1 = -0.04 * x0 + 0.85 * y0 + 1.6
   }
   
   context.fill(CGRect(x: 30 * x1 + Double(imageWH) / 2.0, y: 30 * y1,
                       width: 1, height: 1))
   
   (x0, y0) = (x1, y1)

}

let uiImage = UIImage(cgImage: context.makeImage()!)</lang>

TI-83 BASIC

<lang ti83b>ClrDraw Input "ITERS:",M 0,0,1→[A] [[0,0,0][0,.16,0][0,0,1]]→[B] [[.85,-.04,0][.04,.85,0][0,1.6,1]]→[C] [[.2,.23,0][-.26,.22,0][0,1.6,1]]→[D] [[-.15,.26,0][.28,.24,0][0,.44,1]]→[E] 0→I While I<M randInt(1,100)→R

If R=1 Then [A][B]→[A] 101→R End

If R<86 Then [A][C]→[A] 101→R End

If R<93 Then [A][D]→[A] 101→R End

If R<101:Then [A][E]→[A] End

round([A](1,1)*8+31,0)→E round([A](1,2)*8,0)→F Pxl-On(E,F) I+1→I End</lang>

Unicon

Library: graphics

<lang unicon> link graphics

global x, y

procedure main()

   &window := open("FERN", "g", "size=400,400", "bg=black")
   x := y := 0
   repeat {

draw() delay(30) if *Pending() > 0 then { case Event() of { "q"|"\e": return

           }

}

   }

end

procedure next_point()

   local nx, ny, r
   nx := 0.0
   ny := 0.0
   r := ?100
   if r < 1 then {

nx := 0.0 ny := 0.16 * y

   } else if r < 86 then {

nx := 0.85 * x + 0.04 * y ny := -0.04 * x + 0.85 * y + 1.6

   } else if r < 93 then {

nx := 0.2 * x - 0.26 * y ny := 0.23 * x + 0.22 * y + 1.6

   } else {

nx := -0.15 * x + 0.28 * y ny := 0.26 * x + 0.24 * y + 0.44

   }
   x := nx
   y := ny

end

procedure map(v:real, a, b, c, d)

   return (v - a) / (b - a) * (d - c) + c;

end

procedure draw_point()

   local px, py
   px := map(x, -2.1820, 2.6558, 0.0, 400.0)
   py := map(y, 0.0, 9.9983, 400.0, 0.0)
   Fg("green")
   DrawPoint(px, py)

end

procedure draw()

   every i := 0 to 10000 do {

draw_point() next_point()

   }

end </lang>

VBA

<lang vb>Private Sub plot_coordinate_pairs(x As Variant, y As Variant)

   Dim chrt As Chart
   Set chrt = ActiveSheet.Shapes.AddChart.Chart
   With chrt
       .ChartType = xlXYScatter
       .HasLegend = False
       .SeriesCollection.NewSeries
       .SeriesCollection.Item(1).XValues = x
       .SeriesCollection.Item(1).Values = y
   End With

End Sub Public Sub barnsley_fern()

   Const MAX = 50000
   Dim x(MAX) As Double
   Dim y(MAX) As Double
   x(0) = 0: y(0) = 0
   For i = 1 To MAX
       Select Case CInt(100 * Rnd)
           Case 0 To 1
               x(i) = 0
               y(i) = 0.16 * y(i - 1)
           Case 2 To 85
               x(i) = 0.85 * x(i - 1) + 0.04 * y(i - 1)
               y(i) = -0.04 * x(i - 1) + 0.85 * y(i - 1) + 1.6
           Case 86 To 92
               x(i) = 0.2 * x(i - 1) - 0.26 * y(i - 1)
               y(i) = 0.23 * x(i - 1) + 0.22 * y(i - 1) + 1.6
           Case 93 To 100
               x(i) = -0.15 * x(i - 1) + 0.28 * y(i - 1)
               y(i) = 0.26 * x(i - 1) + 0.24 * y(i - 1) + 0.44
       End Select
   Next i
   plot_coordinate_pairs x, y

End Sub</lang> /* Visual Basic .NET */ Section added

Visual Basic .NET

Works with: Visual Basic .NET version 2011

<lang vbnet>' Barnsley Fern - 11/11/2019 Public Class BarnsleyFern

   Private Sub BarnsleyFern_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
       Const Height = 800
       Dim x, y, xn, yn As Double
       Dim f As Double = Height / 10.6
       Dim offset_x As UInteger = Height \ 4 - Height \ 40
       Dim n, r As UInteger
       Dim Bmp As New Drawing.Bitmap(Height \ 2, Height) 'x,y

'In Form: xPictureBox As PictureBox(800,400)

       xPictureBox.Image = Bmp
       For n = 1 To Height * 50
           r = Int(Rnd() * 100)      ' f from 0 to 99
           Select Case r
               Case 0 To 84
                   xn = 0.85 * x + 0.04 * y
                   yn = -0.04 * x + 0.85 * y + 1.6
               Case 85 To 91
                   xn = 0.2 * x - 0.26 * y
                   yn = 0.23 * x + 0.22 * y + 1.6
               Case 92 To 98
                   xn = -0.15 * x + 0.28 * y
                   yn = 0.26 * x + 0.24 * y + 0.44
               Case Else
                   xn = 0
                   yn = 0.16 * y
           End Select
           x = xn : y = yn
           Bmp.SetPixel(offset_x + x * f, Height - y * f, Color.FromArgb(0, 255, 0)) 'x,y  'r,g,b
       Next n
   End Sub 'Paint

End Class 'BarnsleyFern</lang>

Wren

Translation of: Kotlin
Library: DOME

<lang ecmascript>import "graphics" for Canvas, Color import "dome" for Window import "random" for Random

var Rand = Random.new()

class BarnsleyFern {

   construct new(width, height, points) {
       Window.title = "Barnsley Fern"
       Window.resize(width, height)
       Canvas.resize(width, height)
       _w = width
       _h = height
       _n = points
   }
   init() {
       createFern()
   }
   createFern() {
       var x = 0
       var y = 0
       var c = Color.hex("#32cd32")
       for (i in 0..._n) {
           var tx
           var ty
           var r = Rand.float()
           if (r <= 0.01) {
               tx = 0
               ty = 0.16 * y
           } else if (r <= 0.86) {
               tx =  0.85 * x + 0.04 * y
               ty = -0.04 * x + 0.85 * y + 1.6
           } else if (r <= 0.93) {
               tx = 0.2  * x - 0.26 * y
               ty = 0.23 * x + 0.22 * y + 1.6
           } else {
               tx = -0.15 * x + 0.28 * y
               ty =  0.26 * x + 0.24 * y + 0.44
           }
           x = tx
           y = ty
           Canvas.pset((_w/2 + x * _w/11).round, (_h - y * _h/11).round, c)
       }
   }
   update() {}
   draw(alpha) {}

}

var Game = BarnsleyFern.new(640, 640, 200000)</lang>

XPL0

<lang XPL0>int N, R; real NX, NY, X, Y; [SetVid($12); \set 640x480x4 VGA graphics (on PC or RPi) X:= 0.0; Y:= 0.0; for N:= 0 to 200_000 do

       [R:= Ran(100);  \0..99
       case of
       R < 1:  [NX:= 0.0;              NY:= 0.16*Y];
       R < 8:  [NX:= 0.20*X - 0.26*Y;  NY:= 0.23*X + 0.22*Y + 1.60];
       R < 15: [NX:=-0.15*X + 0.28*Y;  NY:= 0.26*X + 0.24*Y + 0.44]
       other   [NX:= 0.85*X + 0.04*Y;  NY:=-0.04*X + 0.85*Y + 1.60];
       X:= NX;  Y:= NY;
       Point(320+fix(X*40.0), 440-fix(Y*40.0), 2\green\);
       ]

]</lang>

Yabasic

Translation of: ZX Spectrum Basic

Classic style <lang Yabasic>10 REM Fractal Fern 20 LET wid = 800 : LET hei = 600 : open window wid, hei : window origin "cb" 25 backcolor 0, 0, 0 : color 0, 255, 0 : clear window 30 LET maxpoints=wid*hei/2: LET x=0: LET y=0 40 FOR n=1 TO maxpoints 50 LET p=RAN(100) 60 IF p<=1 LET nx=0: LET ny=0.16*y: GOTO 100 70 IF p<=8 LET nx=0.2*x-0.26*y: LET ny=0.23*x+0.22*y+1.6: GOTO 100 80 IF p<=15 LET nx=-0.15*x+0.28*y: LET ny=0.26*x+0.24*y+0.44: GOTO 100 90 LET nx=0.85*x+0.04*y: LET ny=-0.04*x+0.85*y+1.6 100 LET x=nx: LET y=ny 110 DOT x*wid/12,y*hei/12 120 NEXT n</lang> Modern style <lang Yabasic>REM Fractal Fern wid = 800 : hei = 600 : open window wid, hei : window origin "cb" backcolor 0, 0, 0 : color 0, 255, 0 : clear window maxpoints = wid * hei / 2 : x = 0 : y = 0 for n = 1 to maxpoints

  p = ran(100)
  if p <= 1 then nx = 0 : ny = 0.16 * y
  elseif p <= 8 then nx = 0.2 * x - 0.26 * y : ny = 0.23 * x + 0.22 * y + 1.6
  elseif p <= 15 then nx = -0.15 * x + 0.28 * y : ny = 0.26 * x + 0.24 * y + 0.44
  else nx = 0.85 * x + 0.04 * y : ny = -0.04 * x + 0.85 * y + 1.6
  end if
  x = nx : y = ny
  dot x * wid / 12, y * hei / 12

next</lang>

zkl

Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl

Translation of: Java

<lang zkl>fcn barnsleyFern(){

  w,h:=640,640;
  bitmap:=PPM(w+1,h+1,0xFF|FF|FF);  // White background
  x,y, nx,ny:=0.0, 0.0, 0.0, 0.0;
  do(0d100_000){
     r:=(0).random(100);  // [0..100)%
     if     (r<= 1) nx,ny= 0, 		      0.16*y;
     else if(r<= 8) nx,ny= 0.2*x  - 0.26*y,  0.23*x + 0.22*y + 1.6;
     else if(r<=15) nx,ny=-0.15*x + 0.28*y,  0.26*x + 0.24*y + 0.44;
     else           nx,ny= 0.85*x + 0.04*y, -0.04*x + 0.85*y + 1.6;
     x,y=nx,ny;
     bitmap[w/2 + x*60, y*60] = 0x00|FF|00;  // Green dot
  }
  bitmap.writeJPGFile("barnsleyFern.jpg");

}();</lang>

ZX Spectrum Basic

Translation of: zkl

<lang zxbasic>10 REM Fractal Fern 20 PAPER 7: BORDER 7: BRIGHT 1: INK 4: CLS 30 LET maxpoints=20000: LET x=0: LET y=0 40 FOR n=1 TO maxpoints 50 LET p=RND*100 60 IF p<=1 THEN LET nx=0: LET ny=0.16*y: GO TO 100 70 IF p<=8 THEN LET nx=0.2*x-0.26*y: LET ny=0.23*x+0.22*y+1.6: GO TO 100 80 IF p<=15 THEN LET nx=-0.15*x+0.28*y: LET ny=0.26*x+0.24*y+0.44: GO TO 100 90 LET nx=0.85*x+0.04*y: LET ny=-0.04*x+0.85*y+1.6 100 LET x=nx: LET y=ny 110 PLOT x*17+127,y*17 120 NEXT n </lang> It is recommended to run on an emulator that supports running at full speed.