1707 lines
30 KiB
C
1707 lines
30 KiB
C
|
#include "mupdf/fitz.h"
|
||
|
|
||
|
#include <math.h>
|
||
|
|
||
|
/* Fast color transforms */
|
||
|
|
||
|
static void gray_to_gray(fz_context *ctx, fz_color_converter *cc, const float *gray, float *xyz)
|
||
|
{
|
||
|
xyz[0] = gray[0];
|
||
|
}
|
||
|
|
||
|
static void gray_to_rgb(fz_context *ctx, fz_color_converter *cc, const float *gray, float *rgb)
|
||
|
{
|
||
|
rgb[0] = gray[0];
|
||
|
rgb[1] = gray[0];
|
||
|
rgb[2] = gray[0];
|
||
|
}
|
||
|
|
||
|
static void rgb_to_gray(fz_context *ctx, fz_color_converter *cc, const float *rgb, float *gray)
|
||
|
{
|
||
|
gray[0] = rgb[0] * 0.3f + rgb[1] * 0.59f + rgb[2] * 0.11f;
|
||
|
}
|
||
|
|
||
|
static void bgr_to_gray(fz_context *ctx, fz_color_converter *cc, const float *bgr, float *gray)
|
||
|
{
|
||
|
gray[0] = bgr[0] * 0.11f + bgr[1] * 0.59f + bgr[2] * 0.3f;
|
||
|
}
|
||
|
|
||
|
static void rgb_to_rgb(fz_context *ctx, fz_color_converter *cc, const float *rgb, float *xyz)
|
||
|
{
|
||
|
xyz[0] = rgb[0];
|
||
|
xyz[1] = rgb[1];
|
||
|
xyz[2] = rgb[2];
|
||
|
}
|
||
|
|
||
|
static void rgb_to_bgr(fz_context *ctx, fz_color_converter *cc, const float *rgb, float *bgr)
|
||
|
{
|
||
|
bgr[0] = rgb[2];
|
||
|
bgr[1] = rgb[1];
|
||
|
bgr[2] = rgb[0];
|
||
|
}
|
||
|
|
||
|
static void cmyk_to_cmyk(fz_context *ctx, fz_color_converter *cc, const float *cmyk, float *xyz)
|
||
|
{
|
||
|
xyz[0] = cmyk[0];
|
||
|
xyz[1] = cmyk[1];
|
||
|
xyz[2] = cmyk[2];
|
||
|
xyz[3] = cmyk[3];
|
||
|
}
|
||
|
|
||
|
static void gray_to_cmyk(fz_context *ctx, fz_color_converter *cc, const float *gray, float *cmyk)
|
||
|
{
|
||
|
cmyk[0] = 0;
|
||
|
cmyk[1] = 0;
|
||
|
cmyk[2] = 0;
|
||
|
cmyk[3] = 1 - gray[0];
|
||
|
}
|
||
|
|
||
|
static void cmyk_to_gray(fz_context *ctx, fz_color_converter *cc, const float *cmyk, float *gray)
|
||
|
{
|
||
|
float c = cmyk[0] * 0.3f;
|
||
|
float m = cmyk[1] * 0.59f;
|
||
|
float y = cmyk[2] * 0.11f;
|
||
|
gray[0] = 1 - fz_min(c + m + y + cmyk[3], 1);
|
||
|
}
|
||
|
|
||
|
static void rgb_to_cmyk(fz_context *ctx, fz_color_converter *cc, const float *rgb, float *cmyk)
|
||
|
{
|
||
|
float c, m, y, k;
|
||
|
c = 1 - rgb[0];
|
||
|
m = 1 - rgb[1];
|
||
|
y = 1 - rgb[2];
|
||
|
k = fz_min(c, fz_min(m, y));
|
||
|
cmyk[0] = c - k;
|
||
|
cmyk[1] = m - k;
|
||
|
cmyk[2] = y - k;
|
||
|
cmyk[3] = k;
|
||
|
}
|
||
|
|
||
|
static void bgr_to_cmyk(fz_context *ctx, fz_color_converter *cc, const float *bgr, float *cmyk)
|
||
|
{
|
||
|
float c, m, y, k;
|
||
|
c = 1 - bgr[2];
|
||
|
m = 1 - bgr[1];
|
||
|
y = 1 - bgr[0];
|
||
|
k = fz_min(c, fz_min(m, y));
|
||
|
cmyk[0] = c - k;
|
||
|
cmyk[1] = m - k;
|
||
|
cmyk[2] = y - k;
|
||
|
cmyk[3] = k;
|
||
|
}
|
||
|
|
||
|
static void cmyk_to_rgb(fz_context *ctx, fz_color_converter *cc, const float *cmyk, float *rgb)
|
||
|
{
|
||
|
rgb[0] = 1 - fz_min(1, cmyk[0] + cmyk[3]);
|
||
|
rgb[1] = 1 - fz_min(1, cmyk[1] + cmyk[3]);
|
||
|
rgb[2] = 1 - fz_min(1, cmyk[2] + cmyk[3]);
|
||
|
}
|
||
|
|
||
|
static void cmyk_to_bgr(fz_context *ctx, fz_color_converter *cc, const float *cmyk, float *bgr)
|
||
|
{
|
||
|
bgr[0] = 1 - fz_min(cmyk[2] + cmyk[3], 1);
|
||
|
bgr[1] = 1 - fz_min(cmyk[1] + cmyk[3], 1);
|
||
|
bgr[2] = 1 - fz_min(cmyk[0] + cmyk[3], 1);
|
||
|
}
|
||
|
|
||
|
static inline float fung(float x)
|
||
|
{
|
||
|
if (x >= 6.0f / 29.0f)
|
||
|
return x * x * x;
|
||
|
return (108.0f / 841.0f) * (x - (4.0f / 29.0f));
|
||
|
}
|
||
|
|
||
|
static void lab_to_rgb(fz_context *ctx, fz_color_converter *cc, const float *lab, float *rgb)
|
||
|
{
|
||
|
/* input is in range (0..100, -128..127, -128..127) not (0..1, 0..1, 0..1) */
|
||
|
float lstar, astar, bstar, l, m, n, x, y, z, r, g, b;
|
||
|
lstar = lab[0];
|
||
|
astar = lab[1];
|
||
|
bstar = lab[2];
|
||
|
m = (lstar + 16) / 116;
|
||
|
l = m + astar / 500;
|
||
|
n = m - bstar / 200;
|
||
|
x = fung(l);
|
||
|
y = fung(m);
|
||
|
z = fung(n);
|
||
|
r = (3.240449f * x + -1.537136f * y + -0.498531f * z) * 0.830026f;
|
||
|
g = (-0.969265f * x + 1.876011f * y + 0.041556f * z) * 1.05452f;
|
||
|
b = (0.055643f * x + -0.204026f * y + 1.057229f * z) * 1.1003f;
|
||
|
rgb[0] = sqrtf(fz_clamp(r, 0, 1));
|
||
|
rgb[1] = sqrtf(fz_clamp(g, 0, 1));
|
||
|
rgb[2] = sqrtf(fz_clamp(b, 0, 1));
|
||
|
}
|
||
|
|
||
|
static void lab_to_gray(fz_context *ctx, fz_color_converter *cc, const float *lab, float *gray)
|
||
|
{
|
||
|
gray[0] = lab[0] / 100;
|
||
|
}
|
||
|
|
||
|
static void lab_to_bgr(fz_context *ctx, fz_color_converter *cc, const float *lab, float *bgr)
|
||
|
{
|
||
|
float rgb[3];
|
||
|
lab_to_rgb(ctx, cc, lab, rgb);
|
||
|
rgb_to_bgr(ctx, cc, rgb, bgr);
|
||
|
}
|
||
|
|
||
|
static void lab_to_cmyk(fz_context *ctx, fz_color_converter *cc, const float *lab, float *cmyk)
|
||
|
{
|
||
|
float rgb[3];
|
||
|
lab_to_rgb(ctx, cc, lab, rgb);
|
||
|
rgb_to_cmyk(ctx, cc, rgb, cmyk);
|
||
|
}
|
||
|
|
||
|
fz_color_convert_fn *
|
||
|
fz_lookup_fast_color_converter(fz_context *ctx, fz_colorspace *ss, fz_colorspace *ds)
|
||
|
{
|
||
|
int stype = ss->type;
|
||
|
int dtype = ds->type;
|
||
|
|
||
|
if (stype == FZ_COLORSPACE_GRAY)
|
||
|
{
|
||
|
if (dtype == FZ_COLORSPACE_GRAY) return gray_to_gray;
|
||
|
if (dtype == FZ_COLORSPACE_RGB) return gray_to_rgb;
|
||
|
if (dtype == FZ_COLORSPACE_BGR) return gray_to_rgb;
|
||
|
if (dtype == FZ_COLORSPACE_CMYK) return gray_to_cmyk;
|
||
|
}
|
||
|
|
||
|
else if (stype == FZ_COLORSPACE_RGB)
|
||
|
{
|
||
|
if (dtype == FZ_COLORSPACE_GRAY) return rgb_to_gray;
|
||
|
if (dtype == FZ_COLORSPACE_RGB) return rgb_to_rgb;
|
||
|
if (dtype == FZ_COLORSPACE_BGR) return rgb_to_bgr;
|
||
|
if (dtype == FZ_COLORSPACE_CMYK) return rgb_to_cmyk;
|
||
|
}
|
||
|
|
||
|
else if (stype == FZ_COLORSPACE_BGR)
|
||
|
{
|
||
|
if (dtype == FZ_COLORSPACE_GRAY) return bgr_to_gray;
|
||
|
if (dtype == FZ_COLORSPACE_RGB) return rgb_to_bgr;
|
||
|
if (dtype == FZ_COLORSPACE_BGR) return rgb_to_rgb;
|
||
|
if (dtype == FZ_COLORSPACE_CMYK) return bgr_to_cmyk;
|
||
|
}
|
||
|
|
||
|
else if (stype == FZ_COLORSPACE_CMYK)
|
||
|
{
|
||
|
if (dtype == FZ_COLORSPACE_GRAY) return cmyk_to_gray;
|
||
|
if (dtype == FZ_COLORSPACE_RGB) return cmyk_to_rgb;
|
||
|
if (dtype == FZ_COLORSPACE_BGR) return cmyk_to_bgr;
|
||
|
if (dtype == FZ_COLORSPACE_CMYK) return cmyk_to_cmyk;
|
||
|
}
|
||
|
|
||
|
else if (stype == FZ_COLORSPACE_LAB)
|
||
|
{
|
||
|
if (dtype == FZ_COLORSPACE_GRAY) return lab_to_gray;
|
||
|
if (dtype == FZ_COLORSPACE_RGB) return lab_to_rgb;
|
||
|
if (dtype == FZ_COLORSPACE_BGR) return lab_to_bgr;
|
||
|
if (dtype == FZ_COLORSPACE_CMYK) return lab_to_cmyk;
|
||
|
}
|
||
|
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "cannot find color converter");
|
||
|
}
|
||
|
|
||
|
/* Fast pixmap color conversions */
|
||
|
|
||
|
static void fast_gray_to_rgb(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst, int copy_spots)
|
||
|
{
|
||
|
unsigned char *s = src->samples;
|
||
|
unsigned char *d = dst->samples;
|
||
|
size_t w = src->w;
|
||
|
int h = src->h;
|
||
|
int sn = src->n;
|
||
|
int ss = src->s;
|
||
|
int sa = src->alpha;
|
||
|
int dn = dst->n;
|
||
|
int ds = dst->s;
|
||
|
int da = dst->alpha;
|
||
|
ptrdiff_t d_line_inc = dst->stride - w * dn;
|
||
|
ptrdiff_t s_line_inc = src->stride - w * sn;
|
||
|
|
||
|
/* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
|
||
|
if (copy_spots && ss != ds)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "incompatible number of spots when converting pixmap");
|
||
|
if (!da && sa)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "cannot drop alpha when converting pixmap");
|
||
|
|
||
|
if ((int)w < 0 || h < 0)
|
||
|
return;
|
||
|
|
||
|
if (d_line_inc == 0 && s_line_inc == 0)
|
||
|
{
|
||
|
w *= h;
|
||
|
h = 1;
|
||
|
}
|
||
|
|
||
|
if (ss == 0 && ds == 0)
|
||
|
{
|
||
|
/* Common, no spots case */
|
||
|
if (da)
|
||
|
{
|
||
|
if (sa)
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[0];
|
||
|
d[1] = s[0];
|
||
|
d[2] = s[0];
|
||
|
d[3] = s[1];
|
||
|
s += 2;
|
||
|
d += 4;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[0];
|
||
|
d[1] = s[0];
|
||
|
d[2] = s[0];
|
||
|
d[3] = 255;
|
||
|
s++;
|
||
|
d += 4;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[0];
|
||
|
d[1] = s[0];
|
||
|
d[2] = s[0];
|
||
|
s++;
|
||
|
d += 3;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (copy_spots)
|
||
|
{
|
||
|
/* Slower, spots capable version */
|
||
|
int i;
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[0];
|
||
|
d[1] = s[0];
|
||
|
d[2] = s[0];
|
||
|
s += 1;
|
||
|
d += 3;
|
||
|
for (i=ss; i > 0; i--)
|
||
|
*d++ = *s++;
|
||
|
if (da)
|
||
|
*d++ = sa ? *s++ : 255;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[0];
|
||
|
d[1] = s[0];
|
||
|
d[2] = s[0];
|
||
|
s += sn;
|
||
|
d += dn;
|
||
|
if (da)
|
||
|
d[-1] = sa ? s[-1] : 255;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void fast_gray_to_cmyk(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst, int copy_spots)
|
||
|
{
|
||
|
unsigned char *s = src->samples;
|
||
|
unsigned char *d = dst->samples;
|
||
|
size_t w = src->w;
|
||
|
int h = src->h;
|
||
|
int sn = src->n;
|
||
|
int ss = src->s;
|
||
|
int sa = src->alpha;
|
||
|
int dn = dst->n;
|
||
|
int ds = dst->s;
|
||
|
int da = dst->alpha;
|
||
|
ptrdiff_t d_line_inc = dst->stride - w * dn;
|
||
|
ptrdiff_t s_line_inc = src->stride - w * sn;
|
||
|
int k, g;
|
||
|
int a = 255;
|
||
|
int i;
|
||
|
|
||
|
if (copy_spots && ss != ds)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "incompatible number of spots when converting pixmap");
|
||
|
|
||
|
if ((int)w < 0 || h < 0)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "integer overflow");
|
||
|
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
g = s[0];
|
||
|
|
||
|
if (sa)
|
||
|
{
|
||
|
a = s[1+ss];
|
||
|
g = fz_div255(g, a);
|
||
|
}
|
||
|
|
||
|
k = 255 - g;
|
||
|
|
||
|
if (da)
|
||
|
{
|
||
|
*d++ = 0;
|
||
|
*d++ = 0;
|
||
|
*d++ = 0;
|
||
|
*d++ = fz_mul255(k, a);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*d++ = 0;
|
||
|
*d++ = 0;
|
||
|
*d++ = 0;
|
||
|
*d++ = k;
|
||
|
}
|
||
|
|
||
|
if (copy_spots)
|
||
|
{
|
||
|
s += 1;
|
||
|
for (i=ss; i > 0; --i)
|
||
|
*d++ = *s++;
|
||
|
s += sa;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s += 1 + ss + sa;
|
||
|
d += ds;
|
||
|
}
|
||
|
|
||
|
if (da)
|
||
|
{
|
||
|
*d++ = a;
|
||
|
}
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void fast_rgb_to_gray(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst, int copy_spots)
|
||
|
{
|
||
|
unsigned char *s = src->samples;
|
||
|
unsigned char *d = dst->samples;
|
||
|
size_t w = src->w;
|
||
|
int h = src->h;
|
||
|
int sn = src->n;
|
||
|
int ss = src->s;
|
||
|
int sa = src->alpha;
|
||
|
int dn = dst->n;
|
||
|
int ds = dst->s;
|
||
|
int da = dst->alpha;
|
||
|
ptrdiff_t d_line_inc = dst->stride - w * dn;
|
||
|
ptrdiff_t s_line_inc = src->stride - w * sn;
|
||
|
|
||
|
/* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
|
||
|
if (copy_spots && ss != ds)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "incompatible number of spots when converting pixmap");
|
||
|
if (!da && sa)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "cannot drop alpha when converting pixmap");
|
||
|
|
||
|
if ((int)w < 0 || h < 0)
|
||
|
return;
|
||
|
|
||
|
if (d_line_inc == 0 && s_line_inc == 0)
|
||
|
{
|
||
|
w *= h;
|
||
|
h = 1;
|
||
|
}
|
||
|
|
||
|
if (ss == 0 && ds == 0)
|
||
|
{
|
||
|
/* Common, no spots case */
|
||
|
if (da)
|
||
|
{
|
||
|
if (sa)
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
|
||
|
d[1] = s[3];
|
||
|
s += 4;
|
||
|
d += 2;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
|
||
|
d[1] = 255;
|
||
|
s += 3;
|
||
|
d += 2;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
|
||
|
s += 3;
|
||
|
d++;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (copy_spots)
|
||
|
{
|
||
|
/* Slower, spots capable version */
|
||
|
int i;
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
|
||
|
s += 3;
|
||
|
d++;
|
||
|
for (i=ss; i > 0; i--)
|
||
|
*d++ = *s++;
|
||
|
if (da)
|
||
|
*d++ = sa ? *s++ : 255;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
|
||
|
s += sn;
|
||
|
d += dn;
|
||
|
if (da)
|
||
|
d[-1] = sa ? s[-1] : 255;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void fast_bgr_to_gray(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst, int copy_spots)
|
||
|
{
|
||
|
unsigned char *s = src->samples;
|
||
|
unsigned char *d = dst->samples;
|
||
|
size_t w = src->w;
|
||
|
int h = src->h;
|
||
|
int sn = src->n;
|
||
|
int ss = src->s;
|
||
|
int sa = src->alpha;
|
||
|
int dn = dst->n;
|
||
|
int ds = dst->s;
|
||
|
int da = dst->alpha;
|
||
|
ptrdiff_t d_line_inc = dst->stride - w * dn;
|
||
|
ptrdiff_t s_line_inc = src->stride - w * sn;
|
||
|
|
||
|
/* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
|
||
|
if (copy_spots && ss != ds)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "incompatible number of spots when converting pixmap");
|
||
|
if (!da && sa)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "cannot drop alpha when converting pixmap");
|
||
|
|
||
|
if ((int)w < 0 || h < 0)
|
||
|
return;
|
||
|
|
||
|
if (d_line_inc == 0 && s_line_inc == 0)
|
||
|
{
|
||
|
w *= h;
|
||
|
h = 1;
|
||
|
}
|
||
|
|
||
|
if (ss == 0 && ds == 0)
|
||
|
{
|
||
|
/* Common, no spots case */
|
||
|
if (da)
|
||
|
{
|
||
|
if (sa)
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
|
||
|
d[1] = s[3];
|
||
|
s += 4;
|
||
|
d += 2;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
|
||
|
d[1] = 255;
|
||
|
s += 3;
|
||
|
d += 2;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int si = 3 + src->alpha;
|
||
|
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
|
||
|
s += si;
|
||
|
d++;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (copy_spots)
|
||
|
{
|
||
|
/* Slower, spots capable version */
|
||
|
while (h--)
|
||
|
{
|
||
|
int i;
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
|
||
|
s += 3;
|
||
|
d++;
|
||
|
for (i=ss; i > 0; i--)
|
||
|
*d++ = *s++;
|
||
|
if (da)
|
||
|
*d++ = sa ? *s++ : 255;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* Slower, spots capable version */
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
|
||
|
s += sn;
|
||
|
d += dn;
|
||
|
if (da)
|
||
|
d[-1] = sa ? s[-1] : 255;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void fast_rgb_to_cmyk(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst, int copy_spots)
|
||
|
{
|
||
|
unsigned char *s = src->samples;
|
||
|
unsigned char *d = dst->samples;
|
||
|
size_t w = src->w;
|
||
|
int h = src->h;
|
||
|
int sn = src->n;
|
||
|
int ss = src->s;
|
||
|
int sa = src->alpha;
|
||
|
int dn = dst->n;
|
||
|
int ds = dst->s;
|
||
|
int da = dst->alpha;
|
||
|
ptrdiff_t d_line_inc = dst->stride - w * dn;
|
||
|
ptrdiff_t s_line_inc = src->stride - w * sn;
|
||
|
int c, m, y, k, r, g, b;
|
||
|
int a = 255;
|
||
|
int i;
|
||
|
|
||
|
if (copy_spots && ss != ds)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "incompatible number of spots when converting pixmap");
|
||
|
|
||
|
if ((int)w < 0 || h < 0)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "integer overflow");
|
||
|
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
r = s[0];
|
||
|
g = s[1];
|
||
|
b = s[2];
|
||
|
|
||
|
if (sa)
|
||
|
{
|
||
|
a = s[3+ss];
|
||
|
r = fz_div255(r, a);
|
||
|
g = fz_div255(g, a);
|
||
|
b = fz_div255(b, a);
|
||
|
}
|
||
|
|
||
|
c = 255 - r;
|
||
|
m = 255 - g;
|
||
|
y = 255 - b;
|
||
|
k = fz_mini(c, fz_mini(m, y));
|
||
|
c = c - k;
|
||
|
m = m - k;
|
||
|
y = y - k;
|
||
|
|
||
|
if (da)
|
||
|
{
|
||
|
*d++ = fz_mul255(c, a);
|
||
|
*d++ = fz_mul255(m, a);
|
||
|
*d++ = fz_mul255(y, a);
|
||
|
*d++ = fz_mul255(k, a);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*d++ = c;
|
||
|
*d++ = m;
|
||
|
*d++ = y;
|
||
|
*d++ = k;
|
||
|
}
|
||
|
|
||
|
if (copy_spots)
|
||
|
{
|
||
|
s += 3;
|
||
|
for (i=ss; i > 0; --i)
|
||
|
*d++ = *s++;
|
||
|
s += sa;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s += 3 + ss + sa;
|
||
|
d += ds;
|
||
|
}
|
||
|
|
||
|
if (da)
|
||
|
{
|
||
|
*d++ = a;
|
||
|
}
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void fast_bgr_to_cmyk(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst, int copy_spots)
|
||
|
{
|
||
|
unsigned char *s = src->samples;
|
||
|
unsigned char *d = dst->samples;
|
||
|
size_t w = src->w;
|
||
|
int h = src->h;
|
||
|
int sn = src->n;
|
||
|
int ss = src->s;
|
||
|
int sa = src->alpha;
|
||
|
int dn = dst->n;
|
||
|
int ds = dst->s;
|
||
|
int da = dst->alpha;
|
||
|
ptrdiff_t d_line_inc = dst->stride - w * dn;
|
||
|
ptrdiff_t s_line_inc = src->stride - w * sn;
|
||
|
int c, m, y, k, r, g, b;
|
||
|
int a = 255;
|
||
|
int i;
|
||
|
|
||
|
if (copy_spots && ss != ds)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "incompatible number of spots when converting pixmap");
|
||
|
|
||
|
if ((int)w < 0 || h < 0)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "integer overflow");
|
||
|
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
b = s[0];
|
||
|
g = s[1];
|
||
|
r = s[2];
|
||
|
|
||
|
if (sa)
|
||
|
{
|
||
|
a = s[3+ss];
|
||
|
r = fz_div255(r, a);
|
||
|
g = fz_div255(g, a);
|
||
|
b = fz_div255(b, a);
|
||
|
}
|
||
|
|
||
|
c = 255 - r;
|
||
|
m = 255 - g;
|
||
|
y = 255 - b;
|
||
|
k = fz_mini(c, fz_mini(m, y));
|
||
|
c = c - k;
|
||
|
m = m - k;
|
||
|
y = y - k;
|
||
|
|
||
|
if (da)
|
||
|
{
|
||
|
*d++ = fz_mul255(c, a);
|
||
|
*d++ = fz_mul255(m, a);
|
||
|
*d++ = fz_mul255(y, a);
|
||
|
*d++ = fz_mul255(k, a);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*d++ = c;
|
||
|
*d++ = m;
|
||
|
*d++ = y;
|
||
|
*d++ = k;
|
||
|
}
|
||
|
|
||
|
if (copy_spots)
|
||
|
{
|
||
|
s += 3;
|
||
|
for (i=ss; i > 0; --i)
|
||
|
*d++ = *s++;
|
||
|
s += sa;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s += 3 + ss + sa;
|
||
|
d += ds;
|
||
|
}
|
||
|
|
||
|
if (da)
|
||
|
{
|
||
|
*d++ = a;
|
||
|
}
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void fast_cmyk_to_gray(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst, int copy_spots)
|
||
|
{
|
||
|
unsigned char *s = src->samples;
|
||
|
unsigned char *d = dst->samples;
|
||
|
size_t w = src->w;
|
||
|
int h = src->h;
|
||
|
int sn = src->n;
|
||
|
int ss = src->s;
|
||
|
int sa = src->alpha;
|
||
|
int dn = dst->n;
|
||
|
int ds = dst->s;
|
||
|
int da = dst->alpha;
|
||
|
ptrdiff_t d_line_inc = dst->stride - w * dn;
|
||
|
ptrdiff_t s_line_inc = src->stride - w * sn;
|
||
|
int c, m, y, k, g;
|
||
|
int a = 255;
|
||
|
int i;
|
||
|
|
||
|
if (copy_spots && ss != ds)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "incompatible number of spots when converting pixmap");
|
||
|
|
||
|
if ((int)w < 0 || h < 0)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "integer overflow");
|
||
|
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
c = s[0];
|
||
|
m = s[1];
|
||
|
y = s[2];
|
||
|
k = s[3];
|
||
|
|
||
|
if (sa)
|
||
|
{
|
||
|
a = s[4+ss];
|
||
|
c = fz_div255(c, a);
|
||
|
m = fz_div255(m, a);
|
||
|
y = fz_div255(y, a);
|
||
|
k = fz_div255(k, a);
|
||
|
}
|
||
|
|
||
|
g = 255 - fz_mini(c + m + y + k, 255);
|
||
|
|
||
|
if (da)
|
||
|
{
|
||
|
*d++ = fz_mul255(g, a);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*d++ = g;
|
||
|
}
|
||
|
|
||
|
if (copy_spots)
|
||
|
{
|
||
|
s += 4;
|
||
|
for (i=ss; i > 0; --i)
|
||
|
*d++ = *s++;
|
||
|
s += sa;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s += 4 + ss + sa;
|
||
|
d += ds;
|
||
|
}
|
||
|
|
||
|
if (da)
|
||
|
{
|
||
|
*d++ = a;
|
||
|
}
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst, int copy_spots)
|
||
|
{
|
||
|
unsigned char *s = src->samples;
|
||
|
unsigned char *d = dst->samples;
|
||
|
size_t w = src->w;
|
||
|
int h = src->h;
|
||
|
int sn = src->n;
|
||
|
int ss = src->s;
|
||
|
int sa = src->alpha;
|
||
|
int dn = dst->n;
|
||
|
int ds = dst->s;
|
||
|
int da = dst->alpha;
|
||
|
ptrdiff_t d_line_inc = dst->stride - w * dn;
|
||
|
ptrdiff_t s_line_inc = src->stride - w * sn;
|
||
|
int c, m, y, k, r, g, b;
|
||
|
int a = 255;
|
||
|
int i;
|
||
|
|
||
|
if (copy_spots && ss != ds)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "incompatible number of spots when converting pixmap");
|
||
|
|
||
|
if ((int)w < 0 || h < 0)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "integer overflow");
|
||
|
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
c = s[0];
|
||
|
m = s[1];
|
||
|
y = s[2];
|
||
|
k = s[3];
|
||
|
|
||
|
if (sa)
|
||
|
{
|
||
|
a = s[4+ss];
|
||
|
c = fz_div255(c, a);
|
||
|
m = fz_div255(m, a);
|
||
|
y = fz_div255(y, a);
|
||
|
k = fz_div255(k, a);
|
||
|
}
|
||
|
|
||
|
r = 255 - fz_mini(c + k, 255);
|
||
|
g = 255 - fz_mini(m + k, 255);
|
||
|
b = 255 - fz_mini(y + k, 255);
|
||
|
|
||
|
if (da)
|
||
|
{
|
||
|
*d++ = fz_mul255(r, a);
|
||
|
*d++ = fz_mul255(g, a);
|
||
|
*d++ = fz_mul255(b, a);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*d++ = r;
|
||
|
*d++ = g;
|
||
|
*d++ = b;
|
||
|
}
|
||
|
|
||
|
if (copy_spots)
|
||
|
{
|
||
|
s += 4;
|
||
|
for (i=ss; i > 0; --i)
|
||
|
*d++ = *s++;
|
||
|
s += sa;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s += 4 + ss + sa;
|
||
|
d += ds;
|
||
|
}
|
||
|
|
||
|
if (da)
|
||
|
{
|
||
|
*d++ = a;
|
||
|
}
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst, int copy_spots)
|
||
|
{
|
||
|
unsigned char *s = src->samples;
|
||
|
unsigned char *d = dst->samples;
|
||
|
size_t w = src->w;
|
||
|
int h = src->h;
|
||
|
int sn = src->n;
|
||
|
int ss = src->s;
|
||
|
int sa = src->alpha;
|
||
|
int dn = dst->n;
|
||
|
int ds = dst->s;
|
||
|
int da = dst->alpha;
|
||
|
ptrdiff_t d_line_inc = dst->stride - w * dn;
|
||
|
ptrdiff_t s_line_inc = src->stride - w * sn;
|
||
|
int c, m, y, k, r, g, b;
|
||
|
int a = 255;
|
||
|
int i;
|
||
|
|
||
|
if (copy_spots && ss != ds)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "incompatible number of spots when converting pixmap");
|
||
|
|
||
|
if ((int)w < 0 || h < 0)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "integer overflow");
|
||
|
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
c = s[0];
|
||
|
m = s[1];
|
||
|
y = s[2];
|
||
|
k = s[3];
|
||
|
|
||
|
if (sa)
|
||
|
{
|
||
|
a = s[4+ss];
|
||
|
c = fz_div255(c, a);
|
||
|
m = fz_div255(m, a);
|
||
|
y = fz_div255(y, a);
|
||
|
k = fz_div255(k, a);
|
||
|
}
|
||
|
|
||
|
r = 255 - fz_mini(c + k, 255);
|
||
|
g = 255 - fz_mini(m + k, 255);
|
||
|
b = 255 - fz_mini(y + k, 255);
|
||
|
|
||
|
if (da)
|
||
|
{
|
||
|
*d++ = fz_mul255(b, a);
|
||
|
*d++ = fz_mul255(g, a);
|
||
|
*d++ = fz_mul255(r, a);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*d++ = b;
|
||
|
*d++ = g;
|
||
|
*d++ = r;
|
||
|
}
|
||
|
|
||
|
if (copy_spots)
|
||
|
{
|
||
|
s += 4;
|
||
|
for (i=ss; i > 0; --i)
|
||
|
*d++ = *s++;
|
||
|
s += sa;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s += 4 + ss + sa;
|
||
|
d += ds;
|
||
|
}
|
||
|
|
||
|
if (da)
|
||
|
{
|
||
|
*d++ = a;
|
||
|
}
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void fast_rgb_to_bgr(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst, int copy_spots)
|
||
|
{
|
||
|
unsigned char *s = src->samples;
|
||
|
unsigned char *d = dst->samples;
|
||
|
size_t w = src->w;
|
||
|
int h = src->h;
|
||
|
int sn = src->n;
|
||
|
int ss = src->s;
|
||
|
int sa = src->alpha;
|
||
|
int dn = dst->n;
|
||
|
int ds = dst->s;
|
||
|
int da = dst->alpha;
|
||
|
ptrdiff_t d_line_inc = dst->stride - w * dn;
|
||
|
ptrdiff_t s_line_inc = src->stride - w * sn;
|
||
|
|
||
|
/* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
|
||
|
if (copy_spots && ss != ds)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "incompatible number of spots when converting pixmap");
|
||
|
if (!da && sa)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "cannot drop alpha when converting pixmap");
|
||
|
|
||
|
if ((int)w < 0 || h < 0)
|
||
|
return;
|
||
|
|
||
|
if (d_line_inc == 0 && s_line_inc == 0)
|
||
|
{
|
||
|
w *= h;
|
||
|
h = 1;
|
||
|
}
|
||
|
|
||
|
if (ss == 0 && ds == 0)
|
||
|
{
|
||
|
/* Common, no spots case */
|
||
|
if (da)
|
||
|
{
|
||
|
if (sa)
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[2];
|
||
|
d[1] = s[1];
|
||
|
d[2] = s[0];
|
||
|
d[3] = s[3];
|
||
|
s += 4;
|
||
|
d += 4;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[2];
|
||
|
d[1] = s[1];
|
||
|
d[2] = s[0];
|
||
|
d[3] = 255;
|
||
|
s += 3;
|
||
|
d += 4;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[2];
|
||
|
d[1] = s[1];
|
||
|
d[2] = s[0];
|
||
|
s += 3;
|
||
|
d += 3;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (copy_spots)
|
||
|
{
|
||
|
/* Slower, spots capable version */
|
||
|
while (h--)
|
||
|
{
|
||
|
int i;
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[2];
|
||
|
d[1] = s[1];
|
||
|
d[2] = s[0];
|
||
|
s += 3;
|
||
|
d += 3;
|
||
|
for (i=ss; i > 0; i--)
|
||
|
*d++ = *s++;
|
||
|
if (da)
|
||
|
*d++ = sa ? *s++ : 255;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[2];
|
||
|
d[1] = s[1];
|
||
|
d[2] = s[0];
|
||
|
s += sn;
|
||
|
d += dn;
|
||
|
if (da)
|
||
|
d[-1] = sa ? s[-1] : 255;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void fast_gray_to_gray(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst, int copy_spots)
|
||
|
{
|
||
|
unsigned char *s = src->samples;
|
||
|
unsigned char *d = dst->samples;
|
||
|
size_t w = src->w;
|
||
|
int h = src->h;
|
||
|
int sn = src->n;
|
||
|
int ss = src->s;
|
||
|
int sa = src->alpha;
|
||
|
int dn = dst->n;
|
||
|
int ds = dst->s;
|
||
|
int da = dst->alpha;
|
||
|
ptrdiff_t d_line_inc = dst->stride - w * dn;
|
||
|
ptrdiff_t s_line_inc = src->stride - w * sn;
|
||
|
|
||
|
/* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
|
||
|
if (copy_spots && ss != ds)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "incompatible number of spots when converting pixmap");
|
||
|
if (!da && sa)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "cannot drop alpha when converting pixmap");
|
||
|
|
||
|
if ((int)w < 0 || h < 0)
|
||
|
return;
|
||
|
|
||
|
if (d_line_inc == 0 && s_line_inc == 0)
|
||
|
{
|
||
|
w *= h;
|
||
|
h = 1;
|
||
|
}
|
||
|
|
||
|
if (ss == 0 && ds == 0)
|
||
|
{
|
||
|
/* Common, no spots case */
|
||
|
if (da)
|
||
|
{
|
||
|
if (sa)
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[0];
|
||
|
d[1] = s[1];
|
||
|
s += 2;
|
||
|
d += 2;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[0];
|
||
|
d[1] = 255;
|
||
|
s += 1;
|
||
|
d += 2;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[0];
|
||
|
s += 1;
|
||
|
d += 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (copy_spots)
|
||
|
{
|
||
|
/* Slower, spots capable version */
|
||
|
while (h--)
|
||
|
{
|
||
|
int i;
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[0];
|
||
|
s += 1;
|
||
|
d += 1;
|
||
|
for (i=ss; i > 0; i--)
|
||
|
*d++ = *s++;
|
||
|
if (da)
|
||
|
*d++ = sa ? *s++ : 255;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[0];
|
||
|
s += sn;
|
||
|
d += dn;
|
||
|
if (da)
|
||
|
d[-1] = sa ? s[-1] : 255;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void fast_rgb_to_rgb(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst, int copy_spots)
|
||
|
{
|
||
|
unsigned char *s = src->samples;
|
||
|
unsigned char *d = dst->samples;
|
||
|
size_t w = src->w;
|
||
|
int h = src->h;
|
||
|
int sn = src->n;
|
||
|
int ss = src->s;
|
||
|
int sa = src->alpha;
|
||
|
int dn = dst->n;
|
||
|
int ds = dst->s;
|
||
|
int da = dst->alpha;
|
||
|
ptrdiff_t d_line_inc = dst->stride - w * dn;
|
||
|
ptrdiff_t s_line_inc = src->stride - w * sn;
|
||
|
|
||
|
/* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
|
||
|
if (copy_spots && ss != ds)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "incompatible number of spots when converting pixmap");
|
||
|
if (!da && sa)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "cannot drop alpha when converting pixmap");
|
||
|
|
||
|
if ((int)w < 0 || h < 0)
|
||
|
return;
|
||
|
|
||
|
if (d_line_inc == 0 && s_line_inc == 0)
|
||
|
{
|
||
|
w *= h;
|
||
|
h = 1;
|
||
|
}
|
||
|
|
||
|
if (ss == 0 && ds == 0)
|
||
|
{
|
||
|
/* Common, no spots case */
|
||
|
if (da)
|
||
|
{
|
||
|
if (sa)
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[0];
|
||
|
d[1] = s[1];
|
||
|
d[2] = s[2];
|
||
|
d[3] = s[3];
|
||
|
s += 4;
|
||
|
d += 4;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[0];
|
||
|
d[1] = s[1];
|
||
|
d[2] = s[2];
|
||
|
d[3] = 255;
|
||
|
s += 3;
|
||
|
d += 4;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[0];
|
||
|
d[1] = s[1];
|
||
|
d[2] = s[2];
|
||
|
s += 3;
|
||
|
d += 3;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (copy_spots)
|
||
|
{
|
||
|
/* Slower, spots capable version */
|
||
|
while (h--)
|
||
|
{
|
||
|
int i;
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[0];
|
||
|
d[1] = s[1];
|
||
|
d[2] = s[2];
|
||
|
s += 3;
|
||
|
d += 3;
|
||
|
for (i=ss; i > 0; i--)
|
||
|
*d++ = *s++;
|
||
|
if (da)
|
||
|
*d++ = sa ? *s++ : 255;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[0];
|
||
|
d[1] = s[1];
|
||
|
d[2] = s[2];
|
||
|
s += sn;
|
||
|
d += dn;
|
||
|
if (da)
|
||
|
d[-1] = sa ? s[-1] : 255;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void fast_cmyk_to_cmyk(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst, int copy_spots)
|
||
|
{
|
||
|
unsigned char *s = src->samples;
|
||
|
unsigned char *d = dst->samples;
|
||
|
size_t w = src->w;
|
||
|
int h = src->h;
|
||
|
int sn = src->n;
|
||
|
int ss = src->s;
|
||
|
int sa = src->alpha;
|
||
|
int dn = dst->n;
|
||
|
int ds = dst->s;
|
||
|
int da = dst->alpha;
|
||
|
ptrdiff_t d_line_inc = dst->stride - w * dn;
|
||
|
ptrdiff_t s_line_inc = src->stride - w * sn;
|
||
|
|
||
|
/* If copying spots, they must match, and we can never drop alpha (but we can invent it) */
|
||
|
if (copy_spots && ss != ds)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "incompatible number of spots when converting pixmap");
|
||
|
if (!da && sa)
|
||
|
fz_throw(ctx, FZ_ERROR_GENERIC, "cannot drop alpha when converting pixmap");
|
||
|
|
||
|
if ((int)w < 0 || h < 0)
|
||
|
return;
|
||
|
|
||
|
if (d_line_inc == 0 && s_line_inc == 0)
|
||
|
{
|
||
|
w *= h;
|
||
|
h = 1;
|
||
|
}
|
||
|
|
||
|
if (ss == 0 && ds == 0)
|
||
|
{
|
||
|
/* Common, no spots case */
|
||
|
if (da)
|
||
|
{
|
||
|
if (sa)
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[0];
|
||
|
d[1] = s[1];
|
||
|
d[2] = s[2];
|
||
|
d[3] = s[3];
|
||
|
d[4] = s[4];
|
||
|
s += 5;
|
||
|
d += 5;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[0];
|
||
|
d[1] = s[1];
|
||
|
d[2] = s[2];
|
||
|
d[3] = s[3];
|
||
|
d[4] = 255;
|
||
|
s += 4;
|
||
|
d += 5;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[0];
|
||
|
d[1] = s[1];
|
||
|
d[2] = s[2];
|
||
|
d[3] = s[3];
|
||
|
s += 4;
|
||
|
d += 4;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (copy_spots)
|
||
|
{
|
||
|
/* Slower, spots capable version */
|
||
|
while (h--)
|
||
|
{
|
||
|
int i;
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[0];
|
||
|
d[1] = s[1];
|
||
|
d[2] = s[2];
|
||
|
d[3] = s[3];
|
||
|
s += 4;
|
||
|
d += 4;
|
||
|
for (i=ss; i > 0; i--)
|
||
|
*d++ = *s++;
|
||
|
if (da)
|
||
|
*d++ = sa ? *s++ : 255;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
d[0] = s[0];
|
||
|
d[1] = s[1];
|
||
|
d[2] = s[2];
|
||
|
d[3] = s[3];
|
||
|
s += sn;
|
||
|
d += dn;
|
||
|
if (da)
|
||
|
d[-1] = sa ? s[-1] : 255;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
fz_fast_any_to_alpha(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst, int copy_spots)
|
||
|
{
|
||
|
if (!src->alpha)
|
||
|
fz_clear_pixmap_with_value(ctx, dst, 255);
|
||
|
else
|
||
|
{
|
||
|
unsigned char *s = src->samples;
|
||
|
unsigned char *d = dst->samples;
|
||
|
size_t w = src->w;
|
||
|
int h = src->h;
|
||
|
int n = src->n;
|
||
|
ptrdiff_t d_line_inc = dst->stride - w * dst->n;
|
||
|
ptrdiff_t s_line_inc = src->stride - w * src->n;
|
||
|
|
||
|
if ((int)w < 0 || h < 0)
|
||
|
return;
|
||
|
|
||
|
if (d_line_inc == 0 && s_line_inc == 0)
|
||
|
{
|
||
|
w *= h;
|
||
|
h = 1;
|
||
|
}
|
||
|
|
||
|
s += n-1;
|
||
|
while (h--)
|
||
|
{
|
||
|
size_t ww = w;
|
||
|
while (ww--)
|
||
|
{
|
||
|
*d++ = *s;
|
||
|
s += n;
|
||
|
}
|
||
|
d += d_line_inc;
|
||
|
s += s_line_inc;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
fz_convert_fast_pixmap_samples(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst, int copy_spots)
|
||
|
{
|
||
|
fz_colorspace *ss = src->colorspace;
|
||
|
fz_colorspace *ds = dst->colorspace;
|
||
|
int dtype = ds ? ds->type : FZ_COLORSPACE_GRAY;
|
||
|
int stype = ss ? ss->type : FZ_COLORSPACE_GRAY;
|
||
|
|
||
|
if (!ds)
|
||
|
{
|
||
|
fz_fast_any_to_alpha(ctx, src, dst, copy_spots);
|
||
|
}
|
||
|
|
||
|
else if (stype == FZ_COLORSPACE_GRAY)
|
||
|
{
|
||
|
if (dtype == FZ_COLORSPACE_GRAY)
|
||
|
fast_gray_to_gray(ctx, src, dst, copy_spots);
|
||
|
else if (dtype == FZ_COLORSPACE_RGB)
|
||
|
fast_gray_to_rgb(ctx, src, dst, copy_spots);
|
||
|
else if (dtype == FZ_COLORSPACE_BGR)
|
||
|
fast_gray_to_rgb(ctx, src, dst, copy_spots);
|
||
|
else if (dtype == FZ_COLORSPACE_CMYK)
|
||
|
fast_gray_to_cmyk(ctx, src, dst, copy_spots);
|
||
|
else
|
||
|
goto slow;
|
||
|
}
|
||
|
|
||
|
else if (stype == FZ_COLORSPACE_RGB)
|
||
|
{
|
||
|
if (dtype == FZ_COLORSPACE_GRAY)
|
||
|
fast_rgb_to_gray(ctx, src, dst, copy_spots);
|
||
|
else if (dtype == FZ_COLORSPACE_RGB)
|
||
|
fast_rgb_to_rgb(ctx, src, dst, copy_spots);
|
||
|
else if (dtype == FZ_COLORSPACE_BGR)
|
||
|
fast_rgb_to_bgr(ctx, src, dst, copy_spots);
|
||
|
else if (dtype == FZ_COLORSPACE_CMYK)
|
||
|
fast_rgb_to_cmyk(ctx, src, dst, copy_spots);
|
||
|
else
|
||
|
goto slow;
|
||
|
}
|
||
|
|
||
|
else if (stype == FZ_COLORSPACE_BGR)
|
||
|
{
|
||
|
if (dtype == FZ_COLORSPACE_GRAY)
|
||
|
fast_bgr_to_gray(ctx, src, dst, copy_spots);
|
||
|
else if (dtype == FZ_COLORSPACE_RGB)
|
||
|
fast_rgb_to_bgr(ctx, src, dst, copy_spots);
|
||
|
else if (dtype == FZ_COLORSPACE_BGR)
|
||
|
fast_rgb_to_rgb(ctx, src, dst, copy_spots);
|
||
|
else if (dtype == FZ_COLORSPACE_CMYK)
|
||
|
fast_bgr_to_cmyk(ctx, src, dst, copy_spots);
|
||
|
else
|
||
|
goto slow;
|
||
|
}
|
||
|
|
||
|
else if (stype == FZ_COLORSPACE_CMYK)
|
||
|
{
|
||
|
if (dtype == FZ_COLORSPACE_GRAY)
|
||
|
fast_cmyk_to_gray(ctx, src, dst, copy_spots);
|
||
|
else if (dtype == FZ_COLORSPACE_RGB)
|
||
|
fast_cmyk_to_rgb(ctx, src, dst, copy_spots);
|
||
|
else if (dtype == FZ_COLORSPACE_BGR)
|
||
|
fast_cmyk_to_bgr(ctx, src, dst, copy_spots);
|
||
|
else if (dtype == FZ_COLORSPACE_CMYK)
|
||
|
fast_cmyk_to_cmyk(ctx, src, dst, copy_spots);
|
||
|
else
|
||
|
goto slow;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
goto slow;
|
||
|
}
|
||
|
return;
|
||
|
|
||
|
slow:
|
||
|
fz_convert_slow_pixmap_samples(ctx, src, dst, NULL, fz_default_color_params, copy_spots);
|
||
|
}
|