Coder Social home page Coder Social logo

Comments (13)

kimikage avatar kimikage commented on September 21, 2024 1

Crayons.jl has the conversion feature, but I don't think there is a public API just for the conversion. At least, Crayons.jl does not provide an interface to the types defined in ColorTypes.jl.
Another point of concern is that Crayons.jl's implementation is not compatible with XTerm256. (cf. JuliaDocs/ANSIColoredPrinters.jl#8) FWIW, ImageInTerminal.jl has the same issue.

from colors.jl.

kimikage avatar kimikage commented on September 21, 2024 1

At least, as I mentioned above, the current implementations of Crayons.jl and ImageInTerminal.jl assume so-called web-safe colors, not so-called terminal colors.

Therefore, the gist version is better WRT the palette. The problem is how to find the closest color.

On the other hand, converting from a terminal color (index) to RGB is easy.

using Colors, FixedPointNumbers

_to_term_tone256(v::Integer) = v * 0x28 + (v === zero(v) ? 0x00 : 0x37)
function from_term256(i::Integer)
    i8 = i % UInt8
    if i8 < 0x10
        term16 = RGB.(reinterpret.(RGB24, (0x000000, 0x800000, 0x008000, 0x808000, 
                                           0x000080, 0x800080, 0x008080, 0xc0c0c0,
                                           0x808080, 0xff0000, 0x00ff00, 0xffff00,
                                           0x0000ff, 0xff00ff, 0x00ffff, 0xffffff)))
        return @inbounds term16[i8 + 1]
    elseif i8 < 0xe8
        c = i8 - 0x10
        r = _to_term_tone256(c ÷ 0x24) % UInt8
        g = _to_term_tone256((c ÷ 0x6) % 0x6) % UInt8
        b = _to_term_tone256(c % 0x6) % UInt8
        return RGB(reinterpret.(N0f8, (r, g, b))...)
    else
        c = i8 - 0xe8
        return RGB(reinterpret(N0f8, c * 0xa + 0x8))
    end
end

from colors.jl.

kimikage avatar kimikage commented on September 21, 2024 1

Crayons.jl is not dependent on ColorTypes.jl. That's both an advantage and a disadvantage. I am not in a position to decide its dependency.

from colors.jl.

johnnychen94 avatar johnnychen94 commented on September 21, 2024

I think this already exists. See https://github.com/KristofferC/Crayons.jl

from colors.jl.

kimikage avatar kimikage commented on September 21, 2024

Note that I have considered this issue before, and I realized that finding an approximate color is not so easy.

from colors.jl.

jakewilliami avatar jakewilliami commented on September 21, 2024

Micah gave me permission to make public the ported code. You can find it in this gist, though it will probably need a lot of clean-up (see original gist for more detail and notes in comments).

I also contacted Kristoffer, who wrote Crayons.jl. This is what he wrote. This is very reminiscent of this comment in the original gist. Perhaps someone that knows more about colours can shed some light on which method might be better.

Let me know what you think @kimikage.

from colors.jl.

kimikage avatar kimikage commented on September 21, 2024

I'm not happy with it's performance, but the following just works.

_to_term_tone6(v::UInt8) = (((max(v, 0x4a) + 0x0005) * 0x00cd) >> 0xd) - 0x1

to_term256(@nospecialize(c::Color)) = to_term256(RGB24(c))

function to_term256(c::C) where C <: AbstractRGB
    rgb = RGB24(c)
    r0 = reinterpret(red(rgb))
    g0 = reinterpret(green(rgb))
    b0 = reinterpret(blue(rgb))
    rt = _to_term_tone6(r0)
    gt = _to_term_tone6(g0)
    bt = _to_term_tone6(b0)
    d = max(r0, g0, b0) - min(r0, g0, b0)
    if (rt === gt === bt) || d < 0x15
        gr16 = 0x003d * r0 + 0x0079 * g0 + 0x0017 * b0
        ths = (0x04, 0x5c, 0x61, 0x84, 0x89, 0xac, 0xb1, 0xd4, 0xd9, 0xf7) .* 0x00cd
        if mapreduce(th -> gr16 < th, , ths; init=false)
            return Int(min((gr16 - 0x0334) >> 0xb, 0x17)) + 232
        end
    end
    return Int(rt * 0x24 + gt * 0x6 + bt) + 16
end

from colors.jl.

kimikage avatar kimikage commented on September 21, 2024

term256
G - R - B (time-y-x)

The left shows the nearest neighbor colors based on DE_2000(1, 1, 1), and the right shows the channel-wise rounded colors. The result on the left is not necessarily the best (e.g. there should be no sharp edge corners), but the difference is certainly significant.

There are several possible approaches to improve the conversion, but there are the following problems.

  • Searching with a loop is slow.
  • Lookup tables tend to be huge.
  • Converting to a color space such as Lab/Luv is expensive.

from colors.jl.

kimikage avatar kimikage commented on September 21, 2024

term256_yrb
Y (Rec.601) - R - B (time-y-x)

term256_ygb
Y (Rec.601) - G - B (time-y-x)

In the figures above, you can see something like a checker pattern. In other words, this does not seem to be a problem that can be solved by converting to a perceptually uniform color space (e.g. Lab/Luv). This is because converting to a perceptually uniform color space will result in a discontinuity (i.e. zigzag) in the color index space.

Perhaps it is better to diffuse the rounding error in RGB space.

from colors.jl.

kimikage avatar kimikage commented on September 21, 2024

As long as round-trip compatibility is ensured for 240 colors, there is no need to maintain compatibility for the rest. So, I think improvements can be left as a future task.

The other thing we need to decide is the API design.
One option is to provide conversion methods like to_term256/from_term256.
Another option is to define a single-component color like Term256Color <: Color{UInt8, 1} and use the convert scheme for its conversion. However, currently, Color{T,1} is interpreted as grayscale, which can cause trouble.

from colors.jl.

johnnychen94 avatar johnnychen94 commented on September 21, 2024

I know very little about this. My understanding is that you're going to add this into Colors.jl. Just curious to ask, is there any reason that we can't add/extend this functionality inside Crayons?

The other thing we need to decide is the API design.

Both to_term256/from_term256 and Term256Color are good to me.

from colors.jl.

kimikage avatar kimikage commented on September 21, 2024

This is off-topic, but is there a package for color quantization or color reduction in the JuliaImages ecosystem?
The feature for mapping pixel colors to a specific palette (with high quality but high cost) should be there.

from colors.jl.

johnnychen94 avatar johnnychen94 commented on September 21, 2024

I think I've supported this feature in JuliaImages/ImageInTerminal.jl#62... Maybe I should just port the codes to Colors?

from colors.jl.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.