forked from KolibriOS/kolibrios
236 lines
4.2 KiB
C
236 lines
4.2 KiB
C
|
#include "fitz.h"
|
||
|
|
||
|
/* Unpack image samples and optionally pad pixels with opaque alpha */
|
||
|
|
||
|
#define get1(buf,x) ((buf[x >> 3] >> ( 7 - (x & 7) ) ) & 1 )
|
||
|
#define get2(buf,x) ((buf[x >> 2] >> ( ( 3 - (x & 3) ) << 1 ) ) & 3 )
|
||
|
#define get4(buf,x) ((buf[x >> 1] >> ( ( 1 - (x & 1) ) << 2 ) ) & 15 )
|
||
|
#define get8(buf,x) (buf[x])
|
||
|
#define get16(buf,x) (buf[x << 1])
|
||
|
|
||
|
static unsigned char get1_tab_1[256][8];
|
||
|
static unsigned char get1_tab_1p[256][16];
|
||
|
static unsigned char get1_tab_255[256][8];
|
||
|
static unsigned char get1_tab_255p[256][16];
|
||
|
|
||
|
static void
|
||
|
init_get1_tables(void)
|
||
|
{
|
||
|
static int once = 0;
|
||
|
unsigned char bits[1];
|
||
|
int i, k, x;
|
||
|
|
||
|
/* TODO: mutex lock here */
|
||
|
|
||
|
if (once)
|
||
|
return;
|
||
|
|
||
|
for (i = 0; i < 256; i++)
|
||
|
{
|
||
|
bits[0] = i;
|
||
|
for (k = 0; k < 8; k++)
|
||
|
{
|
||
|
x = get1(bits, k);
|
||
|
|
||
|
get1_tab_1[i][k] = x;
|
||
|
get1_tab_1p[i][k * 2] = x;
|
||
|
get1_tab_1p[i][k * 2 + 1] = 255;
|
||
|
|
||
|
get1_tab_255[i][k] = x * 255;
|
||
|
get1_tab_255p[i][k * 2] = x * 255;
|
||
|
get1_tab_255p[i][k * 2 + 1] = 255;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
once = 1;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
fz_unpack_tile(fz_pixmap *dst, unsigned char * restrict src, int n, int depth, int stride, int scale)
|
||
|
{
|
||
|
int pad, x, y, k;
|
||
|
int w = dst->w;
|
||
|
|
||
|
pad = 0;
|
||
|
if (dst->n > n)
|
||
|
pad = 255;
|
||
|
|
||
|
if (depth == 1)
|
||
|
init_get1_tables();
|
||
|
|
||
|
if (scale == 0)
|
||
|
{
|
||
|
switch (depth)
|
||
|
{
|
||
|
case 1: scale = 255; break;
|
||
|
case 2: scale = 85; break;
|
||
|
case 4: scale = 17; break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (y = 0; y < dst->h; y++)
|
||
|
{
|
||
|
unsigned char *sp = src + y * stride;
|
||
|
unsigned char *dp = dst->samples + y * (dst->w * dst->n);
|
||
|
|
||
|
/* Specialized loops */
|
||
|
|
||
|
if (n == 1 && depth == 1 && scale == 1 && !pad)
|
||
|
{
|
||
|
int w3 = w >> 3;
|
||
|
for (x = 0; x < w3; x++)
|
||
|
{
|
||
|
memcpy(dp, get1_tab_1[*sp++], 8);
|
||
|
dp += 8;
|
||
|
}
|
||
|
x = x << 3;
|
||
|
if (x < w)
|
||
|
memcpy(dp, get1_tab_1[*sp], w - x);
|
||
|
}
|
||
|
|
||
|
else if (n == 1 && depth == 1 && scale == 255 && !pad)
|
||
|
{
|
||
|
int w3 = w >> 3;
|
||
|
for (x = 0; x < w3; x++)
|
||
|
{
|
||
|
memcpy(dp, get1_tab_255[*sp++], 8);
|
||
|
dp += 8;
|
||
|
}
|
||
|
x = x << 3;
|
||
|
if (x < w)
|
||
|
memcpy(dp, get1_tab_255[*sp], w - x);
|
||
|
}
|
||
|
|
||
|
else if (n == 1 && depth == 1 && scale == 1 && pad)
|
||
|
{
|
||
|
int w3 = w >> 3;
|
||
|
for (x = 0; x < w3; x++)
|
||
|
{
|
||
|
memcpy(dp, get1_tab_1p[*sp++], 16);
|
||
|
dp += 16;
|
||
|
}
|
||
|
x = x << 3;
|
||
|
if (x < w)
|
||
|
memcpy(dp, get1_tab_1p[*sp], (w - x) << 1);
|
||
|
}
|
||
|
|
||
|
else if (n == 1 && depth == 1 && scale == 255 && pad)
|
||
|
{
|
||
|
int w3 = w >> 3;
|
||
|
for (x = 0; x < w3; x++)
|
||
|
{
|
||
|
memcpy(dp, get1_tab_255p[*sp++], 16);
|
||
|
dp += 16;
|
||
|
}
|
||
|
x = x << 3;
|
||
|
if (x < w)
|
||
|
memcpy(dp, get1_tab_255p[*sp], (w - x) << 1);
|
||
|
}
|
||
|
|
||
|
else if (depth == 8 && !pad)
|
||
|
{
|
||
|
int len = w * n;
|
||
|
while (len--)
|
||
|
*dp++ = *sp++;
|
||
|
}
|
||
|
|
||
|
else if (depth == 8 && pad)
|
||
|
{
|
||
|
for (x = 0; x < w; x++)
|
||
|
{
|
||
|
for (k = 0; k < n; k++)
|
||
|
*dp++ = *sp++;
|
||
|
*dp++ = 255;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else
|
||
|
{
|
||
|
int b = 0;
|
||
|
for (x = 0; x < w; x++)
|
||
|
{
|
||
|
for (k = 0; k < n; k++)
|
||
|
{
|
||
|
switch (depth)
|
||
|
{
|
||
|
case 1: *dp++ = get1(sp, b) * scale; break;
|
||
|
case 2: *dp++ = get2(sp, b) * scale; break;
|
||
|
case 4: *dp++ = get4(sp, b) * scale; break;
|
||
|
case 8: *dp++ = get8(sp, b); break;
|
||
|
case 16: *dp++ = get16(sp, b); break;
|
||
|
}
|
||
|
b++;
|
||
|
}
|
||
|
if (pad)
|
||
|
*dp++ = 255;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Apply decode array */
|
||
|
|
||
|
void
|
||
|
fz_decode_indexed_tile(fz_pixmap *pix, float *decode, int maxval)
|
||
|
{
|
||
|
int add[FZ_MAX_COLORS];
|
||
|
int mul[FZ_MAX_COLORS];
|
||
|
unsigned char *p = pix->samples;
|
||
|
int len = pix->w * pix->h;
|
||
|
int n = pix->n - 1;
|
||
|
int needed;
|
||
|
int k;
|
||
|
|
||
|
needed = 0;
|
||
|
for (k = 0; k < n; k++)
|
||
|
{
|
||
|
int min = decode[k * 2] * 256;
|
||
|
int max = decode[k * 2 + 1] * 256;
|
||
|
add[k] = min;
|
||
|
mul[k] = (max - min) / maxval;
|
||
|
needed |= min != 0 || max != maxval * 256;
|
||
|
}
|
||
|
|
||
|
if (!needed)
|
||
|
return;
|
||
|
|
||
|
while (len--)
|
||
|
{
|
||
|
for (k = 0; k < n; k++)
|
||
|
p[k] = (add[k] + (((p[k] << 8) * mul[k]) >> 8)) >> 8;
|
||
|
p += n + 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
fz_decode_tile(fz_pixmap *pix, float *decode)
|
||
|
{
|
||
|
int add[FZ_MAX_COLORS];
|
||
|
int mul[FZ_MAX_COLORS];
|
||
|
unsigned char *p = pix->samples;
|
||
|
int len = pix->w * pix->h;
|
||
|
int n = MAX(1, pix->n - 1);
|
||
|
int needed;
|
||
|
int k;
|
||
|
|
||
|
needed = 0;
|
||
|
for (k = 0; k < n; k++)
|
||
|
{
|
||
|
int min = decode[k * 2] * 255;
|
||
|
int max = decode[k * 2 + 1] * 255;
|
||
|
add[k] = min;
|
||
|
mul[k] = max - min;
|
||
|
needed |= min != 0 || max != 255;
|
||
|
}
|
||
|
|
||
|
if (!needed)
|
||
|
return;
|
||
|
|
||
|
while (len--)
|
||
|
{
|
||
|
for (k = 0; k < n; k++)
|
||
|
p[k] = add[k] + fz_mul255(p[k], mul[k]);
|
||
|
p += pix->n;
|
||
|
}
|
||
|
}
|