Published
Edited
Oct 6, 2022
Insert cell
# color space determiner
Insert cell
Insert cell
data[0].metadata.QuickTime.ColorRepresentation
Insert cell
data[0].magick.properties['icc:description']
Insert cell
colorSpace = function( data ) {
// GIF doesn't support any kind of color profile
// https://github.com/w3c/ColorWeb-CG/issues/9#issuecomment-758024347
// WebP and JPEG only support via embedded ICC profiles. ImageMagick finds them.
const iccDescription = data.magick.properties['icc:description'];

// normalize...
if ( iccDescription ) {
if ( ( /sRGB/i ).test( iccDescription ) ||
( /IEC61966[-–—]2\.1/i ).test( iccDescription ) {
return { colorspace: 'sRGB', source: 'iccDescription' };
} else if ( iccDescription === 'c2' ||
iccDescription === 'c2ci' ||
iccDescription === 'uRGB' ||
iccDescription === 'nRGB') {
return { colorspace: 'Minimal sRGB', source: 'iccDescription' };
} else if ( iccDescription.match( /P3/ ) {
return 'P3';
} else if ( iccDescription.match( /Adobe\s*RGB/ ) ||
iccDescription === 'opRGB' ) {
return 'AdobeRGB';
} else if ( iccDescription.match( /ProPhoto/ ) {
return 'ProPhoto RGB';
}
}

// png hardcoded primaries
// container 'colr' box for AVIF
const nclx = data.metadata.QuickTime.ColorRepresentation;
let parsedNclx = parsedNclx( nclx );
if ( parsedNclx.colorPrimaries.includes( 'SRGB' ) ) {
return { colorspace: 'sRGB', source: 'colr box' }
}
return 'undefined';
}
Insert cell
parseNclx = function(nclxString) {
// https://github.com/AOMediaCodec/libavif/wiki/CICP
// https://github.com/hortovanyi/avif_experiments/blob/master/include/avif/avif.h
let colorPrimaries = [];
colorPrimaries[1] = [ 'SRGB', 'BT709', 'BT1361_0', 'IEC61966_2_1', 'SYCC', 'IEC61966_2_4' ];
colorPrimaries[2] = [ 'unspecified' ];
colorPrimaries[4] = [ 'BT470_6M' ];
colorPrimaries[5] = [ 'BT601_7_625', 'BT470_6G' ];
colorPrimaries[6] = [ 'BT601_7_525', 'BT1358' ];
colorPrimaries[7] = [ 'ST240' ];
colorPrimaries[8] = [ 'GENERIC_FILM' ];
colorPrimaries[9] = [ 'BT2020', 'BT2100' ];
colorPrimaries[10] = [ 'XYZ', 'ST428' ];
colorPrimaries[11] = [ 'RP431_2', 'ST428' ];
colorPrimaries[12] = [ 'P3', 'EG432_1' ];
colorPrimaries[22] = [ 'EBU3213E' ];

let transferCharacteristics = [];
transferCharacteristics[1] = [ 'BT709', 'BT1361' ];
transferCharacteristics[2] = [ 'unspecified' ];
transferCharacteristics[4] = [ 'GAMMA22' ];
transferCharacteristics[5] = [ 'GAMMA28' ];
transferCharacteristics[6] = [ 'BT601' ];
transferCharacteristics[7] = [ 'ST240' ];
transferCharacteristics[8] = [ 'LINEAR' ];
transferCharacteristics[9] = [ 'LOG_100_1' ];
transferCharacteristics[10] = [ 'LOG_100_SQRT' ];
transferCharacteristics[11] = [ 'IEC61966' ];
transferCharacteristics[12] = [ 'BT1361_EXTENDED' ];
transferCharacteristics[13] = [ 'SRGB', '61966_2_1', 'SYCC' ];
transferCharacteristics[14] = [ 'BT2020_10BIT' ];
transferCharacteristics[15] = [ 'BT2020_12BIT' ];
transferCharacteristics[16] = [ 'BT2100_PQ', 'ST2084' ];
transferCharacteristics[17] = [ 'ST428' ];
transferCharacteristics[18] = [ 'STD_B67', 'BT2100_HLG' ];

let matrixCoefficients = [];
matrixCoefficients[0] = [ 'IDENTITY' ];
matrixCoefficients[1] = [ 'SRGB', 'BT709', 'BT1361_0', 'SYCC' ];
matrixCoefficients[2] = [ 'unspecified' ];
matrixCoefficients[4] = [ 'USFC_73682' ];
matrixCoefficients[5] = [ 'BT470_6B', 'BT601_7_625' ];
matrixCoefficients[6] = [ 'BT601_7_525', 'BT1700_NTSC', 'ST170' ];
matrixCoefficients[7] = [ 'ST240' ];
matrixCoefficients[9] = [ 'BT2020_NCL', 'BT2100' ];
matrixCoefficients[10] = [ 'BT2020_CL' ];
matrixCoefficients[11] = [ 'ST2085' ];
matrixCoefficients[12] = [ 'CHROMA_DERIVED_NCL' ];
matrixCoefficients[13] = [ 'CHROMA_DERIVED_CL' ];
matrixCoefficients[14] = [ 'ICTCP' ];

// colorPrimaries, transferCharacteristics, matrixCoefficients;
const matched = nclxString.match(/nclx\s+(\d+)\s+(\d+)\s+(\d+)/);
return {
// matched,
colorPrimaries: colorPrimaries[ parseInt( matched[ 1 ] ) ],
transferCharacteristics: transferCharacteristics[ parseInt( matched[ 2 ] ) ],
matrixCoefficients: matrixCoefficients[ parseInt( matched[ 3 ] ) ]
}
}
Insert cell
parseNclx( data[0].metadata.QuickTime.ColorRepresentation )
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more