2012-01-29 17:39:56 +00:00
|
|
|
#include "color.h"
|
|
|
|
|
2011-12-10 13:25:22 +00:00
|
|
|
#include <stdlib.h>
|
2012-01-24 13:16:20 +00:00
|
|
|
#include <assert.h>
|
2012-02-21 13:41:02 +00:00
|
|
|
#include <string.h>
|
2011-12-10 13:25:22 +00:00
|
|
|
#include "shared/constants.h"
|
2012-01-29 17:39:56 +00:00
|
|
|
#include "tools.h"
|
2011-12-10 13:25:22 +00:00
|
|
|
|
|
|
|
Color COLOR_TRANSPARENT = {0.0, 0.0, 0.0, 0.0};
|
|
|
|
Color COLOR_BLACK = {0.0, 0.0, 0.0, 1.0};
|
|
|
|
Color COLOR_RED = {1.0, 0.0, 0.0, 1.0};
|
|
|
|
Color COLOR_GREEN = {0.0, 1.0, 0.0, 1.0};
|
|
|
|
Color COLOR_BLUE = {0.0, 0.0, 1.0, 1.0};
|
|
|
|
Color COLOR_WHITE = {1.0, 1.0, 1.0, 1.0};
|
|
|
|
Color COLOR_GREY = {0.5, 0.5, 0.5, 1.0};
|
|
|
|
|
2012-02-21 13:41:02 +00:00
|
|
|
ColorGradationPart COLORGRADATIONPART_NULL;
|
|
|
|
|
|
|
|
void colorInit()
|
|
|
|
{
|
|
|
|
COLORGRADATIONPART_NULL.col = COLOR_TRANSPARENT;
|
|
|
|
COLORGRADATIONPART_NULL.start = 0.0;
|
|
|
|
}
|
|
|
|
|
2012-01-29 17:39:56 +00:00
|
|
|
void colorSave(FILE* f, Color* col)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-29 17:39:56 +00:00
|
|
|
toolsSaveDouble(f, &col->r);
|
|
|
|
toolsSaveDouble(f, &col->g);
|
|
|
|
toolsSaveDouble(f, &col->b);
|
|
|
|
toolsSaveDouble(f, &col->a);
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
2012-01-29 17:39:56 +00:00
|
|
|
void colorLoad(FILE* f, Color* col)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
2012-01-29 17:39:56 +00:00
|
|
|
toolsLoadDouble(f, &col->r);
|
|
|
|
toolsLoadDouble(f, &col->g);
|
|
|
|
toolsLoadDouble(f, &col->b);
|
|
|
|
toolsLoadDouble(f, &col->a);
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int colorTo32BitRGBA(Color* col)
|
|
|
|
{
|
|
|
|
return (((unsigned int)(col->a * 255.0)) << 24) | (((unsigned int)(col->b * 255.0)) << 16) | (((unsigned int)(col->g * 255.0)) << 8) | ((unsigned int)(col->r * 255.0));
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int colorTo32BitBGRA(Color* col)
|
|
|
|
{
|
|
|
|
return (((unsigned int)(col->a * 255.0)) << 24) | (((unsigned int)(col->r * 255.0)) << 16) | (((unsigned int)(col->g * 255.0)) << 8) | ((unsigned int)(col->b * 255.0));
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int colorTo32BitARGB(Color* col)
|
|
|
|
{
|
|
|
|
return (((unsigned int)(col->b * 255.0)) << 24) | (((unsigned int)(col->g * 255.0)) << 16) | (((unsigned int)(col->r * 255.0)) << 8) | ((unsigned int)(col->a * 255.0));
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int colorTo32BitABGR(Color* col)
|
|
|
|
{
|
|
|
|
return (((unsigned int)(col->r * 255.0)) << 24) | (((unsigned int)(col->g * 255.0)) << 16) | (((unsigned int)(col->b * 255.0)) << 8) | ((unsigned int)(col->a * 255.0));
|
|
|
|
}
|
|
|
|
|
|
|
|
void colorMask(Color* base, Color* mask)
|
|
|
|
{
|
|
|
|
double new_a;
|
|
|
|
new_a = base->a + mask->a - (base->a * mask->a);
|
|
|
|
base->r = (mask->r * mask->a + base->r * base->a - base->r * base->a * mask->a) / new_a;
|
|
|
|
base->g = (mask->g * mask->a + base->g * base->a - base->g * base->a * mask->a) / new_a;
|
|
|
|
base->b = (mask->b * mask->a + base->b * base->a - base->b * base->a * mask->a) / new_a;
|
|
|
|
base->a = new_a;
|
2011-12-17 10:55:37 +00:00
|
|
|
|
2011-12-10 13:25:22 +00:00
|
|
|
/*double mask_weight = mask->a;
|
|
|
|
double base_weight = 1.0 - mask_weight;
|
|
|
|
|
|
|
|
base->r = mask->r * mask_weight + base->r * base_weight;
|
|
|
|
base->g = mask->g * mask_weight + base->g * base_weight;
|
|
|
|
base->b = mask->b * mask_weight + base->b * base_weight;
|
|
|
|
base->a = base->a + mask_weight * (1.0 - base->a);*/
|
|
|
|
}
|
|
|
|
|
|
|
|
double colorNormalize(Color* col)
|
|
|
|
{
|
|
|
|
double max = colorGetValue(col);
|
|
|
|
|
2012-01-24 13:16:20 +00:00
|
|
|
assert(col->r >= 0.0);
|
|
|
|
assert(col->g >= 0.0);
|
|
|
|
assert(col->b >= 0.0);
|
|
|
|
assert(col->a >= 0.0);
|
|
|
|
|
2011-12-10 13:25:22 +00:00
|
|
|
if (max > 1.0)
|
|
|
|
{
|
|
|
|
col->r /= max;
|
|
|
|
col->g /= max;
|
|
|
|
col->b /= max;
|
|
|
|
}
|
|
|
|
return max;
|
|
|
|
}
|
|
|
|
|
|
|
|
double colorGetValue(Color* col)
|
|
|
|
{
|
|
|
|
double max;
|
|
|
|
|
|
|
|
max = col->r;
|
|
|
|
if (col->g > max)
|
|
|
|
{
|
|
|
|
max = col->g;
|
|
|
|
}
|
|
|
|
if (col->b > max)
|
|
|
|
{
|
|
|
|
max = col->b;
|
|
|
|
}
|
|
|
|
return max;
|
|
|
|
}
|
|
|
|
|
|
|
|
ColorGradation colorGradationCreate()
|
|
|
|
{
|
|
|
|
ColorGradation result;
|
|
|
|
|
|
|
|
result.nbparts = 0;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
int _part_compare(const void* part1, const void* part2)
|
|
|
|
{
|
2012-02-20 21:17:13 +00:00
|
|
|
if (((ColorGradationPart*)part1)->start > ((ColorGradationPart*)part2)->start)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-29 17:39:56 +00:00
|
|
|
void colorGradationSave(FILE* f, ColorGradation* gradation)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
toolsSaveInt(f, &gradation->nbparts);
|
|
|
|
for (i = 0; i < gradation->nbparts; i++)
|
|
|
|
{
|
|
|
|
toolsSaveDouble(f, &gradation->parts[i].start);
|
|
|
|
colorSave(f, &gradation->parts[i].col);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void colorGradationLoad(FILE* f, ColorGradation* gradation)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
toolsLoadInt(f, &gradation->nbparts);
|
|
|
|
for (i = 0; i < gradation->nbparts; i++)
|
|
|
|
{
|
|
|
|
toolsLoadDouble(f, &gradation->parts[i].start);
|
|
|
|
colorLoad(f, &gradation->parts[i].col);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-21 13:41:02 +00:00
|
|
|
int colorGradationGetPartCount(ColorGradation* gradation)
|
|
|
|
{
|
|
|
|
return gradation->nbparts;
|
|
|
|
}
|
|
|
|
|
|
|
|
int colorGradationAddPart(ColorGradation* gradation)
|
|
|
|
{
|
|
|
|
if (gradation->nbparts == MAX_COLORGRADATION_PARTS)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return gradation->nbparts++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void colorGradationDelPart(ColorGradation* gradation, int part)
|
|
|
|
{
|
|
|
|
if (part >= 0 && part < gradation->nbparts)
|
|
|
|
{
|
|
|
|
memmove(gradation->parts + part, gradation->parts + part + 1, sizeof(ColorGradationPart) * (gradation->nbparts - part - 1));
|
|
|
|
gradation->nbparts--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ColorGradationPart colorGradationGetPart(ColorGradation* gradation, int part)
|
|
|
|
{
|
|
|
|
if (part >= 0 && part < gradation->nbparts)
|
|
|
|
{
|
|
|
|
return gradation->parts[part];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return COLORGRADATIONPART_NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void colorGradationSetPart(ColorGradation* gradation, int part, ColorGradationPart value)
|
|
|
|
{
|
|
|
|
if (part >= 0 && part < gradation->nbparts)
|
|
|
|
{
|
|
|
|
gradation->parts[part] = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void colorGradationQuickAdd(ColorGradation* gradation, double value, Color* col)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
|
|
|
if (gradation->nbparts == MAX_COLORGRADATION_PARTS)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gradation->parts[gradation->nbparts].start = value;
|
|
|
|
gradation->parts[gradation->nbparts].col = *col;
|
|
|
|
|
|
|
|
if (gradation->nbparts++ > 1)
|
|
|
|
{
|
2012-02-20 21:17:13 +00:00
|
|
|
qsort(gradation->parts, gradation->nbparts, sizeof(ColorGradationPart), _part_compare);
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-21 13:41:02 +00:00
|
|
|
void colorGradationQuickAddRgba(ColorGradation* gradation, double value, double r, double g, double b, double a)
|
2011-12-10 13:25:22 +00:00
|
|
|
{
|
|
|
|
Color col;
|
|
|
|
col.r = r;
|
|
|
|
col.g = g;
|
|
|
|
col.b = b;
|
|
|
|
col.a = a;
|
2012-02-21 13:41:02 +00:00
|
|
|
colorGradationQuickAdd(gradation, value, &col);
|
2011-12-10 13:25:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Color colorGradationGet(ColorGradation* gradation, double value)
|
|
|
|
{
|
|
|
|
Color result;
|
|
|
|
int i;
|
|
|
|
double fact;
|
|
|
|
|
|
|
|
if (gradation->nbparts == 0)
|
|
|
|
{
|
|
|
|
return COLOR_TRANSPARENT;
|
|
|
|
}
|
|
|
|
else if (gradation->nbparts == 1 || value <= gradation->parts[0].start)
|
|
|
|
{
|
|
|
|
return gradation->parts[0].col;
|
|
|
|
}
|
|
|
|
else if (value >= gradation->parts[gradation->nbparts - 1].start)
|
|
|
|
{
|
|
|
|
return gradation->parts[gradation->nbparts - 1].col;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = 1; i < gradation->nbparts; i++)
|
|
|
|
{
|
|
|
|
if (value < gradation->parts[i].start)
|
|
|
|
{
|
|
|
|
fact = (value - gradation->parts[i - 1].start) / (gradation->parts[i].start - gradation->parts[i - 1].start);
|
|
|
|
result.r = gradation->parts[i - 1].col.r + (gradation->parts[i].col.r - gradation->parts[i - 1].col.r) * fact;
|
|
|
|
result.g = gradation->parts[i - 1].col.g + (gradation->parts[i].col.g - gradation->parts[i - 1].col.g) * fact;
|
|
|
|
result.b = gradation->parts[i - 1].col.b + (gradation->parts[i].col.b - gradation->parts[i - 1].col.b) * fact;
|
|
|
|
result.a = gradation->parts[i - 1].col.a + (gradation->parts[i].col.a - gradation->parts[i - 1].col.a) * fact;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return gradation->parts[gradation->nbparts - 1].col;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|