overlay->outline_offset = MINIMUM_OUTLINE_OFFSET;
}
+#define CAIRO_UNPREMULTIPLY(a,r,g,b) G_STMT_START { \
+ b = (a > 0) ? MIN ((b * 255 + a / 2) / a, 255) : 0; \
+ g = (a > 0) ? MIN ((g * 255 + a / 2) / a, 255) : 0; \
+ r = (a > 0) ? MIN ((r * 255 + a / 2) / a, 255) : 0; \
+} G_STMT_END
+
static inline void
gst_text_overlay_blit_1 (GstTextOverlay * overlay, guchar * dest, gint xpos,
gint ypos, guchar * text_image, guint dest_stride)
g = pimage[CAIRO_ARGB_G];
r = pimage[CAIRO_ARGB_R];
a = pimage[CAIRO_ARGB_A];
+ CAIRO_UNPREMULTIPLY (a, r, g, b);
+
pimage += 4;
if (a == 0) {
py++;
gint i, j;
gint x, cb, cr;
gushort r, g, b, a;
+ gushort r1, g1, b1, a1;
guchar *pimage1, *pimage2;
guchar *pcb, *pcr;
gint width = overlay->image_width - 2;
g = pimage1[CAIRO_ARGB_G];
r = pimage1[CAIRO_ARGB_R];
a = pimage1[CAIRO_ARGB_A];
+ CAIRO_UNPREMULTIPLY (a, r, g, b);
pimage1 += 4;
- b += pimage1[CAIRO_ARGB_B];
- g += pimage1[CAIRO_ARGB_G];
- r += pimage1[CAIRO_ARGB_R];
- a += pimage1[CAIRO_ARGB_A];
+ b1 = pimage1[CAIRO_ARGB_B];
+ g1 = pimage1[CAIRO_ARGB_G];
+ r1 = pimage1[CAIRO_ARGB_R];
+ a1 = pimage1[CAIRO_ARGB_A];
+ CAIRO_UNPREMULTIPLY (a1, r1, g1, b1);
+ b += b1;
+ g += g1;
+ r += r1;
+ a += a1;
pimage1 += 4;
- b += pimage2[CAIRO_ARGB_B];
- g += pimage2[CAIRO_ARGB_G];
- r += pimage2[CAIRO_ARGB_R];
- a += pimage2[CAIRO_ARGB_A];
+ b1 = pimage2[CAIRO_ARGB_B];
+ g1 = pimage2[CAIRO_ARGB_G];
+ r1 = pimage2[CAIRO_ARGB_R];
+ a1 = pimage2[CAIRO_ARGB_A];
+ CAIRO_UNPREMULTIPLY (a1, r1, g1, b1);
+ b += b1;
+ g += g1;
+ r += r1;
+ a += a1;
pimage2 += 4;
/* + 2 for rounding */
- b += pimage2[CAIRO_ARGB_B] + 2;
- g += pimage2[CAIRO_ARGB_G] + 2;
- r += pimage2[CAIRO_ARGB_R] + 2;
- a += pimage2[CAIRO_ARGB_A] + 2;
+ b1 = pimage2[CAIRO_ARGB_B];
+ g1 = pimage2[CAIRO_ARGB_G];
+ r1 = pimage2[CAIRO_ARGB_R];
+ a1 = pimage2[CAIRO_ARGB_A];
+ CAIRO_UNPREMULTIPLY (a1, r1, g1, b1);
+ b += b1 + 2;
+ g += g1 + 2;
+ r += r1 + 2;
+ a += a1 + 2;
pimage2 += 4;
b /= 4;
g0 = pimage[CAIRO_ARGB_G];
r0 = pimage[CAIRO_ARGB_R];
a0 = pimage[CAIRO_ARGB_A];
+ CAIRO_UNPREMULTIPLY (a0, r0, g0, b0);
pimage += 4;
b1 = pimage[CAIRO_ARGB_B];
g1 = pimage[CAIRO_ARGB_G];
r1 = pimage[CAIRO_ARGB_R];
a1 = pimage[CAIRO_ARGB_A];
+ CAIRO_UNPREMULTIPLY (a1, r1, g1, b1);
pimage += 4;
a0 += a1 + 2;
dest = rgb_pixels + (i + ypos) * 4 * overlay->width + xpos * 4; \
for (j = 0; j < w; j++) { \
a = pimage[CAIRO_ARGB_A]; \
- b = (pimage[CAIRO_ARGB_B] * a + dest[B] * (255-a)) / 255; \
- g = (pimage[CAIRO_ARGB_G] * a + dest[G] * (255-a)) / 255; \
- r = (pimage[CAIRO_ARGB_R] * a + dest[R] * (255-a)) / 255; \
+ b = pimage[CAIRO_ARGB_B]; \
+ g = pimage[CAIRO_ARGB_G]; \
+ r = pimage[CAIRO_ARGB_R]; \
+ CAIRO_UNPREMULTIPLY (a, r, g, b); \
+ b = (b*a + dest[B] * (255-a)) / 255; \
+ g = (g*a + dest[G] * (255-a)) / 255; \
+ r = (r*a + dest[R] * (255-a)) / 255; \
\
dest[B] = b; \
dest[G] = g; \
gst_object_unref (render);
}
+#define CAIRO_UNPREMULTIPLY(a,r,g,b) G_STMT_START { \
+ b = (a > 0) ? MIN ((b * 255 + a / 2) / a, 255) : 0; \
+ g = (a > 0) ? MIN ((g * 255 + a / 2) / a, 255) : 0; \
+ r = (a > 0) ? MIN ((r * 255 + a / 2) / a, 255) : 0; \
+} G_STMT_END
+
static void
gst_text_renderer_image_to_ayuv (GstTextRender * render, guchar * pixbuf,
int xpos, int ypos, int stride)
a = bitp[CAIRO_ARGB_A];
bitp += 4;
+ /* Cairo uses pre-multiplied ARGB, unpremultiply it */
+ CAIRO_UNPREMULTIPLY (a, r, g, b);
+
*p++ = a;
*p++ = CLAMP ((int) (((19595 * r) >> 16) + ((38470 * g) >> 16) +
((7471 * b) >> 16)), 0, 255);
p[2] = bitp[CAIRO_ARGB_G];
p[3] = bitp[CAIRO_ARGB_B];
+ /* Cairo uses pre-multiplied ARGB, unpremultiply it */
+ CAIRO_UNPREMULTIPLY (p[0], p[1], p[2], p[3]);
+
bitp += 4;
p += 4;
}