#include "driver.h"
#include <config.h>
void
cupsDitherDelete(cups_dither_t *d)
{
if (d != NULL)
free(d);
}
void
cupsDitherLine(cups_dither_t *d,
const cups_lut_t *lut,
const short *data,
int num_channels,
unsigned char *p)
{
register int x,
pixel,
e,
e0,e1,e2;
register int errval0,
errval1,
errbase,
errbase0,
errbase1,
errrange;
register int *p0,
*p1;
static char logtable[16384];
static char loginit = 0;
if (!loginit)
{
loginit = 1;
logtable[0] = 0;
for (x = 1; x < 2049; x ++)
logtable[x] = (int)(log(x / 16.0) / log(2.0) + 1.0);
for (; x < 16384; x ++)
logtable[x] = logtable[2049];
}
if (d->row == 0)
{
p0 = d->errors + 2;
p1 = d->errors + 2 + d->width + 4;
e0 = p0[0];
e1 = 0;
e2 = 0;
for (x = d->width;
x > 0;
x --, p0 ++, p1 ++, p ++, data += num_channels)
{
if (*data == 0)
{
*p = 0;
e0 = p0[1];
p1[-1] = e1;
e1 = e2;
e2 = 0;
continue;
}
pixel = lut[*data].intensity + e0 / 128;
if (pixel > CUPS_MAX_LUT)
pixel = CUPS_MAX_LUT;
else if (pixel < 0)
pixel = 0;
*p = lut[pixel].pixel;
e = lut[pixel].error;
if (e > 0)
errrange = logtable[e];
else
errrange = logtable[-e];
errbase = 8 - errrange;
errrange = errrange * 2 + 1;
if (errrange > 1)
{
errbase0 = errbase + (CUPS_RAND() % errrange);
errbase1 = errbase + (CUPS_RAND() % errrange);
}
else
errbase0 = errbase1 = errbase;
errval0 = errbase0 * e;
errval1 = (16 - errbase0) * e;
e0 = p0[1] + 7 * errval0;
e1 = e2 + 5 * errval1;
errval0 = errbase1 * e;
errval1 = (16 - errbase1) * e;
e2 = errval0;
p1[-1] = e1 + 3 * errval1;
}
}
else
{
p0 = d->errors + d->width + 1 + d->width + 4;
p1 = d->errors + d->width + 1;
p += d->width - 1;
data += num_channels * (d->width - 1);
e0 = p0[0];
e1 = 0;
e2 = 0;
for (x = d->width;
x > 0;
x --, p0 --, p1 --, p --, data -= num_channels)
{
if (*data == 0)
{
*p = 0;
e0 = p0[-1];
p1[1] = e1;
e1 = e2;
e2 = 0;
continue;
}
pixel = lut[*data].intensity + e0 / 128;
if (pixel > CUPS_MAX_LUT)
pixel = CUPS_MAX_LUT;
else if (pixel < 0)
pixel = 0;
*p = lut[pixel].pixel;
e = lut[pixel].error;
if (e > 0)
errrange = logtable[e];
else
errrange = logtable[-e];
errbase = 8 - errrange;
errrange = errrange * 2 + 1;
if (errrange > 1)
{
errbase0 = errbase + (CUPS_RAND() % errrange);
errbase1 = errbase + (CUPS_RAND() % errrange);
}
else
errbase0 = errbase1 = errbase;
errval0 = errbase0 * e;
errval1 = (16 - errbase0) * e;
e0 = p0[-1] + 7 * errval0;
e1 = e2 + 5 * errval1;
errval0 = errbase1 * e;
errval1 = (16 - errbase1) * e;
e2 = errval0;
p1[1] = e1 + 3 * errval1;
}
}
d->row = 1 - d->row;
}
cups_dither_t *
cupsDitherNew(int width)
{
cups_dither_t *d;
if ((d = (cups_dither_t *)calloc(1, sizeof(cups_dither_t) +
2 * (width + 4) *
sizeof(int))) == NULL)
return (NULL);
d->width = width;
return (d);
}