web-dev-qa-db-fra.com

Mélanger deux couleurs "naturellement" en javascript

Le problème: Je veux mélanger deux couleurs en javascript et obtenir la couleur résultante. Il y a beaucoup de questions similaires sur SO, mais je ne trouve rien qui fonctionne correctement. Je sais que le mélange de deux peintures (pigments) et de lumières de couleurs différentes donnera des résultats très différents ( http://en.wikipedia.org/wiki/Color_mixing ).

Voici les questions et les suggestions de solutions que j'ai déjà vues et que j'ai essayé de mettre en œuvre:

1: Mélange de deux vecteurs de couleurs RVB pour obtenir la résultante
Donc, mélanger les couleurs en RVB. Je l'ai implémenté, et dans certains cas, cela fonctionne dans certains cas, il ne fonctionne pas.

Exemple de travail: Mélange red avec yellow -> orange. Génial!
http://jsbin.com/afomim/1/edit

Exemple non fonctionnel: Mélange de blue avec yellow -> gray. Pas si bien! :) http://jsbin.com/afomim/5/edit
Je sais qu'en RVB, le mélange blue avec yellow ne fera jamais green, et je comprends pourquoi.

Nous ne trouverons pas la réponse ici, allons de l'avant.

2: Ajout de couleurs (couleurs) ensemble comme de la peinture (bleu + jaune = vert, etc.)

Essayons de travailler avec les valeurs CMJN comme suggéré dans cette discussion. Le mélange de cyan avec yellow donne green:
http://jsbin.com/igaveg/1/edit
mais le mélange de blue avec yellow donne black.
http://jsbin.com/igaveg/2/edit -> Ne fonctionne pas!

3: Comment mélanger les couleurs "naturellement" avec C #?
Une question très similaire. La réponse la plus votée suggère de convertir les couleurs en LAB, et cette solution semble prometteuse.
J'ai donc converti mes couleurs en LAB. L'algo de conversion est correct, je l'ai testé!

http://jsbin.com/oxefox/1/edit

Maintenant, j'ai les deux couleurs dans LAB, mais comment les mélanger?

[~ # ~] note [~ # ~] Je sais que je ne trouverai probablement pas d'algo qui mélange blue avec yellow et donnera le parfait green, mais j'espère pouvoir générer quelque chose de similaire au vert :)

30
Tamás Pap

J'ai consacré 3-4 jours à cette question. C'est un problème vraiment complexe.

Voici ce que vous pouvez faire si vous souhaitez mélanger deux couleurs "naturellement":

  1. Mélange CMJN: ce n'est pas la solution parfaite, mais si vous avez besoin d'une solution maintenant et que vous ne voulez pas passer des mois à apprendre sur le sujet, à expérimenter et à coder, vous pouvez le vérifier: https: // github.com/AndreasSoiron/Color_mixer

  2. Implémentation de la théorie de Kubelka-Munk. J'ai passé beaucoup de temps à lire à ce sujet et à essayer de le comprendre. Cela devrait être la voie à suivre si vous voulez une solution professionnelle, mais elle nécessite 6 paramètres (comme la réflectance, l'absorption, etc.) pour chaque couleur que vous souhaitez mélanger. Avoir R, G, B ne suffit pas. La mise en œuvre de la théorie n'est pas difficile, mais obtenir les paramètres dont vous avez besoin pour chaque couleur semble être la partie manquante. Si vous savez comment le faire, faites le moi savoir :)

  3. Expérimental: vous pouvez faire quelque chose que les développeurs de l'application ipad: Paper ont fait. Ils ont sélectionné manuellement 100 paires de couleurs populaires et testé la façon dont ils devraient se mélanger. En savoir plus ici .

Personnellement, je vais implémenter le mixage CMJN pour le moment, et peut-être plus tard, si j'ai le temps, j'essaierai de faire quelque chose comme les gars de Fiftythree. Va voir :)

33
Tamás Pap

Le modèle de couleur RYB pourrait être un choix approprié pour les calculs de mélange de couleurs. Selon Wikipedia , il est principalement utilisé dans l'enseignement de l'art et du design, en particulier la peinture.

Pour mélanger 2 couleurs, on convertit les deux couleurs de RVB en RYB, mélange les couleurs en ajoutant chaque composante de couleur et reconvertit la couleur résultante de RYB en RVB.

J'ai essayé cela en utilisant Outil de mélange de couleurs en ligne , et les résultats sont

  • 0000FF ( bleu ) mélangé avec # FFFF00 ( jaune ) donne # 008000 ( vert foncé ),

  • FF0000 ( rouge ) mélangé avec # FFFF00 ( jaune ) donne # FFA000 ( orange ).

Cette méthode produit donc exactement les résultats que vous attendiez.

Malheureusement, je n'ai pas pu trouver de référence avec la formule "prête à l'emploi" pour convertir du RVB au RYB et revenir au RVB.

L'article Paint Inspired Color Mixing and Compositing for Visualization - Gossett and Chen décrit l'idée générale du modèle de couleur RYB dans la section "2 RÉALISER UN MÉLANGE DE COULEUR INTUITIF".

Selon cet article, la conversion de RYB en RVB se fait par interpolation trilinéaire .

La partie difficile est la conversion de RGB en RYB, car elle nécessite l'inversion de l'interpolation trilinéaire. Voir Conversion entre les espaces colorimétriques RVB et RYB pour plus d'informations.

Même si cette réponse ne fournit pas de formule complète pour le calcul, j'espère qu'elle donne quelques idées sur la façon de procéder.

12
Martin R

En fait, je suis tombé sur le même problème en essayant de mélanger 2 couleurs RVB ensemble. Ces 2 fonctions ont fonctionné pour moi:

//colorChannelA and colorChannelB are ints ranging from 0 to 255
function colorChannelMixer(colorChannelA, colorChannelB, amountToMix){
    var channelA = colorChannelA*amountToMix;
    var channelB = colorChannelB*(1-amountToMix);
    return parseInt(channelA+channelB);
}
//rgbA and rgbB are arrays, amountToMix ranges from 0.0 to 1.0
//example (red): rgbA = [255,0,0]
function colorMixer(rgbA, rgbB, amountToMix){
    var r = colorChannelMixer(rgbA[0],rgbB[0],amountToMix);
    var g = colorChannelMixer(rgbA[1],rgbB[1],amountToMix);
    var b = colorChannelMixer(rgbA[2],rgbB[2],amountToMix);
    return "rgb("+r+","+g+","+b+")";
}

Pour mélanger uniformément le rouge ([255,0,0]) et le bleu ([0,0,255]), vous pouvez appeler

colorMixer([255,0,0], [0,0,255], 0.5);//returns "rgb(127,0,127)" (purple)

Cela peut vous aider, mais vous devez d'abord convertir chaque valeur de couleur en un tableau. Si vous utilisez Fabric.js pour travailler avec des éléments de canevas, cela devient vraiment facile. Il suffit d'appeler

var rgbA = new fabric.Color(yourColor);
var rgbB = new fabric.Color(yourSecondColor);

puis appelez

colorMixer(rgbA.getSource(),rgbB.getSource(),0.5);

J'espère que ces fonctions vous aideront.

6
Aaron Harris

Avec les couleurs CIELAB, vous disposez de trois coordonnées pour chacune de vos deux couleurs dans l'espace colorimétrique LAB. (Soit dit en passant, excellent travail pour en arriver là). Ce qui fonctionnera le mieux et sera le plus facile à implémenter pour vous, c'est de trouver le milieu tridimensionnel d'un segment de ligne imaginaire joignant les deux points dans l'espace LAB. Vous pouvez le faire facilement en faisant simplement la moyenne de chacun des composants de vos deux couleurs: la moyenne L, la moyenne a et la moyenne b. Puis reconvertissez cette couleur en espace RVB en inversant votre transformation (assurez-vous que votre espace d'éclairage reste le même dans les deux sens).

Votre nouvelle couleur peut être en dehors de l'espace colorimétrique RVB. Dans ce cas, vous pouvez décider de couper à la couleur visible la plus proche. (Les bleus sont particulièrement vulnérables à cela).

4
Plynx

Maintenant que vous avez vos deux couleurs au format LAB (ou L * a * b *), vous pouvez les faire la moyenne ensemble.

L(result) = L(first color) + L(second color) / 2
A(result) = A(first color) + A(second color) / 2
B(result) = B(first color) + B(second color) / 2

Vous le saviez déjà, non? car c'est ce que vous faisiez avec vos couleurs RVB d'origine pour en faire la moyenne.

3
Quuxplusone

Qu'en est-il de la conversion de RVB en CMJN en utilisant this puis:

// CMYK colors
colorA = [2, 90, 94, 0];
colorB = [4, 0, 80, 0]; 

colorMixC = (colorA[0] + colorB[0]) / 2;
colorMixM = (colorA[1] + colorB[1]) / 2;
colorMixY = (colorA[2] + colorB[2]) / 2;
colorMixK = (colorA[3] + colorB[3]) / 2;

Et enfin convertir CMJN en RVB en utilisant this

1
Jordan

Voici un bon article que j'ai écrit sur le mélange de couleurs dans l'espace colorimétrique CIE-LCh, qui produit un mélange qui préserve la teinte, la saturation et la luminance d'une manière cohérente avec la perception de votre œil.

Mélange de couleurs amélioré

1
Stu

Créez l'élément que vous souhaitez peindre:

<DIV ID="SWATCH" STYLE="HEIGHT:50PX;WIDTH:50PX;"></DIV>

Placez les couleurs RVB que vous souhaitez combiner dans un tableau (autant que vous le souhaitez):

var colourArray=['#012345','#6789AB','#CDEFED','#CBA987','#654321'];

Convertissez ensuite toutes les lettres en chiffres et interceptez-les en séquence:

var tempString=[],convertedColourArray=[];
for(i=0;i<colourArray.length;i++){
    for(x=1;x<=6;x++){
        var oldPigment=colourArray[i].charAt(x);
        if(oldPigment<=9)tempString.Push(oldPigment);
        if(oldPigment=='A')tempString.Push(10);
        if(oldPigment=='B')tempString.Push(11);
        if(oldPigment=='C')tempString.Push(12);
        if(oldPigment=='D')tempString.Push(13);
        if(oldPigment=='E')tempString.Push(14);
        if(oldPigment=='F')tempString.Push(15);}
    convertedColourArray.Push(tempString);
    tempString=[];}

Additionnez ensuite chacun des numéros de position d'index:

var colourTotal=0,newColour='#';
for(i=0;i<=5;i++){
    for(x=0;x<convertedColourArray.length;x++)colourTotal+=parseFloat(convertedColourArray[x][i]);

Enfin, prenez le nouveau numéro, convertissez-le en caractère correspondant et ajoutez-le à la variable newColour:

    var newPigment=(Math.floor(colourTotal/colourArray.length));
    if(newPigment<=9)newColour+=newPigment;
    if(newPigment==10)newColour+='A';
    if(newPigment==11)newColour+='B';
    if(newPigment==12)newColour+='C';
    if(newPigment==13)newColour+='D';
    if(newPigment==14)newColour+='E';
    if(newPigment==15)newColour+='F';
    colourTotal=0;}

Maintenant, vous pouvez peindre ce que vous voulez avec la nouvelle couleur:

    document.getElementById('SWATCH').style.backgroundColor=newColour;

J'espère que cela vous aide et n'hésitez pas à y jeter des œufs :)

0
Howard

Vous devez utiliser [~ # ~] cmy [~ # ~] ou [~ # ~] rgb [ ~ # ~] modèle de couleur.

Pourquoi Blue + Yellow ne peut pas être Gray?

Blue + Yellow = (Cyan + Magenta) + Yellow => Gray. Pourquoi pas?

Regardez ça.

Vous pouvez donc utiliser RVB (CMJ) pour mélanger les couleurs.

0
Pylyp