Функция разложения цвета на оттенки. - страница 12

 
Реter Konow:

Вот результат работы моего алгоритма на МТ5. Без лишних и ненужных примочек. 


а код?

 
Nikolai Semko:

Я уже выше продемонстрировал недостаток твоего подхода, а если он совпадает с той палитрой, с которым ты его сравниваешь, то и его тоже, на примере белой линии.
Еще раз другими словами.

Если ты плавноо меняешь цвет от черного (0,0,0) до белого (255,255,255) проходящий через конкретный цвет (r1,g1,b1), то важным показателем является сумма трех цветов R, G и B. Здесь лучше отойти от терминологии, т.к. в ней можно запутаться (яркость, светлота, тон ....) 

Абсолютно очевидно, что в идеале этот показатель должен меняться линейно от 0 до 3*255=765. Ты лупишь свой цвет строго посередине, я же вычисляю вначале сумму изначального цвета и вставляю его в массив градиента в соответствии с этой его суммой RGB. Поэтому моя белая линия не имеет точку перелома в отличии от твоей.

Николай, пока ты не объяснил принцип работы своего алгоритма и говоришь о каких то белых линиях, которые должны быть такими, но не другими...

Очевидно, что ты сам не понимаешь, как раскладывает на оттенки твой алгоритм. У тебя нет целостной концепции. Только путаница из терминов и заимствованный откуда то код...

 
Nikolai Semko:

а код?

Еще не все готово. Признаю, недооценил степень разницы платформ. Алгоритм на МТ5 барахлит в некоторых местах. Но проблема только в коде, а не концепции. 

 
Реter Konow:

Николай, пока ты не объяснил принцип работы своего алгоритма и говоришь о каких то белых линиях, которые должны быть такими, но не другими...

Очевидно, что ты сам не понимаешь, как раскладывает на оттенки твой алгоритм. У тебя нет целостной концепции. Только путаница из терминов и заимствованный откуда то код...

Петр, ну что ты такое говоришь. Если бы я не понимал, то как бы я смог это делать. Писать алгоритм в коде гораздо проще чем описывать его словами. 
Ну скажи ты понимаешь смысл этого кода? Ведь все настолько элементарно и очевидно, что я даже не понимаю какие здесь можно коментарии вставлять.

void Gradient(uint clr1,uint clr2,uint &arr[],uint size)
  {
   if(size==0) return;
   ArrayResize(arr,size);
   rgb c1,c2;
   c1.clr=clr1;
   c2.clr=clr2;
   double R1=c1.c[2],G1=c1.c[1],B1=c1.c[0];
   double R2=c2.c[2],G2=c2.c[1],B2=c2.c[0];
   double deltaR=(R2-R1)/(size-1);
   double deltaG=(G2-G1)/(size-1);
   double deltaB=(B2-B1)/(size-1);
   for(uint i=0;i<size;i++)
     {
      R1+=deltaR; c1.c[2]=uchar (R1+0.4999);
      G1+=deltaG; c1.c[1]=uchar (G1+0.4999);
      B1+=deltaB; c1.c[0]=uchar (B1+0.4999);
      arr[i]=c1.clr;
     }
  }
 
Nikolai Semko:

Петр, ну что ты такое говоришь. Если бы я не понимал, то как бы я смог это делать. Писать алгоритм в коде гораздо проще чем описывать его словами. 
Ну скажи ты понимаешь смысл этого кода? Ведь все настолько элементарно и очевидно, что я даже не понимаю какие здесь можно коментарии вставлять.

Вот как работает твой алгоритм на примере этой функции:

#include <Canvas\iCanvas.mqh> //https://www.mql5.com/ru/code/22164

union rgb {uint clr; uchar c[4];};

void OnStart()
  {
   rgb c,C;
   uint CLR[];
   color clr=clrViolet;
   Gradient(clrWhite, clr, CLR,W.Height/2); // получаем массив градиента от белого цвета до цвета clr 
   for(int y=0; y<W.Height/2; y++) Canvas.LineHorizontal(0,W.Width-1,y,ColorToARGB(CLR[y],240)); // выводим на экран
   Gradient(clr, clrBlack, CLR,W.Height-W.Height/2); // получаем массив градиента от цвета clr до черног цвета  
   for(int y=W.Height/2; y<W.Height; y++) Canvas.LineHorizontal(0,W.Width-1,y,ColorToARGB(CLR[y-W.Height/2],240)); // выводим на экран в продолжение предыдущего
   Canvas.Update();
   Sleep(30000);
   }
//+------------------------------------------------------------------+

void Gradient(uint clr1,uint clr2,uint &arr[],uint size)
  {
   if(size==0) return;
   ArrayResize(arr,size);
   rgb c1,c2;
   c1.clr=clr1;
   c2.clr=clr2;
   double R1=c1.c[2],G1=c1.c[1],B1=c1.c[0];
   double R2=c2.c[2],G2=c2.c[1],B2=c2.c[0];
   double deltaR=(R2-R1)/(size-1);
   double deltaG=(G2-G1)/(size-1);
   double deltaB=(B2-B1)/(size-1);
   for(uint i=0;i<size;i++)
     {
      R1+=deltaR; c1.c[2]=uchar (R1+0.4999);
      G1+=deltaG; c1.c[1]=uchar (G1+0.4999);
      B1+=deltaB; c1.c[0]=uchar (B1+0.4999);
      arr[i]=c1.clr;
     }
  }


 
Nikolai Semko:

Петр, ну что ты такое говоришь. Если бы я не понимал, то как бы я смог это делать. Писать алгоритм в коде гораздо проще чем описывать его словами. 
Ну скажи ты понимаешь смысл этого кода? Ведь все настолько элементарно и очевидно, что я даже не понимаю какие здесь можно коментарии вставлять.

Изложи свою концепцию разложения цвета. Если алгоритм твой, ты ее хорошо знаешь.

 
Реter Konow:

Похоже, это вы себя в чем то убеждаете. Повторяю, не было времени сделать визуализацию. Вы проверили алгоритм в сверении с палитрой?  

Результат работы вашего скрипта для цвета 207,255,65

Результат работы вашего скрипта для цвета 207,255,65.

 
Yury Kulikov:

Результат работы вашего скрипта для цвета 207,255,65.

Спасибо за наблюдение. Я тоже выявил несколько ошибок. Сейчас сделаю гифку с МТ4. Работает неплохо, но на паре цветов есть проблемы.

 

Не получаются у меня качественные гифки. Вот скрипт. Поставьте на МТ4 и увидите все как есть.

//+------------------------------------------------------------------+
//|                                              Gradient test 1.mq4 |
//|                                                      Peter Konow |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Peter Konow"
#property link      "https://www.mql5.com"
#property version   "1.00"
#include <Canvas\Canvas.mqh>
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
union rgb {uint clr; uchar c[4];};
rgb C,cc;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
   CCanvas canvas;
   if(!canvas.CreateBitmapLabel("Gradient",200,200,768,256,COLOR_FORMAT_ARGB_NORMALIZE)) { Print("Error creating canvas: ",GetLastError()); }
   string Main_color = C'190,215,160';
   double d=5;
   string Gradient[256];

   while(!IsStopped())
     {
      C.c[2]=uchar(127.5*(1+sin(d*1.2))+0.4999); C.c[1]=uchar(127.5*(1+sin(d*1.9))+0.4999); C.c[0]=uchar(127.5*(1+sin(d*2.8))+0.4999);  // генерируем новый цвет
      cc.clr=C.clr;
      ulong t=GetMicrosecondCount();
      Диапазон_оттенков(C.clr,Gradient);//Диапазон_оттенков(Main_color,Gradient);
      t=GetMicrosecondCount()-t;
      for(int y=0; y<256; y++)
        {
         //Alert(__FUNCTION__,"  Gradient[",y,"]  ",Gradient[y]);
         canvas.LineHorizontal(0,767,y,ColorToARGB(StringToColor(Gradient[y]),255));
         C.clr=Gradient[y];
         canvas.PixelSet((int)C.c[2]+(int)C.c[1]+(int)C.c[0],y,ColorToARGB(clrWhite));
         if (C.c[1]>0) canvas.PixelSet(int(50.0*(int)C.c[2]/(double)C.c[1]+50.0*(int)C.c[0]/(double)C.c[1]),y,ColorToARGB(clrGreen));
         if (C.c[2]>0) canvas.PixelSet(int(50.0*(int)C.c[1]/(double)C.c[2]+50.0*(int)C.c[0]/(double)C.c[2]),y,ColorToARGB(clrRed));
         if (C.c[0]>0) canvas.PixelSet(int(50.0*(int)C.c[2]/(double)C.c[0]+50.0*(int)C.c[1]/(double)C.c[0]),y,ColorToARGB(clrBlue));
        }
      canvas.FillRectangle(500,75,660,150,ColorToARGB(cc.clr,240));
      canvas.FontSet("Tahoma",20); 
      canvas.TextOut(510,85,"R = "+string(cc.c[2]),ColorToARGB(~cc.clr)); 
      canvas.TextOut(510,107,"G = "+string(cc.c[1]),ColorToARGB(~cc.clr)); 
      canvas.TextOut(510,129,"B = "+string(cc.c[0]),ColorToARGB(~cc.clr));
      canvas.FontSet("Times New Roman",15);
      canvas.TextOut(300,10,"Время формирования градиентного массива из 256 элементов = "+string(t)+" микросекунд",ColorToARGB(clrWhite));
      canvas.Update();
      d+=0.01;
      Sleep(30);
     }
   canvas.Destroy();
//------------------------
// for(int a1 = 0; a1 < 256; a1++)Alert(__FUNCTION__,"  Gradient[",a1,"]  ",Gradient[a1]);
  }
//+------------------------------------------------------------------+
//================================================================================================================================================================
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]);
}
 

Нашел первую ошибку. Исправил. 

Нужно было добавить : 

       if(Comp_1 < 0 )Comp_1 = 0;
       if(Comp_2 < 0 )Comp_2 = 0;
       if(Comp_3 < 0 )Comp_3 = 0;

в каждый цикл. 

Причина обращения: