From f464108b09a79a27a804ea293def282822ad288b Mon Sep 17 00:00:00 2001 From: Torsten Jager Date: Fri, 30 May 2014 15:06:00 +0200 Subject: rgb2yuy2 update. * palette color count guard. * add 4, 2, 1 bit palette support. * use default gray on NULL palette. * optional xine clut_t output. --- src/xine-utils/color.c | 159 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 142 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/xine-utils/color.c b/src/xine-utils/color.c index acc68962e..54ff1db0b 100644 --- a/src/xine-utils/color.c +++ b/src/xine-utils/color.c @@ -1743,15 +1743,17 @@ void init_yuv_conversion(void) { typedef struct { /* unused:1 u:21 v:21 y:21 */ uint64_t t0[256], t1[256], t2[256]; - /* u:12 v:12 y:8 */ - uint32_t p[256]; + /* u:12 v:12 y:8 (rgb_pal8) */ + /* native endian yuyv (other rgb_pal*) */ + uint32_t p[272]; int cm, fmt, pfmt; } rgb2yuy2_t; typedef enum { rgb_bgr = 0, rgb_rgb, rgb_bgra, rgb_argb, rgb_rgba, rgb_rgb555le, rgb_rgb555be, rgb_rgb565le, rgb_rgb565be, - rgb_pal8 + rgb_bgra_clut, rgb_rgba_clut, + rgb_pal8, rgb_pal4, rgb_pal2, rgb_pal1 } rgb_fmt_t; void *rgb2yuy2_alloc (int color_matrix, const char *format) { @@ -1760,9 +1762,13 @@ void *rgb2yuy2_alloc (int color_matrix, const char *format) { float _ry, _gy, _by, _yoffs; float _bv, _bvoffset, _ru, _ruoffset, _gu, _guoffset, _gv, _gvoffset, _burv; int i = -1; - const char *fmts[] = {"bgr", "rgb", "bgra", "argb", "rgba", "rgb555le", "rgb555be", "rgb565le", "rgb565be"}; + const char *fmts[] = { + "bgr", "rgb", "bgra", "argb", "rgba", + "rgb555le", "rgb555be", "rgb565le", "rgb565be", + "bgra_clut", "rgba_clut" + }; - if (format) for (i = 8; i >= 0; i--) if (!strcmp (format, fmts[i])) break; + if (format) for (i = 10; i >= 0; i--) if (!strcmp (format, fmts[i])) break; if (i < 0) return NULL; b = malloc (sizeof (*b)); @@ -1802,9 +1808,11 @@ void *rgb2yuy2_alloc (int color_matrix, const char *format) { case rgb_rgb: case rgb_bgra: case rgb_argb: - case rgb_rgba: { /* 24/32 bit */ + case rgb_rgba: + case rgb_bgra_clut: + case rgb_rgba_clut: { /* 24/32 bit */ uint64_t *rr, *gg, *bb; - if ((b->fmt == rgb_bgr) || (b->fmt == rgb_bgra)) { + if ((b->fmt == rgb_bgr) || (b->fmt == rgb_bgra) || (b->fmt == rgb_bgra_clut)) { bb = b->t0; gg = b->t1; rr = b->t2; @@ -1930,20 +1938,29 @@ void rgb2yuy2_free (void *rgb2yuy2) { void rgb2yuy2_palette (void *rgb2yuy2, const uint8_t *pal, int num_colors, int bits_per_pixel) { rgb2yuy2_t *b = rgb2yuy2; uint64_t v; - uint32_t w; - int mode, i = 0; + uint32_t w, *p; + int mode, i = 0, max_colors; - if (!b || (num_colors < 2) || (num_colors > 256)) return; + if (!b || (num_colors < 2)) return; switch (bits_per_pixel) { - case 8: mode = rgb_pal8; break; -/* case 4: mode = 10; break; not implemented yet - case 2: mode = 11; break; - case 1: mode = 12; break; */ + case 8: mode = rgb_pal8; max_colors = 256; p = b->p; break; + case 4: mode = rgb_pal4; max_colors = 16; p = b->p + 256; break; + case 2: mode = rgb_pal2; max_colors = 4; p = b->p + 256; break; + case 1: mode = rgb_pal1; max_colors = 2; p = b->p + 256; break; default: return; } + if (num_colors > max_colors) num_colors = max_colors; /* fmt now refers to the format of the _palette_ */ if (b->pfmt == -1) b->pfmt = b->fmt; b->fmt = mode; + /* default grays */ + if (!pal) { + for (i = 0; i < num_colors; i++) { + w = (i * 255 + (num_colors - 1) / 2) / (num_colors - 1); + v = b->t0[w] + b->t1[w] + b->t2[w]; + p[i] = ((v >> 31) & 0xfff00000) | ((v >> 22) & 0xfff00) | ((v >> 13) & 0xff); + } + } else /* convert palette */ switch (b->pfmt) { case rgb_bgr: @@ -1952,7 +1969,7 @@ void rgb2yuy2_palette (void *rgb2yuy2, const uint8_t *pal, int num_colors, int b v = b->t0[*pal++]; v += b->t1[*pal++]; v += b->t2[*pal++]; - b->p[i] = ((v >> 31) & 0xfff00000) | ((v >> 22) & 0xfff00) | ((v >> 13) & 0xff); + p[i] = ((v >> 31) & 0xfff00000) | ((v >> 22) & 0xfff00) | ((v >> 13) & 0xff); } break; case rgb_argb: @@ -1964,7 +1981,7 @@ void rgb2yuy2_palette (void *rgb2yuy2, const uint8_t *pal, int num_colors, int b v += b->t1[*pal++]; v += b->t2[*pal]; pal += 2; - b->p[i] = ((v >> 31) & 0xfff00000) | ((v >> 22) & 0xfff00) | ((v >> 13) & 0xff); + p[i] = ((v >> 31) & 0xfff00000) | ((v >> 22) & 0xfff00) | ((v >> 13) & 0xff); } break; default: ; @@ -1972,7 +1989,50 @@ void rgb2yuy2_palette (void *rgb2yuy2, const uint8_t *pal, int num_colors, int b /* black pad rest of palette */ v = b->t0[0] + b->t1[0] + b->t2[0]; w = ((v >> 31) & 0xfff00000) | ((v >> 22) & 0xfff00) | ((v >> 13) & 0xff); - for (; i < 256; i++) b->p[i] = w; + for (; i < max_colors; i++) p[i] = w; + /* more optimization ahead? */ + if (mode != rgb_pal8) { + union {uint8_t bytes[4]; uint32_t word;} tmp; + switch (mode) { + case rgb_pal4: + for (i = 0; i < 256; i++) { + w = p[i >> 4]; + tmp.bytes[0] = w; /* y1 */ + w &= ~255; + w += p[i & 15]; + tmp.bytes[1] = w >> 24; /* u */ + tmp.bytes[2] = w; /* y2 */ + tmp.bytes[3] = w >> 12; /* v */ + b->p[i] = tmp.word; + } + break; + case rgb_pal2: + for (i = 0; i < 16; i++) { + w = p[i >> 2]; + tmp.bytes[0] = w; /* y1 */ + w &= ~255; + w += p[i & 3]; + tmp.bytes[1] = w >> 24; /* u */ + tmp.bytes[2] = w; /* y2 */ + tmp.bytes[3] = w >> 12; /* v */ + b->p[i] = tmp.word; + } + break; + case rgb_pal1: + for (i = 0; i < 4; i++) { + w = p[i >> 1]; + tmp.bytes[0] = w; /* y1 */ + w &= ~255; + w += p[i & 1]; + tmp.bytes[1] = w >> 24; /* u */ + tmp.bytes[2] = w; /* y2 */ + tmp.bytes[3] = w >> 12; /* v */ + b->p[i] = tmp.word; + } + break; + default: ; + } + } } void rgb2yuy2_slice (void *rgb2yuy2, const uint8_t *in, int ipitch, uint8_t *out, int opitch, @@ -2072,5 +2132,70 @@ void rgb2yuy2_slice (void *rgb2yuy2, const uint8_t *in, int ipitch, uint8_t *out out += opad; } break; + case rgb_pal4: + ipad = ipitch - (width / 2); + for (y = height; y; y--) { + uint32_t *o2 = (uint32_t *)out; + for (x = width / 2; x; x--) + *o2++ = b->p[*in++]; + in += ipad; + out += opitch; + } + break; + case rgb_pal2: + ipad = ipitch - (width / 4); + for (y = height; y; y--) { + uint32_t *o2 = (uint32_t *)out; + for (x = width / 4; x; x--) { + *o2++ = b->p[(*in) >> 4]; + *o2++ = b->p[(*in++) & 15]; + } + if (width & 3) + *o2++ = b->p[(*in) >> 4]; + in += ipad; + out += opitch; + } + break; + case rgb_pal1: + ipad = ipitch - (width / 8); + for (y = height; y; y--) { + uint32_t *o2 = (uint32_t *)out; + for (x = width / 8; x; x--) { + *o2++ = b->p[(*in) >> 6]; + *o2++ = b->p[((*in) >> 4) & 3]; + *o2++ = b->p[((*in) >> 2) & 3]; + *o2++ = b->p[(*in++) & 3]; + } + x = width & 7; + if (x) { + *o2++ = b->p[(*in) >> 6]; + if (x > 2) { + *o2++ = b->p[((*in) >> 4) & 3]; + if (x > 4) + *o2++ = b->p[((*in) >> 2) & 3]; + } + } + in += ipad; + out += opitch; + } + break; + case rgb_rgba_clut: + case rgb_bgra_clut: + ipad = ipitch - 4 * width; + opad = opitch - 4 * width; + for (y = height; y; y--) { + for (x = width; x; x--) { + v = b->t0[*in++]; + v += b->t1[*in++]; + v += b->t2[*in++]; + *out++ = v >> 54; /* u */ + *out++ = v >> 33; /* v */ + *out++ = v >> 13; /* y */ + *out++ = *in++; /* a */ + } + in += ipad; + out += opad; + } + break; } } -- cgit v1.2.3