From 4e88d41c8e7a182a239e63c077ff461b8c265bdd Mon Sep 17 00:00:00 2001 From: kimikage Date: Sun, 8 Mar 2020 18:50:30 +0900 Subject: [PATCH] Add example images of simulation of color deficiency --- docs/crosssectionalcharts.jl | 4 +- docs/make.jl | 1 + docs/sampleimages.jl | 93 +++++++++++++++++++++++++++++++ docs/src/advancedfunctions.md | 17 +++++- docs/src/assets/figures/beads.svg | 12 ++++ 5 files changed, 124 insertions(+), 3 deletions(-) create mode 100644 docs/sampleimages.jl create mode 100644 docs/src/assets/figures/beads.svg diff --git a/docs/crosssectionalcharts.jl b/docs/crosssectionalcharts.jl index f3521a43..f5334a78 100644 --- a/docs/crosssectionalcharts.jl +++ b/docs/crosssectionalcharts.jl @@ -172,7 +172,7 @@ function write_png(io::IO, cs::AbstractArray{T}) where T <: Color u16(x) = (u8((x & 0xFFFF)>>8); u8(x)) u32(x) = (u16((x & 0xFFFFFFFF)>>16); u16(x)) b(bstr) = write(buf, bstr) - function pallet(c::Color) + function palette(c::Color) rgb24 = convert(RGB24,c) u8(rgb24.color>>16); u8(rgb24.color>>8); u8(rgb24.color) end @@ -197,7 +197,7 @@ function write_png(io::IO, cs::AbstractArray{T}) where T <: Color u32(n * n * 3); flush(); b(b"PLTE") for y = 1:n, x = 1:n - pallet(cs[y,x]) + palette(cs[y,x]) end crc32() # Image data diff --git a/docs/make.jl b/docs/make.jl index 4406a15f..7416aea0 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -10,6 +10,7 @@ include("crosssectionalcharts.jl") include("colordiffcharts.jl") include("colormaps.jl") include("namedcolorcharts.jl") +include("sampleimages.jl") makedocs( diff --git a/docs/sampleimages.jl b/docs/sampleimages.jl new file mode 100644 index 00000000..a2bb7aa8 --- /dev/null +++ b/docs/sampleimages.jl @@ -0,0 +1,93 @@ + +module SampleImages + +using Colors +using Base64 + +struct BeadsImageSVG <: Main.SVG + buf::IOBuffer +end + + +# The following code is ad-hoc and highly depends on "beads.svg". +# Be careful when modifying the svg file or its code. +function BeadsImageSVG(caption::String; filter=nothing, width="64mm", height="36mm") + io = IOBuffer() + id = string(hash(caption), base=16) + + open(joinpath("assets", "figures", "beads.svg"), "r") do file + for line in eachline(file, keep=true) + occursin(""=> + """width="$width" height="$height" style="display:inline; margin-left:1em; margin-bottom:1em">""") + elseif occursin("filter_beads_g", line) + line = replace(line, "filter_beads_g"=>"filter_"*id) + elseif occursin("", line) + text = """ + $caption + """ + line = replace(line, ""=>text) + end + + m = match(r"data:image/png;base64,([^\"]+)", line) + if filter === nothing || m === nothing + write(io, line) + continue + end + + head = m.offsets[1] + write(io, SubString(line, 1, head - 1)) + src = IOBuffer(m.captures[1]) + b64dec = Base64DecodePipe(src) # decode all for simplicity + b64enc = Base64EncodePipe(io) + write(b64enc, read(b64dec, 33)) # before the length of "PLTE" + replace_palette(b64enc, b64dec, filter) + n = write(b64enc, read(b64dec)) + close(b64enc) + close(b64dec) + write(io, SubString(line, head + length(m.captures[1]), length(line))) + end + end + BeadsImageSVG(io) +end + + +function replace_palette(dest::IO, src::IO, filter) + buf = IOBuffer() # to calculate chunk CRCs + + u8(x) = write(buf, UInt8(x & 0xFF)) + u16(x) = (u8((x & 0xFFFF)>>8); u8(x)) + u32(x) = (u16((x & 0xFFFFFFFF)>>16); u16(x)) + function read_palette() + uint32 = (UInt32(read(src, UInt8)) << 16) | + (UInt32(read(src, UInt8)) << 8) | read(src, UInt8) + reinterpret(RGB24, uint32) + end + function write_palette(c::Color) + rgb24 = convert(RGB24,c) + u8(rgb24.color>>16); u8(rgb24.color>>8); u8(rgb24.color) + end + crct(x) = (for i = 1:8; x = x & 1==1 ? 0xEDB88320 ⊻ (x>>1) : x>>1 end; x) + table = UInt32[crct(i) for i = 0x00:0xFF] + function crc32() + seekstart(buf) + crc = 0xFFFFFFFF + while !eof(buf) + crc = (crc>>8) ⊻ table[(crc&0xFF) ⊻ read(buf, UInt8) + 1] + end + u32(crc ⊻ 0xFFFFFFFF) + end + lenbytes = read(src, 4) + len = (UInt32(lenbytes[3]) << 8) | lenbytes[4] + write(dest, lenbytes) + write(buf, read(src, 4)) # "PLTE" + for i = 1:(len÷3) + write_palette(filter(read_palette())) + end + read(src, 4) # CRC + crc32() + write(dest, take!(seekstart(buf))) +end + +end diff --git a/docs/src/advancedfunctions.md b/docs/src/advancedfunctions.md index c437bb6f..07b71187 100644 --- a/docs/src/advancedfunctions.md +++ b/docs/src/advancedfunctions.md @@ -48,7 +48,22 @@ deuteranopic(c::Color, p::Float64) tritanopic(c::Color, p::Float64) ``` -Also provided are versions of these functions with an extra parameter `p` in `[0, 1]`, giving the degree of photopigment loss, where 1.0 is a complete loss, and 0.0 is no loss at all. +Also provided are versions of these functions with an extra parameter `p` in `[0, 1]`, giving the degree of photopigment loss, where `1.0` is a complete loss, and `0.0` is no loss at all. The partial loss simulates the anomalous trichromacy, i.e. *protanomaly*, *deuteranomaly* and *tritanomaly*. + +```@example deficiency +using Colors #hide +using Main: SampleImages # hide +SampleImages.BeadsImageSVG("Normal") # hide +``` +```@example deficiency +SampleImages.BeadsImageSVG("Protanomaly (p=0.7)", filter=(c->protanopic(c, 0.7))) # hide +``` +```@example deficiency +SampleImages.BeadsImageSVG("Deuteranomaly (p=0.7)", filter=(c->deuteranopic(c, 0.7))) # hide +``` +```@example deficiency +SampleImages.BeadsImageSVG("Tritanomaly (p=0.7)", filter=(c->tritanopic(c, 0.7))) # hide +``` ```@docs protanopic diff --git a/docs/src/assets/figures/beads.svg b/docs/src/assets/figures/beads.svg new file mode 100644 index 00000000..d93975d2 --- /dev/null +++ b/docs/src/assets/figures/beads.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + +