La función de descomponer el color en matices.

 

Durante un mes, resolví obstinadamente el problema de descomponer el color en matices. La tarea resultó ser difícil. Tomé la paleta de colores de Windows como base para el estudio (la que está en las propiedades del gráfico ). Después de un largo estudio, todavía encontré patrones. Y así es como:

  • Primero, descompuse el color en tres componentes principales, determinando el más alto, el medio y el más bajo.
  • Además, comencé a construir gráficos y dibujar líneas a través de los valores de los componentes.
  • Observando los cambios en los números en la paleta al arrastrar el deslizador, me di cuenta que hay una refracción del ángulo de ascenso de las líneas, porque en un momento determinado cambió la tasa de cambio de los números.
  • Puse el eje de refracción de las líneas en el centro del gráfico y vi que cada línea consta de dos segmentos, cada uno de los cuales tiene su propio ángulo de ascensión.
  • Además, experimentando con la paleta de colores, me di cuenta de que hay un ángulo máximo de ascenso del componente más alto. Al principio pensé que eran 67,5 grados. Sin embargo, la práctica ha demostrado que es igual a 63,5 grados.
  • Durante mucho tiempo, no pude averiguar cómo trazar correctamente los segmentos de línea de los componentes de color. Había muchas incógnitas. Pero lo principal es cómo encontrar la coordenada del color original en el gráfico.
  • Continuando con la experimentación con la paleta, noté que al cambiar el valor del color por un cierto número, el control deslizante se mueve una cierta distancia. Gradualmente, me di cuenta de que la distancia de desplazamiento del control deslizante es igual a la mitad del valor del componente menor.
  • Asumí que si encuentro la coordenada del componente más alto en la línea del ángulo de máxima ascensión y sumo la mitad del valor del componente más bajo a este punto, encontraré la coordenada del color original en el gráfico. La práctica ha demostrado que la suposición era correcta.
  • Dada la coordenada del color original y el eje de refracción, pude calcular los ángulos de cada uno de los segmentos y obtener valores para cada componente a lo largo de su línea. Para hacer esto, usé la trigonometría escolar.
  • Después de revisar los cálculos en papel, comencé a escribir la función. Ahora quiero compartirlo con todos.
 //+------------------------------------------------------------------+
//|                                                Full Gradient.mqh |
//|                                                      Peter Konow |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
void Диапазон_оттенков( color _Цвет, string &Все_оттенки[ 256 ])
{
 color R,G,B,q;
 //------------------------------------------------------
 string Этот_цвет;
 double Тангенс_угла_старшего_треугольника_1,      
        Тангенс_угла_среднего_треугольника_1,                  
        Тангенс_угла_младшего_треугольника_1,                       
        Значение_в_точке_преломления_старшей_компоненты,  
        Значение_в_точке_преломления_средней_компоненты,
        Значение_в_точке_преломления_младшей_компоненты,    
        Тангенс_угла_старшего_треугольника_2,
        Тангенс_угла_среднего_треугольника_2,    
        Тангенс_угла_младшего_треугольника_2;
 //------------------------------------------------------
 double pi = 3.1415926536 ,
        Comp_1,Comp_2,Comp_3,
         //-----------------------------------------------
        Первая_компонента,
        Вторая_компонента,
        Третья_компонента,
         //-----------------------------------------------
        Исходный_R = GetR(_Цвет), 
        Исходный_G = GetG(_Цвет),  
        Исходный_B = GetB(_Цвет),  
         //-----------------------------------------------
        Старшая_компонента         = Нужная_компонента(Исходный_R,Исходный_G,Исходный_B, 0 ), 
        Средняя_компонента         = Нужная_компонента(Исходный_R,Исходный_G,Исходный_B, 1 ), 
        Младшая_компонента         = Нужная_компонента(Исходный_R,Исходный_G,Исходный_B, 2 ), 
         //-----------------------------------------------
        Координата_исходного_цвета = Старшая_компонента/ tan (( 63.43989 *pi)/ 180 ) + Младшая_компонента/ 2 ; 
         //-----------------------------------------------
        
 //-----------------------------------------------
 if (Старшая_компонента == Исходный_R)R = Старшая_компонента;
 if (Старшая_компонента == Исходный_G)G = Старшая_компонента; 
 if (Старшая_компонента == Исходный_B)B = Старшая_компонента;     
 //------------------------
 if (Средняя_компонента == Исходный_R)R = Средняя_компонента;
 if (Средняя_компонента == Исходный_G)G = Средняя_компонента; 
 if (Средняя_компонента == Исходный_B)B = Средняя_компонента; 
 //------------------------
 if (Младшая_компонента == Исходный_R)R = Младшая_компонента;
 if (Младшая_компонента == Исходный_G)G = Младшая_компонента; 
 if (Младшая_компонента == Исходный_B)B = Младшая_компонента;     
 //==========================================================================================
 if (Координата_исходного_цвета <= 127 )
   {
    Тангенс_угла_старшего_треугольника_1  = Старшая_компонента/Координата_исходного_цвета;
    Тангенс_угла_среднего_треугольника_1  = Средняя_компонента/Координата_исходного_цвета;     
    Тангенс_угла_младшего_треугольника_1  = Младшая_компонента/Координата_исходного_цвета;
     //-----------------------------------------------
    Значение_в_точке_преломления_старшей_компоненты  = Тангенс_угла_старшего_треугольника_1* 128 ;
    Значение_в_точке_преломления_средней_компоненты  = Тангенс_угла_среднего_треугольника_1* 128 ;
    Значение_в_точке_преломления_младшей_компоненты  = Тангенс_угла_младшего_треугольника_1* 128 ;    
     //-----------------------------------------------    
    Тангенс_угла_старшего_треугольника_2  = ( 255 - Значение_в_точке_преломления_старшей_компоненты)/ 128 ;
    Тангенс_угла_среднего_треугольника_2  = ( 255 - Значение_в_точке_преломления_средней_компоненты)/ 128 ;       
    Тангенс_угла_младшего_треугольника_2  = ( 255 - Значение_в_точке_преломления_младшей_компоненты)/ 128 ;
     //-----------------------------------------------    
     for ( int a1 = 0 ; a1 < 128 ; a1++)
      {
       Comp_1 = Тангенс_угла_старшего_треугольника_1*a1;
       Comp_2 = Тангенс_угла_среднего_треугольника_1*a1;
       Comp_3 = Тангенс_угла_младшего_треугольника_1*a1;
       //---------------------------------------------------
       if (Comp_1 > 255 )Comp_1 = 255 ;
       if (Comp_1 > 255 )Comp_2 = 255 ;
       if (Comp_1 > 255 )Comp_3 = 255 ;
       //---------------------------------------------------
       if (R == Старшая_компонента)Первая_компонента = Comp_1;
       if (R == Средняя_компонента)Первая_компонента = Comp_2;
       if (R == Младшая_компонента)Первая_компонента = Comp_3;
       //---------------------------------------------------
       if (G == Старшая_компонента)Вторая_компонента = Comp_1;
       if (G == Средняя_компонента)Вторая_компонента = Comp_2;
       if (G == Младшая_компонента)Вторая_компонента = Comp_3;
       //---------------------------------------------------
       if (B == Старшая_компонента)Третья_компонента = Comp_1;
       if (B == Средняя_компонента)Третья_компонента = Comp_2;
       if (B == Младшая_компонента)Третья_компонента = Comp_3;
       //---------------------------------------------------
       Этот_цвет = ( string ) MathRound (Первая_компонента) + "," + ( string ) MathRound (Вторая_компонента) + "," + ( string ) MathRound (Третья_компонента);
       //---------------------------------------------------------------------------    
       Все_оттенки[a1] = Этот_цвет; 
       //---------------------------------------------------------------------------
      }
     //------------------------------------------------------------------------------
     for ( int a2 = 255 ; a2 >= a1; a2--)
      {
       Comp_1 = 255 - Тангенс_угла_старшего_треугольника_2*q;
       Comp_2 = 255 - Тангенс_угла_среднего_треугольника_2*q;
       Comp_3 = 255 - Тангенс_угла_младшего_треугольника_2*q;
       //---------------------------------------------------
       if (Comp_1 > 255 )Comp_1 = 255 ;
       if (Comp_1 > 255 )Comp_2 = 255 ;
       if (Comp_1 > 255 )Comp_3 = 255 ;
       //---------------------------------------------------       
       if (R == Старшая_компонента)Первая_компонента = Comp_1;
       if (R == Средняя_компонента)Первая_компонента = Comp_2;
       if (R == Младшая_компонента)Первая_компонента = Comp_3;
       //---------------------------------------------------
       if (G == Старшая_компонента)Вторая_компонента = Comp_1;
       if (G == Средняя_компонента)Вторая_компонента = Comp_2;
       if (G == Младшая_компонента)Вторая_компонента = Comp_3;
       //---------------------------------------------------
       if (B == Старшая_компонента)Третья_компонента = Comp_1;
       if (B == Средняя_компонента)Третья_компонента = Comp_2;
       if (B == Младшая_компонента)Третья_компонента = Comp_3;
       //---------------------------------------------------
       Этот_цвет = ( string ) MathRound (Первая_компонента) + "," + ( string ) MathRound (Вторая_компонента) + "," + ( string ) MathRound (Третья_компонента);
       //---------------------------------------------------------------------------    
       Все_оттенки[a2] = Этот_цвет; 
       //---------------------------------------------------------------------------
       q++;
      }
  } 
 //------------------------------------------------------------------------------
 if (Координата_исходного_цвета > 127 )
   {
    Тангенс_угла_старшего_треугольника_1  = ( 255 - Старшая_компонента)/( 255 - Координата_исходного_цвета);
    Тангенс_угла_среднего_треугольника_1  = ( 255 - Средняя_компонента)/( 255 - Координата_исходного_цвета);       
    Тангенс_угла_младшего_треугольника_1  = ( 255 - Младшая_компонента)/( 255 - Координата_исходного_цвета);
     //-----------------------------------------------
    Значение_в_точке_преломления_старшей_компоненты  = 255 - (Тангенс_угла_старшего_треугольника_1* 128 );
    Значение_в_точке_преломления_средней_компоненты  = 255 - (Тангенс_угла_среднего_треугольника_1* 128 );
    Значение_в_точке_преломления_младшей_компоненты  = 255 - (Тангенс_угла_младшего_треугольника_1* 128 );    
     //-----------------------------------------------    
    Тангенс_угла_старшего_треугольника_2  = Значение_в_точке_преломления_старшей_компоненты/ 128 ;
    Тангенс_угла_среднего_треугольника_2  = Значение_в_точке_преломления_средней_компоненты/ 128 ;      
    Тангенс_угла_младшего_треугольника_2  = Значение_в_точке_преломления_младшей_компоненты/ 128 ;
     //-----------------------------------------------    
     for ( int b1 = 0 ; b1 < 128 ; b1++)
      {
       Comp_1 = Тангенс_угла_старшего_треугольника_2*b1;
       Comp_2 = Тангенс_угла_среднего_треугольника_2*b1;
       Comp_3 = Тангенс_угла_младшего_треугольника_2*b1;
       //---------------------------------------------------
       if (Comp_1 > 255 )Comp_1 = 255 ;
       if (Comp_1 > 255 )Comp_2 = 255 ;
       if (Comp_1 > 255 )Comp_3 = 255 ;
       //---------------------------------------------------
       if (R == Старшая_компонента)Первая_компонента = Comp_1;
       if (R == Средняя_компонента)Первая_компонента = Comp_2;
       if (R == Младшая_компонента)Первая_компонента = Comp_3;
       //---------------------------------------------------
       if (G == Старшая_компонента)Вторая_компонента = Comp_1;
       if (G == Средняя_компонента)Вторая_компонента = Comp_2;
       if (G == Младшая_компонента)Вторая_компонента = Comp_3;
       //---------------------------------------------------
       if (B == Старшая_компонента)Третья_компонента = Comp_1;
       if (B == Средняя_компонента)Третья_компонента = Comp_2;
       if (B == Младшая_компонента)Третья_компонента = Comp_3;
       //---------------------------------------------------
       Этот_цвет = ( string ) MathRound (Первая_компонента) + "," + ( string ) MathRound (Вторая_компонента) + "," + ( string ) MathRound (Третья_компонента);
       //---------------------------------------------------------------------------    
       Все_оттенки[b1] = Этот_цвет; 
       //---------------------------------------------------------------------------
      }
     //------------------------------------------------------------------------------
     for ( int b2 = 255 ; b2 >= b1; b2--)
      {
       Comp_1 = 255 - Тангенс_угла_старшего_треугольника_1*q;
       Comp_2 = 255 - Тангенс_угла_среднего_треугольника_1*q;
       Comp_3 = 255 - Тангенс_угла_младшего_треугольника_1*q;
       //---------------------------------------------------
       if (Comp_1 > 255 )Comp_1 = 255 ;
       if (Comp_1 > 255 )Comp_2 = 255 ;
       if (Comp_1 > 255 )Comp_3 = 255 ;
       //---------------------------------------------------       
       if (R == Старшая_компонента)Первая_компонента = Comp_1;
       if (R == Средняя_компонента)Первая_компонента = Comp_2;
       if (R == Младшая_компонента)Первая_компонента = Comp_3;
       //---------------------------------------------------
       if (G == Старшая_компонента)Вторая_компонента = Comp_1;
       if (G == Средняя_компонента)Вторая_компонента = Comp_2;
       if (G == Младшая_компонента)Вторая_компонента = Comp_3;
       //---------------------------------------------------
       if (B == Старшая_компонента)Третья_компонента = Comp_1;
       if (B == Средняя_компонента)Третья_компонента = Comp_2;
       if (B == Младшая_компонента)Третья_компонента = Comp_3;
       //---------------------------------------------------
       Этот_цвет = ( string ) MathRound (Первая_компонента) + "," + ( string ) MathRound (Вторая_компонента) + "," + ( string ) MathRound (Третья_компонента);
       //---------------------------------------------------------------------------    
       Все_оттенки[b2] = Этот_цвет; 
       //---------------------------------------------------------------------------
       q++;
      }
   }   
 //------------------------------------------------------------------------------  
}
//+------------------------------------------------------------------+
//| Получение значения компонента R                                  |
//+------------------------------------------------------------------+
double GetR( const color aColor)
  {
   return (aColor& 0xff );
  }
//+------------------------------------------------------------------+
//| Получение значения компонента G                                  |
//+------------------------------------------------------------------+
double GetG( const color aColor)
  {
   return ((aColor>> 8 )& 0xff );
  }
//+------------------------------------------------------------------+
//| Получение значения компонента B                                  |
//+------------------------------------------------------------------+
double GetB( const color aColor)
  {
   return ((aColor>> 16 )& 0xff );
  }
//--------------------------------------------------------------------
double Нужная_компонента( double C1, double C2, double C3, int Index)
{
 double Components[ 3 ]; 
 //----------------------------------------------
 Components[ 0 ] = C1;
 Components[ 1 ] = C2;
 Components[ 2 ] = C3;
 //----------------------------------------------
 ArraySort (Components, WHOLE_ARRAY , 0 , MODE_DESCEND );
 //----------------------------------------------
 return (Components[Index]);
}

 

Aquí está el script para probarlo:

void OnStart()
  {
   color Main_color     = C'213,0,0';//здесь ставите нужный цвет. Компилируете. Тот же цвет ставите в цветовой палитре виндоус. Сравниваете цвета.
   string Gradient[256];
   //------------------------
   Диапазон_оттенков(Main_color,Gradient);
   //------------------------
   for(int a1 = 0; a1 < 256; a1++)Alert(__FUNCTION__,"  Gradient[",a1,"]  ",Gradient[a1]);
  }
Archivos adjuntos:
 
Реter Konow:

Aquí está el script para probarlo:

Gracias. Sería bueno escribir el código en inglés con comentarios y enviar dichos códigos a la biblioteca...

 
También es muy interesante cómo se resuelve este problema con la clase CCanvas. ¿Cómo se pueden conseguir todos los matices del color original a través de él?
 
Vladimir Pastushak:

Gracias. Sería bueno escribir el código en inglés con comentarios y enviar dichos códigos a la biblioteca...

De acuerdo. Lo traduciré en mi tiempo libre. ¿Te refieres a la base de código?

 
Реter Konow:

De acuerdo. Lo traduciré en mi tiempo libre. ¿Te refieres al código base?

La base de código tiene una sección de biblioteca, que es donde se apilan y actualizan dichos códigos.

 
Vladimir Pastushak:

La base de código tiene una sección de biblioteca donde se apilan y actualizan dichos códigos.

Ya veo.

 
Vladimir Pastushak:

Gracias. Sería bueno escribir el código en inglés con comentarios y enviar dichos códigos a la biblioteca...

Para CodeBade hay que escribirlo definitivamente en el idioma internacional. Pero, ¿por qué insistir en ello en un foro ruso?

Personalmente estoy disgustado con esta internacional... porque no lo conozco en absoluto y lo entiendo mucho mejor en nuestro ruso nativo.

 

En la colorimetría, según recuerdo, hay un montón de sistemas diferentes.

Probablemente haya un sistema ya preparado que satisfaga las necesidades, y fórmulas para cambiar entre ellos.

 
Georgiy Merts:

En la colorimetría, según recuerdo, hay un montón de sistemas diferentes.

Probablemente haya un sistema ya preparado que satisfaga las necesidades, y fórmulas para ir de un lado a otro.

Tengo una función. Si envías un color, recibes todos los tonos. A continuación, - cualquier gradiente puede ser dibujado simplemente haciendo un bucle de matriz.

 

Un poco más tarde, hice un cambio. Inicialmente, la función void. No devuelve un valor. Pero entonces lo hice de tipo int y añadí

return(Координата_исходного_цвета);

Así, además de la matriz de tonos, la función comenzó a devolver el número de la celda en la que se encuentra el color original que se le envió. Esto facilita el dibujo de un gradiente. Desde el color original puedes moverte hacia la izquierda o hacia la derecha a lo largo del conjunto.