Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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...)
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