Skip to content

madoo.image-detail/v1

Madoo image detail — Fine detail and residuals of an image on small patches, globally and per tone band, and the patches to look at closely with a context rectangle ready for Crop (Image Detail).

Reference madoo.image-detail/v1
Schema id urn:madoo:schema:image-detail:v1
Version 1.0.0
Served at GET /api/v1/json-schemas/madoo.image-detail/v1 · MCP get_json_schema
  • Produced by: image/detail → detail
Field Type Required Rules Description
schema "madoo.image-detail/v1" yes
algorithm_version string yes
image object yes
image.width integer yes ≥ 1 After EXIF orientation.
image.height integer yes ≥ 1
image.orientation_applied boolean yes True when the EXIF orientation rotated or mirrored the image.
color object yes
color.working_space "srgb-8" yes
color.profile_policy one of "srgb", "converted", "assumed_srgb" yes srgb: the file is sRGB; converted: its ICC profile was converted to sRGB; assumed_srgb: an RGB image without a profile, read as sRGB.
color.source_depth integer or null yes Bits per channel of the file.
color.analysis_depth 8 yes
warnings array of string yes Facts that limit how the numbers may be read: a JPEG source (compression can contaminate detail measurements), several frames or pages (the first was measured), a source deeper than 8 bits (measured at 8 bits).
settings object yes
settings.patch_size integer
settings.stride integer
settings.alpha_min integer
settings.max_patches integer
settings.context_size integer
settings.min_separation integer
settings.max_regions integer
settings.mask_threshold integer
settings.step integer
settings.luma_min number
settings.luma_max number
settings.flat_gradient_max number
settings.select array of one of "low_gradient", "detail", "bright_transition"
settings.mask boolean
patches object yes
patches.examined integer yes ≥ 0
patches.opaque integer yes ≥ 0 Patches whose pixels and 3 px neighbourhood are all at alpha_min or more.
patches.eligible integer yes ≥ 0
patches.area_share number or null yes ≥ 0; ≤ 1 Share of the image covered by eligible patches.
patches.excluded object yes
patches.excluded.alpha integer ≥ 0
patches.excluded.too_dark integer ≥ 0
patches.excluded.too_bright integer ≥ 0
patches.excluded.too_structured integer ≥ 0
patches.excluded.outside_mask integer ≥ 0
global object yes
global.n integer yes ≥ 0 Eligible patches. Every figure below is the median across them of the per-patch value.
global.status one of "ok", "not_observable" yes not_observable: the measurement is undefined here (see reason); its numbers are null. Zero is a valid measurement, never a stand-in for null.
global.reason one of null, "no_eligible_pixels", "too_few_samples", "zero_variance", "no_eligible_patches", "mask_empty_in_region" yes
global.gradient number or null Per patch: mean of |Y(x+1,y) - Y(x-1,y)| + |Y(x,y+1) - Y(x,y-1)| (central differences, the two axes summed).
global.residual_mad_3 number or null Per patch: 1.4826 x median(|r - median(r)|) of r = luma minus its 3x3 mean, in luma units.
global.residual_mad_7 number or null Same with the 7x7 mean.
global.residual_corr_x number or null ≥ -1; ≤ 1 Per patch: 3x3 residuals one pixel apart horizontally, centred on the patch mean, sum(a*b) / sum((a^2 + b^2) / 2); null when that energy is below 1e-12.
global.residual_corr_y number or null ≥ -1; ≤ 1 Same for vertically adjacent pixels.
bands array of objects yes min items 5; max items 5 Five equal luma bands of the patch means: [0, 0.2), [0.2, 0.4), [0.4, 0.6), [0.6, 0.8), [0.8, 1].
bands[].n integer yes ≥ 0 Eligible patches. Every figure below is the median across them of the per-patch value.
bands[].status one of "ok", "not_observable" yes not_observable: the measurement is undefined here (see reason); its numbers are null. Zero is a valid measurement, never a stand-in for null.
bands[].reason one of null, "no_eligible_pixels", "too_few_samples", "zero_variance", "no_eligible_patches", "mask_empty_in_region" yes
bands[].gradient number or null Per patch: mean of |Y(x+1,y) - Y(x-1,y)| + |Y(x,y+1) - Y(x,y-1)| (central differences, the two axes summed).
bands[].residual_mad_3 number or null Per patch: 1.4826 x median(|r - median(r)|) of r = luma minus its 3x3 mean, in luma units.
bands[].residual_mad_7 number or null Same with the 7x7 mean.
bands[].residual_corr_x number or null ≥ -1; ≤ 1 Per patch: 3x3 residuals one pixel apart horizontally, centred on the patch mean, sum(a*b) / sum((a^2 + b^2) / 2); null when that energy is below 1e-12.
bands[].residual_corr_y number or null ≥ -1; ≤ 1 Same for vertically adjacent pixels.
bands[].l_min number
bands[].l_max number
selected array of objects yes
selected[].role one of "low_gradient", "detail", "bright_transition", "center_fallback" yes low_gradient: the eligible patch with the lowest gradient; detail: the opaque patch with the highest gradient; bright_transition: the opaque patch with the highest mean + gradient; center_fallback: no candidate patch.
selected[].patch object or null yes
selected[].context object yes Pixels of the oriented image, origin top left; covers columns x..x+width-1 and rows y..y+height-1.
selected[].context.x integer yes ≥ 0
selected[].context.y integer yes ≥ 0
selected[].context.width integer yes ≥ 1
selected[].context.height integer yes ≥ 1
selected[].patch_in_context object or null
selected[].patch_in_context.x integer
selected[].patch_in_context.y integer
selected[].mean number or null
selected[].gradient number or null
selected[].residual_mad_3 number or null
selected[].residual_mad_7 number or null
selected[].residual_corr_x number or null ≥ -1; ≤ 1
selected[].residual_corr_y number or null ≥ -1; ≤ 1
selected[].score number or null
madoo.image-detail/v1 (JSON Schema)
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "urn:madoo:schema:image-detail:v1",
"title": "Madoo image detail",
"description": "What Image Detail (image/detail) measured at native resolution on small patches: fine detail and residuals (which include texture, noise, sharpening and compression — not proof of film grain), and the regions it selected for a closer look.",
"type": "object",
"required": [
"schema",
"algorithm_version",
"image",
"color",
"warnings",
"settings",
"patches",
"global",
"bands",
"selected"
],
"properties": {
"schema": {
"const": "madoo.image-detail/v1"
},
"algorithm_version": {
"type": "string"
},
"image": {
"$ref": "#/$defs/image"
},
"color": {
"$ref": "#/$defs/color"
},
"warnings": {
"$ref": "#/$defs/warnings"
},
"settings": {
"type": "object",
"properties": {
"patch_size": {
"type": "integer"
},
"stride": {
"type": "integer"
},
"alpha_min": {
"type": "integer"
},
"max_patches": {
"type": "integer"
},
"context_size": {
"type": "integer"
},
"min_separation": {
"type": "integer"
},
"max_regions": {
"type": "integer"
},
"mask_threshold": {
"type": "integer"
},
"step": {
"type": "integer"
},
"luma_min": {
"type": "number"
},
"luma_max": {
"type": "number"
},
"flat_gradient_max": {
"type": "number"
},
"select": {
"type": "array",
"items": {
"enum": [
"low_gradient",
"detail",
"bright_transition"
]
}
},
"mask": {
"type": "boolean"
}
}
},
"patches": {
"type": "object",
"required": [
"examined",
"opaque",
"eligible",
"area_share",
"excluded"
],
"properties": {
"examined": {
"type": "integer",
"minimum": 0
},
"opaque": {
"type": "integer",
"minimum": 0,
"description": "Patches whose pixels and 3 px neighbourhood are all at alpha_min or more."
},
"eligible": {
"type": "integer",
"minimum": 0
},
"area_share": {
"type": [
"number",
"null"
],
"minimum": 0,
"maximum": 1,
"description": "Share of the image covered by eligible patches."
},
"excluded": {
"type": "object",
"properties": {
"alpha": {
"type": "integer",
"minimum": 0
},
"too_dark": {
"type": "integer",
"minimum": 0
},
"too_bright": {
"type": "integer",
"minimum": 0
},
"too_structured": {
"type": "integer",
"minimum": 0
},
"outside_mask": {
"type": "integer",
"minimum": 0
}
}
}
}
},
"global": {
"type": "object",
"required": [
"n",
"status",
"reason"
],
"properties": {
"n": {
"type": "integer",
"minimum": 0,
"description": "Eligible patches. Every figure below is the median across them of the per-patch value."
},
"status": {
"$ref": "#/$defs/status"
},
"reason": {
"$ref": "#/$defs/reason"
},
"gradient": {
"type": [
"number",
"null"
],
"description": "Per patch: mean of |Y(x+1,y) - Y(x-1,y)| + |Y(x,y+1) - Y(x,y-1)| (central differences, the two axes summed)."
},
"residual_mad_3": {
"type": [
"number",
"null"
],
"description": "Per patch: 1.4826 x median(|r - median(r)|) of r = luma minus its 3x3 mean, in luma units."
},
"residual_mad_7": {
"type": [
"number",
"null"
],
"description": "Same with the 7x7 mean."
},
"residual_corr_x": {
"type": [
"number",
"null"
],
"minimum": -1,
"maximum": 1,
"description": "Per patch: 3x3 residuals one pixel apart horizontally, centred on the patch mean, sum(a*b) / sum((a^2 + b^2) / 2); null when that energy is below 1e-12."
},
"residual_corr_y": {
"type": [
"number",
"null"
],
"minimum": -1,
"maximum": 1,
"description": "Same for vertically adjacent pixels."
}
}
},
"bands": {
"type": "array",
"minItems": 5,
"maxItems": 5,
"description": "Five equal luma bands of the patch means: [0, 0.2), [0.2, 0.4), [0.4, 0.6), [0.6, 0.8), [0.8, 1].",
"items": {
"type": "object",
"required": [
"n",
"status",
"reason"
],
"properties": {
"n": {
"type": "integer",
"minimum": 0,
"description": "Eligible patches. Every figure below is the median across them of the per-patch value."
},
"status": {
"$ref": "#/$defs/status"
},
"reason": {
"$ref": "#/$defs/reason"
},
"gradient": {
"type": [
"number",
"null"
],
"description": "Per patch: mean of |Y(x+1,y) - Y(x-1,y)| + |Y(x,y+1) - Y(x,y-1)| (central differences, the two axes summed)."
},
"residual_mad_3": {
"type": [
"number",
"null"
],
"description": "Per patch: 1.4826 x median(|r - median(r)|) of r = luma minus its 3x3 mean, in luma units."
},
"residual_mad_7": {
"type": [
"number",
"null"
],
"description": "Same with the 7x7 mean."
},
"residual_corr_x": {
"type": [
"number",
"null"
],
"minimum": -1,
"maximum": 1,
"description": "Per patch: 3x3 residuals one pixel apart horizontally, centred on the patch mean, sum(a*b) / sum((a^2 + b^2) / 2); null when that energy is below 1e-12."
},
"residual_corr_y": {
"type": [
"number",
"null"
],
"minimum": -1,
"maximum": 1,
"description": "Same for vertically adjacent pixels."
},
"l_min": {
"type": "number"
},
"l_max": {
"type": "number"
}
}
}
},
"selected": {
"type": "array",
"items": {
"type": "object",
"required": [
"role",
"patch",
"context"
],
"properties": {
"role": {
"enum": [
"low_gradient",
"detail",
"bright_transition",
"center_fallback"
],
"description": "low_gradient: the eligible patch with the lowest gradient; detail: the opaque patch with the highest gradient; bright_transition: the opaque patch with the highest mean + gradient; center_fallback: no candidate patch."
},
"patch": {
"oneOf": [
{
"$ref": "#/$defs/rect"
},
{
"type": "null"
}
]
},
"context": {
"$ref": "#/$defs/rect",
"description": "Up to context_size, centred on the patch and moved inside the image, never enlarged."
},
"patch_in_context": {
"type": [
"object",
"null"
],
"properties": {
"x": {
"type": "integer"
},
"y": {
"type": "integer"
}
}
},
"mean": {
"type": [
"number",
"null"
]
},
"gradient": {
"type": [
"number",
"null"
]
},
"residual_mad_3": {
"type": [
"number",
"null"
]
},
"residual_mad_7": {
"type": [
"number",
"null"
]
},
"residual_corr_x": {
"type": [
"number",
"null"
],
"minimum": -1,
"maximum": 1
},
"residual_corr_y": {
"type": [
"number",
"null"
],
"minimum": -1,
"maximum": 1
},
"score": {
"type": [
"number",
"null"
]
}
}
}
}
},
"$defs": {
"rect": {
"type": "object",
"required": [
"x",
"y",
"width",
"height"
],
"properties": {
"x": {
"type": "integer",
"minimum": 0
},
"y": {
"type": "integer",
"minimum": 0
},
"width": {
"type": "integer",
"minimum": 1
},
"height": {
"type": "integer",
"minimum": 1
}
},
"description": "Pixels of the oriented image, origin top left; covers columns x..x+width-1 and rows y..y+height-1."
},
"image": {
"type": "object",
"required": [
"width",
"height",
"orientation_applied"
],
"properties": {
"width": {
"type": "integer",
"minimum": 1,
"description": "After EXIF orientation."
},
"height": {
"type": "integer",
"minimum": 1
},
"orientation_applied": {
"type": "boolean",
"description": "True when the EXIF orientation rotated or mirrored the image."
}
}
},
"color": {
"type": "object",
"required": [
"working_space",
"profile_policy",
"source_depth",
"analysis_depth"
],
"properties": {
"working_space": {
"const": "srgb-8"
},
"profile_policy": {
"enum": [
"srgb",
"converted",
"assumed_srgb"
],
"description": "srgb: the file is sRGB; converted: its ICC profile was converted to sRGB; assumed_srgb: an RGB image without a profile, read as sRGB."
},
"source_depth": {
"type": [
"integer",
"null"
],
"description": "Bits per channel of the file."
},
"analysis_depth": {
"const": 8
}
}
},
"sampling": {
"type": "object",
"required": [
"method",
"step",
"eligible_pixels",
"sampled_pixels"
],
"properties": {
"method": {
"enum": [
"grid",
"full"
]
},
"step": {
"type": "integer",
"minimum": 1
},
"eligible_pixels": {
"type": "integer",
"minimum": 0,
"description": "Pixels of the region that may be measured: opaque enough and inside the mask."
},
"sampled_pixels": {
"type": "integer",
"minimum": 0
}
}
},
"warnings": {
"type": "array",
"items": {
"type": "string"
},
"description": "Facts that limit how the numbers may be read: a JPEG source (compression can contaminate detail measurements), several frames or pages (the first was measured), a source deeper than 8 bits (measured at 8 bits)."
},
"status": {
"enum": [
"ok",
"not_observable"
],
"description": "not_observable: the measurement is undefined here (see reason); its numbers are null. Zero is a valid measurement, never a stand-in for null."
},
"reason": {
"type": [
"string",
"null"
],
"enum": [
null,
"no_eligible_pixels",
"too_few_samples",
"zero_variance",
"no_eligible_patches",
"mask_empty_in_region"
]
}
}
}