Skip to content

Commit

Permalink
enh(refactor): simplify and rationalise function names
Browse files Browse the repository at this point in the history
  • Loading branch information
jdmorriso committed Apr 29, 2022
1 parent 8e3ade4 commit 6d64ceb
Show file tree
Hide file tree
Showing 15 changed files with 330 additions and 204 deletions.
25 changes: 21 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,32 @@
# color-cam16
Perceptual Color Space and Language based on the CAM16 Uniform Color Space

## Color Space Background
## Defining and Manipulating Colors
color-cam16 is a TypeScript library for defining and manipulating colors. Generate color sequences. Define color relationships. Determine color differences. Find analogous and complimentary colors. Ensure color contrast. Match real world colors.

The library uses a uniform color space based on human perception and human semantics. Colors can be warmer or cooler, lighter or darker, stronger or weaker. You can define a set of colors and their relationships in plain text. The library can parse a color description and calculate the relevant colors of a theme.
The library uses a uniform color space based on human perception and human semantics. You can define a set of colors by their relationships in plain text. Define colors as warmer, cooler, lighter, darker, stronger, weaker, analogous, triadic, or complimentary. Declare how many steps between colors to form color sequences. The library will parse the color description and generate a set of colors for a color theme.

## Color Space Transforms
- JuMuHu_to_color
- label_to_color

![](https://readme-swatches.vercel.app/008000)
![](https://readme-swatches.vercel.app/0080FF)
![](https://readme-swatches.vercel.app/A080FF)

## Color Space Analysis
- delta_e
- find_closest_color
- find_strongest_color
- find_strongest_Mu
- cluster_colors

## Color Names

## Color Language
- label_to_name
- name_to_color
- find_closet_names

## Color Language
- parse_colors
- rainbow_colors
- adjust_color
36 changes: 18 additions & 18 deletions src/analysis.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { JuMuHu, JuMuHuHex, CAM16u } from "./types"
import { JuMuHu, CAM16u } from "./types"
import { c360, MuHu_to_ab } from "./utility"
import { cam16_ucs_to_hex, cam16_ucs_to_hex_ingamut } from "./transform_rev"
import { JuMuHu_to_hex, JuMuHu_to_color } from "./transform_rev"

/**
* Find the maximum Mu for a given Hu and Ju, using a recursive binary search
Expand All @@ -12,12 +12,12 @@ import { cam16_ucs_to_hex, cam16_ucs_to_hex_ingamut } from "./transform_rev"
* @param {number} n (default=0) - number of iterations so far
* @returns number - the maximum Mu for the given Hu and Ju, to an accuracy of +/- 0.1
*/
export function find_largest_Mu(ucs: JuMuHu, min: number = 0, max: number = 100, n: number = 0): number {
export function find_strongest_Mu(ucs: JuMuHu, min: number = 0, max: number = 100, n: number = 0): number {
if (max - min < 0.1) return min
if ((n++ > 13) || (n < 0)) return 0
const half = (max + min) / 2
const hex = cam16_ucs_to_hex({ Ju: ucs.Ju, Mu: half, Hu: ucs.Hu })
return (hex == '') ? find_largest_Mu(ucs, min, half, n) : find_largest_Mu(ucs, half, max, n)
const hex = JuMuHu_to_hex({ Ju: ucs.Ju, Mu: half, Hu: ucs.Hu })
return (hex == '') ? find_strongest_Mu(ucs, min, half, n) : find_strongest_Mu(ucs, half, max, n)
}

/** Find the approximate dMu/dJu gradient at highest chroma for a given Hu and Ju
Expand All @@ -27,8 +27,8 @@ export function find_largest_Mu(ucs: JuMuHu, min: number = 0, max: number = 100,
*/
function gradient_dMu_dJu(Hu: number, Ju: number): number {
const epsilon = 0.1
const Mu1 = find_largest_Mu({ Hu, Ju, Mu: 0 })
const Mu2 = find_largest_Mu({ Hu, Ju: Ju + epsilon, Mu: 0 })
const Mu1 = find_strongest_Mu({ Hu, Ju, Mu: 0 })
const Mu2 = find_strongest_Mu({ Hu, Ju: Ju + epsilon, Mu: 0 })
return (Mu2 - Mu1) / epsilon
}

Expand Down Expand Up @@ -87,19 +87,19 @@ export function find_strongest_Ju(Hu: number, min: number = 5, max: number = 95,
}
}

export function find_strongest_ucs(Hu: number): JuMuHuHex {
export function find_strongest_color(Hu: number): CAM16u {
const Ju = find_strongest_Ju(Hu)
const Mu = find_largest_Mu({ Ju, Mu: 0, Hu })
return cam16_ucs_to_hex_ingamut({ Ju, Mu, Hu })
const Mu = find_strongest_Mu({ Ju, Mu: 0, Hu })
return JuMuHu_to_color({ Ju, Mu, Hu })
}

export function cam16_ucs_rainbow({ Hu1 = 0, Hu2 = 360, steps = 13 }): JuMuHuHex[] {
export function rainbow_colors({ Hu1 = 0, Hu2 = 360, steps = 13 }): CAM16u[] {
if (steps == 0) {
return [find_strongest_ucs(Hu1)]
return [find_strongest_color(Hu1)]
} else {
return Array(steps + 1).fill(0).map((_, i) => {
const Hu = Hu1 + i * (Hu2 - Hu1) / steps
return find_strongest_ucs(Hu)
return find_strongest_color(Hu)
})
}
}
Expand All @@ -114,7 +114,7 @@ export function cam16_ucs_rainbow({ Hu1 = 0, Hu2 = 360, steps = 13 }): JuMuHuHex
* @param {JuMuHu} y - Object with CAM16UCS components { Ju: lightness, Mu: colorfulness, Hu: hue angle [0-360] }
* @returns {number} - A value which represents the similarity of two colors (0=same, 25=very different)
*/
export function deltaE_ucs(x: JuMuHu | CAM16u, y: JuMuHu | CAM16u): number {
export function delta_e(x: JuMuHu, y: JuMuHu): number {
const xab = MuHu_to_ab(x)
const yab = MuHu_to_ab(y)
const da = xab.a - yab.a, db = xab.b - yab.b, dj = x.Ju - y.Ju;
Expand Down Expand Up @@ -153,9 +153,9 @@ export function shortest_signed_distance(a: number, b: number): number {
* @param {number} adj.steps=1 - Optional number of adjusted colors for each input color
* @param {boolean} adj.contrast=false - Optional flag to indicate lightness change by contrast, ie if Cn.Ju>50 then negative Jub
* @param {JuMuHu} color1,color2,color3, ... - Input color object(s) to adjust
* @returns {JuMuHuHex[]} - A flattened Array of objects holding the adjusted colors
* @returns {CAM16u[]} - A flattened Array of objects holding the adjusted colors
*/
export function cam16_ucs_adjust({ Jua = 1, Jub = 0, Mua = 1, Mub = 0, Hua = 1, Hub = 0, steps = 1, contrast = false }, ...colors: JuMuHuHex[]): JuMuHuHex[] {
export function adjust_colors({ Jua = 1, Jub = 0, Mua = 1, Mub = 0, Hua = 1, Hub = 0, steps = 1, contrast = false }, ...colors: CAM16u[]): CAM16u[] {
// for each of the colors in the arguments
return colors.map(Cn => {
// work out the starting and finishing colors
Expand All @@ -164,7 +164,7 @@ export function cam16_ucs_adjust({ Jua = 1, Jub = 0, Mua = 1, Mub = 0, Hua = 1,
const cf = { Ju: Cn.Ju * Jua + Jub * cc, Mu: Cn.Mu * Mua + Mub, Hu: Cn.Hu * Hua + Hub }
// create array if steps > 1
if (steps == 1) {
return [cam16_ucs_to_hex_ingamut(cf)]
return [JuMuHu_to_color(cf)]
} else {
const dJu = (cf.Ju - cs.Ju) / (steps - 1)
const dMu = (cf.Mu - cs.Mu) / (steps - 1)
Expand All @@ -175,7 +175,7 @@ export function cam16_ucs_adjust({ Jua = 1, Jub = 0, Mua = 1, Mub = 0, Hua = 1,
Mu: cs.Mu + i * dMu,
Hu: cs.Hu + i * dHu
}
return cam16_ucs_to_hex_ingamut(ct)
return JuMuHu_to_color(ct)
})
}
// flatten the array of arrays to a single array of colors
Expand Down
Loading

0 comments on commit 6d64ceb

Please sign in to comment.