[FFmpeg-cvslog] sws: rgb/bgr 4/8 error diffusion dither

Michael Niedermayer git at videolan.org
Sat Jan 19 02:39:55 CET 2013


ffmpeg | branch: master | Michael Niedermayer <michaelni at gmx.at> | Sat Jan 19 01:39:42 2013 +0100| [ca447592b18a196ea3fdf9d91e0fe031bfe8b737] | committer: Michael Niedermayer

sws: rgb/bgr 4/8 error diffusion dither

Signed-off-by: Michael Niedermayer <michaelni at gmx.at>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=ca447592b18a196ea3fdf9d91e0fe031bfe8b737
---

 libswscale/output.c |   58 +++++++++++++++++++++++++++++++++++++++++++++++++++
 libswscale/utils.c  |    7 ++++++-
 2 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/libswscale/output.c b/libswscale/output.c
index d2244c2..665176a 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 53f4fb8..8637195 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));



More information about the ffmpeg-cvslog mailing list