CIEDE2000-Implementierung in JavaScript

Funktionsversion: v1.0.0
Statistiken der Website
Anzahl der Besuche918
Anzahl der angesehenen Dateien914 + 371

Diese Seite prĂ€sentiert eine Referenzimplementierung der CIEDE2000-Formel fĂŒr den Farbabstand in JavaScript. Wenn Sie eine genaue Übereinstimmung mit Implementierungen von Drittanbietern bis zu 10 Dezimalstellen erreichen möchten, mĂŒssen Sie möglicherweise Änderungen am Quellcode vornehmen, insbesondere einige Zeilen auskommentieren und dekomentieren, was ĂŒber den folgenden Link automatisch erfolgen kann.

Diagramm der vollstÀndigen CIEDE2000-Formel mit L*a*b*-Komponenten und Anpassungen

Die Funktion ΔE2000 in JavaScript

Betrachten wir die gÀngigere und akademische (Sharma, 2005) der beiden Formulierungen.

// This function written in JavaScript is not affiliated with the CIE (International Commission on Illumination),
// and is released into the public domain. It is provided "as is" without any warranty, express or implied.

// The classic CIE ΔE2000 implementation, which operates on two L*a*b* colors, and returns their difference.
// "l" ranges from 0 to 100, while "a" and "b" are unbounded and commonly clamped to the range of -128 to 127.
function ciede_2000(l_1, a_1, b_1, l_2, a_2, b_2, k_l, k_c, k_h, canonical) {
	"use strict"
	// Working in JavaScript with the CIEDE2000 color-difference formula.
	// k_l, k_c, k_h are parametric factors to be adjusted according to
	// different viewing parameters such as textures, backgrounds...
	var n = (Math.sqrt(a_1 * a_1 + b_1 * b_1) + Math.sqrt(a_2 * a_2 + b_2 * b_2)) * 0.5;
	n = n * n * n * n * n * n * n;
	// A factor involving chroma raised to the power of 7 designed to make
	// the influence of chroma on the total color difference more accurate.
	n = 1.0 + 0.5 * (1.0 - Math.sqrt(n / (n + 6103515625.0)));
	// Application of the chroma correction factor.
	var c_1 = Math.sqrt(a_1 * a_1 * n * n + b_1 * b_1);
	var c_2 = Math.sqrt(a_2 * a_2 * n * n + b_2 * b_2);
	// atan2 is preferred over atan because it accurately computes the angle of
	// a point (x, y) in all quadrants, handling the signs of both coordinates.
	var h_1 = Math.atan2(b_1, a_1 * n), h_2 = Math.atan2(b_2, a_2 * n);
	h_1 += 2.0 * Math.PI * (h_1 < 0.0);
	h_2 += 2.0 * Math.PI * (h_2 < 0.0);
	n = Math.abs(h_2 - h_1);
	// Cross-implementation consistent rounding.
	if (Math.PI - 1E-14 < n && n < Math.PI + 1E-14)
		n = Math.PI;
	// When the hue angles lie in different quadrants, the straightforward
	// average can produce a mean that incorrectly suggests a hue angle in
	// the wrong quadrant, the next lines handle this issue.
	var h_m = (h_1 + h_2) * 0.5, h_d = (h_2 - h_1) * 0.5;
	if (Math.PI < n) {
		h_d += Math.PI;
		if (canonical) // Sharma’s implementation, OpenJDK, ...
			h_m += h_m < Math.PI ? Math.PI : -Math.PI;
		else // Lindbloom’s implementation, Netflix’s VMAF, ...
			h_m += Math.PI;
	}
	var p = 36.0 * h_m - 55.0 * Math.PI;
	n = (c_1 + c_2) * 0.5;
	n = n * n * n * n * n * n * n;
	// The hue rotation correction term is designed to account for the
	// non-linear behavior of hue differences in the blue region.
	var r_t = -2.0 * Math.sqrt(n / (n + 6103515625.0))
		* Math.sin(Math.PI / 3.0 * Math.exp(p * p / (-25.0 * Math.PI * Math.PI)));
	n = (l_1 + l_2) * 0.5;
	n = (n - 50.0) * (n - 50.0);
	// Lightness.
	var l = (l_2 - l_1) / ((k_l || 1.0) * (1.0 + 0.015 * n / Math.sqrt(20.0 + n)));
	// These coefficients adjust the impact of different harmonic
	// components on the hue difference calculation.
	var t = 1.0	+ 0.24 * Math.sin(2.0 * h_m + Math.PI * 0.5)
			+ 0.32 * Math.sin(3.0 * h_m + 8.0 * Math.PI / 15.0)
			- 0.17 * Math.sin(h_m + Math.PI / 3.0)
			- 0.20 * Math.sin(4.0 * h_m + 3.0 * Math.PI / 20.0);
	n = c_1 + c_2;
	// Hue.
	var h = 2.0 * Math.sqrt(c_1 * c_2) * Math.sin(h_d) / ((k_h || 1.0) * (1.0 + 0.0075 * n * t));
	// Chroma.
	var c = (c_2 - c_1) / ((k_c || 1.0) * (1.0 + 0.0225 * n));
	// Returning the square root ensures that dE00 accurately reflects the
	// geometric distance in color space, which can range from 0 to around 185.
	return Math.sqrt(l * l + h * h + c * c + c * h * r_t);
}

// GitHub Project : https://github.com/michel-leonard/ciede2000-color-matching
//   Online Tests : https://michel-leonard.github.io/ciede2000-color-matching

// L1 = 54.8   a1 = 23.5   b1 = 2.0
// L2 = 53.3   a2 = 29.5   b2 = -2.2
// CIE ΔE00 = 4.1622955128 (Bruce Lindbloom, Netflix’s VMAF, ...)
// CIE ΔE00 = 4.1622807178 (Gaurav Sharma, OpenJDK, ...)
// Deviation between implementations ≈ 1.5e-5

// See the source code comments for easy switching between these two widely used ΔE*00 implementation variants.

Ihr Leistungstest

Genauigkeit und ZuverlÀssigkeit des Quellcodes

Der Unterschied zwischen den Formulierungen von Sharma und Lindbloom ĂŒberschreitet niemals ±0,0003 beim endgĂŒltigen ΔE2000, was dem ĂŒblichen Unterschied zwischen zwei 32-Bit-Implementierungen entspricht und fĂŒr das menschliche Auge nicht wahrnehmbar ist. Unsere 64-Bit-Implementierungen, die alle miteinander konsistent sind, garantieren mindestens 10 korrekte Dezimalstellen, sodass die Wahl einer Formulierung gegenĂŒber einer anderen hauptsĂ€chlich von der gewĂŒnschten InteroperabilitĂ€t abhĂ€ngt. Die Formulierung, die standardmĂ€ĂŸig auf dieser Seite erscheint, ist die am hĂ€ufigsten verwendete (ihr Mikrovorteil liegt in ihrer Verankerung in der Gemeinschaft und darin, dass sie leichter ist als ihr Analogon, wenn sie vektorisiert ist).

✎ Wenn Sie im Quellcode einen Kommentar finden, der nicht einer anderen Sprache entspricht, informieren Sie bitte den Autor der Website, der Ihren Vorschlag prĂŒfen und in den Quellcode einarbeiten wird.

Wie kann man RGB-Farben in L*a*b* umwandeln?

FĂŒr die Konvertierung mĂŒssen Sie den XYZ-Zwischenfarbraum verwenden. Falls Sie Hilfe benötigen, finden Sie den Quellcode am Ende dieser Seite (unter Verwendung des 1964 formalisierten D65-Weißpunkts).

Wertebereiche in CIELAB und Interpretation des ΔE2000

Im CIELAB-Farbraum steht die Komponente L* fĂŒr die Helligkeit und reicht normalerweise von 0 (schwarz) bis 100 (weiß). Die Komponenten a* und b* beschreiben die Farbachsen: a* verlĂ€uft von GrĂŒn nach Rot, b* von Blau nach Gelb. In der Praxis liegen a* und b* meist im Bereich von -128 bis +127, können aber je nach Farbumrechnung leicht darĂŒber hinausgehen.

Beispiel fĂŒr zwei Farben, die laut CIEDE2000 einen gerade noch wahrnehmbaren Unterschied (JND) aufweisen
Farbe 1Farbe 2Wert des ΔE2000
1
2
3
Beispiele fĂŒr CIEDE2000-Werte, berechnet zwischen zwei unterschiedlichen Farben
Farbe 1Farbe 2Wert des ΔE2000
5
10
15

Parameter k_l, k_c und k_h

Die Parameter k_l, k_c und k_h sind Gewichtungsfaktoren, die jeweils auf die Helligkeits- (ΔL*), Chroma- (ΔC*) und Farbton- (ΔH*) Terme in der CIEDE2000-Formel angewendet werden. Ihr Standardwert ist 1, was den von der Internationale Beleuchtungskommission empfohlenen Standardbeobachtungsbedingungen entspricht. In der Praxis werden diese Koeffizienten angepasst, um spezielle Bedingungen widerzuspiegeln: Zum Beispiel wird k_l = 2 manchmal verwendet, um Helligkeitsunterschieden mehr Gewicht zu geben (hĂ€ufig im Druckwesen), wĂ€hrend k_c oder k_h reduziert werden können, um die Toleranz gegenĂŒber SĂ€ttigungs- oder Farbtonabweichungen je nach QualitĂ€tskontrolle zu erhöhen. Je nach Kontext liegen diese Koeffizienten typischerweise zwischen 0,5 und 2.

ΔE2000 (CIEDE2000) gibt den wahrgenommenen Unterschied zwischen zwei Farben an: 0 bedeutet identische Farben, höhere Werte (bis etwa 185 in extremen FĂ€llen) zeigen eine stĂ€rkere Abweichung. Beispielsweise entsprechen Werte um 5 eher Ă€hnlichen Farben, wĂ€hrend Werte um 15 deutlich unterschiedliche Farben anzeigen.

Anwendungsbeispiel in JavaScript

// Define color 1 in L*a*b* space
const l1 = 43.2, a1 = 31.2, b1 = 4.1;

// Define color 2 in L*a*b* space
const l2 = 43.0, a2 = 35.5, b2 = -4.3;

// Calculate ΔE2000 color difference
const deltaE = ciede_2000(l1, a1, b1, l2, a2, b2);
console.log(deltaE);

// .................................................. This shows a ΔE2000 of 5.2895865658
// As explained in the comments, compliance with Gaurav Sharma would display 5.2895721943

Testergebnisse

Der in der Sprache C99 geschriebene und mit 250 prĂ€zisen statischen Tests versehene Treiber hat bewiesen, dass diese JavaScript-Funktion mit der in anderen Programmiersprachen zur VerfĂŒgung gestellten CIEDE2000-Funktion interoperabel ist.

CIEDE2000 Verification Summary :
  First Verified Line : 19.8,86.4,126,87,48.32,-70.5,86.66139766452334
             Duration : 36.48 s
            Successes : 10000000
               Errors : 0
      Average Delta E : 62.9463
    Average Deviation : 6.0717893379802488e-15
    Maximum Deviation : 2.2737367544323206e-13

⚡ Vergleich von RGB und Hexadezimalfarben fĂŒr das Web

Nur 3 KB – Einfach. Schnell. Diese kompakte JavaScript-Funktion akzeptiert zwei Farben im RGB- oder Hexadezimalformat und gibt die CIE ΔE2000-Farbabweichung unter Verwendung des Standardlichts D65 zurĂŒck.

// This function written in JavaScript is not affiliated with the CIE (International Commission on Illumination),
// and is released into the public domain. It is provided "as is" without any warranty, express or implied.

// This function accepts both RGB and hexadecimal color formats and computes the color difference using the CIE ΔE2000 formula.
// Examples of use :
// - ciede_2000('#00F', '#483D8B')
// - ciede_2000('#483d8b', 75,0,130)
// - ciede_2000(75, 0, 130, '#00008b')
// - ciede_2000(0, 0, 139, 0, 0, 128)

// GitHub : https://github.com/michel-leonard/ciede2000-color-matching

;function ciede_2000(a,b,c,d,e,f){"use strict";var k_l=1.0,k_c=1.0,k_h=1.0,g,h,i,j,k,l,m,n,o,p,q,r,s=0.040448236277105097;if(typeof a=='string'){g=parseInt((a.length===4?a[0]+a[1]+a[1]+a[2]+a[2]+a[3]+a[3]:a).substring(1),16);if(typeof b=='string'){h=parseInt((b.length===4?b[0]+b[1]+b[1]+b[2]+b[2]+b[3]+b[3]:b).substring(1),16);d=h>>16&0xff;e=h>>8&0xff;f=h&0xff;}else{f=d;e=c;d=b;}a=g>>16&0xff;b=g>>8&0xff;c=g&0xff}else if(typeof d=='string'){g=parseInt((d.length===4?d[0]+d[1]+d[1]+d[2]+d[2]+d[3]+d[3]:d).substring(1),16);d=g>>16&0xff;e=g>>8&0xff;f=g&0xff;}a/=255.0;b/=255.0;c/=255.0;a=a<s?a/12.92:Math.pow((a+0.055)/1.055,2.4);b=b<s?b/12.92:Math.pow((b+0.055)/1.055,2.4);c=c<s?c/12.92:Math.pow((c+0.055)/1.055,2.4);g=a*41.24564390896921145+b*35.75760776439090507+c*18.04374830853290341;h=a*21.26728514056222474+b*71.51521552878181013+c*7.21749933075596513;i=a*1.93338955823293176+b*11.91919550818385936+c*95.03040770337479886;a=g/95.047;b=h/100.0;c=i/108.883;a=a<216.0/24389.0?((841.0/108.0)*a)+(4.0/29.0):Math.cbrt(a);b=b<216.0/24389.0?((841.0/108.0)*b)+(4.0/29.0):Math.cbrt(b);c=c<216.0/24389.0?((841.0/108.0)*c)+(4.0/29.0):Math.cbrt(c);g=(116.0*b)-16.0;h=500.0*(a-b);i=200.0*(b-c);d/=255.0;e/=255.0;f/=255.0;d=d<s?d/12.92:Math.pow((d+0.055)/1.055,2.4);e=e<s?e/12.92:Math.pow((e+0.055)/1.055,2.4);f=f<s?f/12.92:Math.pow((f+0.055)/1.055,2.4);j=d*41.24564390896921145+e*35.75760776439090507+f*18.04374830853290341;k=d*21.26728514056222474+e*71.51521552878181013+f*7.21749933075596513;l=d*1.93338955823293176+e*11.91919550818385936+f*95.03040770337479886;d=j/95.047;e=k/100.0;f=l/108.883;d=d<216.0/24389.0?((841.0/108.0)*d)+(4.0/29.0):Math.cbrt(d);e=e<216.0/24389.0?((841.0/108.0)*e)+(4.0/29.0):Math.cbrt(e);f=f<216.0/24389.0?((841.0/108.0)*f)+(4.0/29.0):Math.cbrt(f);j=(116.0*e)-16.0;k=500.0*(d-e);l=200.0*(e-f);d=(Math.sqrt(h*h+i*i)+Math.sqrt(k*k+l*l))*0.5;d=d*d*d*d*d*d*d;d=1.0+0.5*(1.0-Math.sqrt(d/(d+6103515625.0)));m=Math.sqrt(h*h*d*d+i*i);n=Math.sqrt(k*k*d*d+l*l);o=Math.atan2(i,h*d);p=Math.atan2(l,k*d);o+=2.0*Math.PI*(o<0.0);p+=2.0*Math.PI*(p<0.0);d=Math.abs(p-o);if(Math.PI-1E-14<d&&d<Math.PI+1E-14)d=Math.PI;q=(o+p)*0.5;r=(p-o)*0.5;if(Math.PI<d){r+=Math.PI;q+=Math.PI;}e=36.0*q-55.0*Math.PI;d=(m+n)*0.5;d=d*d*d*d*d*d*d;s=-2.0*Math.sqrt(d/(d+6103515625.0))*Math.sin(Math.PI/3.0*Math.exp(e*e/(-25.0*Math.PI*Math.PI)));d=(g+j)*0.5;d=(d-50.0)*(d-50.0);f=(j-g)/(k_l*(1.0+0.015*d/Math.sqrt(20.0+d)));a=1.0+0.24*Math.sin(2.0*q+Math.PI*0.5)+0.32*Math.sin(3.0*q+8.0*Math.PI/15.0)-0.17*Math.sin(q+Math.PI/3.0)-0.20*Math.sin(4.0*q+3.0*Math.PI/20.0);d=m+n;b=2.0*Math.sqrt(m*n)*Math.sin(r)/(k_h*(1.0+0.0075*d*a));c=(n-m)/(k_c*(1.0+0.0225*d));return Math.sqrt(f*f+b*b+c*c+c*b*s);};

Dateien zum Herunterladen

Eine Datei unten unterstĂŒtzt Berechnungen mit beliebiger Genauigkeit in JavaScript (nĂŒtzlich, wenn Sie ΔE2000 in der Metrologie behandeln). Verwenden Sie diese von Michel zur VerfĂŒgung gestellten Dateien frei, auch fĂŒr kommerzielle Zwecke.

Statistiken der Website : Dateidownloads
DateiGrĂ¶ĂŸeAnzahl der Klicks
ciede-2000.js4 KB129
ciede-2000-driver.js7 KB105
ciede-2000-multiprecision.js37 KB108
ciede-2000-random.js6 KB94
compare-hex-colors.js8 KB95
compare-rgb-colors.js8 KB99
test-js-multiprecision.yml7 KB74
test-js.yml3 KB70
vs-chroma.yml4 KB71
vs-npm-delta-e.yml4 KB69
reference-dataset.txt4 KB371
Klicken Sie auf js.zip, um alle Dateien in einem Archiv herunterzuladen.

Gemeinschaft

Was halten Sie von diesem Quellcode oder von CIEDE2000? Ihre Meinung ist uns wichtig! Das GÀstebuch enthÀlt bereits 9 EintrÀge - davon 1 auf Deutsch. Schauen Sie sich dort um und teilen Sie Ihre Meinung mit.