Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update API and add conditional dependencies #45

Merged
merged 22 commits into from
Oct 17, 2021
Merged

Conversation

adrhill
Copy link
Collaborator

@adrhill adrhill commented Sep 28, 2021

Closes #39:

API updates:

  • Removes SeparateSpace (and AbstractFixedColorDither) and instead automatically applies per-channel dithering on images with multiple channels
  • Adds error messages when attempting to dither in color with Algorithms that don't support it

New functionality using Requires.jl

  • support for ColorSchemes.jl

  • support for braille printouts using UnicodePlots.jl:

    julia> braille(img, FloydSteinberg())
    ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
    ⠀⡘⢌⠢⢁⠢⡑⢌⠢⡑⢌⢂⢂⠢⢊⢐⠐⢌⠐⢌⠐⢌⢂⠆⡒⢌⢂⠢⢂⠕⡌⢆⠕⢌⢢⢂⠪⡐⢔⠰⡐⡐⡐⡐⡐⡐⠔⡐⢔⠰⢐⠐⡐⡐⢀⠂⡐⡀⢂⠐⡀⡂⢐⢀⠂⠀
    ⠀⡘⢔⠡⡁⡂⡪⡐⡑⢌⠢⡁⠢⠨⢐⠠⢁⠢⠨⢐⠨⠐⢔⠑⢌⠢⡑⢌⠢⡑⡜⡔⡜⡔⡱⡨⠱⡑⡑⢌⠂⠕⡐⡐⠔⡨⠨⢐⠡⠨⡐⠨⠠⠐⡀⠂⠄⢂⠐⢐⠀⡂⠐⡀⠂⠀
    ⠀⡘⠔⢅⠂⡂⡢⢊⢌⠢⡑⠨⡈⠄⠅⠌⡐⠠⡁⠢⢈⠌⠢⠑⠡⠑⢌⢢⢣⠫⠪⢪⡨⣢⠱⡌⢇⠣⠪⡊⢎⠪⡐⠌⠔⠠⠑⠠⠡⡑⠠⠡⠈⠄⠠⠁⠨⠀⠌⠠⠐⡀⠡⠀⡂⠀
    ⠀⡘⢜⢐⠌⡐⢌⢂⠆⢕⠨⡂⡂⠅⠡⢁⢂⢁⠂⠅⡂⢌⠂⡅⡕⡍⡎⣎⣦⢷⢻⢱⢍⣆⢧⡪⡢⢎⢆⢎⢐⠅⡂⠅⠅⢂⠁⠅⠅⡂⠅⡡⠁⠌⠠⠈⠄⠡⠈⠄⡁⢐⠈⠄⠄⠀
    ⠀⡘⡌⡢⠨⢐⠰⡐⢅⢑⠌⠔⡠⠡⢑⢐⢐⢐⢈⠢⠨⡂⣎⢞⡼⣪⡯⢯⢺⢝⢽⢹⠵⣕⡕⢕⢩⢑⠱⡐⡑⠔⡌⠌⡂⡂⠌⠄⠅⢂⠡⠀⠅⡈⠄⠨⠀⠡⠈⠄⡐⢀⠂⠂⠂⠀
    ⠀⠢⡑⠔⡁⠢⠡⡊⢔⠐⢅⢑⠄⠕⡐⡐⡐⡐⢐⠌⡎⡮⣪⢧⢏⠇⡫⣈⡂⡅⠕⡐⡁⠢⡉⢎⢆⢥⢑⢌⠢⡑⢌⠣⡂⡂⠅⡃⠕⡀⢂⠡⠁⠄⠂⢂⠡⠈⠄⡁⠄⠂⡈⠈⠄⠀
    ⠀⢅⠣⡑⠠⠁⠅⠌⠠⢁⠂⠢⡈⡂⡂⡂⠢⡈⢆⢕⠵⢝⠪⡨⡂⣑⠡⡂⡊⠪⢱⠑⢔⠡⡀⠂⠕⢓⠕⠥⠡⠐⡀⠅⠌⡐⠨⢐⢅⢂⠂⠌⡨⠠⢁⠂⠄⡁⠂⠄⢂⠡⠀⠅⠂⠀
    ⠀⠢⡑⢌⠂⠅⠊⠌⡌⡢⢈⢂⢂⢂⠢⡈⠢⡸⣰⢣⢋⠔⡐⡐⠌⠢⢑⠰⡈⡊⡂⠅⠣⡊⡐⠅⠌⠂⠡⢁⢁⠁⠄⠂⡁⡂⢁⠂⡂⡣⢃⠕⠠⡡⢂⠐⡀⢂⠡⠈⠄⢐⠈⠄⢁⠀
    ⠀⢅⢣⠑⠌⠌⠨⠨⡂⢎⢐⢐⢐⢐⢐⠨⡐⡕⡎⢆⠢⢑⢐⢀⠡⢑⢄⡅⣂⡂⡢⡡⡡⢂⢂⠅⢅⠨⠐⠠⢐⢠⢡⢡⢂⢢⠡⡊⡄⡐⠀⠅⡑⡐⢐⠐⡐⢀⠂⡁⠌⡀⠂⠌⡀⠀
    ⠀⡘⢔⠅⡑⡁⠅⡑⢌⠆⡢⢂⢂⢂⢂⠢⣪⢪⢊⠄⡅⠆⢂⠠⢂⢕⣷⣽⣺⢮⢷⣳⣽⣺⡼⣵⣳⣌⢎⢬⣢⣳⢽⡺⡜⡎⡎⡎⡎⡔⢁⠨⢐⢈⢂⢂⠂⡂⢐⠀⡂⠄⢁⠂⠠⠀
    ⠀⡘⠔⢅⠢⢂⠡⢊⢔⢑⠄⢅⠂⡂⡪⡸⣜⠜⢔⠰⡠⢁⠢⡈⡂⣓⢗⡷⡯⣿⢽⣻⣞⣷⣟⣷⢷⣻⣟⣿⣺⣽⣳⣝⢮⢺⢸⢸⢸⠠⢑⢐⢀⢂⢂⢂⢌⢐⠐⡀⢂⠈⠄⠨⠀⠀
    ⠀⡘⢜⢐⠅⠅⠌⡂⢆⠣⡑⢔⢡⢪⣪⢺⢘⠌⠢⢁⢂⠅⡊⠄⡂⡪⣓⢯⢿⣽⣻⡽⣞⣷⣻⣞⣟⣷⣻⣞⣗⡯⣞⡮⡺⣕⢕⢇⢇⠊⠠⠐⡐⡐⢔⢐⠠⢂⠌⡐⠠⠈⠄⠡⠈⠀
    ⠀⠸⡐⢅⢊⠂⠅⡪⠨⡪⡘⡬⣪⢞⢮⠣⡡⡪⡊⡂⠄⡂⡢⢈⠐⡰⣜⡽⣽⣺⣳⢿⢽⣳⡯⣞⣗⣟⡾⣞⣗⣯⢷⣝⢽⡸⡜⣜⢢⢑⠀⠅⠂⢅⢕⠡⡑⠅⡢⠨⠈⠄⠡⠈⠄⠀
    ⠀⢱⠨⡂⢆⢑⠨⡐⡱⡡⡳⣱⢳⢽⢕⢕⢕⡕⠅⡐⠐⠐⠀⠄⢨⣫⡺⣪⢷⣳⡯⣟⣯⡷⣟⣯⢿⣞⡿⣽⣻⣞⣯⢾⢕⠯⡪⢒⢑⢕⠀⠂⠡⠈⠆⠕⢌⢌⢐⠨⠠⠡⢈⠐⡀⠀
    ⠀⢢⠱⡈⡢⢁⢂⢊⢆⢳⢱⣪⢏⣗⢕⡽⡸⡠⢁⠂⡈⠠⠁⡈⡸⣲⡹⡸⡱⡐⠍⡙⠜⡙⠝⡚⢽⣺⢽⣳⢳⢑⠡⠑⡁⢅⠂⢕⢔⡒⡌⢠⠁⡈⠌⢈⢐⢁⢂⠌⡐⠡⠐⡀⠂⠀
    ⠀⠢⡃⡪⢐⠐⠄⢕⡘⣎⣞⢮⢯⣪⡳⡱⡝⡐⢄⠡⠐⡀⢁⠠⡺⢼⢽⢵⢵⣘⢷⡰⣱⢖⡵⣼⢸⣪⣿⡪⡲⣢⢫⢆⣎⢮⢣⡱⣸⢸⠠⡇⡇⡀⠨⠀⡂⠢⡂⡢⠨⡈⡂⠄⢁⠀
    ⠀⡑⢅⢊⠔⡁⠅⢕⢜⡼⡜⣎⣗⢮⢞⢵⢱⡘⢄⠂⠡⠠⠀⠄⡣⡻⣽⣻⣿⣽⡷⣯⣯⣿⣺⡳⡣⣗⣗⡇⡏⡞⡮⡷⡽⣮⡳⣝⢮⢪⢊⢮⡣⠐⠀⠅⡂⢅⠢⡪⡨⢀⢂⠈⡀⠀
    ⠀⡘⢌⠔⡨⠠⠡⡑⣕⢽⢺⢜⣮⡳⡝⣜⢕⢜⢰⠡⡡⣑⠡⠐⢨⢹⣪⢷⡿⣾⣟⣯⡷⣷⢯⢯⡺⡵⣗⡇⡇⡇⡯⣏⡯⣞⣝⢮⢣⢣⢑⢵⡋⢀⠁⡂⠌⢆⠕⡜⢔⢁⢂⠐⡀⠀
    ⠀⠌⢆⠅⢌⠌⡂⡕⡼⡱⡝⣞⢮⡺⡱⡕⡕⣕⢕⢕⠢⠈⡐⠈⡀⡣⡳⣝⡯⣷⢟⣷⣻⣽⢽⣣⢯⢞⣗⢧⢣⢣⡫⣞⢮⡳⡕⡵⡱⡑⡅⠃⡀⠂⡐⠠⢁⢣⢣⢣⢑⢐⢀⠂⠄⠀
    ⠀⡑⢅⠪⡐⠌⡢⡱⡹⣜⡝⡮⡳⣕⢕⢕⢽⢸⢘⢔⠕⠁⢀⠐⢀⢪⢪⢺⡪⣗⣟⢾⢵⢯⣟⢮⡳⡯⣯⢧⢣⢣⡳⡕⡧⡳⣱⢱⠱⡘⡌⠠⠀⢂⠐⡈⠄⡊⡎⢎⢢⠡⠂⠨⠀⠀
    ⠀⡘⢌⠢⡈⡂⡊⡢⡯⣖⢽⣺⢽⢸⡸⢜⢜⡜⡜⡜⠈⠄⠂⠀⡂⢪⢪⡪⡺⡵⣫⢯⢯⣻⣞⡧⣇⢏⢞⢕⢕⢕⢵⢹⢪⡣⡣⡣⢣⢣⢑⠀⡈⠀⢂⠐⡐⡐⢌⠢⡑⠨⠈⠄⡁⠀
    ⠀⡘⠔⡁⡢⡢⢕⣝⢽⡺⣳⡳⣝⢼⢸⡸⣱⢱⢑⠡⠁⡂⠄⠁⠠⢱⢱⢕⣝⢎⡯⣏⢯⢞⣞⢽⡺⣪⢪⢪⢪⢪⢪⢪⢢⢣⢣⠣⡣⢣⠡⠀⠠⠈⠀⠂⡂⠌⡂⡑⠌⠌⠄⠅⠄⠀
    ⠀⢌⠪⡐⡱⡸⡕⡧⡣⡳⣕⢯⢮⢳⢕⡝⡜⢔⠔⠨⢐⢀⠂⠈⡀⢊⢎⢗⢎⢧⢻⣪⢏⣇⡳⡹⣙⢕⠯⡓⡝⡸⡘⣌⢮⢪⢪⢪⢪⢊⠢⠐⠀⠂⢁⠐⠠⢑⠐⢌⢊⠄⠅⡊⠄⠀
    ⠀⢐⢑⡜⡎⡎⡮⡣⣫⢯⢞⣽⣪⢗⡵⢣⠡⡃⡊⠌⡂⠄⠠⠁⠀⠄⠊⢎⢏⣎⢧⣳⢽⡪⡯⡺⡝⡕⡏⡞⡕⡕⡕⡕⡕⡕⢕⢕⢑⢜⢌⢕⠥⡨⢀⠀⠂⠠⠑⡐⡐⠌⡐⠄⠕⠀
    ⠀⠨⣪⢪⠪⡪⡪⡮⣳⢽⣝⢮⢞⡕⡕⢅⢣⢃⠂⠅⡀⢂⠐⠈⢀⠐⠀⠄⢑⢎⢎⢮⢷⣝⣝⢮⣺⣸⢜⣜⣜⢼⢸⡸⡜⡜⢌⢆⢇⠧⡱⡡⡣⡳⡰⣑⢌⠀⡐⠀⠄⢁⠂⢁⠁⠀
    ⠀⢐⢕⣕⢵⡱⣝⡾⡽⣵⣗⢯⠣⡣⡱⣱⠣⡁⠪⡐⢀⠂⠠⠁⠠⠀⠂⠈⡀⠢⡱⡑⢵⢳⢝⣟⡾⣽⢽⣞⡮⡫⡣⡣⢣⢪⢸⢜⢎⢇⢇⢇⢇⢇⢏⢮⢪⡣⣂⠐⡀⠄⠐⠀⠄⠀
    ⠀⡜⣼⡸⡵⣽⣳⢯⢯⢳⢣⢣⢏⢮⡚⡎⠌⢌⠪⡐⠠⠈⠄⡁⢂⠈⡀⠁⡀⠌⠜⡜⡜⢜⢱⠱⢝⢕⠏⡎⡎⡇⢇⢣⢕⢕⢕⢵⡱⡱⡱⡕⣕⢵⢹⢸⡱⣹⢸⢢⠠⠐⠈⢐⠀⠀
    ⠀⡗⣵⣺⢯⢗⢗⢽⡱⣝⣕⢏⡞⢜⢨⠐⠈⠄⡑⠐⢈⠨⠐⢀⠂⠄⠀⢂⠀⠄⡑⢜⢜⢕⢱⡑⡕⡢⡱⣨⡲⡸⡜⣜⢜⢮⢝⢼⡸⡪⣣⢫⡪⡪⡪⡪⡪⡪⡪⡪⢪⠠⠈⡀⠂⠀
    ⠀⣟⣞⢮⢳⢝⣵⡳⡯⡳⣕⢗⠕⡡⠂⢂⠡⠈⠄⠡⠐⠠⢁⠐⠠⠈⡀⠂⠐⡐⢌⢪⢪⢪⡳⣝⢮⡳⣝⢮⢮⢳⢝⣎⢯⡺⣝⢵⢕⡝⡼⣱⢝⢼⡱⡝⣜⢜⢜⢜⢮⢹⠰⢀⠁⠀
    ⠀⢧⣳⢽⣹⢝⡮⡳⣝⢵⠳⣡⠕⠠⠡⠡⢂⠡⠁⢂⢈⠐⡀⠂⡁⠄⠠⠈⠠⠠⠑⠌⣎⢧⡣⣳⡹⣝⢮⣳⡳⣝⣵⡳⡯⡯⣯⡳⡱⡱⣝⡮⣏⣗⢝⢮⡺⣜⡕⡧⣣⢣⡹⡐⠄⠀
    ⠀⡟⣎⢷⢕⡯⣞⣝⢎⢇⠝⡐⠨⠨⠨⠈⠄⠂⠡⠐⢀⠀⡂⢐⠀⡐⠀⠌⠀⡂⠡⢑⢼⡱⣝⢖⡕⣗⢝⣞⢞⡵⣳⢽⣝⣟⣞⢮⢣⡫⣞⡺⣪⡪⣝⢵⢹⢲⡹⡜⣎⢧⡣⣣⣓⠀
    ⠀⢮⣺⢝⣗⢽⢜⡜⣊⠢⢊⢄⢃⠡⠐⠈⠄⡁⠅⠡⠀⠄⢂⠐⡀⢂⠀⠂⠁⠄⢅⠕⡵⣝⢮⡳⣝⢮⣣⢳⢝⡽⣪⢷⣳⣳⣳⣝⢮⢞⢎⡞⣆⢧⡣⣳⡹⣱⢝⢞⢼⢕⣝⢮⣪
  • support for Clustering.jl for automated color palette generation

    dither(img, FloydSteinberg(), 4)

    clustered_lab_4

    dither(img, FloydSteinberg(), 8)

    clustered_lab_8

    dither(img, FloydSteinberg(), 16)

    clustered_lab_16

@adrhill adrhill changed the title Update API Update API and add conditional dependencies Sep 28, 2021
src/dither_api.jl Outdated Show resolved Hide resolved
@codecov
Copy link

codecov bot commented Sep 28, 2021

Codecov Report

Merging #45 (3c383ad) into master (06d57fc) will increase coverage by 1.87%.
The diff coverage is 97.26%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #45      +/-   ##
==========================================
+ Coverage   89.34%   91.21%   +1.87%     
==========================================
  Files          11       14       +3     
  Lines         169      205      +36     
==========================================
+ Hits          151      187      +36     
  Misses         18       18              
Impacted Files Coverage Δ
src/dither_api.jl 87.50% <91.30%> (+4.89%) ⬆️
src/DitherPunk.jl 100.00% <100.00%> (ø)
src/braille.jl 100.00% <100.00%> (ø)
src/clustering.jl 100.00% <100.00%> (ø)
src/colorschemes.jl 100.00% <100.00%> (ø)
src/colorspaces.jl 71.42% <100.00%> (ø)
src/error_diffusion.jl 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 06d57fc...3c383ad. Read the comment docs.

Copy link
Member

@johnnychen94 johnnychen94 left a comment

Choose a reason for hiding this comment

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

Sorry for the delay! A very quick check on the interfaces and didn't check the implementation details.

src/DitherPunk.jl Outdated Show resolved Hide resolved
src/dither_api.jl Outdated Show resolved Hide resolved
Comment on lines -15 to -17
struct SeparateSpace{A<:AbstractDither} <: AbstractFixedColorDither
alg::A
end
Copy link
Member

@johnnychen94 johnnychen94 Oct 14, 2021

Choose a reason for hiding this comment

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

Deleting a method without any deprecation can be very very breaking and thus triggers a major version v2.0.0.

Usually, a better practice is to start with some deprecations first to accumulate more breaking changes so that we don't break people's code too often. Might just keep them here for a while or move to a new file src/deprecated.jl and insert a deprecation message. For example, if I understand this change correctly:

struct SeparateSpace{A<:AbstractDither} <: AbstractFixedColorDither
    alg::A
    function SeparateSpace(alg::AbstractDither)
        Base.depwarn("SeparateSpace is no longer need, please load `Clustering` package instead.", :SeparateSpace)
    end
end

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I was actually thinking about making this v2.0.0 as it breaks some previous assumptions:

Previously, to apply per-channel dithering, methods had to be wrapped in the SeparateSpace() meta-method. In this version, we apply channel-wise dithering by default, such that

dither(Gray.(img), FloydSteinberg())  # => binary dithering (black & white output)
dither(RGB.(img), FloydSteinberg())   # => per-channel binary dithering (2^3 color output)

So this release is already going to be breaking w.r.t. the outputs!
Would you be ok with dropping SeparateSpace if we make this v2.0.0?

Copy link
Member

Choose a reason for hiding this comment

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

Okay, this sounds like a valid argument to me.

Just a quick question: does this dither(RGB.(img), FloydSteinberg()) require loading a Clustering? If so then we might want to make it a direct dependency.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No, that's going to be the default behaviour. (Clustering.jl just adds optional automatic color scheme generation.)

I have one last question: is there a best practice for doc strings on functionality added by conditional dependencies? Is it possible to just add the following to src/clustering.jl?

"""
[Extra docstring]
"""
dither

"""
[Extra docstring]
"""
dither!

My thinking is that these docstrings should also only be loaded when using Clustering.jl.

Copy link
Member

Choose a reason for hiding this comment

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

This is an interesting question. You can actually have more than one piece of docstrings for the same function:

"""
    foo(x)

The docstring for foo(x)
"""
foo(x)

"""
    foo(x, y)

The docstring for foo(x, y)
"""
foo(x, y)

and one can check the docstring for the specific method:

help?> foo(1)
  foo(x)


  The docstring for foo(x)

help?> foo(1, 2)
  foo(x, y)


  The docstring for foo(x, y)

without the arguments, it prints all docstring:

help?> foo
search: floor pointer_from_objref OverflowError RoundFromZero unsafe_copyto! functionloc

Couldn't find foo
Perhaps you meant for, floor, fdio, fd, fld, fma, eof, cos, cot, log, mod, xor, Bool, do or foldl
  foo(x)


  The docstring for foo(x)

  ────────────────────────────────────────────────────────────────────────────────────────────────

  foo(x, y)


  The docstring for foo(x, y)

@johnnychen94
Copy link
Member

For small projects, none of these are required but still I'd like to write it down in case you're not aware of:

It would be great to keep track of noteworthy breaking changes in README.md or CHANGELOG.md. See also https://github.com/JuliaGraphics/ColorVectorSpace.jl#abs-and-abs2 and https://github.com/JuliaImages/ImageTransformations.jl/blob/master/CHANGELOG.md.

An alternative is to rebase these 19 commits into a few (say, 3-5) commits and then directly merge without squashing. This would give a more clear changelog in git history form; again another case of why we want to make each PR logically small 😆.

Copy link
Member

@johnnychen94 johnnychen94 left a comment

Choose a reason for hiding this comment

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

The interfaces change looks good to me. With only two small comments. Feel free to merge when you're ready.

@adrhill
Copy link
Collaborator Author

adrhill commented Oct 17, 2021

For small projects, none of these are required but still I'd like to write it down in case you're not aware of:

It would be great to keep track of noteworthy breaking changes in README.md or CHANGELOG.md. See also https://github.com/JuliaGraphics/ColorVectorSpace.jl#abs-and-abs2 and https://github.com/JuliaImages/ImageTransformations.jl/blob/master/CHANGELOG.md.

I will add that!

An alternative is to rebase these 19 commits into a few (say, 3-5) commits and then directly merge without squashing. This would give a more clear changelog in git history form; again another case of why we want to make each PR logically small 😆.

Yeah, I should have broken issue #39 down into three separate "atomic" issues. That's how I ended up with this large PR. Next time I'll plan more carefully.

@adrhill adrhill merged commit b445a18 into master Oct 17, 2021
@adrhill adrhill deleted the adrhill/api-update branch October 17, 2021 12:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

DitherPunk API planning
3 participants