To be able to edit code and run cells, you need to run the notebook yourself. Where would you like to run the notebook?

In the cloud (experimental)

Binder is a free, open source service that runs scientific notebooks in the cloud! It will take a while, usually 2-7 minutes to get a session.

On your computer

(Recommended if you want to store your changes.)

  1. Copy the notebook URL:
  2. Run Pluto

    (Also see: How to install Julia and Pluto)

  3. Paste URL in the Open box

Frontmatter

If you are publishing this notebook on the web, you can set the parameters below to provide HTML metadata. This is useful for search engines and social media.

Author 1
👀 Reading hidden code
begin
import Pkg
Pkg.activate(mktempdir())
end
❔
  Activating new project at `/tmp/jl_tTvwMz`
120 ms
👀 Reading hidden code
begin
# we will work with the package Images.jl, and to display images on the screen,
# we also need ImageIO and ImageMagick
Pkg.add(["Images", "ImageIO", "ImageMagick"])
# we also use PlutoUI for some interactivity
Pkg.add("PlutoUI")
# now that it is installed, we can import it inside out notebook:
using Images
using PlutoUI
end
❔
    Updating registry at `~/.julia/registries/General.toml`
   Resolving package versions...
    Updating `/tmp/jl_tTvwMz/Project.toml`
  [82e4d734] + ImageIO v0.6.9
  [6218d12a] + ImageMagick v1.4.0
  [916415d5] + Images v0.26.2
    Updating `/tmp/jl_tTvwMz/Manifest.toml`
  [621f4979] + AbstractFFTs v1.5.0
  [79e6a3ab] + Adapt v3.7.2
  [66dad0bd] + AliasTables v1.1.3
  [ec485272] + ArnoldiMethod v0.4.0
  [4fba245c] + ArrayInterface v7.5.1
  [13072b0f] + AxisAlgorithms v1.1.0
  [39de3d68] + AxisArrays v0.4.7
  [62783981] + BitTwiddlingConvenienceFunctions v0.1.6
  [fa961155] + CEnum v0.5.0
  [2a0fbf3d] + CPUSummary v0.2.6
  [aafaddc9] + CatIndices v0.2.2
  [d360d2e6] + ChainRulesCore v1.25.1
  [9e997f8a] + ChangesOfVariables v0.1.9
  [fb6a15b2] + CloseOpenIntervals v0.1.13
  [aaaa29a8] + Clustering v0.15.8
  [35d6a980] + ColorSchemes v3.29.0
  [3da002f7] + ColorTypes v0.12.0
  [c3611d14] + ColorVectorSpace v0.11.0
  [5ae59095] + Colors v0.13.0
  [bbf7d656] + CommonSubexpressions v0.3.1
  [34da2185] + Compat v4.16.0
  [ed09eef8] + ComputationalResources v0.3.2
  [187b0558] + ConstructionBase v1.5.8
  [150eb455] + CoordinateTransformations v0.6.3
  [adafc99b] + CpuId v0.3.1
  [dc8bdbbb] + CustomUnitRanges v1.0.2
  [9a962f9c] + DataAPI v1.16.0
  [864edb3b] + DataStructures v0.18.20
  [163ba53b] + DiffResults v1.1.0
  [b552c78f] + DiffRules v1.15.1
  [b4f34e82] + Distances v0.10.12
  [ffbed154] + DocStringExtensions v0.9.3
  [4f61f5a4] + FFTViews v0.3.2
  [7a1cc6ca] + FFTW v1.8.1
  [5789e2e9] + FileIO v1.17.0
  [53c48c17] + FixedPointNumbers v0.8.5
  [f6369f11] + ForwardDiff v0.10.38
  [a2bd30eb] + Graphics v1.1.3
  [86223c79] + Graphs v1.12.0
  [2c695a8d] + HistogramThresholding v0.3.1
  [3e5b6fbb] + HostCPUFeatures v0.1.17
  [615f187c] + IfElse v0.1.1
  [2803e5a7] + ImageAxes v0.6.12
  [c817782e] + ImageBase v0.1.7
  [cbc4b850] + ImageBinarization v0.3.1
  [f332f351] + ImageContrastAdjustment v0.3.12
  [a09fc81d] + ImageCore v0.10.5
  [89d5987c] + ImageCorners v0.1.3
  [51556ac3] + ImageDistances v0.2.17
  [6a3955dd] + ImageFiltering v0.7.9
  [82e4d734] + ImageIO v0.6.9
  [6218d12a] + ImageMagick v1.4.0
  [bc367c6b] + ImageMetadata v0.9.10
  [787d08f9] + ImageMorphology v0.4.5
  [2996bd0c] + ImageQualityIndexes v0.3.7
  [80713f31] + ImageSegmentation v1.8.4
  [4e3cecfd] + ImageShow v0.3.8
  [02fcd773] + ImageTransformations v0.10.1
  [916415d5] + Images v0.26.2
  [9b13fd28] + IndirectArrays v1.0.0
  [d25df0c9] + Inflate v0.1.5
  [1d092043] + IntegralArrays v0.1.6
  [a98d9a8b] + Interpolations v0.15.1
  [8197267c] + IntervalSets v0.7.10
  [3587e190] + InverseFunctions v0.1.17
  [92d709cd] + IrrationalConstants v0.2.4
  [c8e1da08] + IterTools v1.4.0
  [033835bb] + JLD2 v0.5.11
  [692b3bcd] + JLLWrappers v1.7.0
  [b835a17e] + JpegTurbo v0.1.5
  [10f19ff3] + LayoutPointers v0.1.17
  [8cdb02fc] + LazyModules v0.3.1
  [2ab3a3ac] + LogExpFunctions v0.3.28
  [bdcacae8] + LoopVectorization v0.12.171
  [1914dd2f] + MacroTools v0.5.15
  [d125e4d3] + ManualMemory v0.1.8
  [dbb5928d] + MappedArrays v0.4.2
  [626554b9] + MetaGraphs v0.8.0
  [e1d29d7a] + Missings v1.2.0
  [e94cdb99] + MosaicViews v0.3.4
  [77ba4419] + NaNMath v1.0.3
  [b8a86587] + NearestNeighbors v0.4.21
  [f09324ee] + Netpbm v1.1.1
  [6fe1bfb0] + OffsetArrays v1.15.0
  [52e1d378] + OpenEXR v0.3.3
  [bac558e1] + OrderedCollections v1.8.0
  [f57f5aa1] + PNGFiles v0.4.4
  [5432bcbf] + PaddedViews v0.5.12
  [d96e819e] + Parameters v0.12.3
  [eebad327] + PkgVersion v0.3.3
  [1d0040c9] + PolyesterWeave v0.2.2
  [f27b6e38] + Polynomials v4.0.19
  [aea7be01] + PrecompileTools v1.2.1
  [21216c6a] + Preferences v1.4.3
  [92933f4c] + ProgressMeter v1.10.2
  [43287f4e] + PtrArrays v1.3.0
  [4b34888f] + QOI v1.0.1
  [94ee1d12] + Quaternions v0.7.6
  [b3c3ace0] + RangeArrays v0.3.2
  [c84ed2f1] + Ratios v0.4.5
  [c1ae055f] + RealDot v0.1.0
  [3cdcf5f2] + RecipesBase v1.3.4
  [189a3867] + Reexport v1.2.2
  [dee08c22] + RegionTrees v0.3.2
  [ae029012] + Requires v1.3.1
  [6038ab10] + Rotations v1.7.1
  [fdea26ae] + SIMD v3.7.1
  [94e857df] + SIMDTypes v0.1.0
  [476501e8] + SLEEFPirates v0.6.43
  [efcf1570] + Setfield v1.1.2
  [699a6c99] + SimpleTraits v0.9.4
  [47aef6b3] + SimpleWeightedGraphs v1.4.0
  [45858cf5] + Sixel v0.1.3
  [a2af1166] + SortingAlgorithms v1.2.1
  [276daf66] + SpecialFunctions v2.5.0
  [cae243ae] + StackViews v0.1.1
  [aedffcd0] + Static v0.8.9
  [0d7ed370] + StaticArrayInterface v1.6.0
  [90137ffa] + StaticArrays v1.9.13
  [1e83bf80] + StaticArraysCore v1.4.3
  [82ae8749] + StatsAPI v1.7.0
  [2913bbd2] + StatsBase v0.34.4
  [62fd8b95] + TensorCore v0.1.1
  [8290d209] + ThreadingUtilities v0.5.2
  [731e570b] + TiffImages v0.11.3
  [06e1c1a7] + TiledIteration v0.5.0
  [3bb67fe8] + TranscodingStreams v0.11.3
  [3a884ed6] + UnPack v1.0.2
  [3d5dd08c] + VectorizationBase v0.21.71
  [e3aaa7dc] + WebP v0.1.3
  [efce3f68] + WoodburyMatrices v1.0.0
  [f5851436] + FFTW_jll v3.3.10+3
  [61579ee1] + Ghostscript_jll v9.55.0+4
  [59f7168a] + Giflib_jll v5.2.3+0
  [c73af94c] + ImageMagick_jll v7.1.1+1
  [905a6f67] + Imath_jll v3.1.11+0
  [1d5cc7b8] + IntelOpenMP_jll v2025.0.4+0
  [aacddb02] + JpegTurbo_jll v3.1.1+0
  [88015f11] + LERC_jll v3.0.0+1
  [d4300ac3] + Libgcrypt_jll v1.11.0+0
  [7e76a0d4] + Libglvnd_jll v1.7.0+0
  [7add5ba3] + Libgpg_error_jll v1.51.1+0
  [94ce4f54] + Libiconv_jll v1.18.0+0
  [89763e89] + Libtiff_jll v4.4.0+0
  [d3a379c0] + LittleCMS_jll v2.12.0+0
  [856f044c] + MKL_jll v2025.0.1+1
  [18a262bb] + OpenEXR_jll v3.2.4+0
  [643b3616] + OpenJpeg_jll v2.4.0+0
  [efe28fd5] + OpenSpecFun_jll v0.5.6+0
  [02c8fc9c] + XML2_jll v2.13.6+1
  [aed1982a] + XSLT_jll v1.1.42+0
  [4f6342f7] + Xorg_libX11_jll v1.8.6+3
  [0c0b7dd1] + Xorg_libXau_jll v1.0.12+0
  [a3789734] + Xorg_libXdmcp_jll v1.1.5+0
  [1082639a] + Xorg_libXext_jll v1.3.6+3
  [14d82f49] + Xorg_libpthread_stubs_jll v0.1.2+0
  [c7cfdc94] + Xorg_libxcb_jll v1.17.0+3
  [c5fb5394] + Xorg_xtrans_jll v1.5.1+0
  [3161d3a3] + Zstd_jll v1.5.7+1
  [b53b4c65] + libpng_jll v1.6.47+0
  [075b6546] + libsixel_jll v1.10.5+0
  [c5f90fcd] + libwebp_jll v1.4.0+0
  [1317d2d5] + oneTBB_jll v2022.0.0+0
  [0dad84c5] + ArgTools
  [56f22d72] + Artifacts
  [2a0f44e3] + Base64
  [ade2ca70] + Dates
  [8ba89e20] + Distributed
  [f43a241f] + Downloads
  [7b1f6079] + FileWatching
  [9fa8497b] + Future
  [b77e0a4c] + InteractiveUtils
  [4af54fe1] + LazyArtifacts
  [b27032c2] + LibCURL
  [76f85450] + LibGit2
  [8f399da3] + Libdl
  [37e2e46d] + LinearAlgebra
  [56ddb016] + Logging
  [d6f4376e] + Markdown
  [a63ad114] + Mmap
  [ca575930] + NetworkOptions
  [44cfe95a] + Pkg
  [de0858da] + Printf
  [3fa0cd96] + REPL
  [9a3f8284] + Random
  [ea8e919c] + SHA
  [9e88b42a] + Serialization
  [1a1011a3] + SharedArrays
  [6462fe0b] + Sockets
  [2f01184e] + SparseArrays
  [10745b16] + Statistics
  [4607b0f0] + SuiteSparse
  [fa267f1f] + TOML
  [a4e569a6] + Tar
  [8dfed614] + Test
  [cf7118a7] + UUIDs
  [4ec0a83e] + Unicode
  [e66e0078] + CompilerSupportLibraries_jll
  [deac9b47] + LibCURL_jll
  [29816b5a] + LibSSH2_jll
  [c8ffd9c3] + MbedTLS_jll
  [14a3606d] + MozillaCACerts_jll
  [4536629a] + OpenBLAS_jll
  [05823500] + OpenLibm_jll
  [83775a58] + Zlib_jll
  [8e850b90] + libblastrampoline_jll
  [8e850ede] + nghttp2_jll
  [3f19e933] + p7zip_jll
   Resolving package versions...
    Updating `/tmp/jl_tTvwMz/Project.toml`
  [7f904dfe] + PlutoUI v0.7.23
    Updating `/tmp/jl_tTvwMz/Manifest.toml`
  [6e696c72] + AbstractPlutoDingetjes v1.3.2
  [47d2ed2b] + Hyperscript v0.0.4
  [ac1192a8] + HypertextLiteral v0.9.5
  [b5f81e59] + IOCapture v0.2.5
  [682c06a0] + JSON v0.21.4
  [69de0a69] + Parsers v2.8.1
  [7f904dfe] + PlutoUI v0.7.23
  [410a4b4d] + Tricks v0.1.10
11.4 s
👀 Reading hidden code
using LinearAlgebra
311 μs
svd_compress (generic function with 1 method)
👀 Reading hidden code
function svd_compress(i, N)
📚 = svd(i)
📚.U[:,1:N] * Diagonal(📚.S[1:N]) * 📚.Vt[1:N,:] .|> Gray
end
739 μs
👀 Reading hidden code
@bind n Slider(1:20)
227 ms
Error message

MethodError: no method matching getindex(::Missing, ::String)

Stack trace

Here is what happened, the most recent locations are first:

  1. unwrap_js_image_data(raw_js_image_data::Missing)
    	# So to get the red values for each pixel, we take every 4th value, starting at 	# the 1st:	reds_flat = UInt8.(raw_js_image_data["data"][1:4:end])	greens_flat = UInt8.(raw_js_image_data["data"][2:4:end])	blues_flat = UInt8.(raw_js_image_data["data"][3:4:end])
  2. Show more...
beep boop CRASH 🤖
let
i = process_raw_js_image_data(img)
svd_compress(i .|> red, n)
end
👀 Reading hidden code
---
@bind img html"""
<canvas width="200" height="200" style="position: relative; display: block;"></canvas>
<button>Clear</button>

<script>
const canvas = this.querySelector("canvas")
const button = this.querySelector("button")
const ctx = canvas.getContext("2d")

function send_image(){
// 🐸 We send the value back to Julia 🐸 //
canvas.value = {
width: 200,
height: 200,
data: ctx.getImageData(0,0,200,200).data,
}
canvas.dispatchEvent(new CustomEvent("input"))
}

var prev_pos = [80, 40]

function clear(){
ctx.fillStyle = '#ffecec'
ctx.fillRect(0, 0, 200, 200)

send_image()
}
clear()

function onmove(e){
const new_pos = [e.layerX, e.layerY]
ctx.lineTo(...new_pos)
ctx.stroke()
prev_pos = new_pos

send_image()
}

canvas.onmousedown = e => {
prev_pos = [e.layerX, e.layerY]
ctx.strokeStyle = '#003d6d'
ctx.lineWidth = 5
ctx.beginPath()
ctx.moveTo(...prev_pos)
canvas.onmousemove = onmove
}

button.onclick = clear

canvas.onmouseup = e => {
canvas.onmousemove = null
}

// Fire a fake mousemoveevent to show something
onmove({layerX: 130, layerY: 160})

</script>
"""
👀 Reading hidden code
44.2 ms
unwrap_js_image_data (generic function with 1 method)
function unwrap_js_image_data(raw_js_image_data)
# the raw image data is a long byte array, we need to transform it into something
# more "Julian" - something with more _structure_.
# The encoding of the raw byte stream is:
# every 4 bytes is a single pixel
# every pixel has 4 values: Red, Green, Blue, Alpha
# (we ignore alpha for this notebook)
# So to get the red values for each pixel, we take every 4th value, starting at
# the 1st:
reds_flat = UInt8.(raw_js_image_data["data"][1:4:end])
greens_flat = UInt8.(raw_js_image_data["data"][2:4:end])
blues_flat = UInt8.(raw_js_image_data["data"][3:4:end])
# but these are still 1-dimensional arrays, nicknamed 'flat' arrays
# We will 'reshape' this into 2D arrays:
width = raw_js_image_data["width"]
height = raw_js_image_data["height"]
# shuffle and flip to get it in the right shape
reds = reshape(reds_flat, (width, height))' / 255.0
greens = reshape(greens_flat, (width, height))' / 255.0
blues = reshape(blues_flat, (width, height))' / 255.0
(reds=reds, greens=greens, blues=blues)
end
👀 Reading hidden code
1.4 ms
process_raw_js_image_data (generic function with 1 method)
function process_raw_js_image_data(raw_js_image_data)
# we have our 2D array for each color
# Let's create a single 2D array, where each value contains the R, G and B value of
# that pixel
RGB.(unwrap_js_image_data(raw_js_image_data)...)
end
👀 Reading hidden code
450 μs