Skip to content

Commit

Permalink
ascii_display -> ascii_show - fix downscaling - docs - cov (#8)
Browse files Browse the repository at this point in the history
* rework for `ReferenceTests`

* fix uncovered cond
  • Loading branch information
t-bltg authored Aug 11, 2022
1 parent f6644c4 commit c988dc2
Show file tree
Hide file tree
Showing 36 changed files with 299 additions and 153 deletions.
1 change: 1 addition & 0 deletions .JuliaFormatter.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
style = "blue"
short_to_long_function_def = false
long_to_short_function_def = true
trailing_comma = "nothing"
always_use_return = false
import_to_using = false
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "XTermColors"
uuid = "c8c2cc18-de81-4e68-b407-38a3a0c0491f"
version = "0.1.1"
version = "0.2.0"

[deps]
Crayons = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f"
Expand Down
2 changes: 1 addition & 1 deletion src/XTermColors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ using Crayons

import OffsetArrays: Origin

export ascii_display
export ascii_show

include("colorant2ansi.jl")
include("ascii.jl")
Expand Down
83 changes: 51 additions & 32 deletions src/ascii.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ const RESET = Crayon(; reset=true)

function _charof(alpha)
alpha_chars = ALPHA_CHARS[]
idx = round(Int, alpha * (length(alpha_chars) - 1))
alpha_chars[clamp(idx + 1, 1, length(alpha_chars))]
nc = length(alpha_chars)
idx = round(Int, alpha * (nc - 1))
alpha_chars[clamp(idx + 1, 1, nc)]
end

function _downscale_small(img::AbstractMatrix{<:Colorant}, maxsize::NTuple{2,Int})
Expand All @@ -27,20 +28,20 @@ function _downscale_small(img::AbstractMatrix{<:Colorant}, maxsize::NTuple{2,Int
b. number of visible characters per line (the remaining are colorcodes).
=#
maxheight, maxwidth = max.(maxsize, 5)
h, w = map(length, axes(img))
h, w = size(img)
while ceil(h / 2) > maxheight || w > maxwidth
img = restrict(img)
h, w = map(length, axes(img))
h, w = size(img)
end
img, SmallBlocks((length(1:2:h), w))
end

function _downscale_big(img::AbstractMatrix{<:Colorant}, maxsize::NTuple{2,Int})
maxheight, maxwidth = max.(maxsize, 5)
h, w = map(length, axes(img))
h, w = size(img)
while h > maxheight || 2w > maxwidth
img = restrict(img)
h, w = map(length, axes(img))
h, w = size(img)
end
img, BigBlocks((h, 2w))
end
Expand Down Expand Up @@ -72,20 +73,21 @@ function _printc(io::IO, x::Crayon, args...)
end

"""
ascii_encode([io::IO], enc::ImageEncoder, colordepth::TermColorDepth, img, [maxheight], [maxwidth])
ascii_encode(io::IO, enc::ImageEncoder, colordepth::TermColorDepth, img; trail_nl::Bool=false, ret::Bool=false)
Transforms the pixel of the given image `img`, which has to be an
array of `Colorant`, into a string of unicode characters using
ansi terminal colors or directly writes into a i/o stream.
- The encoder `enc` specifies which kind of unicode represenation
should be used.
- The encoder `enc` specifies which kind of unicode represenation should be used.
- The `colordepth` can either be `TermColor8bit()` or `TermColor24bit()`
and specifies which terminal color codes should be used.
It `ret` is set, the function returns a vector of strings containing the encoded image.
Each element represent one line. The lines do not contain newline characters.
If `trail_nl` is given, a final trailing newline is appended.
"""
function ascii_encode(
io::IO,
Expand Down Expand Up @@ -190,51 +192,68 @@ function ascii_encode(
ret ? readlines(io) : nothing
end

# use a `PipeBuffer` as io and returns encoded data reading lines of this buffer (using `readlines(io)`)
ascii_encode(enc::SmallBlocks, args...) = ascii_encode(PipeBuffer(), enc, args...; ret=true)
color_buffer() = IOContext(PipeBuffer(), :color => Base.get_have_color())

ascii_encode(enc::BigBlocks, args...) = ascii_encode(PipeBuffer(), enc, args...; ret=true)
# use a `PipeBuffer` as io and returns encoded data reading lines of this buffer (using `readlines(io)`)
ascii_encode(enc::SmallBlocks, args...; kws...) =
ascii_encode(color_buffer(), enc, args...; ret=true, kws...)
ascii_encode(enc::BigBlocks, args...; kws...) =
ascii_encode(color_buffer(), enc, args...; ret=true, kws...)

"""
ascii_display([stream], img, [depth::TermColorDepth], [maxsize])
ascii_show(stream, img, colordepth::TermColorDepth, encoder::Symbol=:auto, maxsize::Tuple=displaysize(io))
Displays the given image `img` using unicode characters and terminal colors.
`img` has to be an array of `Colorant`.
- `maxheight` and `maxwidth` specify the maximum numbers of
string characters that should be used for the resulting image.
- `maxsize` specifies the maximum numbers of string characters (lines, columns)
that should be used for the resulting image.
Larger images are downscaled automatically using `restrict`.
If working in the REPL, the function tries to choose the encoding
based on the current display size. The image will also be
downsampled to fit into the display (using `restrict`).
If working in the REPL, the function tries to choose the encoding based on the current display size.
The image will also be downsampled to fit into the display (using `restrict`).
"""
function ascii_display(
function ascii_show(
io::IO,
img::AbstractMatrix{<:Colorant},
colordepth::TermColorDepth,
encoder::Symbol=:auto,
maxsize::Tuple=displaysize(io);
kwargs...
kws...
)
io_h, io_w = maxsize
img_h, img_w = map(length, axes(img))
downscale = img_h io_h - 4 && 2img_w io_w ? _downscale_big : _downscale_small
img, enc = downscale(img, (io_h - 4, io_w))
ascii_encode(io, enc, colordepth, img; kwargs...)
io
downscale = if encoder === :auto
img_h, img_w = size(img)
img_h io_h && 2img_w io_w ? _downscale_big : _downscale_small
elseif encoder === :small
_downscale_small
elseif encoder === :big
_downscale_big
end
img, enc = downscale(img, (io_h, io_w))
ascii_encode(io, enc, colordepth, img; kws...)
end

function ascii_display(
function ascii_show(
io::IO,
img::AbstractVector{<:Colorant},
colordepth::TermColorDepth,
encoder::Symbol=:auto,
maxsize::Tuple=displaysize(io);
kwargs...
kws...
)
io_h, io_w = maxsize
img_w = length(img)
downscale = 3img_w io_w ? _downscale_big : _downscale_small
_, io_w = maxsize
downscale = if encoder === :auto
img_w = length(img)
3img_w io_w ? _downscale_big : _downscale_small
elseif encoder === :small
_downscale_small
elseif encoder === :big
_downscale_big
end
img, enc = downscale(img, io_w)
ascii_encode(io, enc, colordepth, img; kwargs...)
io
ascii_encode(io, enc, colordepth, img; kws...)
end

ascii_show(img::AbstractArray{<:Colorant}, args...; kws...) =
ascii_show(color_buffer(), img, args...; ret=true, kws...)
11 changes: 3 additions & 8 deletions src/colorant2ansi.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,11 @@ colorant2ansi(color) = _colorant2ansi(color, TermColor8bit())
function _colorant2ansi(
col::Union{AbstractRGB,AbstractGray,Color{<:Any,1}}, ::TermColor8bit
)
r, g, b = rgb = clamped01_rgb(col)
cube = 16 + 36trunc(Int, 5r) + 6trunc(Int, 5g) + trunc(Int, 5b) # 216 colors levels: cube 6x6x6
r, g, b = clamped01_rgb(col)
if r == g == b
if r % 43 == 16 # prefer cube gray levels: 16, 59, 102, 145, 188, 231
cube
else
232 + clamp(trunc(Int, (23 + 2)r), 0, 23) # 24 gray levels + black + white = 26
end
232 + clamp(trunc(Int, (23 + 2)r), 0, 23) # 24 gray levels + black + white = 26
else
cube
16 + 36trunc(Int, 5r) + 6trunc(Int, 5g) + trunc(Int, 5b) # 216 colors levels: cube 6x6x6
end
end
_colorant2ansi(col::Union{AbstractRGB,AbstractGray,Color{<:Any,1}}, ::TermColor24bit) =
Expand Down
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions test/reference/show_lighthouse_20_auto_8bit.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
████████████████
1 change: 1 addition & 0 deletions test/reference/show_lighthouse_20_big_8bit.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
██ ██ ██  … ██ ██ ██ 
1 change: 1 addition & 0 deletions test/reference/show_lighthouse_20_small_8bit.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
████████████████
9 changes: 9 additions & 0 deletions test/reference/show_lighthouse_20x20_big_8bit.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
██████████████████
██████████████████
██████████████████
██████████████████
██████████████████
██████████████████
██████████████████
██████████████████
██████████████████
8 changes: 8 additions & 0 deletions test/reference/show_lighthouse_20x20_small_8bit.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
1 change: 1 addition & 0 deletions test/reference/show_lighthouse_80_auto_8bit.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
██████████████████████████████
1 change: 1 addition & 0 deletions test/reference/show_lighthouse_80_big_8bit.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██  … ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ 
1 change: 1 addition & 0 deletions test/reference/show_lighthouse_80_small_8bit.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
██████████████████████████████
Loading

2 comments on commit c988dc2

@t-bltg
Copy link
Member Author

@t-bltg t-bltg commented on c988dc2 Aug 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/66074

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.2.0 -m "<description of version>" c988dc276e252764d8a439b3e1996371b29ca795
git push origin v0.2.0

Please sign in to comment.