📄 gradient.cpp
字号:
*s /= (*l <= 0.5f) ? (v + m ) :
(2.0f - v - m) ;
}
else
return;
r2 = (v - r) / vm;
g2 = (v - g) / vm;
b2 = (v - b) / vm;
if (r == v)
*h = (g == m ? 5.0f + b2 : 1.0f - g2);
else if (g == v)
*h = (b == m ? 1.0f + r2 : 3.0f - b2);
else
*h = (r == m ? 3.0f + g2 : 5.0f - r2);
*h /= 6.0f;
}
void HSL_to_RGB(float h, float sl, float l, float *r, float *g, float *b)
{
float v;
v = (l <= 0.5f) ? (l * (1.0f + sl)) : (l + sl - l * sl);
if (v <= 0) {
*r = *g = *b = 0.0f;
}
else
{
float m;
float sv;
int sextant;
float fract, vsf, mid1, mid2;
m = l + l - v;
sv = (v - m ) / v;
h *= 6.0f;
sextant = (int)h;
fract = h - sextant;
vsf = v * sv * fract;
mid1 = m + vsf;
mid2 = v - vsf;
switch (sextant)
{
case 0: *r = v; *g = mid1; *b = m; break;
case 1: *r = mid2; *g = v; *b = m; break;
case 2: *r = m; *g = v; *b = mid1; break;
case 3: *r = m; *g = mid2; *b = v; break;
case 4: *r = mid1; *g = m; *b = v; break;
case 5: *r = v; *g = m; *b = mid2; break;
}
}
}
COLORREF CGradient::InterpolateHSLClockwise(COLORREF first, COLORREF second, float position, float start, float end)
{
float sh = 0, ss = 0, sl = 0, eh = 0, es = 0, el = 0, h = 0, s = 0, l = 0, r = 0, g = 0, b = 0;
RGB_to_HSL((float)GetRValue(first)/255.0f, (float)GetGValue(first)/255.0f,
(float)GetBValue(first)/255.0f, &sh, &ss, &sl);
RGB_to_HSL((float)GetRValue(second)/255.0f, (float)GetGValue(second)/255.0f,
(float)GetBValue(second)/255.0f, &eh, &es, &el);
sh = sh - floorf(sh);
eh = eh - floorf(eh);
//Interpolate H clockwise
if(eh >= sh) h = (eh*(position - start) + sh*(end-position))/(end-start);
else h = ((eh + 1.0f)*(position - start) + sh*(end-position))/(end-start);
h = (h>=1.0f)?h-1.0f:h;
s = ((es*(position - start) + ss*(end-position))/(end-start));
l = ((el*(position - start) + sl*(end-position))/(end-start));
HSL_to_RGB(h, s, l, &r, &g, &b);
return RGB((BYTE)(r*255.0f), (BYTE)(g*255.0f), (BYTE)(b*255.0f));
}
COLORREF CGradient::InterpolateHSLAntiClockwise(COLORREF first, COLORREF second, float position, float start, float end)
{
float sh = 0, ss = 0, sl = 0, eh = 0, es = 0, el = 0, h = 0, s = 0, l = 0, r = 0, g = 0, b = 0;
RGB_to_HSL((float)GetRValue(first)/255.0f, (float)GetGValue(first)/255.0f,
(float)GetBValue(first)/255.0f, &sh, &ss, &sl);
RGB_to_HSL((float)GetRValue(second)/255.0f, (float)GetGValue(second)/255.0f,
(float)GetBValue(second)/255.0f, &eh, &es, &el);
sh = sh - floorf(sh);
eh = eh - floorf(eh);
//Interpolate H anticlockwise
if(eh <= sh) h = (eh*(position - start) + sh*(end-position))/(end-start);
else h = ((eh + 1.0f)*(position - start) + sh*(end-position))/(end-start);
h = (h>=1.0f)?h-1.0f:h;
s = ((es*(position - start) + ss*(end-position))/(end-start));
l = ((el*(position - start) + sl*(end-position))/(end-start));
HSL_to_RGB(h, s, l, &r, &g, &b);
return RGB((BYTE)(r*255.0f), (BYTE)(g*255.0f), (BYTE)(b*255.0f));
}
COLORREF CGradient::InterpolateHSLLongest(COLORREF first, COLORREF second, float position, float start, float end)
{
float sh = 0, ss = 0, sl = 0, eh = 0, es = 0, el = 0, h = 0, s = 0, l = 0, r = 0, g = 0, b = 0;
RGB_to_HSL((float)GetRValue(first)/255.0f, (float)GetGValue(first)/255.0f,
(float)GetBValue(first)/255.0f, &sh, &ss, &sl);
RGB_to_HSL((float)GetRValue(second)/255.0f, (float)GetGValue(second)/255.0f,
(float)GetBValue(second)/255.0f, &eh, &es, &el);
sh = sh - (float)floor(sh);
eh = eh - (float)floor(eh);
//Interpolate H short route
if(((eh-sh)-floor(eh-sh) < 0.5f)?(eh < sh):(eh >= sh)) h = (eh*(position - start) + sh*(end-position))/(end-start);
else h = ((eh+(sh>eh?1.0f:-1.0f))*(position - start) + sh*(end-position))/(end-start);
//TRACE3("sh: %f eh: %f h: %f\n", sh, eh, h);
h = h - floorf(h);
s = ((es*(position - start) + ss*(end-position))/(end-start));
l = ((el*(position - start) + sl*(end-position))/(end-start));
HSL_to_RGB(h, s, l, &r, &g, &b);
return RGB((BYTE)(r*255.0f), (BYTE)(g*255.0f), (BYTE)(b*255.0f));
}
COLORREF CGradient::InterpolateHSLShortest(COLORREF first, COLORREF second, float position, float start, float end)
{
float sh = 0, ss = 0, sl = 0, eh = 0, es = 0, el = 0, h = 0, s = 0, l = 0, r = 0, g = 0, b = 0;
RGB_to_HSL((float)GetRValue(first)/255.0f, (float)GetGValue(first)/255.0f,
(float)GetBValue(first)/255.0f, &sh, &ss, &sl);
RGB_to_HSL((float)GetRValue(second)/255.0f, (float)GetGValue(second)/255.0f,
(float)GetBValue(second)/255.0f, &eh, &es, &el);
sh = sh - (float)floor(sh);
eh = eh - (float)floor(eh);
//Interpolate H short route
if(((eh-sh)-floor(eh-sh) > 0.5f)?(eh < sh):(eh >= sh)) h = (eh*(position - start) + sh*(end-position))/(end-start);
else h = ((eh+(sh>eh?1.0f:-1.0f))*(position - start) + sh*(end-position))/(end-start);
//TRACE3("sh: %f eh: %f h: %f\n", sh, eh, h);
h = h - floorf(h);
s = ((es*(position - start) + ss*(end-position))/(end-start));
l = ((el*(position - start) + sl*(end-position))/(end-start));
HSL_to_RGB(h, s, l, &r, &g, &b);
return RGB((BYTE)(r*255.0f), (BYTE)(g*255.0f), (BYTE)(b*255.0f));
}
int CGradient::IndexFromPos(float pos)
{
ASSERT(pos >= 0.0f && pos <= 1.0f);
// positions betwen 0 and 1!
if(pos < pegs[0].position)
return STARTPEG;
for(int i = 0; i < pegs.GetSize()-1; i++)
if(pos >= pegs[i].position && pos <= pegs[i+1].position)
return i;
return -1; // Eh? somethings wrong here
}
int CGradient::IndexFromId(UINT id)
{
for(int i = 0; i < pegs.GetSize(); i++)
if(id == pegs[i].GetID())
return i;
return -1;
}
//----- Fast sorting alogarithm functions -----//
int CGradient::Partition(int lb, int ub)
{
CPeg temppeg, pivot;
int i, j, p;
/* select pivot and exchange with 1st element */
p = lb + ((ub - lb)>>1);
pivot = pegs[p];
pegs[p] = pegs[lb];
/* sort lb+1..ub based on pivot */
i = lb+1;
j = ub;
while(1)
{
while(i < j && pivot.position >= pegs[i].position) i++;
while(j >= i && pegs[j].position >= pivot.position) j--;
if(i >= j) break;
temppeg.colour = pegs[i].colour;
temppeg.position = pegs[i].position;
pegs[i].colour = pegs[j].colour;
pegs[i].position = pegs[j].position;
pegs[j].colour = temppeg.colour;
pegs[j].position = temppeg.position;
j--; i++;
}
/* pivot belongs in a[j] */
pegs[lb] = pegs[j];
pegs[j] = pivot;
return j;
}
void CGradient::QuickSort(int lb, int ub)
{
int m;
/**************************
* sort array pegs[lb..ub] *
**************************/
while (lb < ub)
{
/* quickly sort short lists */
if (ub - lb <= 12)
{
InsertSort(lb, ub);
return;
}
m = Partition(lb, ub);
if (m - lb <= ub - m)
{
QuickSort(lb, m - 1);
lb = m + 1;
}
else
{
QuickSort(m + 1, ub);
ub = m - 1;
}
}
}
void CGradient::InsertSort(int lb, int ub)
{
CPeg temppeg;
for (int i = lb + 1; i <= ub; i++)
{
temppeg = pegs[i];
for(int j = i-1; j >= lb && pegs[j].position > temppeg.position; j--)
pegs[j+1] = pegs[j];
pegs[j+1] = temppeg;
}
}
COLORREF CGradient::ColourFromPosition(float pos)
{
if(pos < 0 || pos > 1)
{
ASSERT(0); // Position out of bounds!!
return 0;
}
if(pos == 0 && m_UseBackground)
return m_Background.colour;
InterpolateFn Interpolate = GetInterpolationProc();
ASSERT(Interpolate != NULL);
if(m_Quantization != -1)
pos = ((float)(int)(pos*m_Quantization))/m_Quantization + 0.5f / m_Quantization;
if(pegs.GetSize() > 0)
{
//Some thing are aready constant and so can be found early
float firstpegpos = pegs[0].position;
float lastpegpos = pegs[pegs.GetUpperBound()].position;
if(pos <= firstpegpos)
return Interpolate(m_StartPeg.colour, pegs[0].colour, pos, 0,
firstpegpos+1);
else if(pos > lastpegpos)
return Interpolate(pegs[pegs.GetUpperBound()].colour, m_EndPeg.colour,
pos, lastpegpos, 1);
else
{
int curpeg;
curpeg = IndexFromPos(pos);
return Interpolate(pegs[curpeg].colour, pegs[curpeg+1].colour, pos,
pegs[curpeg].position, pegs[curpeg+1].position);
}
}
else
{
//When there are no extra pegs we can just interpolate the start and end
return Interpolate(m_StartPeg.colour, m_EndPeg.colour, pos, 0, 1);
}
}
void CGradient::Serialize(CArchive &ar)
{
if(ar.IsLoading())
{
int pegcount, temp;
ar >> m_Background.colour;
ar >> m_StartPeg.colour;
ar >> m_EndPeg.colour;
ar >> m_UseBackground;
ar >> m_Quantization;
ar >> temp;
m_InterpolationMethod = (CGradient::InterpolationMethod)temp;
ar >> pegcount;
pegs.SetSize(pegcount);
for(int i = 0; i < pegcount; i++)
pegs[i].Serialize(ar);
}
else
{
ar << m_Background.colour;
ar << m_StartPeg.colour;
ar << m_EndPeg.colour;
ar << (unsigned int)m_UseBackground;
ar << m_Quantization;
ar << (unsigned int)m_InterpolationMethod;
ar << pegs.GetSize();
for(int i = 0; i < pegs.GetSize(); i++)
pegs[i].Serialize(ar);
}
}
CGradient::InterpolationMethod CGradient::GetInterpolationMethod() const
{
return m_InterpolationMethod;
}
void CGradient::SetInterpolationMethod(const InterpolationMethod method)
{
m_InterpolationMethod = method;
}
int CGradient::GetQuantization() const
{
return m_Quantization;
}
void CGradient::SetQuantization(const int entries)
{
m_Quantization = entries;
}
InterpolateFn CGradient::GetInterpolationProc()
{
switch(m_InterpolationMethod)
{
case Linear: return InterpolateLinear;
case FlatStart: return InterpolateFlatStart;
case FlatMid: return InterpolateFlatMid;
case FlatEnd: return InterpolateFlatEnd;
case Cosine: return InterpolateCosine;
case HSLRedBlue: return InterpolateHSLClockwise;
case HSLBlueRed: return InterpolateHSLAntiClockwise;
case HSLShortest: return InterpolateHSLShortest;
case HSLLongest: return InterpolateHSLLongest;
case Reverse: return InterpolateReverse;
default: return 0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -