Ответ 1
вопрос 1:
Способы смешивания оттенков, насыщенности, цвета и яркости фотошоп основаны на цветовом пространстве с размерами, которые в статье HSL и HSV называет оттенок, цветность и яркость. Обратите внимание, что это пространство отличается от HSL и HSV, и только тембр оттенка разделяется между тремя; Подробности см. в этой статье.
Режим смешивания оттенков сохраняет яркость и цветность нижнего слоя, принимая оттенок верхнего слоя.
Режим наложения насыщения сохраняет яркость и оттенок нижнего слоя, принимая цветность верхнего слоя.
Режим цветной смешивания сохраняет яркость нижнего слоя, принимая оттенок и цветность верхнего слоя.
После более чем трех часов экспериментов я добился обновления конвертера HSV → RGB в рабочий насыщающий блендер. Другие режимы смешивания должны быть одинаковыми.
Вот код:
#include <cmath>
#include <iostream>
using namespace std;
struct HSVColor
{
float H,S,V;
};
struct RGBColor
{
float R,G,B;
RGBColor() = default;
RGBColor(int r,int g, int b):
R(r/255.0),
G(g/255.0),
B(b/255.0)
{
}
};
HSVColor RGBToHSV(const RGBColor& RGB)
{
float Max;
float Min;
float Chroma;
HSVColor HSV;
Min = min(min(RGB.R, RGB.G), RGB.B);
Max = max(max(RGB.R, RGB.G), RGB.B);
Chroma = Max - Min;
//If Chroma is 0, then S is 0 by definition, and H is undefined but 0 by convention.
if(Chroma != 0)
{
if(RGB.R == Max)
{
HSV.H = (RGB.G - RGB.B) / Chroma;
if(HSV.H < 0.0)
{
HSV.H += 6.0;
}
}
else if(RGB.G == Max)
{
HSV.H = ((RGB.B - RGB.R) / Chroma) + 2.0;
}
else //RGB.B == Max
{
HSV.H = ((RGB.R - RGB.G) / Chroma) + 4.0;
}
HSV.H *= 60.0;
HSV.S = Chroma / Max;
}
HSV.V = Max;
return HSV;
}
RGBColor Saturate(const HSVColor& HSV,const HSVColor& overlay)
{
float os = overlay.S;
float ov = overlay.V;
float Min;
float Chroma;
float Hdash;
float X;
RGBColor RGB{0,0,0};
Chroma = os * ov; // Orginal was HSV.S * HSV.V
Hdash = HSV.H / 60.0;
X = Chroma * (1.0 - abs(fmod(Hdash , 2.0) - 1.0));
if(Hdash < 1.0)
{
RGB.R = Chroma;
RGB.G = X;
}
else if(Hdash < 2.0)
{
RGB.R = X;
RGB.G = Chroma;
}
else if(Hdash < 3.0)
{
RGB.G = Chroma;
RGB.B = X;
}
else if(Hdash < 4.0)
{
RGB.G= X;
RGB.B = Chroma;
}
else if(Hdash < 5.0)
{
RGB.R = X;
RGB.B = Chroma;
}
else if(Hdash <= 6.0)
{
RGB.R = Chroma;
RGB.B = X;
}
Min = ov - Chroma; // Orginal was HSV.V - Chroma
RGB.R += Min;
RGB.G += Min;
RGB.B += Min;
return RGB;
}
int main(){
RGBColor base{51, 34, 68};
RGBColor overly{85, 119, 17};
RGBColor r = Saturate(RGBToHSV(base),RGBToHSV(overly));
cout << int(r.R*255) << endl;
cout << int(r.G*255) << endl;
cout << int(r.B*255) << endl;
}
оригинальный код конверсии HSV ↔ RGB здесь: http://wiki.beyondunreal.com/HSV-RGB_Conversion
вопрос 2.
С насыщением это на самом деле легко, После насыщения смешивания используйте нормальное альфа-смешение в цветовом пространстве rgb.
RGBColor base;
RGBColor overly;
RGBColor saturated = Saturate(base,overly);
RGBColor result = AlphaBlend(base,saturated,overly.alpha);
Примечание: это может не работать с другими режимами смешивания.