mirror of https://github.com/odrling/Aegisub
Added functions for direct conversion between HSL and HSV. (hsl_to_hsv is still incomplete, and works over rgb atm)
Added some special cases to the HSV and HSl to RGB conversions, as a "fix" for bug #28. Random hacking on text_extents in a vain attempt at making its calculations more exact. Originally committed to SVN as r232.
This commit is contained in:
parent
180f323676
commit
e6c2f3c083
|
@ -302,7 +302,9 @@ namespace AutomationHelper {
|
||||||
if (!thedc) return 0;
|
if (!thedc) return 0;
|
||||||
SetMapMode(thedc, MM_TEXT);
|
SetMapMode(thedc, MM_TEXT);
|
||||||
|
|
||||||
fontsize = -MulDiv((int)(fontsize+0.5), GetDeviceCaps(thedc, LOGPIXELSY), 72);
|
HDC dczero = GetDC(0);
|
||||||
|
fontsize = -MulDiv((int)(fontsize+0.5), GetDeviceCaps(dczero, LOGPIXELSY), 72);
|
||||||
|
ReleaseDC(0, dczero);
|
||||||
|
|
||||||
LOGFONT lf;
|
LOGFONT lf;
|
||||||
ZeroMemory(&lf, sizeof(lf));
|
ZeroMemory(&lf, sizeof(lf));
|
||||||
|
@ -323,16 +325,17 @@ namespace AutomationHelper {
|
||||||
SelectObject(thedc, thefont);
|
SelectObject(thedc, thefont);
|
||||||
|
|
||||||
SIZE sz;
|
SIZE sz;
|
||||||
|
size_t thetextlen = intext.length();
|
||||||
|
const wchar_t *thetext = intext.wc_str();
|
||||||
if (spacing) {
|
if (spacing) {
|
||||||
resx = 0;
|
resx = 0;
|
||||||
for (unsigned int i = 0; i < intext.length(); i++) {
|
for (unsigned int i = 0; i < thetextlen; i++) {
|
||||||
wchar_t c = intext[i];
|
GetTextExtentPoint32(thedc, &thetext[i], 1, &sz);
|
||||||
GetTextExtentPoint32(thedc, &c, 1, &sz);
|
|
||||||
resx += sz.cx + spacing;
|
resx += sz.cx + spacing;
|
||||||
resy = sz.cy;
|
resy = sz.cy;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GetTextExtentPoint32(thedc, intext.wc_str(), intext.Length(), &sz);
|
GetTextExtentPoint32(thedc, thetext, thetextlen, &sz);
|
||||||
resx = sz.cx;
|
resx = sz.cx;
|
||||||
resy = sz.cy;
|
resy = sz.cy;
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,56 +59,151 @@ void hsl_to_rgb(int H, int S, int L, unsigned char *R, unsigned char *G, unsigne
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (L == 128 && S == 255) {
|
||||||
|
switch (H) {
|
||||||
|
case 0:
|
||||||
|
case 255: // actually this is wrong, since this is more like 359 degrees... but it's what you'd expect (sadly :)
|
||||||
|
*R = 255;
|
||||||
|
*G = 0;
|
||||||
|
*B = 0;
|
||||||
|
return;
|
||||||
|
case 43:
|
||||||
|
*R = 255;
|
||||||
|
*G = 255;
|
||||||
|
*B = 0;
|
||||||
|
return;
|
||||||
|
case 85:
|
||||||
|
*R = 0;
|
||||||
|
*G = 255;
|
||||||
|
*B = 0;
|
||||||
|
return;
|
||||||
|
case 128:
|
||||||
|
*R = 0;
|
||||||
|
*G = 255;
|
||||||
|
*B = 255;
|
||||||
|
return;
|
||||||
|
case 171:
|
||||||
|
*R = 0;
|
||||||
|
*G = 0;
|
||||||
|
*B = 255;
|
||||||
|
return;
|
||||||
|
case 213:
|
||||||
|
*R = 255;
|
||||||
|
*G = 0;
|
||||||
|
*B = 255;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*const int scale = 64;
|
||||||
|
|
||||||
int r, g, b;
|
int r, g, b;
|
||||||
|
|
||||||
|
H *= scale;
|
||||||
|
S *= scale;
|
||||||
|
L *= scale;
|
||||||
|
|
||||||
int temp2;
|
int temp2;
|
||||||
if (L < 128) {
|
if (L < 128*scale) {
|
||||||
temp2 = L * (256 + S) / 256;
|
temp2 = L * (256*scale + S) / (256*scale);
|
||||||
} else {
|
} else {
|
||||||
temp2 = L + S - L * S / 256;
|
temp2 = L + S - L * S / (256*scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
int temp1 = 2*L - temp2;
|
int temp1 = 2*L - temp2;
|
||||||
|
|
||||||
int temp3[3];
|
int temp3[3];
|
||||||
temp3[0] = H + 256/3;
|
temp3[0] = H + (256*scale)/3;
|
||||||
if (temp3[0] < 0) temp3[0] += 256;
|
if (temp3[0] < 0) temp3[0] += (256*scale);
|
||||||
if (temp3[0] > 256) temp3[0] -= 256;
|
if (temp3[0] > (256*scale)) temp3[0] -= (256*scale);
|
||||||
temp3[1] = H;
|
temp3[1] = H;
|
||||||
temp3[2] = H - 256/3;
|
temp3[2] = H - (256*scale)/3;
|
||||||
if (temp3[2] < 0) temp3[2] += 256;
|
if (temp3[2] < 0) temp3[2] += (256*scale);
|
||||||
if (temp3[2] > 256) temp3[2] -= 256;
|
if (temp3[2] > (256*scale)) temp3[2] -= (256*scale);
|
||||||
|
|
||||||
if (6 * temp3[0] < 255)
|
if (6 * temp3[0] < (256*scale))
|
||||||
r = temp1 + (temp2 - temp1) * 6 * temp3[0] / 256;
|
r = temp1 + (temp2 - temp1) * 6 * temp3[0] / (256*scale);
|
||||||
else if (2 * temp3[0] < 255)
|
else if (2 * temp3[0] < (256*scale))
|
||||||
r = temp2;
|
r = temp2;
|
||||||
else if (3 * temp3[0] < 511)
|
else if (3 * temp3[0] < (2*256*scale))
|
||||||
r = temp1 + (temp2 - temp1) * ((512/3) - temp3[0]) * 6 / 256;
|
r = temp1 + (temp2 - temp1) * ((512*scale/3) - temp3[0]) * 6 / (256*scale);
|
||||||
else
|
else
|
||||||
r = temp1;
|
r = temp1;
|
||||||
|
|
||||||
if (6 * temp3[1] < 255)
|
if (6 * temp3[1] < (256*scale))
|
||||||
g = temp1 + (temp2 - temp1) * 6 * temp3[1] / 256;
|
g = temp1 + (temp2 - temp1) * 6 * temp3[1] / (256*scale);
|
||||||
else if (2 * temp3[1] < 255)
|
else if (2 * temp3[1] < (256*scale))
|
||||||
g = temp2;
|
g = temp2;
|
||||||
else if (3 * temp3[1] < 511)
|
else if (3 * temp3[1] < (2*256*scale))
|
||||||
g = temp1 + (temp2 - temp1) * ((512/3) - temp3[1]) * 6 / 256;
|
g = temp1 + (temp2 - temp1) * ((512*scale/3) - temp3[1]) * 6 / (256*scale);
|
||||||
else
|
else
|
||||||
g = temp1;
|
g = temp1;
|
||||||
|
|
||||||
if (6 * temp3[2] < 255)
|
if (6 * temp3[2] < (256*scale))
|
||||||
b = temp1 + (temp2 - temp1) * 6 * temp3[2] / 256;
|
b = temp1 + (temp2 - temp1) * 6 * temp3[2] / (256*scale);
|
||||||
else if (2 * temp3[2] < 255)
|
else if (2 * temp3[2] < (256*scale))
|
||||||
b = temp2;
|
b = temp2;
|
||||||
else if (3 * temp3[2] < 511)
|
else if (3 * temp3[2] < (2*256*scale))
|
||||||
b = temp1 + (temp2 - temp1) * ((512/3) - temp3[2]) * 6 / 256;
|
b = temp1 + (temp2 - temp1) * ((512*scale/3) - temp3[2]) * 6 / (256*scale);
|
||||||
else
|
else
|
||||||
b = temp1;
|
b = temp1;
|
||||||
|
|
||||||
*R = clip_colorval(r);
|
*R = clip_colorval(r/scale);
|
||||||
*G = clip_colorval(g);
|
*G = clip_colorval(g/scale);
|
||||||
*B = clip_colorval(b);
|
*B = clip_colorval(b/scale);*/
|
||||||
|
|
||||||
|
float h, s, l, r, g, b;
|
||||||
|
h = H / 255.f;
|
||||||
|
s = S / 255.f;
|
||||||
|
l = L / 255.f;
|
||||||
|
|
||||||
|
float temp2;
|
||||||
|
if (l < .5) {
|
||||||
|
temp2 = l * (1. + s);
|
||||||
|
} else {
|
||||||
|
temp2 = l + s - l*s;
|
||||||
|
}
|
||||||
|
|
||||||
|
float temp1 = 2.f * l - temp2;
|
||||||
|
|
||||||
|
// assume h is in range [0;1]
|
||||||
|
float temp3[3];
|
||||||
|
temp3[0] = h + 1.f/3.f;
|
||||||
|
if (temp3[0] > 1.f) temp3[0] -= 1.f;
|
||||||
|
temp3[1] = h;
|
||||||
|
temp3[2] = h - 1.f/3.f;
|
||||||
|
if (temp3[2] < 0.f) temp3[2] += 1.f;
|
||||||
|
|
||||||
|
if (6.f * temp3[0] < 1.f)
|
||||||
|
r = temp1 + (temp2 - temp1) * 6.f * temp3[0];
|
||||||
|
else if (2.f * temp3[0] < 1.f)
|
||||||
|
r = temp2;
|
||||||
|
else if (3.f * temp3[0] < 2.f)
|
||||||
|
r = temp1 + (temp2 - temp1) * ((2.f/3.f) - temp3[0]) * 6.f;
|
||||||
|
else
|
||||||
|
r = temp1;
|
||||||
|
|
||||||
|
if (6.f * temp3[1] < 1.f)
|
||||||
|
g = temp1 + (temp2 - temp1) * 6.f * temp3[1];
|
||||||
|
else if (2.f * temp3[1] < 1.f)
|
||||||
|
g = temp2;
|
||||||
|
else if (3.f * temp3[1] < 2.f)
|
||||||
|
g = temp1 + (temp2 - temp1) * ((2.f/3.f) - temp3[1]) * 6.f;
|
||||||
|
else
|
||||||
|
g = temp1;
|
||||||
|
|
||||||
|
if (6.f * temp3[2] < 1.f)
|
||||||
|
b = temp1 + (temp2 - temp1) * 6.f * temp3[2];
|
||||||
|
else if (2.f * temp3[2] < 1.f)
|
||||||
|
b = temp2;
|
||||||
|
else if (3.f * temp3[2] < 2.f)
|
||||||
|
b = temp1 + (temp2 - temp1) * ((2.f/3.f) - temp3[2]) * 6.f;
|
||||||
|
else
|
||||||
|
b = temp1;
|
||||||
|
|
||||||
|
*R = clip_colorval((int)(r*255));
|
||||||
|
*G = clip_colorval((int)(g*255));
|
||||||
|
*B = clip_colorval((int)(b*255));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -118,6 +213,43 @@ void hsv_to_rgb(int H, int S, int V, unsigned char *R, unsigned char *G, unsigne
|
||||||
{
|
{
|
||||||
*R = *G = *B = 0;
|
*R = *G = *B = 0;
|
||||||
|
|
||||||
|
// some special cases... oh yeah baby!
|
||||||
|
if (S == 255) {
|
||||||
|
switch (H) {
|
||||||
|
case 0:
|
||||||
|
case 255: // actually this is wrong, since this is more like 359 degrees... but it's what you'd expect (sadly :)
|
||||||
|
*R = V;
|
||||||
|
*G = 0;
|
||||||
|
*B = 0;
|
||||||
|
return;
|
||||||
|
case 43:
|
||||||
|
*R = V;
|
||||||
|
*G = V;
|
||||||
|
*B = 0;
|
||||||
|
return;
|
||||||
|
case 85:
|
||||||
|
*R = 0;
|
||||||
|
*G = V;
|
||||||
|
*B = 0;
|
||||||
|
return;
|
||||||
|
case 128:
|
||||||
|
*R = 0;
|
||||||
|
*G = V;
|
||||||
|
*B = V;
|
||||||
|
return;
|
||||||
|
case 171:
|
||||||
|
*R = 0;
|
||||||
|
*G = 0;
|
||||||
|
*B = V;
|
||||||
|
return;
|
||||||
|
case 213:
|
||||||
|
*R = V;
|
||||||
|
*G = 0;
|
||||||
|
*B = V;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Cap values
|
// Cap values
|
||||||
unsigned int h = H * 360;
|
unsigned int h = H * 360;
|
||||||
unsigned int s = clip_colorval(S)*256;
|
unsigned int s = clip_colorval(S)*256;
|
||||||
|
@ -318,6 +450,54 @@ void rgb_to_hsv(int R, int G, int B, unsigned char *H, unsigned char *S, unsigne
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void hsv_to_hsl(int iH, int iS, int iV, unsigned char *oH, unsigned char *oS, unsigned char *oL)
|
||||||
|
{
|
||||||
|
int p = iV * (255 - iS);
|
||||||
|
*oH = iH;
|
||||||
|
*oL = clip_colorval((p + iV*255)/255/2);
|
||||||
|
if (*oL == 0) {
|
||||||
|
*oS = iS; // oS is actually undefined, so any value should work ;)
|
||||||
|
} else if (*oL <= 128) {
|
||||||
|
*oS = clip_colorval((iV*255 - p) / (2 * *oL));
|
||||||
|
} else {
|
||||||
|
*oS = clip_colorval((iV*255 - p) / (511 - 2 * *oL));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void hsl_to_hsv(int iH, int iS, int iL, unsigned char *oH, unsigned char *oS, unsigned char *oV)
|
||||||
|
{
|
||||||
|
// temporary solution...
|
||||||
|
hsl_to_rgb(iH, iS, iL, oH, oS, oV);
|
||||||
|
rgb_to_hsv(*oH, *oS, *oV, oH, oS, oV);
|
||||||
|
|
||||||
|
// can this really be so hard? it seems way harder to deduce a formula for this than for the other direction
|
||||||
|
|
||||||
|
/* *oH = iH;
|
||||||
|
|
||||||
|
if (iS == 0) {
|
||||||
|
*oS = 0;
|
||||||
|
*oV = iL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int temp2;
|
||||||
|
if (iL < 128) {
|
||||||
|
temp2 = iL * (255 + iS);
|
||||||
|
} else {
|
||||||
|
temp2 = iL*255 + iS*255 - iL*iS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int temp1 = 2 * iL*255 - temp2;
|
||||||
|
|
||||||
|
int temp3[3];
|
||||||
|
temp3[0] = iH + 255/3;
|
||||||
|
if (temp3[0] > 255) temp3[0] -= 255;
|
||||||
|
temp3[1] = iH;
|
||||||
|
temp3[2] = iH - 255/3;
|
||||||
|
if (temp3[2] < 0) temp3[2] += 255;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
wxString color_to_html(wxColour color)
|
wxString color_to_html(wxColour color)
|
||||||
{
|
{
|
||||||
|
|
|
@ -67,6 +67,10 @@ void rgb_to_hsl(int R, int G, int B, unsigned char *H, unsigned char *S, unsigne
|
||||||
// Convert an RGB color to HSV; all values are expected to be in range 0..255
|
// Convert an RGB color to HSV; all values are expected to be in range 0..255
|
||||||
void rgb_to_hsv(int R, int G, int B, unsigned char *H, unsigned char *S, unsigned char *V);
|
void rgb_to_hsv(int R, int G, int B, unsigned char *H, unsigned char *S, unsigned char *V);
|
||||||
|
|
||||||
|
void hsv_to_hsl(int iH, int iS, int iV, unsigned char *oH, unsigned char *oS, unsigned char *oL);
|
||||||
|
|
||||||
|
void hsl_to_hsv(int iH, int iS, int iL, unsigned char *oH, unsigned char *oS, unsigned char *oV);
|
||||||
|
|
||||||
|
|
||||||
// Convert a wxColour to a HTML hex string
|
// Convert a wxColour to a HTML hex string
|
||||||
wxString color_to_html(wxColour color);
|
wxString color_to_html(wxColour color);
|
||||||
|
|
|
@ -689,7 +689,7 @@ void DialogColorPicker::UpdateFromHSL()
|
||||||
l = hsl_input[2]->GetValue();
|
l = hsl_input[2]->GetValue();
|
||||||
hsl_to_rgb(h, s, l, &r, &g, &b);
|
hsl_to_rgb(h, s, l, &r, &g, &b);
|
||||||
//rgb_to_yuv(r, g, b, &y, &u, &v);
|
//rgb_to_yuv(r, g, b, &y, &u, &v);
|
||||||
rgb_to_hsv(r, g, b, &h2, &s2, &v2);
|
hsl_to_hsv(h, s, l, &h2, &s2, &v2);
|
||||||
rgb_input[0]->SetValue(r);
|
rgb_input[0]->SetValue(r);
|
||||||
rgb_input[1]->SetValue(g);
|
rgb_input[1]->SetValue(g);
|
||||||
rgb_input[2]->SetValue(b);
|
rgb_input[2]->SetValue(b);
|
||||||
|
@ -720,7 +720,7 @@ void DialogColorPicker::UpdateFromHSV()
|
||||||
v2 = hsv_input[2]->GetValue();
|
v2 = hsv_input[2]->GetValue();
|
||||||
hsv_to_rgb(h2, s2, v2, &r, &g, &b);
|
hsv_to_rgb(h2, s2, v2, &r, &g, &b);
|
||||||
//rgb_to_yuv(r, g, b, &y, &u, &v);
|
//rgb_to_yuv(r, g, b, &y, &u, &v);
|
||||||
rgb_to_hsl(r, g, b, &h, &s, &l);
|
hsv_to_hsl(h2, s2, v2, &h, &s, &l);
|
||||||
rgb_input[0]->SetValue(r);
|
rgb_input[0]->SetValue(r);
|
||||||
rgb_input[1]->SetValue(g);
|
rgb_input[1]->SetValue(g);
|
||||||
rgb_input[2]->SetValue(b);
|
rgb_input[2]->SetValue(b);
|
||||||
|
|
Loading…
Reference in New Issue