CMYKColorTypes

This package is an add-on to ColorTypes, and provides color types for process color, i.e. cyan, magenta, yellow and key (black) color model.

Type design

The CMYK type is defined as follows:

struct CMYK{T <: Fractional} <: AbstractCMYK{T}
    c::T # cyan in [0, 1]
    m::T # magenta in [0, 1]
    y::T # yellow in [0, 1]
    k::T # black in [0, 1]
    CMYK{T}(c::T, m::T, y::T, k::T=zero(T)) where {T} = new{T}(c, m, y, k)
end

For each component value, 0 means 0% ink density and 1 means 100% ink density. Thus, CMYK(0, 0, 0, 0) means white (i.e. the underlying color) and CMYK(1, 1, 1, 1) means registration black (or 400% black). Note that some graphics tools and image formats may encode 0% ink density as a saturated value and 100% ink density as zero. You can invert the scale using CMYKColorTypes.complement.

The parameter T specifies the type of the components. You can use AbstractFloat and FixedPoint for T. It defaults to N0f8.

In addition, the transparent color variants ACMYK and CMYKA are defined.

Similarly to AbstractRGB and TransparentRGB, CMYK and ACMYK/CMYKA are defined as subtypes of AbstractCMYK and TransparentCMYK respectively. Although this package does not define any other concrete types, some subtypes specific to certain storage formats or color profiles may be used. When writing generic code, it is recommended to use the accessors (cyan, magenta, yellow, and black), instead of accessing the fields directly.

CMYK, ACMYK, and CMYKA have the constructors within the same style as for the other color types defined in ColorTypes.jl.

julia> CMYK{Float32}(1, 0.5, 0.2, 0) # explicitly specifying the component typeCMYK{Float32}(1.0f0,0.5f0,0.2f0,0.0f0)
julia> CMYK(1, 0, 0, 0) # If all arguments are integers (`0` or `1`), `N0f8` will be usedCMYK{N0f8}(1.0,0.0,0.0,0.0)
julia> CMYK(1, 0.5, 0.2f0, 0) # the component type is promoted to `Float64`CMYK{Float64}(1.0,0.5,0.20000000298023224,0.0)
julia> CMYK(1.0f0, 0.5f0, 0.2f0) # `k` (black) can be omittedCMYK{Float32}(1.0f0,0.5f0,0.2f0,0.0f0)
julia> ACMYK(1, 0.5, 0.2, 0, 0.8) # alpha (`= 0.8`) is always lastACMYK{Float64}(1.0,0.5,0.2,0.0,0.8)
julia> ACMYK(CMYK(1, 0, 0, 0)) # alpha defaults to `1`ACMYK{N0f8}(1.0,0.0,0.0,0.0,1.0)
julia> CMYKA(ACMYK(1, 0, 0, 0, 1), 0.8) # overwriting the alphaCMYKA{N0f8}(1.0,0.0,0.0,0.0,0.8)

Conversion

In principle, CMYKColorTypes does not support the color space conversion. While RGB is associated with an absolute color space "sRGB" by default, CMYK is not associated with a specific color profile. There is no point in conversions which are not based on color profiles, and the handling of color profiles is out of scope of this minimal package.

In practice, however, CMYKColorTypes does implement the conversion between AbstractRGB and CMYK only for preview purposes.

Warning

You should never use the default conversions for commercial printing or academic papers. For color space conversions, please use proper color profiles and configurations (e.g. rendering intent) with a color management system.

The implementation of the default conversions is completely custom to this package, and there are no intentions to keep it compatible in future versions.

julia> using ColorTypes;
julia> convert(RGB, CMYK(1.0, 0.5, 0.2, 0.1))RGB{Float64}(0.058651506900787354,0.3476904034614563,0.6008919477462769)
julia> convert(CMYK, RGB24(1.0, 0.5, 0.2))CMYK{N0f8}(0.0,0.0,0.0,0.0)
using Colors
[CMYK(1.0, 0.5, 0.2, 0.1), CMYK(0.1, 1.0, 0.5, 0.2), CMYK(0.2, 0.1, 1.0, 0.5)]

On the other hand, in some use cases, conversion methods that are independent of color profiles and devices may be useful. Hence, this package provides the conversion methods defined in CSS Color Module Level 4 (Working Draft) as CMYKColorTypes.naively_convert.

julia> using CMYKColorTypes: naively_convert;
julia> seagreen = colorant"seagreen"RGB{N0f8}(0.18,0.545,0.341)
julia> naively_convert(CMYK, seagreen)CMYK{N0f8}(0.671,0.0,0.373,0.455)

Of course, this methods yields very different results from conversions based on practical color profiles for printed materials.

  • Lab colors from the Fogra MediaWedge CMYK V3.0
  • naively_convert
  • default conversion

Arithmetic

If we consider each CMYK component value as an amount of ink, it is physically reasonable to assume the linearity. Therefore, the arithmetic operations of addition, subtraction and real number scaling are implemented. However, there are no definitions for multiplying CMYK colors or for arithmetic between different color spaces.

julia> CMYK(0.1, 0.2, 0.3, 0.5) + CMYK(0.0, 0.2, 0.125, 0.25)CMYK{Float64}(0.1,0.4,0.425,0.75)
julia> CMYK(0.1, 0.2, 0.3, 0.5) - CMYK(0.0, 0.2, 0.125, 0.25)CMYK{Float64}(0.1,0.0,0.175,0.25)
julia> CMYK(0.1, 0.2, 0.3, 0.5) * 0.5CMYK{Float64}(0.05,0.1,0.15,0.25)
julia> CMYK(0.1, 0.2, 0.3, 0.5) / 2CMYK{Float64}(0.05,0.1,0.15,0.25)

Note that if the component type is a FixedPoint type such as N0f8, the operation result will be wrapped around when an overflow occurs.

julia> using FixedPointNumbers;
julia> CMYK{N0f8}(0.2, 0.4, 0.6, 0.8) + CMYK{N0f8}(0.4, 0.4, 0.4, 0.4) # overflow in KCMYK{N0f8}(0.6,0.8,1.0,0.196)