Mandelbrot set

You are encouraged to solve this task according to the task description, using any language you may know.


Task

Generate and draw the Mandelbrot set.



Note that there are many algorithms to draw Mandelbrot set and there are many functions which generate it .




import Foundation
import Numerics
import QDBMP
 
public typealias Color = (red: UInt8, green: UInt8, blue: UInt8)
 
public class BitmapDrawer {
  public let imageHeight: Int
  public let imageWidth: Int
 
  var grid: [[Color?]]
 
  private let bmp: OpaquePointer
 
  public init(height: Int, width: Int) {
    self.imageHeight = height
    self.imageWidth = width
    self.grid = [[Color?]](repeating: [Color?](repeating: nil, count: height), count: width)
    self.bmp = BMP_Create(UInt(width), UInt(height), 24)
 
    checkError()
  }
 
  deinit {
    BMP_Free(bmp)
  }
 
  private func checkError() {
    let err = BMP_GetError()
 
    guard err == BMP_STATUS(0) else {
      fatalError("\(err)")
    }
  }
 
  public func save(to path: String = "~/Desktop/out.bmp") {
    for x in 0..<imageWidth {
      for y in 0..<imageHeight {
        guard let color = grid[x][y] else { continue }
 
        BMP_SetPixelRGB(bmp, UInt(x), UInt(y), color.red, color.green, color.blue)
        checkError()
      }
    }
 
    (path as NSString).expandingTildeInPath.withCString {s in
      BMP_WriteFile(bmp, s)
    }
  }
 
  public func setPixel(x: Int, y: Int, to color: Color?) {
    grid[x][y] = color
  }
}
 
let imageSize = 10_000
let canvas = BitmapDrawer(height: imageSize, width: imageSize)
let maxIterations = 256
let cxMin = -2.0
let cxMax = 1.0
let cyMin = -1.5
let cyMax = 1.5
let scaleX = (cxMax - cxMin) / Double(imageSize)
let scaleY = (cyMax - cyMin) / Double(imageSize)
 
for x in 0..<imageSize {
  for y in 0..<imageSize {
    let cx = cxMin + Double(x) * scaleX
    let cy = cyMin + Double(y) * scaleY
 
    let c = Complex(cx, cy)
    var z = Complex(0.0, 0.0)
    var i = 0
 
    for t in 0..<maxIterations {
      if z.magnitude > 2 {
        break
      }
 
      z = z * z + c
      i = t
    }
 
    canvas.setPixel(x: x, y: y, to: Color(red: UInt8(i), green: UInt8(i), blue: UInt8(i)))
  }
}
 
canvas.save()