#include "driver.h"
void
cupsRGBDelete(cups_rgb_t *rgbptr)
{
if (rgbptr == NULL)
return;
free(rgbptr->colors[0][0][0]);
free(rgbptr->colors[0][0]);
free(rgbptr->colors[0]);
free(rgbptr->colors);
free(rgbptr);
}
void
cupsRGBDoGray(cups_rgb_t *rgbptr,
const unsigned char *input,
unsigned char *output,
int num_pixels)
{
int i;
int lastgray;
int xs, ys, zs,
g, gi, gm0, gm1;
const unsigned char *color;
int tempg;
int rgbsize;
if (!rgbptr || !input || !output || num_pixels <= 0)
return;
lastgray = -1;
rgbsize = rgbptr->num_channels;
xs = rgbptr->cube_size * rgbptr->cube_size * rgbptr->num_channels;
ys = rgbptr->cube_size * rgbptr->num_channels;
zs = rgbptr->num_channels;
while (num_pixels > 0)
{
num_pixels --;
g = cups_srgb_lut[*input++];
if (g == lastgray)
{
memcpy(output, output - rgbptr->num_channels, rgbsize);
output += rgbptr->num_channels;
continue;
}
else if (g == 0x00 && rgbptr->cache_init)
{
memcpy(output, rgbptr->black, rgbsize);
output += rgbptr->num_channels;
continue;
}
else if (g == 0xff && rgbptr->cache_init)
{
memcpy(output, rgbptr->white, rgbsize);
output += rgbptr->num_channels;
continue;
}
gi = rgbptr->cube_index[g];
gm0 = rgbptr->cube_mult[g];
gm1 = 256 - gm0;
color = rgbptr->colors[gi][gi][gi];
for (i = 0; i < rgbptr->num_channels; i ++, color ++)
{
tempg = (color[0] * gm0 + color[xs + ys + zs] * gm1) / 256;
if (tempg > 255)
*output++ = 255;
else if (tempg < 0)
*output++ = 0;
else
*output++ = tempg;
}
}
}
void
cupsRGBDoRGB(cups_rgb_t *rgbptr,
const unsigned char *input,
unsigned char *output,
int num_pixels)
{
int i;
int rgb,
lastrgb;
int r, ri, rm0, rm1, rs,
g, gi, gm0, gm1, gs,
b, bi, bm0, bm1, bs;
const unsigned char *color;
int tempr,
tempg,
tempb ;
int rgbsize;
if (!rgbptr || !input || !output || num_pixels <= 0)
return;
lastrgb = -1;
rgbsize = rgbptr->num_channels;
rs = rgbptr->cube_size * rgbptr->cube_size * rgbptr->num_channels;
gs = rgbptr->cube_size * rgbptr->num_channels;
bs = rgbptr->num_channels;
while (num_pixels > 0)
{
num_pixels --;
r = cups_srgb_lut[*input++];
g = cups_srgb_lut[*input++];
b = cups_srgb_lut[*input++];
rgb = (((r << 8) | g) << 8) | b;
if (rgb == lastrgb)
{
memcpy(output, output - rgbptr->num_channels, rgbsize);
output += rgbptr->num_channels;
continue;
}
else if (rgb == 0x000000 && rgbptr->cache_init)
{
memcpy(output, rgbptr->black, rgbsize);
output += rgbptr->num_channels;
continue;
}
else if (rgb == 0xffffff && rgbptr->cache_init)
{
memcpy(output, rgbptr->white, rgbsize);
output += rgbptr->num_channels;
continue;
}
ri = rgbptr->cube_index[r];
rm0 = rgbptr->cube_mult[r];
rm1 = 256 - rm0;
gi = rgbptr->cube_index[g];
gm0 = rgbptr->cube_mult[g];
gm1 = 256 - gm0;
bi = rgbptr->cube_index[b];
bm0 = rgbptr->cube_mult[b];
bm1 = 256 - bm0;
color = rgbptr->colors[ri][gi][bi];
for (i = rgbptr->num_channels; i > 0; i --, color ++)
{
tempb = (color[0] * bm0 + color[bs] * bm1) / 256;
tempg = tempb * gm0;
tempb = (color[gs] * gm0 + color[gs + bs] * bm1) / 256;
tempg = (tempg + tempb * gm1) / 256;
tempr = tempg * rm0;
tempb = (color[rs] * bm0 + color[rs + bs] * bm1) / 256;
tempg = tempb * gm0;
tempb = (color[rs + gs] * bm0 + color[rs + gs + bs] * bm1) / 256;
tempg = (tempg + tempb * gm1) / 256;
tempr = (tempr + tempg * rm1) / 256;
if (tempr > 255)
*output++ = 255;
else if (tempr < 0)
*output++ = 0;
else
*output++ = tempr;
}
}
}
cups_rgb_t *
cupsRGBLoad(ppd_file_t *ppd,
const char *colormodel,
const char *media,
const char *resolution)
{
int i,
cube_size,
num_channels,
num_samples;
cups_sample_t *samples;
float values[7];
char spec[PPD_MAX_NAME];
ppd_attr_t *attr;
cups_rgb_t *rgbptr;
if ((attr = cupsFindAttr(ppd, "cupsRGBProfile", colormodel, media,
resolution, spec, sizeof(spec))) == NULL)
{
fputs("DEBUG2: No cupsRGBProfile attribute found for the current settings!\n", stderr);
return (NULL);
}
if (!attr->value || sscanf(attr->value, "%d%d%d", &cube_size, &num_channels,
&num_samples) != 3)
{
fprintf(stderr, "ERROR: Bad cupsRGBProfile attribute \'%s\'!\n",
attr->value ? attr->value : "(null)");
return (NULL);
}
if (cube_size < 2 || cube_size > 16 ||
num_channels < 1 || num_channels > CUPS_MAX_RGB ||
num_samples != (cube_size * cube_size * cube_size))
{
fprintf(stderr, "ERROR: Bad cupsRGBProfile attribute \'%s\'!\n",
attr->value);
return (NULL);
}
if ((samples = calloc(num_samples, sizeof(cups_sample_t))) == NULL)
{
fputs("ERROR: Unable to allocate memory for RGB profile!\n", stderr);
return (NULL);
}
for (i = 0; i < num_samples; i ++)
if ((attr = ppdFindNextAttr(ppd, "cupsRGBSample", spec)) == NULL)
break;
else if (!attr->value)
{
fputs("ERROR: Bad cupsRGBSample value!\n", stderr);
break;
}
else if (sscanf(attr->value, "%f%f%f%f%f%f%f", values + 0,
values + 1, values + 2, values + 3, values + 4, values + 5,
values + 6) != (3 + num_channels))
{
fputs("ERROR: Bad cupsRGBSample value!\n", stderr);
break;
}
else
{
samples[i].rgb[0] = (int)(255.0 * values[0] + 0.5);
samples[i].rgb[1] = (int)(255.0 * values[1] + 0.5);
samples[i].rgb[2] = (int)(255.0 * values[2] + 0.5);
samples[i].colors[0] = (int)(255.0 * values[3] + 0.5);
if (num_channels > 1)
samples[i].colors[1] = (int)(255.0 * values[4] + 0.5);
if (num_channels > 2)
samples[i].colors[2] = (int)(255.0 * values[5] + 0.5);
if (num_channels > 3)
samples[i].colors[3] = (int)(255.0 * values[6] + 0.5);
}
if (i == num_samples)
rgbptr = cupsRGBNew(num_samples, samples, cube_size, num_channels);
else
rgbptr = NULL;
free(samples);
return (rgbptr);
}
cups_rgb_t *
cupsRGBNew(int num_samples,
cups_sample_t *samples,
int cube_size,
int num_channels)
{
cups_rgb_t *rgbptr;
int i;
int r, g, b;
int tempsize;
unsigned char *tempc;
unsigned char **tempb ;
unsigned char ***tempg;
unsigned char ****tempr;
unsigned char rgb[3];
if (!samples || num_samples != (cube_size * cube_size * cube_size) ||
num_channels <= 0 || num_channels > CUPS_MAX_RGB)
return (NULL);
if ((rgbptr = calloc(1, sizeof(cups_rgb_t))) == NULL)
return (NULL);
tempsize = cube_size * cube_size * cube_size;
tempc = calloc(tempsize, num_channels);
tempb = calloc(tempsize, sizeof(unsigned char *));
tempg = calloc(cube_size * cube_size, sizeof(unsigned char **));
tempr = calloc(cube_size, sizeof(unsigned char ***));
if (tempc == NULL || tempb == NULL || tempg == NULL || tempr == NULL)
{
free(rgbptr);
if (tempc)
free(tempc);
if (tempb)
free(tempb);
if (tempg)
free(tempg);
if (tempr)
free(tempr);
return (NULL);
}
for (i = 0, r = 0; r < cube_size; r ++)
{
tempr[r] = tempg + r * cube_size;
for (g = 0; g < cube_size; g ++)
{
tempr[r][g] = tempb + i;
for (b = 0; b < cube_size; b ++, i ++)
tempr[r][g][b] = tempc + i * num_channels;
}
}
for (i = 0; i < num_samples; i ++)
{
r = samples[i].rgb[0] * (cube_size - 1) / 255;
g = samples[i].rgb[1] * (cube_size - 1) / 255;
b = samples[i].rgb[2] * (cube_size - 1) / 255;
memcpy(tempr[r][g][b], samples[i].colors, num_channels);
}
rgbptr->cube_size = cube_size;
rgbptr->num_channels = num_channels;
rgbptr->colors = tempr;
for (i = 0; i < 256; i ++)
{
rgbptr->cube_index[i] = i * (cube_size - 1) / 256;
if (i == 0)
rgbptr->cube_mult[i] = 256;
else
rgbptr->cube_mult[i] = 255 - ((i * (cube_size - 1)) & 255);
}
rgb[0] = 0;
rgb[1] = 0;
rgb[2] = 0;
cupsRGBDoRGB(rgbptr, rgb, rgbptr->black, 1);
rgb[0] = 255;
rgb[1] = 255;
rgb[2] = 255;
cupsRGBDoRGB(rgbptr, rgb, rgbptr->white, 1);
rgbptr->cache_init = 1;
return (rgbptr);
}