mirror of
https://github.com/ctm/executor.git
synced 2024-09-29 03:54:26 +00:00
309 lines
7.6 KiB
C
309 lines
7.6 KiB
C
|
/* Copyright 1994, 1995 by Abacus Research and
|
||
|
* Development, Inc. All rights reserved.
|
||
|
*/
|
||
|
|
||
|
#if !defined (OMIT_RCSID_STRINGS)
|
||
|
char ROMlib_rcsid_qCConv[] =
|
||
|
"$Id: qCConv.c 63 2004-12-24 18:19:43Z ctm $";
|
||
|
#endif
|
||
|
|
||
|
#include "rsys/common.h"
|
||
|
#include "QuickDraw.h"
|
||
|
|
||
|
/* cmy and rgb color spaces are simply complements */
|
||
|
|
||
|
P2 (PUBLIC pascal trap, void, CMY2RGB,
|
||
|
CMYColor *, cmy_color,
|
||
|
RGBColor *, rgb_color)
|
||
|
{
|
||
|
rgb_color->red = ~cmy_color->cyan;
|
||
|
rgb_color->green = ~cmy_color->magenta;
|
||
|
rgb_color->blue = ~cmy_color->yellow;
|
||
|
}
|
||
|
|
||
|
P2 (PUBLIC pascal trap, void, RGB2CMY,
|
||
|
RGBColor *, rgb_color,
|
||
|
CMYColor *, cmy_color)
|
||
|
{
|
||
|
/* use `bar = ~foo' instead of `bar = CW (MaxSmallFract - CW (foo))'
|
||
|
to compute the complement value */
|
||
|
|
||
|
cmy_color->cyan = ~rgb_color->red;
|
||
|
cmy_color->magenta = ~rgb_color->green;
|
||
|
cmy_color->yellow = ~rgb_color->blue;
|
||
|
}
|
||
|
|
||
|
#define SF_MULT(x,y) (((x) * (y)) / 65535)
|
||
|
#define SF_DIV(x,y) (((x) * 65535) / (y))
|
||
|
|
||
|
#define C_TO_SF(c) ((c) * 65535)
|
||
|
#define SF_TO_C(sf) ((sf) / 65535)
|
||
|
|
||
|
#define ANGLE_TO_SF(angle) (C_TO_SF (angle) / 360)
|
||
|
|
||
|
|
||
|
static inline unsigned short
|
||
|
value (unsigned long n1, unsigned long n2, unsigned long hue)
|
||
|
{
|
||
|
if (hue < ANGLE_TO_SF (60))
|
||
|
return CW (n1 + SF_MULT (n2 - n1,
|
||
|
SF_MULT (hue, C_TO_SF (6))));
|
||
|
else if (hue < ANGLE_TO_SF (180))
|
||
|
return CW (n2);
|
||
|
else if (hue < ANGLE_TO_SF (240))
|
||
|
return CW (n1 + SF_MULT (n2 - n1,
|
||
|
SF_MULT (ANGLE_TO_SF (240) - hue,
|
||
|
C_TO_SF (6))));
|
||
|
else
|
||
|
return CW (n1);
|
||
|
}
|
||
|
|
||
|
|
||
|
P2 (PUBLIC pascal trap, void, HSL2RGB,
|
||
|
HSLColor *, hsl_color,
|
||
|
RGBColor *, rgb_color)
|
||
|
{
|
||
|
if (hsl_color->saturation == CWC (0))
|
||
|
{
|
||
|
rgb_color->red = hsl_color->lightness;
|
||
|
rgb_color->green = hsl_color->lightness;
|
||
|
rgb_color->blue = hsl_color->lightness;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
unsigned long m1, m2;
|
||
|
|
||
|
/* the hue represents a angle in the range [0, 360) */
|
||
|
unsigned long h = CW (hsl_color->hue);
|
||
|
unsigned long s = CW (hsl_color->saturation);
|
||
|
unsigned long l = CW (hsl_color->lightness);
|
||
|
|
||
|
if (l <= (MaxSmallFract / 2))
|
||
|
m2 = SF_MULT (l, (C_TO_SF (1) + s));
|
||
|
else
|
||
|
m2 = l + s - SF_MULT (l, s);
|
||
|
m1 = SF_MULT (l, C_TO_SF (2)) - m2;
|
||
|
|
||
|
rgb_color->red = value (m1, m2,
|
||
|
(h >= ANGLE_TO_SF (240)) ? (h - ANGLE_TO_SF (240))
|
||
|
: (h + ANGLE_TO_SF (120)));
|
||
|
rgb_color->green = value (m1, m2, h);
|
||
|
rgb_color->blue = value (m1, m2,
|
||
|
(h < ANGLE_TO_SF (120)) ? (h + ANGLE_TO_SF (240))
|
||
|
: (h - ANGLE_TO_SF (120)));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
P2 (PUBLIC pascal trap, void, RGB2HSL,
|
||
|
RGBColor *, rgb_color,
|
||
|
HSLColor *, hsl_color)
|
||
|
{
|
||
|
unsigned long r = CW (rgb_color->red);
|
||
|
unsigned long g = CW (rgb_color->green);
|
||
|
unsigned long b = CW (rgb_color->blue);
|
||
|
|
||
|
unsigned long max = MAX (r, MAX (g, b));
|
||
|
unsigned long min = MIN (r, MIN (g, b));
|
||
|
|
||
|
unsigned long h;
|
||
|
unsigned long s;
|
||
|
unsigned long l = (min + max) / 2;
|
||
|
|
||
|
if (min == max)
|
||
|
{
|
||
|
/* achromatic case, because all rgb color components
|
||
|
are equal */
|
||
|
s = 0;
|
||
|
/* the value of h in this case is meaningless, should
|
||
|
investigate what the Mac color conversion routines do */
|
||
|
h = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
unsigned long delta = max - min;
|
||
|
|
||
|
if (l <= (MaxSmallFract / 2))
|
||
|
{
|
||
|
s = SF_DIV (delta, max + min);
|
||
|
gui_assert (s <= MaxSmallFract);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s = SF_DIV (delta, C_TO_SF (2) - max - min);
|
||
|
gui_assert (s <= MaxSmallFract);
|
||
|
}
|
||
|
|
||
|
if (r == max)
|
||
|
{
|
||
|
if (g >= b)
|
||
|
h = SF_MULT (SF_DIV (g - b, delta), ANGLE_TO_SF (60));
|
||
|
else
|
||
|
h = ANGLE_TO_SF (360) - SF_MULT (SF_DIV (b - g, delta), ANGLE_TO_SF (60));
|
||
|
|
||
|
}
|
||
|
else if (g == max)
|
||
|
{
|
||
|
if (b >= r)
|
||
|
h = ANGLE_TO_SF (120) + SF_MULT (SF_DIV (b - r, delta), ANGLE_TO_SF (60));
|
||
|
else
|
||
|
h = ANGLE_TO_SF (120) - SF_MULT (SF_DIV (r - b, delta), ANGLE_TO_SF (60));
|
||
|
}
|
||
|
else if (b == max)
|
||
|
{
|
||
|
if (r >= g)
|
||
|
h = ANGLE_TO_SF (240) + SF_MULT (SF_DIV (r - g, delta), ANGLE_TO_SF (60));
|
||
|
else
|
||
|
h = ANGLE_TO_SF (240) - SF_MULT (SF_DIV (g - r, delta), ANGLE_TO_SF (60));
|
||
|
}
|
||
|
else
|
||
|
gui_fatal("r = 0x%lx, g = 0x%lx, b = 0x%lx", r, g, b);
|
||
|
}
|
||
|
|
||
|
hsl_color->hue = CW (h);
|
||
|
hsl_color->saturation = CW (s);
|
||
|
hsl_color->lightness = CW (l);
|
||
|
}
|
||
|
|
||
|
P2 (PUBLIC pascal trap, void, HSV2RGB,
|
||
|
HSVColor *, hsv_color,
|
||
|
RGBColor *, rgb_color)
|
||
|
{
|
||
|
if (hsv_color->saturation == CWC (0))
|
||
|
{
|
||
|
rgb_color->red = hsv_color->value;
|
||
|
rgb_color->green = hsv_color->value;
|
||
|
rgb_color->blue = hsv_color->value;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* the hue represents a angle in the range [0, 360) */
|
||
|
unsigned long h = CW (hsv_color->hue);
|
||
|
unsigned long s = CW (hsv_color->saturation);
|
||
|
unsigned long v = CW (hsv_color->value);
|
||
|
|
||
|
/* one of the six color verticies of the hex cone, [0, 6) */
|
||
|
unsigned sextant = SF_TO_C (h * 6);
|
||
|
/* `fractional' portion of h, in the range [0,1] */
|
||
|
/* unsigned long f = 6 * (h % ANGLE_TO_SF (60)); */
|
||
|
unsigned long f = 6 * (h - ANGLE_TO_SF (sextant * 60));
|
||
|
|
||
|
unsigned long p = SF_MULT (v, C_TO_SF (1) - s);
|
||
|
unsigned long q = SF_MULT (v, C_TO_SF (1) - SF_MULT (s, f));
|
||
|
unsigned long t = SF_MULT (v, (C_TO_SF (1)
|
||
|
- SF_MULT (s, C_TO_SF (1) - f)));
|
||
|
|
||
|
switch (sextant)
|
||
|
{
|
||
|
case 0:
|
||
|
rgb_color->red = CW (v);
|
||
|
rgb_color->green = CW (t);
|
||
|
rgb_color->blue = CW (p);
|
||
|
break;
|
||
|
case 1:
|
||
|
rgb_color->red = CW (q);
|
||
|
rgb_color->green = CW (v);
|
||
|
rgb_color->blue = CW (p);
|
||
|
break;
|
||
|
case 2:
|
||
|
rgb_color->red = CW (p);
|
||
|
rgb_color->green = CW (v);
|
||
|
rgb_color->blue = CW (t);
|
||
|
break;
|
||
|
case 3:
|
||
|
rgb_color->red = CW (p);
|
||
|
rgb_color->green = CW (q);
|
||
|
rgb_color->blue = CW (v);
|
||
|
break;
|
||
|
case 4:
|
||
|
rgb_color->red = CW (t);
|
||
|
rgb_color->green = CW (p);
|
||
|
rgb_color->blue = CW (v);
|
||
|
break;
|
||
|
case 5:
|
||
|
case 6:
|
||
|
rgb_color->red = CW (v);
|
||
|
rgb_color->green = CW (p);
|
||
|
rgb_color->blue = CW (q);
|
||
|
break;
|
||
|
default:
|
||
|
gui_fatal ("sextant = %d", sextant);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
P2 (PUBLIC pascal trap, void, RGB2HSV,
|
||
|
RGBColor *, rgb_color,
|
||
|
HSVColor *, hsv_color)
|
||
|
{
|
||
|
unsigned long r = CW (rgb_color->red);
|
||
|
unsigned long g = CW (rgb_color->green);
|
||
|
unsigned long b = CW (rgb_color->blue);
|
||
|
|
||
|
unsigned long max = MAX (r, MAX (g, b));
|
||
|
unsigned long min = MIN (r, MIN (g, b));
|
||
|
|
||
|
unsigned long h;
|
||
|
unsigned long s;
|
||
|
unsigned long v = max;
|
||
|
|
||
|
if (max != 0)
|
||
|
{
|
||
|
s = SF_DIV (max - min, max);
|
||
|
gui_assert (s <= MaxSmallFract);
|
||
|
}
|
||
|
else
|
||
|
s = 0;
|
||
|
|
||
|
if (s == 0)
|
||
|
{
|
||
|
/* the value of h in this case is meaningless, should
|
||
|
investigate what the Mac color conversion routines do */
|
||
|
h = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
unsigned long delta = max - min;
|
||
|
|
||
|
if (r == max)
|
||
|
{
|
||
|
if (g >= b)
|
||
|
h = SF_MULT (SF_DIV (g - b, delta), ANGLE_TO_SF (60));
|
||
|
else
|
||
|
h = ANGLE_TO_SF (360) - SF_MULT (SF_DIV (b - g, delta), ANGLE_TO_SF (60));
|
||
|
|
||
|
}
|
||
|
else if (g == max)
|
||
|
{
|
||
|
if (b >= r)
|
||
|
h = ANGLE_TO_SF (120) + SF_MULT (SF_DIV (b - r, delta), ANGLE_TO_SF (60));
|
||
|
else
|
||
|
h = ANGLE_TO_SF (120) - SF_MULT (SF_DIV (r - b, delta), ANGLE_TO_SF (60));
|
||
|
}
|
||
|
else if (b == max)
|
||
|
{
|
||
|
if (r >= g)
|
||
|
h = ANGLE_TO_SF (240) + SF_MULT (SF_DIV (r - g, delta), ANGLE_TO_SF (60));
|
||
|
else
|
||
|
h = ANGLE_TO_SF (240) - SF_MULT (SF_DIV (g - r, delta), ANGLE_TO_SF (60));
|
||
|
}
|
||
|
else
|
||
|
gui_fatal ("r = 0x%lx, g = 0x%lx, b = 0x%lx", r, g, b);
|
||
|
}
|
||
|
|
||
|
hsv_color->hue = CW (h);
|
||
|
hsv_color->saturation = CW (s);
|
||
|
hsv_color->value = CW (v);
|
||
|
}
|
||
|
|
||
|
P1 (PUBLIC pascal trap, SmallFract, Fix2SmallFract,
|
||
|
Fixed, f)
|
||
|
{
|
||
|
return f & 0xFFFF;
|
||
|
}
|
||
|
|
||
|
P1 (PUBLIC pascal trap, Fixed, SmallFract2Fix,
|
||
|
SmallFract, sf)
|
||
|
{
|
||
|
return sf;
|
||
|
}
|