summaryrefslogtreecommitdiff
path: root/source/fitz/colorspace.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2016-05-23 17:45:21 +0100
committerRobin Watts <robin.watts@artifex.com>2016-05-24 12:48:35 +0100
commitd0b78f4166a1503ce522944002b3aab035724cd9 (patch)
treeb8c680dc401db56a28be1110759219c7c175dd8d /source/fitz/colorspace.c
parent841952db71d6541a2e98fd4d1d49dede284b2cf8 (diff)
downloadmupdf-d0b78f4166a1503ce522944002b3aab035724cd9.tar.xz
fz_pixmap revamp: add stride and make alpha optional
fz_pixmaps now have an explicit stride value. By default no change from before, but code all copes with extra gaps at the end of the line. The alpha data in fz_pixmaps is no longer compulsory. mudraw: use rgb not rgba (ppmraw), cmyk not cmyka (pkmraw). Update halftone code to not expect alpha plane. Update PNG writing to cope with alpha less input. Also hide repeated params within the png output context. ARM code needs updating.
Diffstat (limited to 'source/fitz/colorspace.c')
-rw-r--r--source/fitz/colorspace.c1309
1 files changed, 1016 insertions, 293 deletions
diff --git a/source/fitz/colorspace.c b/source/fitz/colorspace.c
index 026953cb..b4d511e8 100644
--- a/source/fitz/colorspace.c
+++ b/source/fitz/colorspace.c
@@ -283,15 +283,74 @@ static void fast_gray_to_rgb(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 3);
+ int s_line_inc = src->stride - w * (src->alpha + 1);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
{
- d[0] = s[0];
- d[1] = s[0];
- d[2] = s[0];
- d[3] = s[1];
- s += 2;
- d += 4;
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int 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--)
+ {
+ int 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
+ {
+ int si = 1 + src->alpha;
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = s[0];
+ d[1] = s[0];
+ d[2] = s[0];
+ s += si;
+ d += 3;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -299,16 +358,77 @@ static void fast_gray_to_cmyk(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 4);
+ int s_line_inc = src->stride - w * (src->alpha + 1);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = 0;
+ d[1] = 0;
+ d[2] = 0;
+ d[3] = 255 - s[0];
+ d[4] = s[1];
+ s += 2;
+ d += 5;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = 0;
+ d[1] = 0;
+ d[2] = 0;
+ d[3] = 255 - s[0];
+ d[4] = 255;
+ s++;
+ d += 5;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ }
+ else
{
- d[0] = 0;
- d[1] = 0;
- d[2] = 0;
- d[3] = 255 - s[0];
- d[4] = s[1];
- s += 2;
- d += 5;
+ int si = 1 + src->alpha;
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = 0;
+ d[1] = 0;
+ d[2] = 0;
+ d[3] = 255 - s[0];
+ s += si;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -316,13 +436,68 @@ static void fast_rgb_to_gray(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 1);
+ int s_line_inc = src->stride - w * (src->alpha + 3);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int 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--)
+ {
+ int 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
{
- d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
- d[1] = s[3];
- s += 4;
- d += 2;
+ int sn = src->n;
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
+ s += sn;
+ d++;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -330,13 +505,68 @@ static void fast_bgr_to_gray(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 1);
+ int s_line_inc = src->stride - w * (src->alpha + 3);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int 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--)
+ {
+ int 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
{
- d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
- d[1] = s[3];
- s += 4;
- d += 2;
+ int si = 3 + src->alpha;
+
+ while (h--)
+ {
+ int 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;
+ }
}
}
@@ -344,20 +574,89 @@ static void fast_rgb_to_cmyk(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 4);
+ int s_line_inc = src->stride - w * (src->alpha + 3);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = 255 - s[0];
+ unsigned char m = 255 - s[1];
+ unsigned char y = 255 - s[2];
+ unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
+ d[0] = c - k;
+ d[1] = m - k;
+ d[2] = y - k;
+ d[3] = k;
+ d[4] = s[3];
+ s += 4;
+ d += 5;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = 255 - s[0];
+ unsigned char m = 255 - s[1];
+ unsigned char y = 255 - s[2];
+ unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
+ d[0] = c - k;
+ d[1] = m - k;
+ d[2] = y - k;
+ d[3] = k;
+ d[4] = 255;
+ s += 3;
+ d += 5;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ }
+ else
{
- unsigned char c = 255 - s[0];
- unsigned char m = 255 - s[1];
- unsigned char y = 255 - s[2];
- unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
- d[0] = c - k;
- d[1] = m - k;
- d[2] = y - k;
- d[3] = k;
- d[4] = s[3];
- s += 4;
- d += 5;
+ int si = 3 + src->alpha;
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = 255 - s[0];
+ unsigned char m = 255 - s[1];
+ unsigned char y = 255 - s[2];
+ unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
+ d[0] = c - k;
+ d[1] = m - k;
+ d[2] = y - k;
+ d[3] = k;
+ s += si;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -365,20 +664,89 @@ static void fast_bgr_to_cmyk(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 4);
+ int s_line_inc = src->stride - w * (src->alpha + 3);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
{
- unsigned char c = 255 - s[2];
- unsigned char m = 255 - s[1];
- unsigned char y = 255 - s[0];
- unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
- d[0] = c - k;
- d[1] = m - k;
- d[2] = y - k;
- d[3] = k;
- d[4] = s[3];
- s += 4;
- d += 5;
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = 255 - s[2];
+ unsigned char m = 255 - s[1];
+ unsigned char y = 255 - s[0];
+ unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
+ d[0] = c - k;
+ d[1] = m - k;
+ d[2] = y - k;
+ d[3] = k;
+ d[4] = s[3];
+ s += 4;
+ d += 5;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = 255 - s[2];
+ unsigned char m = 255 - s[1];
+ unsigned char y = 255 - s[0];
+ unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
+ d[0] = c - k;
+ d[1] = m - k;
+ d[2] = y - k;
+ d[3] = k;
+ d[4] = 255;
+ s += 3;
+ d += 5;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ }
+ else
+ {
+ int si = 3 + src->alpha;
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = 255 - s[2];
+ unsigned char m = 255 - s[1];
+ unsigned char y = 255 - s[0];
+ unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
+ d[0] = c - k;
+ d[1] = m - k;
+ d[2] = y - k;
+ d[3] = k;
+ s += si;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -386,16 +754,76 @@ static void fast_cmyk_to_gray(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 1);
+ int s_line_inc = src->stride - w * (src->alpha + 4);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
{
- unsigned char c = fz_mul255(s[0], 77);
- unsigned char m = fz_mul255(s[1], 150);
- unsigned char y = fz_mul255(s[2], 28);
- d[0] = 255 - (unsigned char)fz_mini(c + m + y + s[3], 255);
- d[1] = s[4];
- s += 5;
- d += 2;
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = fz_mul255(s[0], 77);
+ unsigned char m = fz_mul255(s[1], 150);
+ unsigned char y = fz_mul255(s[2], 28);
+ d[0] = 255 - (unsigned char)fz_mini(c + m + y + s[3], 255);
+ d[1] = s[4];
+ s += 5;
+ d += 2;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = fz_mul255(s[0], 77);
+ unsigned char m = fz_mul255(s[1], 150);
+ unsigned char y = fz_mul255(s[2], 28);
+ d[0] = 255 - (unsigned char)fz_mini(c + m + y + s[3], 255);
+ d[1] = 255;
+ s += 3;
+ d += 2;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ }
+ else
+ {
+ int si = 4 + src->alpha;
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = fz_mul255(s[0], 77);
+ unsigned char m = fz_mul255(s[1], 150);
+ unsigned char y = fz_mul255(s[2], 28);
+ d[0] = 255 - (unsigned char)fz_mini(c + m + y + s[3], 255);
+ s += si;
+ d++;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -592,15 +1020,150 @@ fast_cmyk_to_rgb_ARM(unsigned char *dst, unsigned char *src, int n)
}
#endif
+static inline void cached_cmyk_conv(unsigned char *restrict const pr, unsigned char *restrict const pg, unsigned char *restrict const pb,
+ unsigned int *restrict const C, unsigned int *restrict const M, unsigned int *restrict const Y, unsigned int *restrict const K,
+ unsigned int c, unsigned int m, unsigned int y, unsigned int k)
+{
+#ifdef SLOWCMYK
+ unsigned int r, g, b;
+ unsigned int cm, c1m, cm1, c1m1, c1m1y, c1m1y1, c1my, c1my1, cm1y, cm1y1, cmy, cmy1;
+ unsigned int x0, x1;
+
+ if (c == *C && m == *M && y == *Y && k == *K)
+ {
+ /* Nothing to do */
+ }
+ else if (k == 0 && c == 0 && m == 0 && y == 0)
+ {
+ *pr = *pg = *pb = 255;
+ *C = 0;
+ *M = 0;
+ *Y = 0;
+ *K = 0;
+ }
+ else if (k == 255)
+ {
+ *pr = *pg = *pb = 0;
+ *C = 0;
+ *M = 0;
+ *Y = 0;
+ *K = 255;
+ }
+ else
+ {
+ c += c>>7;
+ m += m>>7;
+ y += y>>7;
+ k += k>>7;
+ y >>= 1; /* Ditch 1 bit of Y to avoid overflow */
+ cm = c * m;
+ c1m = (m<<8) - cm;
+ cm1 = (c<<8) - cm;
+ c1m1 = ((256 - m)<<8) - cm1;
+ c1m1y = c1m1 * y;
+ c1m1y1 = (c1m1<<7) - c1m1y;
+ c1my = c1m * y;
+ c1my1 = (c1m<<7) - c1my;
+ cm1y = cm1 * y;
+ cm1y1 = (cm1<<7) - cm1y;
+ cmy = cm * y;
+ cmy1 = (cm<<7) - cmy;
+
+ /* this is a matrix multiplication, unrolled for performance */
+ x1 = c1m1y1 * k; /* 0 0 0 1 */
+ x0 = (c1m1y1<<8) - x1; /* 0 0 0 0 */
+ x1 = x1>>8; /* From 23 fractional bits to 15 */
+ r = g = b = x0;
+ r += 35 * x1; /* 0.1373 */
+ g += 31 * x1; /* 0.1216 */
+ b += 32 * x1; /* 0.1255 */
+
+ x1 = c1m1y * k; /* 0 0 1 1 */
+ x0 = (c1m1y<<8) - x1; /* 0 0 1 0 */
+ x1 >>= 8; /* From 23 fractional bits to 15 */
+ r += 28 * x1; /* 0.1098 */
+ g += 26 * x1; /* 0.1020 */
+ r += x0;
+ x0 >>= 8; /* From 23 fractional bits to 15 */
+ g += 243 * x0; /* 0.9490 */
+
+ x1 = c1my1 * k; /* 0 1 0 1 */
+ x0 = (c1my1<<8) - x1; /* 0 1 0 0 */
+ x1 >>= 8; /* From 23 fractional bits to 15 */
+ x0 >>= 8; /* From 23 fractional bits to 15 */
+ r += 36 * x1; /* 0.1412 */
+ r += 237 * x0; /* 0.9255 */
+ b += 141 * x0; /* 0.5490 */
+
+ x1 = c1my * k; /* 0 1 1 1 */
+ x0 = (c1my<<8) - x1; /* 0 1 1 0 */
+ x1 >>= 8; /* From 23 fractional bits to 15 */
+ x0 >>= 8; /* From 23 fractional bits to 15 */
+ r += 34 * x1; /* 0.1333 */
+ r += 238 * x0; /* 0.9294 */
+ g += 28 * x0; /* 0.1098 */
+ b += 36 * x0; /* 0.1412 */
+
+ x1 = cm1y1 * k; /* 1 0 0 1 */
+ x0 = (cm1y1<<8) - x1; /* 1 0 0 0 */
+ x1 >>= 8; /* From 23 fractional bits to 15 */
+ x0 >>= 8; /* From 23 fractional bits to 15 */
+ g += 15 * x1; /* 0.0588 */
+ b += 36 * x1; /* 0.1412 */
+ g += 174 * x0; /* 0.6784 */
+ b += 240 * x0; /* 0.9373 */
+
+ x1 = cm1y * k; /* 1 0 1 1 */
+ x0 = (cm1y<<8) - x1; /* 1 0 1 0 */
+ x1 >>= 8; /* From 23 fractional bits to 15 */
+ x0 >>= 8; /* From 23 fractional bits to 15 */
+ g += 19 * x1; /* 0.0745 */
+ g += 167 * x0; /* 0.6510 */
+ b += 80 * x0; /* 0.3137 */
+
+ x1 = cmy1 * k; /* 1 1 0 1 */
+ x0 = (cmy1<<8) - x1; /* 1 1 0 0 */
+ x1 >>= 8; /* From 23 fractional bits to 15 */
+ x0 >>= 8; /* From 23 fractional bits to 15 */
+ b += 2 * x1; /* 0.0078 */
+ r += 46 * x0; /* 0.1804 */
+ g += 49 * x0; /* 0.1922 */
+ b += 147 * x0; /* 0.5725 */
+
+ x0 = cmy * (256-k); /* 1 1 1 0 */
+ x0 >>= 8; /* From 23 fractional bits to 15 */
+ r += 54 * x0; /* 0.2118 */
+ g += 54 * x0; /* 0.2119 */
+ b += 57 * x0; /* 0.2235 */
+
+ r -= (r>>8);
+ g -= (g>>8);
+ b -= (b>>8);
+ *pr = r>>23;
+ *pg = g>>23;
+ *pb = b>>23;
+ *C = c;
+ *M = m;
+ *Y = y;
+ *K = k;
+ }
+#else
+ *pr = 255 - (unsigned char)fz_mini(c + k, 255);
+ *pg = 255 - (unsigned char)fz_mini(m + k, 255);
+ *pb = 255 - (unsigned char)fz_mini(y + k, 255);
+#endif
+}
+
static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
-#ifdef ARCH_ARM
- fast_cmyk_to_rgb_ARM(d, s, n);
-#else
- unsigned int C,M,Y,K,r,g,b;
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 3);
+ int s_line_inc = src->stride - w * (src->alpha + 4);
+ unsigned int C,M,Y,K;
+ unsigned char r,g,b;
C = 0;
M = 0;
@@ -610,174 +1173,169 @@ static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
g = 255;
b = 255;
- while (n--)
+ if (d_line_inc == 0 && s_line_inc == 0)
{
-#ifdef SLOWCMYK
- unsigned int c = s[0];
- unsigned int m = s[1];
- unsigned int y = s[2];
- unsigned int k = s[3];
- unsigned int cm, c1m, cm1, c1m1, c1m1y, c1m1y1, c1my, c1my1, cm1y, cm1y1, cmy, cmy1;
- unsigned int x0, x1;
-
- if (c == C && m == M && y == Y && k == K)
- {
- /* Nothing to do */
- }
- else if (k == 0 && c == 0 && m == 0 && y == 0)
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
{
- r = g = b = 255;
- C = 0;
- M = 0;
- Y = 0;
- K = 0;
+#ifdef ARCH_ARM
+ if (h == 1)
+ {
+ fast_cmyk_to_rgb_ARM(d, s, w);
+ return;
+ }
+#endif
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ cached_cmyk_conv(&r, &g, &b, &C, &M, &Y, &K, s[0], s[1], s[2], s[3]);
+ d[0] = r;
+ d[1] = g;
+ d[2] = b;
+ d[3] = s[4];
+ s += 5;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
- else if (k == 255)
+ else
{
- r = g = b = 0;
- C = 0;
- M = 0;
- Y = 0;
- K = 255;
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ cached_cmyk_conv(&r, &g, &b, &C, &M, &Y, &K, s[0], s[1], s[2], s[3]);
+ d[0] = r;
+ d[1] = g;
+ d[2] = b;
+ d[3] = 255;
+ s += 4;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
- else
+ }
+ else
+ {
+ /* We shouldn't lose alpha */
+ assert(src->alpha == 0);
+
+ while (h--)
{
- c += c>>7;
- m += m>>7;
- y += y>>7;
- k += k>>7;
- y >>= 1; /* Ditch 1 bit of Y to avoid overflow */
- cm = c * m;
- c1m = (m<<8) - cm;
- cm1 = (c<<8) - cm;
- c1m1 = ((256 - m)<<8) - cm1;
- c1m1y = c1m1 * y;
- c1m1y1 = (c1m1<<7) - c1m1y;
- c1my = c1m * y;
- c1my1 = (c1m<<7) - c1my;
- cm1y = cm1 * y;
- cm1y1 = (cm1<<7) - cm1y;
- cmy = cm * y;
- cmy1 = (cm<<7) - cmy;
-
- /* this is a matrix multiplication, unrolled for performance */
- x1 = c1m1y1 * k; /* 0 0 0 1 */
- x0 = (c1m1y1<<8) - x1; /* 0 0 0 0 */
- x1 = x1>>8; /* From 23 fractional bits to 15 */
- r = g = b = x0;
- r += 35 * x1; /* 0.1373 */
- g += 31 * x1; /* 0.1216 */
- b += 32 * x1; /* 0.1255 */
-
- x1 = c1m1y * k; /* 0 0 1 1 */
- x0 = (c1m1y<<8) - x1; /* 0 0 1 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- r += 28 * x1; /* 0.1098 */
- g += 26 * x1; /* 0.1020 */
- r += x0;
- x0 >>= 8; /* From 23 fractional bits to 15 */
- g += 243 * x0; /* 0.9490 */
-
- x1 = c1my1 * k; /* 0 1 0 1 */
- x0 = (c1my1<<8) - x1; /* 0 1 0 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- r += 36 * x1; /* 0.1412 */
- r += 237 * x0; /* 0.9255 */
- b += 141 * x0; /* 0.5490 */
-
- x1 = c1my * k; /* 0 1 1 1 */
- x0 = (c1my<<8) - x1; /* 0 1 1 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- r += 34 * x1; /* 0.1333 */
- r += 238 * x0; /* 0.9294 */
- g += 28 * x0; /* 0.1098 */
- b += 36 * x0; /* 0.1412 */
-
- x1 = cm1y1 * k; /* 1 0 0 1 */
- x0 = (cm1y1<<8) - x1; /* 1 0 0 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- g += 15 * x1; /* 0.0588 */
- b += 36 * x1; /* 0.1412 */
- g += 174 * x0; /* 0.6784 */
- b += 240 * x0; /* 0.9373 */
-
- x1 = cm1y * k; /* 1 0 1 1 */
- x0 = (cm1y<<8) - x1; /* 1 0 1 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- g += 19 * x1; /* 0.0745 */
- g += 167 * x0; /* 0.6510 */
- b += 80 * x0; /* 0.3137 */
-
- x1 = cmy1 * k; /* 1 1 0 1 */
- x0 = (cmy1<<8) - x1; /* 1 1 0 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- b += 2 * x1; /* 0.0078 */
- r += 46 * x0; /* 0.1804 */
- g += 49 * x0; /* 0.1922 */
- b += 147 * x0; /* 0.5725 */
-
- x0 = cmy * (256-k); /* 1 1 1 0 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- r += 54 * x0; /* 0.2118 */
- g += 54 * x0; /* 0.2119 */
- b += 57 * x0; /* 0.2235 */
-
- r -= (r>>8);
- g -= (g>>8);
- b -= (b>>8);
- r = r>>23;
- g = g>>23;
- b = b>>23;
- C = c;
- M = m;
- Y = y;
- K = k;
+ int ww = w;
+ while (ww--)
+ {
+ cached_cmyk_conv(&r, &g, &b, &C, &M, &Y, &K, s[0], s[1], s[2], s[3]);
+ d[0] = r;
+ d[1] = g;
+ d[2] = b;
+ s += 4;
+ d += 3;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
}
- d[0] = r;
- d[1] = g;
- d[2] = b;
-#else
- d[0] = 255 - (unsigned char)fz_mini(s[0] + s[3], 255);
- d[1] = 255 - (unsigned char)fz_mini(s[1] + s[3], 255);
- d[2] = 255 - (unsigned char)fz_mini(s[2] + s[3], 255);
-#endif
- d[3] = s[4];
- s += 5;
- d += 4;
}
-#endif
}
static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 3);
+ int s_line_inc = src->stride - w * (src->alpha + 4);
+ unsigned int C,M,Y,K;
+ unsigned char r,g,b;
+
+ C = 0;
+ M = 0;
+ Y = 0;
+ K = 0;
+ r = 255;
+ g = 255;
+ b = 255;
+
+ if (d_line_inc == 0 && s_line_inc == 0)
{
-#ifdef SLOWCMYK
- float cmyk[4], rgb[3];
- cmyk[0] = s[0] / 255.0f;
- cmyk[1] = s[1] / 255.0f;
- cmyk[2] = s[2] / 255.0f;
- cmyk[3] = s[3] / 255.0f;
- cmyk_to_rgb(ctx, NULL, cmyk, rgb);
- d[0] = rgb[2] * 255;
- d[1] = rgb[1] * 255;
- d[2] = rgb[0] * 255;
-#else
- d[0] = 255 - (unsigned char)fz_mini(s[2] + s[3], 255);
- d[1] = 255 - (unsigned char)fz_mini(s[1] + s[3], 255);
- d[2] = 255 - (unsigned char)fz_mini(s[0] + s[3], 255);
-#endif
- d[3] = s[4];
- s += 5;
- d += 4;
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ cached_cmyk_conv(&r, &g, &b, &C, &M, &Y, &K, s[0], s[1], s[2], s[3]);
+ d[0] = b;
+ d[1] = g;
+ d[2] = r;
+ d[3] = s[4];
+ s += 5;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ cached_cmyk_conv(&r, &g, &b, &C, &M, &Y, &K, s[0], s[1], s[2], s[3]);
+ d[0] = b;
+ d[1] = g;
+ d[2] = r;
+ d[3] = 255;
+ s += 4;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ }
+ else
+ {
+ /* We shouldn't lose alpha */
+ assert(src->alpha == 0);
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ cached_cmyk_conv(&r, &g, &b, &C, &M, &Y, &K, s[0], s[1], s[2], s[3]);
+ d[0] = b;
+ d[1] = g;
+ d[2] = r;
+ s += 4;
+ d += 3;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -785,15 +1343,69 @@ static void fast_rgb_to_bgr(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 3);
+ int s_line_inc = src->stride - w * (src->alpha + 3);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int 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--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = s[2];
+ d[1] = s[1];
+ d[2] = s[0];
+ d[3] = 255;
+ s += 3;
+ d += 4;
+ }
+ }
+ }
+ }
+ else
{
- d[0] = s[2];
- d[1] = s[1];
- d[2] = s[0];
- d[3] = s[3];
- s += 4;
- d += 4;
+ /* We shouldn't lose alpha */
+ assert(src->alpha == 0);
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = s[2];
+ d[1] = s[1];
+ d[2] = s[0];
+ s += 3;
+ d += 3;
+ }
+ }
}
}
@@ -804,7 +1416,12 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
float dstv[FZ_MAX_COLORS];
int srcn, dstn;
int k, i;
- unsigned int xy;
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * dst->n;
+ int s_line_inc = src->stride - w * src->n;
+ int da = dst->alpha;
+ int sa = src->alpha;
fz_colorspace *ss = src->colorspace;
fz_colorspace *ds = dst->colorspace;
@@ -812,14 +1429,18 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- assert(src->w == dst->w && src->h == dst->h);
- assert(src->n == ss->n + 1);
- assert(dst->n == ds->n + 1);
-
srcn = ss->n;
dstn = ds->n;
- xy = (unsigned int)(src->w * src->h);
+ assert(src->w == dst->w && src->h == dst->h);
+ assert(src->n == srcn + sa);
+ assert(dst->n == dstn + da);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
/* Special case for Lab colorspace (scaling of components to float) */
if (!strcmp(ss->name, "Lab") && srcn == 3)
@@ -827,38 +1448,52 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
fz_color_converter cc;
fz_lookup_color_converter(ctx, &cc, ds, ss);
- for (; xy > 0; xy--)
+ while (h--)
{
- srcv[0] = *s++ / 255.0f * 100;
- srcv[1] = *s++ - 128;
- srcv[2] = *s++ - 128;
-
- cc.convert(ctx, &cc, dstv, srcv);
+ int ww = w;
+ while (ww--)
+ {
+ srcv[0] = *s++ / 255.0f * 100;
+ srcv[1] = *s++ - 128;
+ srcv[2] = *s++ - 128;
- for (k = 0; k < dstn; k++)
- *d++ = dstv[k] * 255;
+ cc.convert(ctx, &cc, dstv, srcv);
- *d++ = *s++;
+ for (k = 0; k < dstn; k++)
+ *d++ = dstv[k] * 255;
+ if (da)
+ *d++ = (sa ? *s : 255);
+ s += sa;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
}
}
/* Brute-force for small images */
- else if (xy < 256)
+ else if (w*h < 256)
{
fz_color_converter cc;
fz_lookup_color_converter(ctx, &cc, ds, ss);
- for (; xy > 0; xy--)
+ while (h--)
{
- for (k = 0; k < srcn; k++)
- srcv[k] = *s++ / 255.0f;
-
- cc.convert(ctx, &cc, dstv, srcv);
+ int ww = w;
+ while (ww--)
+ {
+ for (k = 0; k < srcn; k++)
+ srcv[k] = *s++ / 255.0f;
- for (k = 0; k < dstn; k++)
- *d++ = dstv[k] * 255;
+ cc.convert(ctx, &cc, dstv, srcv);
- *d++ = *s++;
+ for (k = 0; k < dstn; k++)
+ *d++ = dstv[k] * 255;
+ if (da)
+ *d++ = (sa ? *s : 255);
+ s += sa;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
}
}
@@ -877,12 +1512,20 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
lookup[i * dstn + k] = dstv[k] * 255;
}
- for (; xy > 0; xy--)
+ while (h--)
{
- i = *s++;
- for (k = 0; k < dstn; k++)
- *d++ = lookup[i * dstn + k];
- *d++ = *s++;
+ int ww = w;
+ while (ww--)
+ {
+ i = *s++;
+ for (k = 0; k < dstn; k++)
+ *d++ = lookup[i * dstn + k];
+ if (da)
+ *d++ = (sa ? *s : 255);
+ s += sa;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
}
}
@@ -893,57 +1536,109 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
unsigned char *color;
unsigned char dummy = s[0] ^ 255;
unsigned char *sold = &dummy;
+ unsigned char *dold;
fz_color_converter cc;
fz_lookup_color_converter(ctx, &cc, ds, ss);
lookup = fz_new_hash_table(ctx, 509, srcn, -1);
- for (; xy > 0; xy--)
+ while (h--)
{
- if (*s == *sold && memcmp(sold,s,srcn) == 0)
- {
- sold = s;
- memcpy(d, d-dstn-1, dstn);
- d += dstn;
- s += srcn;
- *d++ = *s++;
- }
- else
+ int ww = w;
+ while (ww--)
{
- sold = s;
- color = fz_hash_find(ctx, lookup, s);
- if (color)
+ if (*s == *sold && memcmp(sold,s,srcn) == 0)
{
- memcpy(d, color, dstn);
- s += srcn;
+ sold = s;
+ memcpy(d, dold, dstn);
d += dstn;
- *d++ = *s++;
+ s += srcn;
+ if (da)
+ *d++ = (sa ? *s : 255);
+ s += sa;
}
else
{
- for (k = 0; k < srcn; k++)
- srcv[k] = *s++ / 255.0f;
- cc.convert(ctx, &cc, dstv, srcv);
- for (k = 0; k < dstn; k++)
- *d++ = dstv[k] * 255;
-
- fz_hash_insert(ctx, lookup, s - srcn, d - dstn);
-
- *d++ = *s++;
+ sold = s;
+ dold = d;
+ color = fz_hash_find(ctx, lookup, s);
+ if (color)
+ {
+ memcpy(d, color, dstn);
+ s += srcn;
+ d += dstn;
+ if (dst->alpha)
+ *d++ = (sa ? *s : 255);
+ s += sa;
+ }
+ else
+ {
+ for (k = 0; k < srcn; k++)
+ srcv[k] = *s++ / 255.0f;
+ cc.convert(ctx, &cc, dstv, srcv);
+ for (k = 0; k < dstn; k++)
+ *d++ = dstv[k] * 255;
+
+ fz_hash_insert(ctx, lookup, s - srcn, d - dstn);
+
+ if (dst->alpha)
+ *d++ = (sa ? *s : 255);
+ s += sa;
+ }
}
}
+ d += d_line_inc;
+ s += s_line_inc;
}
fz_drop_hash(ctx, lookup);
}
}
+static void fast_copy_alpha(fz_pixmap *dst, fz_pixmap *src)
+{
+ unsigned char *s = src->samples;
+ unsigned char *d = dst->samples;
+ int w = src->w;
+ int h = src->h;
+ int n = src->n;
+ int d_line_inc = dst->stride - w * dst->n;
+ int s_line_inc = src->stride - w * src->n;
+
+ assert(dst->alpha && src->alpha && dst->n == 1);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
+
+ s += n-1;
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ *d++ = *s;
+ s += n;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+}
+
void
fz_convert_pixmap(fz_context *ctx, fz_pixmap *dp, fz_pixmap *sp)
{
fz_colorspace *ss = sp->colorspace;
fz_colorspace *ds = dp->colorspace;
+ if (ds == NULL && sp->alpha)
+ {
+ fast_copy_alpha(dp, sp);
+ return;
+ }
+
assert(ss && ds);
dp->interpolate = sp->interpolate;
@@ -993,6 +1688,11 @@ std_conv_color(fz_context *ctx, fz_color_converter *cc, float *dstv, const float
fz_colorspace *srcs = cc->ss;
fz_colorspace *dsts = cc->ds;
+ if (srcs == NULL)
+ srcs = fz_device_rgb(ctx);
+ if (dsts == NULL)
+ dsts = fz_device_rgb(ctx);
+
if (srcs != dsts)
{
assert(srcs->to_rgb && dsts->from_rgb);
@@ -1238,6 +1938,7 @@ fz_expand_indexed_pixmap(fz_context *ctx, fz_pixmap *src)
int y, x, k, n, high;
unsigned char *lookup;
fz_irect bbox;
+ int s_line_inc, d_line_inc;
assert(src->colorspace->to_rgb == indexed_to_rgb);
assert(src->n == 2);
@@ -1247,20 +1948,42 @@ fz_expand_indexed_pixmap(fz_context *ctx, fz_pixmap *src)
lookup = idx->lookup;
n = idx->base->n;
- dst = fz_new_pixmap_with_bbox(ctx, idx->base, fz_pixmap_bbox(ctx, src, &bbox));
+ dst = fz_new_pixmap_with_bbox(ctx, idx->base, fz_pixmap_bbox(ctx, src, &bbox), src->alpha);
s = src->samples;
d = dst->samples;
+ s_line_inc = src->stride - src->w * src->n;
+ d_line_inc = dst->stride - dst->w * dst->n;
- for (y = 0; y < src->h; y++)
+ if (src->alpha)
+ {
+ for (y = 0; y < src->h; y++)
+ {
+ for (x = 0; x < src->w; x++)
+ {
+ int v = *s++;
+ int a = *s++;
+ v = fz_mini(v, high);
+ for (k = 0; k < n; k++)
+ *d++ = fz_mul255(lookup[v * n + k], a);
+ *d++ = a;
+ }
+ s += s_line_inc;
+ d += d_line_inc;
+ }
+ }
+ else
{
- for (x = 0; x < src->w; x++)
+ for (y = 0; y < src->h; y++)
{
- int v = *s++;
- int a = *s++;
- v = fz_mini(v, high);
- for (k = 0; k < n; k++)
- *d++ = fz_mul255(lookup[v * n + k], a);
- *d++ = a;
+ for (x = 0; x < src->w; x++)
+ {
+ int v = *s++;
+ v = fz_mini(v, high);
+ for (k = 0; k < n; k++)
+ *d++ = lookup[v * n + k];
+ }
+ s += s_line_inc;
+ d += d_line_inc;
}
}