summaryrefslogtreecommitdiff
path: root/draw
diff options
context:
space:
mode:
authorRobin Watts <Robin.Watts@artifex.com>2011-04-05 20:30:38 +0100
committerTor Andersson <tor.andersson@artifex.com>2011-04-06 02:10:48 +0200
commit87103a29cc90e5b48279f31ae98de1d530b90f18 (patch)
tree148f02554c26b7635383eb315b89b15959d83ac6 /draw
parent4bce9580c3ff1e2a4e755c35ac3c1a913aebdcbb (diff)
downloadmupdf-87103a29cc90e5b48279f31ae98de1d530b90f18.tar.xz
Add special case gray image -> rgb device rendering code.
New code to render grayscale images on an rgb device without converting to rgb first.
Diffstat (limited to 'draw')
-rw-r--r--draw/draw_affine.c165
-rw-r--r--draw/draw_device.c15
2 files changed, 166 insertions, 14 deletions
diff --git a/draw/draw_affine.c b/draw/draw_affine.c
index dce2189d..68323876 100644
--- a/draw/draw_affine.c
+++ b/draw/draw_affine.c
@@ -59,6 +59,37 @@ fz_paint_affine_alpha_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, i
}
}
+/* Special case code for gray -> rgb */
+static inline void
+fz_paint_affine_alpha_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int alpha)
+{
+ while (w--)
+ {
+ int ui = u >> 16;
+ int vi = v >> 16;
+ if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
+ {
+ int uf = u & 0xffff;
+ int vf = v & 0xffff;
+ byte *a = sample_nearest(sp, sw, sh, 2, ui, vi);
+ byte *b = sample_nearest(sp, sw, sh, 2, ui+1, vi);
+ byte *c = sample_nearest(sp, sw, sh, 2, ui, vi+1);
+ byte *d = sample_nearest(sp, sw, sh, 2, ui+1, vi+1);
+ int y = bilerp(a[1], b[1], c[1], d[1], uf, vf);
+ int t = 255 - fz_mul255(y, alpha);
+ int x = bilerp(a[0], b[0], c[0], d[0], uf, vf);
+ x = fz_mul255(x, alpha);
+ dp[0] = x + fz_mul255(dp[0], t);
+ dp[1] = x + fz_mul255(dp[1], t);
+ dp[2] = x + fz_mul255(dp[2], t);
+ dp[3] = fz_mul255(y, alpha) + fz_mul255(dp[3], t);
+ }
+ dp += 4;
+ u += fa;
+ v += fb;
+ }
+}
+
static inline void
fz_paint_affine_alpha_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha)
{
@@ -81,6 +112,29 @@ fz_paint_affine_alpha_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, i
}
}
+static inline void
+fz_paint_affine_alpha_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int alpha)
+{
+ while (w--)
+ {
+ int ui = u >> 16;
+ int vi = v >> 16;
+ if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
+ {
+ byte *sample = sp + ((vi * sw + ui) * 2);
+ int t = 255 - fz_mul255(sample[1], alpha);
+ int x = fz_mul255(sample[0], alpha);
+ dp[0] = x + fz_mul255(dp[0], t);
+ dp[1] = x + fz_mul255(dp[1], t);
+ dp[2] = x + fz_mul255(dp[2], t);
+ dp[3] = fz_mul255(sample[1], alpha) + fz_mul255(dp[3], t);
+ }
+ dp += 4;
+ u += fa;
+ v += fb;
+ }
+}
+
/* Blend premultiplied source image over destination */
static inline void
@@ -114,6 +168,35 @@ fz_paint_affine_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
}
static inline void
+fz_paint_affine_solid_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w)
+{
+ while (w--)
+ {
+ int ui = u >> 16;
+ int vi = v >> 16;
+ if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
+ {
+ int uf = u & 0xffff;
+ int vf = v & 0xffff;
+ byte *a = sample_nearest(sp, sw, sh, 2, ui, vi);
+ byte *b = sample_nearest(sp, sw, sh, 2, ui+1, vi);
+ byte *c = sample_nearest(sp, sw, sh, 2, ui, vi+1);
+ byte *d = sample_nearest(sp, sw, sh, 2, ui+1, vi+1);
+ int y = bilerp(a[1], b[1], c[1], d[1], uf, vf);
+ int t = 255 - y;
+ int x = bilerp(a[0], b[0], c[0], d[0], uf, vf);
+ dp[0] = x + fz_mul255(dp[0], t);
+ dp[1] = x + fz_mul255(dp[1], t);
+ dp[2] = x + fz_mul255(dp[2], t);
+ dp[3] = y + fz_mul255(dp[3], t);
+ }
+ dp += 4;
+ u += fa;
+ v += fb;
+ }
+}
+
+static inline void
fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n)
{
int k;
@@ -135,6 +218,28 @@ fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
}
}
+static inline void
+fz_paint_affine_solid_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w)
+{
+ while (w--)
+ {
+ int ui = u >> 16;
+ int vi = v >> 16;
+ if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
+ {
+ byte *sample = sp + ((vi * sw + ui) * 2);
+ int t = 255 - sample[1];
+ dp[0] = sample[0] + fz_mul255(dp[0], t);
+ dp[1] = sample[0] + fz_mul255(dp[1], t);
+ dp[2] = sample[0] + fz_mul255(dp[2], t);
+ dp[3] = sample[1] + fz_mul255(dp[3], t);
+ }
+ dp += 4;
+ u += fa;
+ v += fb;
+ }
+}
+
/* Blend non-premultiplied color in source image mask over destination */
static inline void
@@ -192,7 +297,7 @@ fz_paint_affine_color_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, i
}
static void
-fz_paint_affine_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha)
+fz_paint_affine_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused*/)
{
if (alpha == 255)
{
@@ -217,7 +322,20 @@ fz_paint_affine_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, i
}
static void
-fz_paint_affine_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha)
+fz_paint_affine_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused*/)
+{
+ if (alpha == 255)
+ {
+ fz_paint_affine_solid_g2rgb_lerp(dp, sp, sw, sh, u, v, fa, fb, w);
+ }
+ else if (alpha > 0)
+ {
+ fz_paint_affine_alpha_g2rgb_lerp(dp, sp, sw, sh, u, v, fa, fb, w, alpha);
+ }
+}
+
+static void
+fz_paint_affine_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused */)
{
if (alpha == 255)
{
@@ -242,7 +360,20 @@ fz_paint_affine_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, i
}
static void
-fz_paint_affine_color_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, byte *color)
+fz_paint_affine_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused*/)
+{
+ if (alpha == 255)
+ {
+ fz_paint_affine_solid_g2rgb_near(dp, sp, sw, sh, u, v, fa, fb, w);
+ }
+ else if (alpha > 0)
+ {
+ fz_paint_affine_alpha_g2rgb_near(dp, sp, sw, sh, u, v, fa, fb, w, alpha);
+ }
+}
+
+static void
+fz_paint_affine_color_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha/*unused*/, byte *color)
{
switch (n)
{
@@ -253,7 +384,7 @@ fz_paint_affine_color_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int
}
static void
-fz_paint_affine_color_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, byte *color)
+fz_paint_affine_color_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha/*unused*/, byte *color)
{
switch (n)
{
@@ -275,6 +406,7 @@ fz_paint_image_imp(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *img, fz_matrix ct
fz_matrix inv;
fz_bbox bbox;
int dolerp;
+ void (*paintfn)(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color);
/* grid fit the image */
if (fz_is_rectilinear(ctm))
@@ -335,22 +467,35 @@ fz_paint_image_imp(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *img, fz_matrix ct
/* TODO: if (fb == 0 && fa == 1) call fz_paint_span */
- while (h--)
+ if (dst->n == 4 && img->n == 2)
+ {
+ assert(color == NULL);
+ if (dolerp)
+ paintfn = fz_paint_affine_g2rgb_lerp;
+ else
+ paintfn = fz_paint_affine_g2rgb_near;
+ }
+ else
{
if (dolerp)
{
if (color)
- fz_paint_affine_color_lerp(dp, sp, sw, sh, u, v, fa, fb, w, n, color);
+ paintfn = fz_paint_affine_color_lerp;
else
- fz_paint_affine_lerp(dp, sp, sw, sh, u, v, fa, fb, w, n, alpha);
+ paintfn = fz_paint_affine_lerp;
}
else
{
if (color)
- fz_paint_affine_color_near(dp, sp, sw, sh, u, v, fa, fb, w, n, color);
+ paintfn = fz_paint_affine_color_near;
else
- fz_paint_affine_near(dp, sp, sw, sh, u, v, fa, fb, w, n, alpha);
+ paintfn = fz_paint_affine_near;
}
+ }
+
+ while (h--)
+ {
+ paintfn(dp, sp, sw, sh, u, v, fa, fb, w, n, alpha, color);
dp += dst->w * n;
u += fc;
v += fd;
@@ -367,6 +512,6 @@ fz_paint_image_with_color(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *img, fz_ma
void
fz_paint_image(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *img, fz_matrix ctm, int alpha)
{
- assert(dst->n == img->n);
+ assert(dst->n == img->n || (dst->n == 4 && img->n == 2));
fz_paint_image_imp(dst, scissor, img, ctm, NULL, alpha);
}
diff --git a/draw/draw_device.c b/draw/draw_device.c
index 05f96f28..e49fb04d 100644
--- a/draw/draw_device.c
+++ b/draw/draw_device.c
@@ -615,11 +615,18 @@ fz_draw_fill_image(void *user, fz_pixmap *image, fz_matrix ctm, float alpha)
image = scaled;
}
- if (image->colorspace != model && after)
+ if (image->colorspace != model)
{
- converted = fz_new_pixmap(model, image->x, image->y, image->w, image->h);
- fz_convert_pixmap(image, converted);
- image = converted;
+ if (image->colorspace == fz_device_gray && model == fz_device_rgb)
+ {
+ /* We have special case rendering code for gray -> rgb */
+ }
+ else
+ {
+ converted = fz_new_pixmap(model, image->x, image->y, image->w, image->h);
+ fz_convert_pixmap(image, converted);
+ image = converted;
+ }
}
fz_paint_image(dev->dest, dev->scissor, image, ctm, alpha * 255);