diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2013-01-19 01:39:42 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2013-01-19 02:38:48 +0100 |
commit | ca447592b18a196ea3fdf9d91e0fe031bfe8b737 (patch) | |
tree | 84c1b13a6859879f62ab232232caf62c88ccae22 | |
parent | d7a46ca179e4d72c925345cfe208de3572f89d6e (diff) | |
download | ffmpeg-ca447592b18a196ea3fdf9d91e0fe031bfe8b737.tar.gz |
sws: rgb/bgr 4/8 error diffusion dither
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | libswscale/output.c | 58 | ||||
-rw-r--r-- | libswscale/utils.c | 7 |
2 files changed, 64 insertions, 1 deletions
diff --git a/libswscale/output.c b/libswscale/output.c index d2244c21cc..665176a11d 100644 --- a/libswscale/output.c +++ b/libswscale/output.c @@ -1227,6 +1227,8 @@ yuv2rgb_full_X_c_template(SwsContext *c, const int16_t *lumFilter, { int i; int step = (target == AV_PIX_FMT_RGB24 || target == AV_PIX_FMT_BGR24) ? 3 : 4; + int err[4] = {0}; + int isrgb8 = target == AV_PIX_FMT_BGR8 || target == AV_PIX_FMT_RGB8; for (i = 0; i < dstW; i++) { int j; @@ -1301,9 +1303,48 @@ yuv2rgb_full_X_c_template(SwsContext *c, const int16_t *lumFilter, dest[2] = R >> 22; dest[3] = hasAlpha ? A : 255; break; + case AV_PIX_FMT_BGR4_BYTE: + case AV_PIX_FMT_RGB4_BYTE: + case AV_PIX_FMT_BGR8: + case AV_PIX_FMT_RGB8: + { + int r,g,b; + R >>= 22; + G >>= 22; + B >>= 22; + R += (7*err[0] + 1*c->dither_error[0][i] + 5*c->dither_error[0][i+1] + 3*c->dither_error[0][i+2])>>4; + G += (7*err[1] + 1*c->dither_error[1][i] + 5*c->dither_error[1][i+1] + 3*c->dither_error[1][i+2])>>4; + B += (7*err[2] + 1*c->dither_error[2][i] + 5*c->dither_error[2][i+1] + 3*c->dither_error[2][i+2])>>4; + c->dither_error[0][i] = err[0]; + c->dither_error[1][i] = err[1]; + c->dither_error[2][i] = err[2]; + r = R >> (isrgb8 ? 5 : 7); + g = G >> (isrgb8 ? 5 : 6); + b = B >> (isrgb8 ? 6 : 7); + r = av_clip(r, 0, isrgb8 ? 7 : 1); + g = av_clip(g, 0, isrgb8 ? 7 : 3); + b = av_clip(b, 0, isrgb8 ? 3 : 1); + err[0] = R - r*(isrgb8 ? 36 : 255); + err[1] = G - g*(isrgb8 ? 36 : 85); + err[2] = B - b*(isrgb8 ? 85 : 255); + if(target == AV_PIX_FMT_BGR4_BYTE) { + dest[0] = r + 2*g + 8*b; + } else if(target == AV_PIX_FMT_RGB4_BYTE) { + dest[0] = b + 2*g + 8*r; + } else if(target == AV_PIX_FMT_BGR8) { + dest[0] = r + 8*g + 64*b; + } else if(target == AV_PIX_FMT_RGB8) { + dest[0] = b + 4*g + 32*r; + } else + av_assert2(0); + step = 1; + break;} } dest += step; } + c->dither_error[0][i] = err[0]; + c->dither_error[1][i] = err[1]; + c->dither_error[2][i] = err[2]; } #if CONFIG_SMALL @@ -1326,6 +1367,11 @@ YUV2RGBWRAPPERX(yuv2, rgb_full, xrgb32_full, AV_PIX_FMT_ARGB, 0) YUV2RGBWRAPPERX(yuv2, rgb_full, bgr24_full, AV_PIX_FMT_BGR24, 0) YUV2RGBWRAPPERX(yuv2, rgb_full, rgb24_full, AV_PIX_FMT_RGB24, 0) +YUV2RGBWRAPPERX(yuv2, rgb_full, bgr4_byte_full, AV_PIX_FMT_BGR4_BYTE, 0) +YUV2RGBWRAPPERX(yuv2, rgb_full, rgb4_byte_full, AV_PIX_FMT_RGB4_BYTE, 0) +YUV2RGBWRAPPERX(yuv2, rgb_full, bgr8_full, AV_PIX_FMT_BGR8, 0) +YUV2RGBWRAPPERX(yuv2, rgb_full, rgb8_full, AV_PIX_FMT_RGB8, 0) + av_cold void ff_sws_init_output_funcs(SwsContext *c, yuv2planar1_fn *yuv2plane1, yuv2planarX_fn *yuv2planeX, @@ -1426,6 +1472,18 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c, case AV_PIX_FMT_BGR24: *yuv2packedX = yuv2bgr24_full_X_c; break; + case AV_PIX_FMT_BGR4_BYTE: + *yuv2packedX = yuv2bgr4_byte_full_X_c; + break; + case AV_PIX_FMT_RGB4_BYTE: + *yuv2packedX = yuv2rgb4_byte_full_X_c; + break; + case AV_PIX_FMT_BGR8: + *yuv2packedX = yuv2bgr8_full_X_c; + break; + case AV_PIX_FMT_RGB8: + *yuv2packedX = yuv2rgb8_full_X_c; + break; } if(!*yuv2packedX) goto YUV_PACKED; diff --git a/libswscale/utils.c b/libswscale/utils.c index 53f4fb8121..8637195e16 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -1008,7 +1008,12 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, dstFormat != AV_PIX_FMT_BGRA && dstFormat != AV_PIX_FMT_ABGR && dstFormat != AV_PIX_FMT_RGB24 && - dstFormat != AV_PIX_FMT_BGR24) { + dstFormat != AV_PIX_FMT_BGR24 && + dstFormat != AV_PIX_FMT_BGR4_BYTE && + dstFormat != AV_PIX_FMT_RGB4_BYTE && + dstFormat != AV_PIX_FMT_BGR8 && + dstFormat != AV_PIX_FMT_RGB8 + ) { av_log(c, AV_LOG_WARNING, "full chroma interpolation for destination format '%s' not yet implemented\n", av_get_pix_fmt_name(dstFormat)); |