From f5d0b915f7c6b01c92b513fafcffb9d5f1cbb12c Mon Sep 17 00:00:00 2001 From: Gerhard Dorn <67096719+dorn-gerhard@users.noreply.github.com> Date: Sat, 2 Dec 2023 15:02:42 +0100 Subject: [PATCH] update help and docstring, add tests for DrawCanvas --- src/WebcamInput.jl | 216 +++++++++++++++++++++++---------------------- test/runtests.jl | 10 ++- 2 files changed, 120 insertions(+), 106 deletions(-) diff --git a/src/WebcamInput.jl b/src/WebcamInput.jl index 05472c3a..021f50a3 100644 --- a/src/WebcamInput.jl +++ b/src/WebcamInput.jl @@ -1,5 +1,5 @@ ### A Pluto.jl notebook ### -# v0.19.14 +# v0.19.32 using Markdown using InteractiveUtils @@ -21,7 +21,8 @@ begin import Pkg Pkg.activate(temp=true) Pkg.add(["ImageShow", "ImageIO", "PNGFiles"]) - using ImageShow, ImageIO, PNGFiles # these packages are only loaded in this notebook (to see the images), not in the PlutoUI package + using ImageShow, ImageIO + using PNGFiles # these packages are only loaded in this notebook (to see the images), not in the PlutoUI package Pkg.activate(Base.current_project(@__DIR__)) Pkg.instantiate() @@ -206,27 +207,30 @@ const css = @htl(""""""); # ╔═╡ 3d2ed3d4-60a7-416c-aaae-4dc662127f5b -const help = @htl(""" +const help(input_type = "Webcam") = @htl("""
-

Welcome to the PlutoUI Webcam!

+

Welcome to the PlutoUI $(input_type)!

-

👉🏾 To disable this help message, you can use WebcamInput(;help=false)

+

👉🏾 To disable this help message, you can use $(input_type)Input(;help=false)

-

👉🏾 The bound value will be a Matrix{RGB}. By default, this will be displayed using text, but if you add import ImageShow, ImageIO somewhere in your notebook, it will be displayed as an image.

+

👉🏾 The bound (return) value will be a Matrix{$(input_type == "Webcam" ? "RGB" : "Gray")}. By default, this will be displayed using text, but if you add import ImageShow, ImageIO somewhere in your notebook, it will be displayed as an image.

- - + +
default
with import ImageShow, ImageIO
-

👉🏾 Check out the Live docs for WebcamInput to learn more!

+

👉🏾 Check out the Live docs for $(input_type)Input to learn more!

""") +# ╔═╡ 0de03ade-682d-41b7-a617-2d2ad3e8aa0c +help("DrawCanvas") + # ╔═╡ 06062a16-d9e1-46ef-95bd-cdae8b03bafd function webcam_html(webcam) @@ -480,24 +484,40 @@ md""" # DrawCanvas """ +# ╔═╡ df4f5b5f-664c-4082-82d8-25c6c99c6637 +const standard_gray_default_avoid_allocs(width = 300, height = 300) = ImageDataToRGBA(Gray{N0f8}, Dict{Any,Any}( + "width" => width, "height" => height, + "data" => [UInt8(255) for _ in 1:width*height] +)) + +# ╔═╡ ecbefadd-63d6-404a-98b8-b36ec92552fc +standard_gray_default_avoid_allocs |> typeof + +# ╔═╡ 1b72472c-ce91-474d-8695-e7a2b2633366 +const standard_gray_default = collect(standard_gray_default_avoid_allocs(100,100)) + +# ╔═╡ 821d603d-df17-43ab-993b-f90418766ad7 +md""" +## TODOs: +- add `default` as keyword argument for DrawCanvas(;) + docstring: `default::Matrix{Gray{N0f8}}` set a default image, which is used until the user captures an image. Defaults to a **1x1 transparent image**. + - `default::Matrix{Gray{N0f8}}` set a default image, which is used until the user captures an image. Defaults to a **1x1 transparent image**. +""" + # ╔═╡ 86c652d4-fa0f-4cfa-831f-e9a893351b81 function canvas_html(canvas) - @htl """
""" +""" end # ╔═╡ b31f6b0e-45be-441b-9694-4c786235f132 @@ -649,7 +651,8 @@ begin help::Bool = true avoid_allocs::Bool = false output_size::Tuple{Int64,Int64}=(200,200) - default::Union{Nothing,AbstractMatrix{RGB{N0f8}}}=nothing + # TODO remove me + # default::Union{Nothing,AbstractMatrix{Gray{N0f8}}}=nothing end @doc """ @@ -657,29 +660,28 @@ begin @bind image DrawCanvas(; kwargs...) ``` - A canvas that you can draw on with your mouse / touch screen. The current drawing is returned as a `Matrix{RGB}` via `@bind`. + A canvas that you can draw on with your mouse / touch screen. The current drawing is returned as a `Matrix{Gray}` via `@bind`. - # How to use a `Matrix{RGB}` + # How to use a `Matrix{Gray}` - The output type is of the type `Matrix{RGB{N0f8}}`, let's break that down: - - `Matrix`: This is a 2D **Array**, which you can index like `img[10,20]` to get an entry, of type `RGB{N0f8}`. - - `RGB` (from [ColorTypes.jl](https://github.com/JuliaGraphics/ColorTypes.jl)): a `struct` with fields `r` (Red), `g` (Green) and `b` (Blue), each of type `N0f8`. These are the digital 'channel' value that make up a color. + The output type is of the type `Matrix{Gray{N0f8}}`, let's break that down: + - `Matrix`: This is a 2D **Array**, which you can index like `img[10,20]` to get an entry, of type `Gray{N0f8}`. + - `Gray` (from [ColorTypes.jl](https://github.com/JuliaGraphics/ColorTypes.jl)): a `struct` with a single field `val` of type `N0f8`. This is the gray value with 0 indicating black and 1 indicating white. - `N0f8` (from [FixedPointNumbers.jl](https://github.com/JuliaMath/FixedPointNumbers.jl)): a special type of floating point number that uses only 8 bits. Think of it as a `Float8`, rather than the usual `Float64`. You can use `Float64(x)` to convert to a normal `Float64`. - By default, a `Matrix{RGB}` will be displayed using text, but if you add + By default, a `Matrix{Gray}` will be displayed using text, but if you add ```julia import ImageShow, ImageIO ``` - somewhere in your notebook, then Pluto will be able to display the matrix as a color image. + somewhere in your notebook, then Pluto will be able to display the matrix as a grayscale image. For more image manipulation capabilities, check out [`Images.jl`](https://github.com/JuliaImages/Images.jl). # Keyword arguments - - `help::Bool=true` by default, we display a little help message when you use `WebcamInput`. You can disable that here. - - `default::Matrix{RGB{N0f8}}` set a default image, which is used until the user captures an image. Defaults to a **1x1 transparent image**. + - `help::Bool=true` by default, we display a little help message when you use `DrawCanvas`. You can disable that here. - `max_size::Int64` when given, this constraints the largest dimension of the image, while maintaining aspect ratio. A lower value has better performance. - - `avoid_allocs::Bool=false` when set to `true`, we lazily convert the raw `Vector{UInt8}` camera data to a `AbstractMatrix{RGB{N0f8}}`, with zero allocations. This will lead to better performance, but the bound value will be an `AbstractMatrix`, not a `Matrix`. + - `avoid_allocs::Bool=false` when set to `true`, we lazily convert the raw `Vector{UInt8}` camera data to a `AbstractMatrix{Gray{N0f8}}`, with zero allocations. This will lead to better performance, but the bound value will be an `AbstractMatrix`, not a `Matrix`. # Examples @@ -702,19 +704,19 @@ begin size(image) ``` - To get the **green** channel value of the **top right** pixel of the image: + To get the **gray** value of the **top right** pixel of the image: ```julia - image[1, end].g + image[1, end].val ``` """ DrawCanvas end function AbstractPlutoDingetjes.Bonds.initial_value(w::DrawCanvas) - return w.default !== nothing ? - w.default : - w.avoid_allocs ? standard_default_avoid_allocs : standard_default + #w.default !== nothing ? + #w.default : + w.avoid_allocs ? standard_gray_default_avoid_allocs(w.output_size[2], w.output_size[1]) : standard_gray_default end Base.get(w::DrawCanvas) = AbstractPlutoDingetjes.Bonds.initial_value(w) @@ -728,7 +730,7 @@ begin end function Base.show(io::IO, m::MIME"text/html", webcam::DrawCanvas) - webcam.help && @info help + webcam.help && @info help("DrawCanvas") Base.show(io, m, canvas_html(webcam)) end result @@ -820,14 +822,17 @@ begin end function Base.show(io::IO, m::MIME"text/html", webcam::WebcamInput) - webcam.help && @info help + webcam.help && @info help() Base.show(io, m, webcam_html(webcam)) end result end # ╔═╡ 5d9f2eeb-4cf6-4ab7-8475-301547570a32 -export WebcamInput +export WebcamInput, DrawCanvas + +# ╔═╡ d1079194-d891-4c78-a4d6-7af96acc52c2 +WebcamInput() # ╔═╡ ba3b6ecb-062e-4dd3-bfbe-a757fd63c4a7 # ╠═╡ skip_as_script = true @@ -835,21 +840,6 @@ export WebcamInput @bind img1 WebcamInput(; max_size=200) ╠═╡ =# -# ╔═╡ d0b8b2ac-60be-481d-8085-3e57525e4a74 -#=╠═╡ -size(img1) - ╠═╡ =# - -# ╔═╡ 55ca59b0-c292-4711-9aa6-81499184423c -#=╠═╡ -typeof(img1) - ╠═╡ =# - -# ╔═╡ 62334cca-b9db-4eb0-91e2-25af04c58d0e -#=╠═╡ -img1 - ╠═╡ =# - # ╔═╡ cad85f17-ff15-4a1d-8897-6a0a7ca59023 #=╠═╡ [img1 img1[end:-1:1, :] @@ -862,11 +852,6 @@ img1[:, end:-1:1] img1[end:-1:1, end:-1:1]] @bind img2 WebcamInput(; avoid_allocs=true, max_size=40, help=false) ╠═╡ =# -# ╔═╡ 28d5de0c-f619-4ffd-9be0-623999b437e0 -#=╠═╡ -size(img2) - ╠═╡ =# - # ╔═╡ be1b7fd5-6a06-4dee-a479-c84b56edbaba #=╠═╡ typeof(img2) @@ -898,19 +883,35 @@ img3 ╠═╡ =# # ╔═╡ b75fcead-799b-4022-af43-79c4387d64dc -cb1 = @bind c1 DrawCanvas(help=false) +cb1 = @bind c1 DrawCanvas(help=false, avoid_allocs = true ) -# ╔═╡ 0f9aeadb-03a6-40b3-8030-2497c0ab2e7d +# ╔═╡ bf84e792-ac4e-472d-8f0c-051c86fbac4d c1 -# ╔═╡ 0ce12c7d-38d2-42ed-80a4-2cec28ab5f54 -cb1 +# ╔═╡ a1b8bd97-204e-469b-bc68-400f5734618e +#el = DrawCanvas(; help=false) +# @test default(el) isa Matrix{Gray{N0f8}} +# @test size(default(el)) == (200,200) +# +# el = DrawCanvas(; help=false, avoid_allocs=true) +# @test !(default(el) isa Matrix{Gray{N0f8}}) +# @test default(el) isa AbstractMatrix{Gray{N0f8}} +# @test size(default(el)) == (200,200) -# ╔═╡ 6b5a4aca-3abc-4670-adcc-37539d7530ac +# ╔═╡ 0d3ba370-7ad4-4c1e-b3b4-16b71e66cdcf +dc2 = DrawCanvas() + +# ╔═╡ 140e673f-38a3-443d-bfab-643cbb455bd6 c1 -# ╔═╡ d87918b5-4879-491b-93e0-28d707c17423 -reinterpret(Bool,c1["data"]) +# ╔═╡ 9cf9a6bd-49e4-4580-a4cb-1d3575f1356e +cb3 = @bind c3 DrawCanvas(help=false ) + +# ╔═╡ 4776122c-a950-48e6-8fb2-e1391d1464e3 +c3 + +# ╔═╡ 00a9bd8b-083f-4feb-8576-9e013ef76448 +typeof(c3) # ╔═╡ Cell order: # ╠═1791669b-d1ee-4c62-9485-52d8493888a7 @@ -921,22 +922,20 @@ reinterpret(Bool,c1["data"]) # ╠═39f594bb-6326-4431-9fad-8974fef608a1 # ╠═31dff3d3-b3ee-426d-aec8-ee811820d842 # ╠═5104aabe-43f7-451e-b4c1-68c0b345669e +# ╠═d1079194-d891-4c78-a4d6-7af96acc52c2 # ╟─43332d10-a10b-4acc-a3ac-8c4b4eb58c46 # ╠═6dd82485-a392-4110-9148-f70f0e7c0985 # ╠═c917c90c-6999-4553-9187-a84e1f3b9315 # ╠═9a07c7f4-e2c1-4322-bcbc-c7db90af0059 # ╠═43f46ca7-08e0-4687-87eb-218df976a8a5 -# ╟─d9b806a2-de81-4b50-88cd-acf7db35da9a +# ╠═d9b806a2-de81-4b50-88cd-acf7db35da9a # ╟─97e2467e-ca58-4b5f-949d-ad95253b1ac0 -# ╟─3d2ed3d4-60a7-416c-aaae-4dc662127f5b +# ╠═3d2ed3d4-60a7-416c-aaae-4dc662127f5b +# ╠═0de03ade-682d-41b7-a617-2d2ad3e8aa0c # ╟─06062a16-d9e1-46ef-95bd-cdae8b03bafd # ╠═ba3b6ecb-062e-4dd3-bfbe-a757fd63c4a7 -# ╠═d0b8b2ac-60be-481d-8085-3e57525e4a74 -# ╠═55ca59b0-c292-4711-9aa6-81499184423c -# ╠═62334cca-b9db-4eb0-91e2-25af04c58d0e # ╠═cad85f17-ff15-4a1d-8897-6a0a7ca59023 # ╠═30267bdc-fe1d-4c73-b322-e19f3e934749 -# ╠═28d5de0c-f619-4ffd-9be0-623999b437e0 # ╠═be1b7fd5-6a06-4dee-a479-c84b56edbaba # ╠═033fea3f-f0e2-4362-96ce-041b7e0c27c6 # ╠═04bbfc5b-2eb2-4024-a035-ddc8fe60a932 @@ -946,9 +945,16 @@ reinterpret(Bool,c1["data"]) # ╠═af7b1cec-2a47-4d90-8e66-90940ae3a087 # ╟─c0b1da1e-8023-4b88-86c2-d93afd40618b # ╠═b31f6b0e-45be-441b-9694-4c786235f132 +# ╠═df4f5b5f-664c-4082-82d8-25c6c99c6637 +# ╠═ecbefadd-63d6-404a-98b8-b36ec92552fc +# ╠═1b72472c-ce91-474d-8695-e7a2b2633366 +# ╠═821d603d-df17-43ab-993b-f90418766ad7 # ╠═86c652d4-fa0f-4cfa-831f-e9a893351b81 # ╠═b75fcead-799b-4022-af43-79c4387d64dc -# ╠═0f9aeadb-03a6-40b3-8030-2497c0ab2e7d -# ╠═0ce12c7d-38d2-42ed-80a4-2cec28ab5f54 -# ╠═6b5a4aca-3abc-4670-adcc-37539d7530ac -# ╠═d87918b5-4879-491b-93e0-28d707c17423 +# ╠═bf84e792-ac4e-472d-8f0c-051c86fbac4d +# ╠═a1b8bd97-204e-469b-bc68-400f5734618e +# ╠═0d3ba370-7ad4-4c1e-b3b4-16b71e66cdcf +# ╠═140e673f-38a3-443d-bfab-643cbb455bd6 +# ╠═9cf9a6bd-49e4-4580-a4cb-1d3575f1356e +# ╠═4776122c-a950-48e6-8fb2-e1391d1464e3 +# ╠═00a9bd8b-083f-4feb-8576-9e013ef76448 diff --git a/test/runtests.jl b/test/runtests.jl index d7481182..171f2446 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,7 +2,7 @@ using PlutoUI using Test import AbstractPlutoDingetjes using HypertextLiteral -import ColorTypes: RGB, N0f8, Colorant +import ColorTypes: RGB, N0f8, Colorant, Gray import Logging using Dates @@ -355,6 +355,14 @@ transform(el, x) = AbstractPlutoDingetjes.Bonds.transform_value(el, x) @test default(el) isa AbstractMatrix{RGB{N0f8}} @test size(default(el)) == (1,1) + el = DrawCanvas(; help=false) + @test default(el) isa Matrix{Gray{N0f8}} + @test size(default(el)) == (100,100) + + el = DrawCanvas(; help=false, avoid_allocs=true) + @test !(default(el) isa Matrix{Gray{N0f8}}) + @test default(el) isa AbstractMatrix{Gray{N0f8}} + @test size(default(el)) == (200,200) el = confirm(Slider([sin, cos])) @test default(el) == sin