Skip to content

madoo.color-palette/v1

Madoo color palette — The colors an image is made of, by share: hex, OKLCh, CSS name, dominant, accent and background roles, a readable text color (Color Palette).

Reference madoo.color-palette/v1
Schema id urn:madoo:schema:color-palette:v1
Version 1.0.0
Served at GET /api/v1/json-schemas/madoo.color-palette/v1 · MCP get_json_schema
  • Produced by: image/color_palette → palette
Field Type Required Rules Description
schema "madoo.color-palette/v1" yes
image object yes
image.width integer yes ≥ 1
image.height integer yes ≥ 1
image.analysed_pixels integer yes ≥ 1 Pixels read: the whole image, or a sample of about one megapixel (nearest pixel, never averaged) for a larger one.
image.transparent_proportion number yes ≥ 0; ≤ 1 Share of the pixels read that are transparent (alpha under 128) and left out: the background of a cut-out.
settings object yes
settings.count integer yes ≥ 1; ≤ 16
settings.background one of "mark", "exclude", "keep" yes
settings.min_proportion number yes ≥ 0; ≤ 0.5
settings.merge_distance number yes ≥ 0; ≤ 0.3 A color closer than this (OKLab) to a larger one is counted in it instead of taking a place; a vivid color is never counted in a grey.
colors array of objects yes max items 16
colors[].hex string yes pattern “^#[0-9A-F]{6}$”
colors[].rgb array of integer yes min items 3; max items 3
colors[].oklch object yes
colors[].oklch.l number yes Lightness, 0 (black) to 1 (white).
colors[].oklch.c number yes Chroma: 0 for a grey, about 0.3 for the most vivid sRGB colors.
colors[].oklch.h number yes Hue in degrees, 0 to 360; 0 for a grey.
colors[].proportion number yes ≥ 0; ≤ 1
colors[].name string yes The nearest CSS named color (gray, navy, wheat…), measured in OKLab.
colors[].roles array of one of "dominant", "accent", "background" yes dominant: the largest color that is not the background. accent: the most chromatic color (chroma at least 0.05), possibly the dominant one; the palette always shows it. background: the color surrounding the subject on the image border, with the shades of its backdrop.
colors[].text_color one of "#000000", "#FFFFFF" yes Black or white, whichever is more readable on this color (WCAG 2 contrast).
colors[].contrast number yes ≥ 1; ≤ 21 WCAG 2 contrast ratio of text_color on this color; 4.5 is the usual minimum for body text.
dominant string or null yes Hex of the dominant color; null when the image has no opaque pixel.
accent string or null yes Hex of the accent color; null in a neutral image (whites, greys, blacks).
background string or null yes Hex of the background found on the border, also when it is excluded from colors; null when none surrounds the subject (a cut-out, a split image) or background is keep.
other_proportion number yes ≥ 0; ≤ 1
madoo.color-palette/v1 (JSON Schema)
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "urn:madoo:schema:color-palette:v1",
"title": "Madoo color palette",
"description": "The colors an image is made of (Color Palette, image/color_palette). Colors are sRGB, ordered by how much of the image they cover. proportion is a share of the pixels the palette describes: the opaque pixels (alpha at least 128), without the background when it is excluded. other_proportion is what the listed colors leave out (colors under min_proportion or beyond count). The same image always gives the same document.",
"type": "object",
"required": [
"schema",
"image",
"settings",
"colors",
"dominant",
"accent",
"background",
"other_proportion"
],
"properties": {
"schema": {
"const": "madoo.color-palette/v1"
},
"image": {
"type": "object",
"required": [
"width",
"height",
"analysed_pixels",
"transparent_proportion"
],
"properties": {
"width": {
"type": "integer",
"minimum": 1
},
"height": {
"type": "integer",
"minimum": 1
},
"analysed_pixels": {
"type": "integer",
"minimum": 1,
"description": "Pixels read: the whole image, or a sample of about one megapixel (nearest pixel, never averaged) for a larger one."
},
"transparent_proportion": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Share of the pixels read that are transparent (alpha under 128) and left out: the background of a cut-out."
}
}
},
"settings": {
"type": "object",
"required": [
"count",
"background",
"min_proportion",
"merge_distance"
],
"properties": {
"count": {
"type": "integer",
"minimum": 1,
"maximum": 16
},
"background": {
"enum": [
"mark",
"exclude",
"keep"
]
},
"min_proportion": {
"type": "number",
"minimum": 0,
"maximum": 0.5
},
"merge_distance": {
"type": "number",
"minimum": 0,
"maximum": 0.3,
"description": "A color closer than this (OKLab) to a larger one is counted in it instead of taking a place; a vivid color is never counted in a grey."
}
}
},
"colors": {
"type": "array",
"maxItems": 16,
"items": {
"type": "object",
"required": [
"hex",
"rgb",
"oklch",
"proportion",
"name",
"roles",
"text_color",
"contrast"
],
"properties": {
"hex": {
"type": "string",
"pattern": "^#[0-9A-F]{6}$"
},
"rgb": {
"type": "array",
"items": {
"type": "integer",
"minimum": 0,
"maximum": 255
},
"minItems": 3,
"maxItems": 3
},
"oklch": {
"type": "object",
"required": [
"l",
"c",
"h"
],
"properties": {
"l": {
"type": "number",
"description": "Lightness, 0 (black) to 1 (white)."
},
"c": {
"type": "number",
"description": "Chroma: 0 for a grey, about 0.3 for the most vivid sRGB colors."
},
"h": {
"type": "number",
"description": "Hue in degrees, 0 to 360; 0 for a grey."
}
}
},
"proportion": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"name": {
"type": "string",
"description": "The nearest CSS named color (gray, navy, wheat…), measured in OKLab."
},
"roles": {
"type": "array",
"items": {
"enum": [
"dominant",
"accent",
"background"
]
},
"description": "dominant: the largest color that is not the background. accent: the most chromatic color (chroma at least 0.05), possibly the dominant one; the palette always shows it. background: the color surrounding the subject on the image border, with the shades of its backdrop."
},
"text_color": {
"enum": [
"#000000",
"#FFFFFF"
],
"description": "Black or white, whichever is more readable on this color (WCAG 2 contrast)."
},
"contrast": {
"type": "number",
"minimum": 1,
"maximum": 21,
"description": "WCAG 2 contrast ratio of text_color on this color; 4.5 is the usual minimum for body text."
}
}
}
},
"dominant": {
"type": [
"string",
"null"
],
"description": "Hex of the dominant color; null when the image has no opaque pixel."
},
"accent": {
"type": [
"string",
"null"
],
"description": "Hex of the accent color; null in a neutral image (whites, greys, blacks)."
},
"background": {
"type": [
"string",
"null"
],
"description": "Hex of the background found on the border, also when it is excluded from colors; null when none surrounds the subject (a cut-out, a split image) or background is keep."
},
"other_proportion": {
"type": "number",
"minimum": 0,
"maximum": 1
}
},
"examples": [
{
"schema": "madoo.color-palette/v1",
"image": {
"width": 1600,
"height": 1200,
"analysed_pixels": 1047252,
"transparent_proportion": 0
},
"settings": {
"count": 6,
"background": "mark",
"min_proportion": 0.01,
"merge_distance": 0.12
},
"colors": [
{
"hex": "#F4F1EC",
"rgb": [
244,
241,
236
],
"oklch": {
"l": 0.9591,
"c": 0.0074,
"h": 80.72
},
"proportion": 0.5821,
"name": "whitesmoke",
"roles": [
"background"
],
"text_color": "#000000",
"contrast": 18.64
},
{
"hex": "#1F3A5F",
"rgb": [
31,
58,
95
],
"oklch": {
"l": 0.3467,
"c": 0.0731,
"h": 256.69
},
"proportion": 0.2412,
"name": "darkslategray",
"roles": [
"dominant"
],
"text_color": "#FFFFFF",
"contrast": 11.48
},
{
"hex": "#C8102E",
"rgb": [
200,
16,
46
],
"oklch": {
"l": 0.5304,
"c": 0.2074,
"h": 22.32
},
"proportion": 0.0934,
"name": "crimson",
"roles": [
"accent"
],
"text_color": "#FFFFFF",
"contrast": 5.88
}
],
"dominant": "#1F3A5F",
"accent": "#C8102E",
"background": "#F4F1EC",
"other_proportion": 0.0833
}
]
}