diff --git a/Manifest.toml b/Manifest.toml
index ae3e78a..cac0bfb 100644
--- a/Manifest.toml
+++ b/Manifest.toml
@@ -2,7 +2,7 @@
 
 julia_version = "1.11.4"
 manifest_format = "2.0"
-project_hash = "0a18a0873213e0e8660a5eb202a1fa9f1621a652"
+project_hash = "6ff2a6774137725477bae8d2113d6856bc327396"
 
 [[deps.AbstractFFTs]]
 deps = ["LinearAlgebra"]
@@ -1093,6 +1093,11 @@ git-tree-sha1 = "b9039e93773ddcfc828f12aadf7115b4b4d225f5"
 uuid = "b3c3ace0-ae52-54e7-9d0b-2c1406fd6b9d"
 version = "0.3.2"
 
+[[deps.Ranges]]
+git-tree-sha1 = "b5dd6c6cba97d1fa0641797cb08d4fd913c5fcd5"
+uuid = "eb7db99b-64ae-4b81-85c2-3439b6569b78"
+version = "0.1.0"
+
 [[deps.Ratios]]
 deps = ["Requires"]
 git-tree-sha1 = "1342a47bf3260ee108163042310d26f2be5ec90b"
diff --git a/Project.toml b/Project.toml
index 9661941..73bcad6 100644
--- a/Project.toml
+++ b/Project.toml
@@ -7,10 +7,12 @@ version = "0.1.0"
 FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
 Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
 Luxor = "ae8d54c2-7ccd-5906-9d76-62fc9837b5bc"
+Ranges = "eb7db99b-64ae-4b81-85c2-3439b6569b78"
 VideoIO = "d6d074c3-1acf-5d4c-9a43-ef38773959a2"
 
 [compat]
 FileIO = "1.17.0"
 Images = "0.26.2"
 Luxor = "4.2.0"
+Ranges = "0.1.0"
 VideoIO = "1.1.1"
diff --git a/src/fractal.jl b/src/fractal.jl
new file mode 100644
index 0000000..a941e3e
--- /dev/null
+++ b/src/fractal.jl
@@ -0,0 +1,60 @@
+using Luxor, Ranges
+include("image.jl")
+
+function sample(m, u, v)
+    width, height = size(m)
+    i = trunc(Int, u * width)
+    j = trunc(Int, v * height)
+    if i <= 0 || i > width || j <= 0 || j > height
+        return 0.
+    else
+        return greyscale(m[i,j])
+    end
+end
+
+function is_stable(m, z1, z2, z)
+    iter = 1000
+    x1 = real(z1)
+    y1 = imag(z1)
+    x2 = real(z2)
+    y2 = imag(z2)
+    c = z
+    for _ in 1:iter
+        if abs(z) > 2
+            return false
+        end
+        # Sample the image at position z
+        u = (real(z) - x1) / (x2 - x1)
+        v = (imag(z) - y1) / (y2 - y1)
+        f = sample(m, u, v)
+        if f == 0
+            z = z^2
+        else
+            z = z^2 + c
+        end
+    end
+    true
+end
+
+function mandel(m, z1::Complex, z2::Complex)
+    width, height = size(m)
+    buffer = zeros(ARGB32, width, height)
+    for (i, x) in enumerate(range(real(z1), real(z2), width))
+        for (j, y) in enumerate(range(imag(z1), imag(z2), height))
+            t = greyscale(m[i,j])
+            s = is_stable(m, z1, z2, x + y * im)
+            if t > 0.5
+                if s
+                    buffer[i,j] = colorant"white"
+                else
+                    buffer[i,j] = colorant"blue"
+                end
+            else
+                if s
+                    buffer[i,j] = colorant"red"
+                end
+            end
+        end
+    end
+    return buffer
+end
diff --git a/src/image.jl b/src/image.jl
new file mode 100644
index 0000000..3eaf2f9
--- /dev/null
+++ b/src/image.jl
@@ -0,0 +1,8 @@
+using Images
+
+"""
+Converts image to grayscale
+"""
+function greyscale(c::Images.RGB)::Real
+    return Real(c.r)
+end