0% found this document useful (0 votes)
150 views5 pages

RGB Chips - DCTL

The document defines UI parameters for a color transformation tool, including settings for saturation, number of hues, columns, and clamping options. It includes functions for converting HSV to RGB, performing linear algebra operations, and generating random values. The main transformation function calculates RGB values based on user-defined parameters and applies various effects such as shuffling and gap handling.

Uploaded by

khlilshekkhlil
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
150 views5 pages

RGB Chips - DCTL

The document defines UI parameters for a color transformation tool, including settings for saturation, number of hues, columns, and clamping options. It includes functions for converting HSV to RGB, performing linear algebra operations, and generating random values. The main transformation function calculates RGB values based on user-defined parameters and applies various effects such as shuffling and gap handling.

Uploaded by

khlilshekkhlil
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 5

// clang-format off

DEFINE_UI_PARAMS(saturation, Saturation, DCTLUI_SLIDER_FLOAT, 1.0, 0.0, 2.0, 0.01)


DEFINE_UI_PARAMS(num_hues, Number of Hues, DCTLUI_SLIDER_INT, 36, 3, 72, 1)
DEFINE_UI_PARAMS(num_cols, Number of Columns, DCTLUI_SLIDER_INT, 24, 1, 100, 1)
DEFINE_UI_PARAMS(seed, Seed, DCTLUI_SLIDER_INT, 1, 1, 200, 1)
DEFINE_UI_PARAMS(mid_gray, Mid Gray, DCTLUI_VALUE_BOX, 1.0)
DEFINE_UI_PARAMS(clamp_output_min, Min Clamp, DCTLUI_VALUE_BOX, 0.0)
DEFINE_UI_PARAMS(clamp_output_max, Max Clamp, DCTLUI_VALUE_BOX, 1.0)
DEFINE_UI_PARAMS(clamp_output, Clamp Output, DCTLUI_CHECK_BOX, 0)
DEFINE_UI_PARAMS(gray_ramp, Gray Ramp, DCTLUI_CHECK_BOX, 0)
DEFINE_UI_PARAMS(vertical, Vertical, DCTLUI_CHECK_BOX, 0)
DEFINE_UI_PARAMS(band_interval, Band Interval, DCTLUI_COMBO_BOX, 1, {EQUAL,
EXPONENTIAL}, {Equal (Log), Exponential (Linear)})
DEFINE_UI_PARAMS(model, Model, DCTLUI_COMBO_BOX, 0, {HSV, SPHERICAL}, {HSV,
Spherical})
DEFINE_UI_PARAMS(shuffle, Shuffle, DCTLUI_COMBO_BOX, 0, {SHUFFLE_NONE,
SHUFFLE_HUES}, {None, Hues})
DEFINE_UI_PARAMS(continuous, Continuous Mode, DCTLUI_COMBO_BOX, 0, {DISCRETE,
CONTINUOUS_HUE, CONTINUOUS_EXP, CONTINUOUS_BOTH}, {Discrete, Continuous Hue,
Continuous Exp, Fully Continuous})
DEFINE_UI_PARAMS(gaps, Row Gaps, DCTLUI_COMBO_BOX, 0, {GAPS_NONE, GAPS_BLACK,
GAPS_WHITE, GAPS_MID_GREY, GAPS_GRAYSCALE}, {None, Black, White, Mid Grey,
Grayscale})

// clang-format on

__DEVICE__ float3 hsv_to_rgb(float hue, float sat, float val) {


// assume hue is in degrees
hue = _fmod(hue, 360.0f);
float c = val * sat;
float x = c * (1.0 - _fabs(_fmod(hue / 60.0f, 2.0f) - 1.0f));
float m = val - c;
float3 rgbp;
if (0.0 <= hue && hue < 60.0) {
rgbp = make_float3(c, x, 0.0);
} else if (60.0 <= hue && hue < 120.0) {
rgbp = make_float3(x, c, 0.0);
} else if (120.0 <= hue && hue < 180.0) {
rgbp = make_float3(0.0, c, x);
} else if (180.0 <= hue && hue < 240.0) {
rgbp = make_float3(0.0, x, c);
} else if (240.0 <= hue && hue < 300.0) {
rgbp = make_float3(x, 0.0, c);
} else { // if (300.0 < hue && hue < 360.0) {
rgbp = make_float3(c, 0.0, x);
}
return rgbp + m;
}

#define PI (3.1415926535)

// LINEAR ALGEBRA FUNCTIONS


__DEVICE__ float3 cross_product(float3 a, float3 b) {
float3 out = make_float3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x *
b.y - a.y * b.x);
return out;
}

__DEVICE__ inline float pow2f(float base) {


return base * base;
}

__DEVICE__ float dot_product(float3 a, float3 b) {


return a.x * b.x + a.y * b.y + a.z * b.z;
}

__DEVICE__ float norm_f3(float3 a) {


return _sqrtf(pow2f(a.x) + pow2f(a.y) + pow2f(a.z));
}

__DEVICE__ float3 unit_vec(float3 a) {


float norm = norm_f3(a);
float3 out = make_float3(a.x / norm, a.y / norm, a.z / norm);
return out;
}

__DEVICE__ float3 mv_33_3(float mat[3][3], float3 v) {


float3 out = make_float3(mat[0][0] * v.x + mat[0][1] * v.y + mat[0][2] * v.z,
mat[1][0] * v.x + mat[1][1] * v.y + mat[1][2] * v.z,
mat[2][0] * v.x + mat[2][1] * v.y + mat[2][2] * v.z);
return out;
}

__DEVICE__ void make_rotation_mat_axis_angle(float mat[3][3], float3 axis, float


angle) {
// Axis assumed to be unit vector, angle assuemd to be in radians
float c = _cosf(angle);
float s = _sinf(angle);

mat[0][0] = c + pow2f(axis.x) * (1.0 - c);


mat[0][1] = axis.x * axis.y * (1.0 - c) - axis.z * s;
mat[0][2] = axis.x * axis.z * (1.0 - c) + axis.y * s;
mat[1][0] = axis.x * axis.y * (1.0 - c) + axis.z * s;
mat[1][1] = c + pow2f(axis.y) * (1.0 - c);
mat[1][2] = axis.y * axis.z * (1.0 - c) - axis.x * s;
mat[2][0] = axis.z * axis.x * (1.0 - c) - axis.y * s;
mat[2][1] = axis.z * axis.y * (1.0 - c) + axis.x * s;
mat[2][2] = c + pow2f(axis.z) * (1.0 - c);
}

__DEVICE__ float3 spherical_to_rgb(float hue, float sat, float value) {


// Assume Hue is in degrees
// Scale saturation so that 1.0 fully saturates RGB colors.
// Value of 1.0 scaled to (1.0, 1.0, 1.0);
sat *= _acosf(dot_product(unit_vec(make_float3(1.0, 1.0, 0.0)),
unit_vec(make_float3(1.0, 1.0, 1.0))));
hue *= 2.0 * PI / 360.0;
value *= norm_f3(make_float3(1.0, 1.0, 1.0));
const float3 achromatic = make_float3(1.0, 1.0, 1.0);
const float3 red_axis = make_float3(1.0, 0.0, 0.0);

float rot_mat_inv[3][3] = {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}};
float rot_mat2_inv[3][3] = {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}};
make_rotation_mat_axis_angle(rot_mat_inv, unit_vec(cross_product(red_axis,
achromatic)), _acosf(dot_product(red_axis, unit_vec(achromatic))));
make_rotation_mat_axis_angle(rot_mat2_inv, red_axis, -3.0 * PI / 4.0);

float3 direction = make_float3(1.0, 1.0, 1.0);


direction.x = value * _cosf(sat);
direction.z = value * _sinf(hue) * _sinf(sat);
direction.y = value * _cosf(hue) * _sinf(sat);

float3 x = mv_33_3(rot_mat2_inv, direction);


x = mv_33_3(rot_mat_inv, x);
return x;
}

typedef uint rand_state;

__DEVICE__ float _randu_xorshift(__PRIVATE__ rand_state* seed) {


rand_state x = *seed;
x ^= (x << 13 | x >> 19);
x ^= (x >> 7 | x << 25);
x ^= (x << 15 | x >> 15);
*seed = x;
return (((float)x) / (float)(~((rand_state)0)));
}

__DEVICE__ inline float randu(__PRIVATE__ rand_state* seed) {


return _randu_xorshift(seed);
}

__DEVICE__ float sample_uniform(float a, float b, __PRIVATE__ rand_state* seed) {


float range = b - a;
float x = randu(seed);
return a + range * x;
}

__DEVICE__ float shuffle_rows(float curr_row, int num_rows, int gray_ramp,


__PRIVATE__ rand_state* seed) {
int indices[73] = {};
for (int i = 0; i < num_rows + gray_ramp; i++) {
indices[i] = i - gray_ramp;
}
for (int i = gray_ramp; i <= curr_row + gray_ramp; i++) {
int j = (int)sample_uniform(i, num_rows + gray_ramp, seed);
int temp = indices[i];
indices[i] = indices[j];
indices[j] = temp;
}
return indices[(int)_floorf(curr_row) + gray_ramp] + (curr_row -
_floorf(curr_row));
}

__DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R,
float p_G, float p_B) {
uint state = seed;

float x = (float)(p_X + 1) / (float)(p_Width);


float y = (float)(p_Y + 1) / (float)(p_Height);

if (vertical) {
float temp = x;
x = y;
y = temp;
}
float curr_row_cont = y * (num_hues + gray_ramp) - gray_ramp;
float curr_col_cont = x * num_cols;
float curr_row = curr_row_cont;
float curr_col = curr_col_cont;

if (shuffle == SHUFFLE_HUES) {
randu(&state);
randu(&state);
randu(&state);
curr_row_cont = shuffle_rows(curr_row_cont, num_hues, gray_ramp, &state);
curr_row = curr_row_cont;
}

if (continuous == CONTINUOUS_HUE || continuous == DISCRETE) {


curr_col = _ceilf(curr_col_cont);
}
if (continuous == CONTINUOUS_EXP || continuous == DISCRETE) {
curr_row = _floorf(curr_row_cont);
}

if (band_interval == EXPONENTIAL) {
curr_col -= _round(num_cols / 2.0);
}

float3 rgb;
float3 hsv;

bool is_gap = false;


if (gaps != GAPS_NONE) {
float3 gaps_color;
if (gaps == GAPS_BLACK) {
gaps_color = make_float3(0.0, 0.0, 0.0);
} else if (gaps == GAPS_WHITE) {
gaps_color = make_float3(1.0, 1.0, 1.0);
} else if (gaps == GAPS_MID_GREY) {
gaps_color = make_float3(mid_gray, mid_gray, mid_gray);
} else if (gaps == GAPS_GRAYSCALE) {
if (band_interval == EQUAL) {
gaps_color = hsv_to_rgb(0.0, 0.0, curr_col_cont / num_cols);
} else if (band_interval == EXPONENTIAL) {
gaps_color = hsv_to_rgb(0.0, 0.0, _exp2f(curr_col) * mid_gray);
}
}
if (continuous == DISCRETE || continuous == CONTINUOUS_EXP) {
if (_fabs(curr_row_cont - curr_row) <= 0.25 || _fabs(curr_row_cont -
curr_row) >= 0.75) {
is_gap = true;
rgb = gaps_color;
}
}
}

if (band_interval == EQUAL) {
if (gray_ramp && curr_row < 0) {
hsv = make_float3(0.0, 0.0, curr_col / num_cols);
} else {
hsv = make_float3((curr_row / num_hues) * 360.0, saturation, curr_col /
num_cols);
}
} else if (band_interval == EXPONENTIAL) {
if (gray_ramp && curr_row < 0) {
hsv = make_float3(0.0, 0.0, _exp2f(curr_col) * mid_gray);
} else {
hsv = make_float3((curr_row / num_hues) * 360.0, saturation,
_exp2f(curr_col) * mid_gray);
}
}

if (!is_gap) {
if (model == SPHERICAL) {
rgb = spherical_to_rgb(hsv.x, hsv.y, hsv.z);
} else if (model == HSV) {
rgb = hsv_to_rgb(hsv.x, hsv.y, hsv.z);
}
}

if (clamp_output) {
if (rgb.x > clamp_output_max || rgb.y > clamp_output_max || rgb.z >
clamp_output_max || rgb.x < clamp_output_min || rgb.y < clamp_output_min ||
rgb.z < clamp_output_min) {
rgb = make_float3(clamp_output_min, clamp_output_min,
clamp_output_min);
}
}

return rgb;
}

You might also like