]> git.sesse.net Git - vlc/commitdiff
. suite de l'output 8 bits couleur/n&b
authorSam Hocevar <sam@videolan.org>
Mon, 7 Feb 2000 05:13:22 +0000 (05:13 +0000)
committerSam Hocevar <sam@videolan.org>
Mon, 7 Feb 2000 05:13:22 +0000 (05:13 +0000)
 . correction d'un bug dans la g�n�ration de la palette optimale
 . YUV avec dithering mortel qui tue

todo:
 . x11 (�a ne marche qu'en framebuffer pour le moment)
 . mettre la g�n�ration de palette dans video_yuv
 . refaire marcher l'output framebuffer pour bpp!=8

include/video_output.h
src/video_output/video_fb.c
src/video_output/video_yuv.c

index 00a56b74fef70aa9b09f642ba2a24b4368c3bc83..cc23c514d4db4e9be8bc31112f0cb6153809fea2 100644 (file)
@@ -125,7 +125,7 @@ typedef struct vout_thread_s
     u32                 i_blue_pixel;                                 /* blue */
     
     /* Palette */
-    u8                  lookup[1377];       /* lookup table for 8 bpp palette */
+    u8                  lookup[2176];       /* lookup table for 8 bpp palette */
 
     /* Pictures and rendering properties */
     boolean_t           b_grayscale;            /* color or grayscale display */
index 0a14d11f9aa16198761d0242b8694555c4204612..f2a2445ccca1483e41974817c8fe0cbbf39afcaf 100644 (file)
 #include "intf_msg.h"
 #include "main.h"
 
-#define RGB_MIN -24
-#define RGB_MAX 283
+//#define RGB_MIN 0
+//#define RGB_MAX 255
+#define RGB_MIN 0
+#define RGB_MAX 255
+#define SHIFT 20
+#define U_GREEN_COEF    ((int)(-0.391 * (1<<SHIFT) / 1.164))
+#define U_BLUE_COEF     ((int)(2.018 * (1<<SHIFT) / 1.164))
+#define V_RED_COEF      ((int)(1.596 * (1<<SHIFT) / 1.164))
+#define V_GREEN_COEF    ((int)(-0.813 * (1<<SHIFT) / 1.164))
 
 /******************************************************************************
  * vout_sys_t: video output framebuffer method descriptor
@@ -224,7 +231,7 @@ static int FBOpenDisplay( vout_thread_t *p_vout )
 
         /* initializes black & white palette */
        //FBInitBWPalette( p_vout );
-       FBInitRGBPalette( p_vout );
+        FBInitRGBPalette( p_vout );
 
         p_vout->i_bytes_per_pixel = 1;
         p_vout->i_bytes_per_line = p_vout->i_width;
@@ -299,54 +306,91 @@ static void FBCloseDisplay( vout_thread_t *p_vout )
  *****************************************************************************/
 static void FBInitRGBPalette( vout_thread_t *p_vout )
 {
+    #define SATURATE( x )    \
+    x = x + ( x >> 3 ) - 16; \
+    if( x < 0 ) x = 0;       \
+    if( x > 255 ) x = 255;
+
     int y,u,v;
-    float r,g,b;
+    int r,g,b;
+    int uvRed, uvGreen, uvBlue;
     unsigned int counter = 0;
     unsigned int allocated = 0;
-    unsigned int lastallocated = 0;
     unsigned short red[256], green[256], blue[256], transp[256];
+    unsigned char extralookup[2176];
     struct fb_cmap cmap = { 0, 256, red, green, blue, transp };
 
     for ( y = 0; y <= 256; y += 16 )
-    for ( u = -256; u <= 256; u += 64 )
-    for ( v = -256; v <= 256; v += 64 )
     {
-        r = (0.99     * y + 1.0      * u - 0.01     * v);
-        g = (1.005085 * y - 0.508475 * u - 0.181356 * v);
-        b = (1.0      * y                + 1.0      * v);
-
-        if( r > RGB_MIN && g > RGB_MIN && b > RGB_MIN
-            && r < RGB_MAX && g < RGB_MAX && b < RGB_MAX )
+        for ( u = 0; u <= 256; u += 32 )
+        for ( v = 0; v <= 256; v += 32 )
         {
-            if(allocated == 256) { fprintf(stderr, "sorry, no colors left\n"); exit(1); }
-            if(r<0) r=0;
-            if(g<0) g=0;
-            if(b<0) b=0;
-            if(r>255) r=255;
-            if(g>255) g=255;
-            if(b>255) b=255;
-
-            red[allocated] = (int)r << 8;
-            green[allocated] = (int)g << 8;
-            blue[allocated] = (int)b << 8;
-            transp[allocated] = 0;
-
-            u += 256;
-            v += 256;
-            //printf("%x (%i:%i:%i) %i %i %i\n", (y>>4)*81 + (u>>6)*9 + (v>>6), y>>4, u>>6, v>>6, (int)r, (int)g, (int)b);
-            //printf("%i %i\n", counter, (y>>4)*81 + (u>>6)*9 + (v>>6) );
-
-            u -= 256;
-            v -= 256;
-            /* allocate color */
-            p_vout->lookup[counter] = allocated;
-            allocated++;
-            /* set last allocated index */
-            lastallocated = allocated - 1;
+            uvRed = (V_RED_COEF*(v-128)) >> SHIFT;
+            uvGreen = (U_GREEN_COEF*(u-128) + V_GREEN_COEF*(v-128)) >> SHIFT;
+            uvBlue = (U_BLUE_COEF*(u-128)) >> SHIFT;
+            r = y + uvRed;
+            g = y + uvGreen;
+            b = y + uvBlue;
+    
+            if( r >= RGB_MIN && g >= RGB_MIN && b >= RGB_MIN
+                && r <= RGB_MAX && g <= RGB_MAX && b <= RGB_MAX )
+            {
+                if(allocated == 256) { fprintf(stderr, "sorry, no colors left\n"); exit(1); }
+                /* saturate the colors */
+                SATURATE( r );
+                SATURATE( g );
+                SATURATE( b );
+
+                red[allocated] = r << 8;
+                green[allocated] = g << 8;
+                blue[allocated] = b << 8;
+                transp[allocated] = 0;
+
+                /* allocate color */
+                extralookup[counter] = 1;
+                p_vout->lookup[counter++] = allocated;
+                allocated++;
+            }
+            else
+            {
+                extralookup[counter] = 0;
+                p_vout->lookup[counter++] = 0;
+            }
         }
-        else p_vout->lookup[counter] = lastallocated;
+        counter += 128-81;
+    }
 
-        counter++;
+    counter = 0;
+    for ( y = 0; y <= 256; y += 16 )
+    {
+        for ( u = 0; u <= 256; u += 32 )
+        for ( v = 0; v <= 256; v += 32 )
+        {
+            int y2, u2, v2;
+            int dist = 100000000;
+
+            if( p_vout->lookup[counter] || y==0)
+            {
+                counter++;
+                continue;
+            }
+
+           for( y2 = y-16; y2 <= y; y2+= 16 )
+            for( u2 = 0; u2 <= 256; u2 += 32 )
+            for( v2 = 0; v2 <= 256; v2 += 32 )
+            {
+                if( extralookup[((y2>>4)<<7) + (u2>>5)*9 + (v2>>5)])
+                    /* find the nearest color */
+                    if( 128*(y-y2) + (u-u2)*(u-u2) + (v-v2)*(v-v2) < dist )
+                    {
+                        p_vout->lookup[counter] = p_vout->lookup[((y2>>4)<<7) + (u2>>5)*9 + (v2>>5)];
+                        dist = 128*(y-y2) + (u-u2)*(u-u2) + (v-v2)*(v-v2);
+                    }
+            }
+            counter++;
+        }
+        counter += 128-81;
     }
 
     ioctl( p_vout->p_sys->i_fb_dev, FBIOPUTCMAP, &cmap );
@@ -369,3 +413,4 @@ static void FBInitBWPalette( vout_thread_t *p_vout )
 
     ioctl( p_vout->p_sys->i_fb_dev, FBIOPUTCMAP, &cmap );
 }
+
index 4937367c1175e8d1fe9627a0a31cbb68ee228f56..d5938880b94dc4dd2ba712753bfb49ccb40add54 100644 (file)
@@ -163,10 +163,67 @@ static void     ConvertYUV444RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data
     i_blue =    (U_BLUE_COEF * i_uval) >> SHIFT;                              \
     CONVERT_Y_PIXEL( BPP )                                                    \
 
+/*****************************************************************************
+ * CONVERT_4YUV_PIXELS, CONVERT_4YUV_PIXELS_SCALE: dither 4 pixels in 8 bpp
+ *****************************************************************************
+ * These macros dither 4 pixels in 8 bpp, with or without horiz. scaling
+ *****************************************************************************/
+#define CONVERT_4YUV_PIXELS( CHROMA )                                         \
+    *p_pic++ = p_vout->lookup[                                                \
+        (((*p_y++ + dither10[i_real_y]) >> 4) << 7)                           \
+      + ((*p_u + dither20[i_real_y]) >> 5) * 9                                \
+      + ((*p_v + dither20[i_real_y]) >> 5) ];                                 \
+    *p_pic++ = p_vout->lookup[                                                \
+        (((*p_y++ + dither11[i_real_y]) >> 4) << 7)                           \
+      + ((*p_u++ + dither21[i_real_y]) >> 5) * 9                              \
+      + ((*p_v++ + dither21[i_real_y]) >> 5) ];                               \
+    *p_pic++ = p_vout->lookup[                                                \
+        (((*p_y++ + dither12[i_real_y]) >> 4) << 7)                           \
+      + ((*p_u + dither22[i_real_y]) >> 5) * 9                                \
+      + ((*p_v + dither22[i_real_y]) >> 5) ];                                 \
+    *p_pic++ = p_vout->lookup[                                                \
+        (((*p_y++ + dither13[i_real_y]) >> 4) << 7)                           \
+      + ((*p_u++ + dither23[i_real_y]) >> 5) * 9                              \
+      + ((*p_v++ + dither23[i_real_y]) >> 5) ];                               \
+#define CONVERT_4YUV_PIXELS_SCALE( CHROMA )                                   \
+    *p_pic++ = p_vout->lookup[                                                \
+        (((*p_y + dither10[i_real_y]) >> 4) << 7)                             \
+        + ((*p_u + dither20[i_real_y])   >> 5) * 9                            \
+        + ((*p_v + dither20[i_real_y])   >> 5) ];                             \
+    i_jump_uv = (i_jump_uv + *p_offset) & 0x1;                                \
+    p_y += *p_offset;                                                         \
+    p_u += *p_offset   & i_jump_uv;                                           \
+    p_v += *p_offset++ & i_jump_uv;                                           \
+    *p_pic++ = p_vout->lookup[                                                \
+        (((*p_y + dither11[i_real_y]) >> 4) << 7)                             \
+        + ((*p_u + dither21[i_real_y])   >> 5) * 9                            \
+        + ((*p_v + dither21[i_real_y])   >> 5) ];                             \
+    i_jump_uv = (i_jump_uv + *p_offset) & 0x1;                                \
+    p_y += *p_offset;                                                         \
+    p_u += *p_offset   & i_jump_uv;                                           \
+    p_v += *p_offset++ & i_jump_uv;                                           \
+    *p_pic++ = p_vout->lookup[                                                \
+        (((*p_y + dither12[i_real_y]) >> 4) << 7)                             \
+        + ((*p_u + dither22[i_real_y])   >> 5) * 9                            \
+        + ((*p_v + dither22[i_real_y])   >> 5) ];                             \
+    i_jump_uv = (i_jump_uv + *p_offset) & 0x1;                                \
+    p_y += *p_offset;                                                         \
+    p_u += *p_offset   & i_jump_uv;                                           \
+    p_v += *p_offset++ & i_jump_uv;                                           \
+    *p_pic++ = p_vout->lookup[                                                \
+        (((*p_y + dither13[i_real_y]) >> 4) << 7)                             \
+        + ((*p_u + dither23[i_real_y])   >> 5) * 9                            \
+        + ((*p_v + dither23[i_real_y])   >> 5) ];                             \
+    i_jump_uv = (i_jump_uv + *p_offset) & 0x1;                                \
+    p_y += *p_offset;                                                         \
+    p_u += *p_offset   & i_jump_uv;                                           \
+    p_v += *p_offset++ & i_jump_uv;                                           \
+
 /*****************************************************************************
  * SCALE_WIDTH: scale a line horizontally
  *****************************************************************************
- * This macro scale a line using rendering buffer and offset array. It works
+ * This macro scales a line using rendering buffer and offset array. It works
  * for 1, 2 and 4 Bpp.
  *****************************************************************************/
 #define SCALE_WIDTH                                                           \
@@ -204,11 +261,45 @@ static void     ConvertYUV444RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data
         p_pic += i_pic_width + i_pic_line_width;                              \
     }                                                                         \
 
+
+/*****************************************************************************
+ * SCALE_WIDTH_DITHER: scale a line horizontally for dithered 8 bpp
+ *****************************************************************************
+ * This macro scales a line using an offset array.
+ *****************************************************************************/
+#define SCALE_WIDTH_DITHER( CHROMA )                                          \
+    if( b_horizontal_scaling )                                                \
+    {                                                                         \
+        /* Horizontal scaling, but we can't use a buffer due to dither */     \
+        p_offset = p_offset_start;                                            \
+       i_jump_uv = 0;                                                        \
+        for( i_x = i_pic_width / 16; i_x--; )                                 \
+        {                                                                     \
+            CONVERT_4YUV_PIXELS_SCALE( CHROMA )                               \
+            CONVERT_4YUV_PIXELS_SCALE( CHROMA )                               \
+            CONVERT_4YUV_PIXELS_SCALE( CHROMA )                               \
+            CONVERT_4YUV_PIXELS_SCALE( CHROMA )                               \
+        }                                                                     \
+    }                                                                         \
+    else                                                                      \
+    {                                                                         \
+        for( i_x = i_width / 16; i_x--;  )                                    \
+        {                                                                     \
+            CONVERT_4YUV_PIXELS( CHROMA )                                     \
+            CONVERT_4YUV_PIXELS( CHROMA )                                     \
+            CONVERT_4YUV_PIXELS( CHROMA )                                     \
+            CONVERT_4YUV_PIXELS( CHROMA )                                     \
+       }                                                                     \
+    }                                                                         \
+    /* Increment of picture pointer to end of line is still needed */         \
+    p_pic += i_pic_line_width;                                                \
+    i_real_y = (i_real_y + 1) & 0x3;                                          \
+
 /*****************************************************************************
  * SCALE_HEIGHT: handle vertical scaling
  *****************************************************************************
  * This macro handle vertical scaling for a picture. CHROMA may be 420, 422 or
- * 444 for RGB conversion, or 400 for gray convertion. It works for 1, 2, 3
+ * 444 for RGB conversion, or 400 for gray conversion. It works for 1, 2, 3
  * and 4 Bpp.
  *****************************************************************************/
 #define SCALE_HEIGHT( CHROMA, BPP )                                           \
@@ -278,6 +369,63 @@ static void     ConvertYUV444RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data
         break;                                                                \
     }                                                                         \
 
+/*****************************************************************************
+ * SCALE_HEIGHT_DITHER: handle vertical scaling for dithered 8 bpp
+ *****************************************************************************
+ * This macro handles vertical scaling for a picture. CHROMA may be 420, 422 or
+ * 444 for RGB conversion, or 400 for gray conversion.
+ *****************************************************************************/
+#define SCALE_HEIGHT_DITHER( CHROMA )                                         \
+                                                                              \
+    /* If line is odd, rewind 4:2:0 U and V samples */                        \
+    if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) )                \
+    {                                                                         \
+        p_u -= i_chroma_width;                                                \
+        p_v -= i_chroma_width;                                                \
+    }                                                                         \
+                                                                              \
+    /*                                                                        \
+     * Handle vertical scaling. The current line can be copied or next one    \
+     * can be ignored.                                                        \
+     */                                                                       \
+                                                                              \
+    switch( i_vertical_scaling )                                              \
+    {                                                                         \
+    case -1:                             /* vertical scaling factor is < 1 */ \
+        while( (i_scale_count -= i_pic_height) >= 0 )                         \
+        {                                                                     \
+            /* Height reduction: skip next source line */                     \
+            p_y += i_width;                                                   \
+            i_y++;                                                            \
+            if( (CHROMA == 420) || (CHROMA == 422) )                          \
+            {                                                                 \
+                if( i_y & 0x1 )                                               \
+                {                                                             \
+                    p_u += i_chroma_width;                                    \
+                    p_v += i_chroma_width;                                    \
+                }                                                             \
+            }                                                                 \
+            else if( CHROMA == 444 )                                          \
+            {                                                                 \
+                p_u += i_width;                                               \
+                p_v += i_width;                                               \
+            }                                                                 \
+        }                                                                     \
+        i_scale_count += i_height;                                            \
+        break;                                                                \
+    case 1:                              /* vertical scaling factor is > 1 */ \
+        while( (i_scale_count -= i_height) > 0 )                              \
+        {                                                                     \
+            SCALE_WIDTH_DITHER( CHROMA );                                     \
+            p_y -= i_width;                                                   \
+            p_u -= i_chroma_width;                                            \
+            p_v -= i_chroma_width;                                            \
+            p_pic +=        i_pic_line_width;                                 \
+        }                                                                     \
+        i_scale_count += i_pic_height;                                        \
+        break;                                                                \
+    }                                                                         \
+
 /*****************************************************************************
  * vout_InitYUV: allocate and initialize translations tables
  *****************************************************************************
@@ -292,7 +440,8 @@ int vout_InitYUV( vout_thread_t *p_vout )
     switch( p_vout->i_bytes_per_pixel )
     {
     case 1:
-        tables_size = sizeof( u8 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : RGB_TABLE_SIZE);
+        /* nothing to allocate - will put the palette here afterwards */
+        tables_size = 1;
         break;        
     case 2:
         tables_size = sizeof( u16 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : RGB_TABLE_SIZE);
@@ -399,16 +548,6 @@ static void SetYUV( vout_thread_t *p_vout )
         switch( p_vout->i_bytes_per_pixel )
         {
         case 1:
-            p_vout->yuv.yuv.p_gray8 =  (u8 *)p_vout->yuv.p_base + GRAY_MARGIN;
-            for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
-            {
-                p_vout->yuv.yuv.p_gray8[ -i_index ] =      RGB2PIXEL( p_vout, pi_gamma[0], pi_gamma[0], pi_gamma[0] );
-                p_vout->yuv.yuv.p_gray8[ 256 + i_index ] = RGB2PIXEL( p_vout, pi_gamma[255], pi_gamma[255], pi_gamma[255] );
-            }            
-            for( i_index = 0; i_index < 256; i_index++) 
-            {
-                p_vout->yuv.yuv.p_gray8[ i_index ] = RGB2PIXEL( p_vout, pi_gamma[i_index], pi_gamma[i_index], pi_gamma[i_index] );
-            }
             break;        
         case 2:
             p_vout->yuv.yuv.p_gray16 =  (u16 *)p_vout->yuv.p_base + GRAY_MARGIN;
@@ -443,28 +582,6 @@ static void SetYUV( vout_thread_t *p_vout )
         switch( p_vout->i_bytes_per_pixel )
         {
         case 1:
-            p_vout->yuv.yuv.p_rgb8 = (u8 *)p_vout->yuv.p_base;
-            for( i_index = 0; i_index < RED_MARGIN; i_index++ )
-            {
-                p_vout->yuv.yuv.p_rgb8[RED_OFFSET - RED_MARGIN + i_index] = RGB2PIXEL( p_vout, pi_gamma[0], 0, 0 );
-                p_vout->yuv.yuv.p_rgb8[RED_OFFSET + 256 + i_index] =        RGB2PIXEL( p_vout, pi_gamma[255], 0, 0 );
-            }
-            for( i_index = 0; i_index < GREEN_MARGIN; i_index++ )
-            {
-                p_vout->yuv.yuv.p_rgb8[GREEN_OFFSET - GREEN_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[0], 0 );
-                p_vout->yuv.yuv.p_rgb8[GREEN_OFFSET + 256 + i_index] =          RGB2PIXEL( p_vout, 0, pi_gamma[255], 0 );
-            }
-            for( i_index = 0; i_index < BLUE_MARGIN; i_index++ )
-            {
-                p_vout->yuv.yuv.p_rgb8[BLUE_OFFSET - BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[0] );
-                p_vout->yuv.yuv.p_rgb8[BLUE_OFFSET + BLUE_MARGIN + i_index] = RGB2PIXEL( p_vout, 0, 0, pi_gamma[255] );
-            }
-            for( i_index = 0; i_index < 256; i_index++ )
-            {
-                p_vout->yuv.yuv.p_rgb8[RED_OFFSET + i_index] =   RGB2PIXEL( p_vout, pi_gamma[ i_index ], 0, 0 );
-                p_vout->yuv.yuv.p_rgb8[GREEN_OFFSET + i_index] = RGB2PIXEL( p_vout, 0, pi_gamma[ i_index ], 0 );
-                p_vout->yuv.yuv.p_rgb8[BLUE_OFFSET + i_index] =  RGB2PIXEL( p_vout, 0, 0, pi_gamma[ i_index ] ); 
-            }            
             break;        
         case 2:
             p_vout->yuv.yuv.p_rgb16 = (u16 *)p_vout->yuv.p_base;
@@ -691,22 +808,14 @@ static void ConvertY4Gray8( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_y,
          * pixels wide blocks */
         for( i_x = i_width / 16; i_x--;  )
         {
-            *p_buffer++ = *p_y++;
-            *p_buffer++ = *p_y++;
-            *p_buffer++ = *p_y++;
-            *p_buffer++ = *p_y++;
-            *p_buffer++ = *p_y++;
-            *p_buffer++ = *p_y++;
-            *p_buffer++ = *p_y++;
-            *p_buffer++ = *p_y++;
-            *p_buffer++ = *p_y++;
-            *p_buffer++ = *p_y++;
-            *p_buffer++ = *p_y++;
-            *p_buffer++ = *p_y++;
-            *p_buffer++ = *p_y++;
-            *p_buffer++ = *p_y++;
-            *p_buffer++ = *p_y++;
-            *p_buffer++ = *p_y++;
+            *p_buffer++ = *p_y++; *p_buffer++ = *p_y++;
+            *p_buffer++ = *p_y++; *p_buffer++ = *p_y++;
+            *p_buffer++ = *p_y++; *p_buffer++ = *p_y++;
+            *p_buffer++ = *p_y++; *p_buffer++ = *p_y++;
+            *p_buffer++ = *p_y++; *p_buffer++ = *p_y++;
+            *p_buffer++ = *p_y++; *p_buffer++ = *p_y++;
+            *p_buffer++ = *p_y++; *p_buffer++ = *p_y++;
+            *p_buffer++ = *p_y++; *p_buffer++ = *p_y++;
         }             
 
         /* Do horizontal and vertical scaling */
@@ -759,22 +868,14 @@ static void ConvertY4Gray16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y
          * pixels wide blocks */
         for( i_x = i_width / 16; i_x--;  )
         {
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
+            *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
+            *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
+            *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
+            *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
+            *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
+            *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
+            *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
+            *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
         }             
 
         /* Do horizontal and vertical scaling */
@@ -837,22 +938,14 @@ static void ConvertY4Gray32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y
          * pixels wide blocks */
         for( i_x = i_width / 16; i_x--;  )
         {
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
-            *p_buffer++ = p_gray[ *p_y++ ];
+            *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
+            *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
+            *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
+            *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
+            *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
+            *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
+            *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
+            *p_buffer++ = p_gray[ *p_y++ ]; *p_buffer++ = p_gray[ *p_y++ ];
         }             
 
         /* Do horizontal and vertical scaling */
@@ -872,25 +965,32 @@ static void ConvertYUV420RGB8( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_
     int         i_vertical_scaling;                 /* vertical scaling type */
     int         i_x, i_y;                 /* horizontal and vertical indexes */
     int         i_scale_count;                       /* scale modulo counter */
-    int         i_uval, i_vval;                           /* U and V samples */
-    int         i_red, i_green, i_blue;          /* U and V modified samples */
+    int         i_jump_uv;
+    int         i_real_y;
     int         i_chroma_width;                              /* chroma width */
-    u8 *        p_yuv;                              /* base conversion table */
-    u8 *        p_ybase;                     /* Y dependant conversion table */
-    u8 *        p_pic_start;       /* beginning of the current line for copy */
-    u8 *        p_buffer_start;                   /* conversion buffer start */
-    u8 *        p_buffer;                       /* conversion buffer pointer */
-    u8 *        p_foo;                       /* conversion buffer pointer */
     int *       p_offset_start;                        /* offset array start */
     int *       p_offset;                            /* offset array pointer */
     
+    int dither10[4] = { 0x0, 0x8, 0x2, 0xa };
+    int dither11[4] = { 0xc, 0x4, 0xe, 0x6 };
+    int dither12[4] = { 0x3, 0xb, 0x1, 0x9 };
+    int dither13[4] = { 0xf, 0x7, 0xd, 0x5 };
+    int dither20[4] = { 0x00, 0x10, 0x04, 0x14 };
+    int dither21[4] = { 0x18, 0x08, 0x1c, 0x0c };
+    int dither22[4] = { 0x06, 0x16, 0x02, 0x12 };
+    int dither23[4] = { 0x1e, 0x0e, 0x1a, 0x0a };
+
+    //int dither[4][4] = { { 0, 8, 2, 10 }, { 12, 4, 14, 16 }, { 3, 11, 1, 9}, {15, 7, 13, 5} };
+    //int dither[4][4] = { { 7, 8, 0, 15 }, { 0, 15, 8, 7 }, { 7, 0, 15, 8 }, { 15, 7, 8, 0 } };
+    //int dither[4][4] = { { 0, 15, 0, 15 }, { 15, 0, 15, 0 }, { 0, 15, 0, 15 }, { 15, 0, 15, 0 } };
+    //int dither[4][4] = { { 15, 15, 0, 0 }, { 15, 15, 0, 0 }, { 0, 0, 15, 15 }, { 0, 0, 15, 15 } };
+    //int dither[4][4] = { { 8, 8, 8, 8 }, { 8, 8, 8, 8 }, { 8, 8, 8, 8 }, { 8, 8, 8, 8 } };
+    //int dither[4][4] = { { 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 }, { 12, 13, 14, 15 } };
     /* 
      * Initialize some values  - i_pic_line_width will store the line skip 
      */
     i_pic_line_width -= i_pic_width;
     i_chroma_width =    i_width / 2;
-    p_yuv =             p_vout->yuv.yuv.p_rgb8;
-    p_buffer_start =    p_vout->yuv.p_buffer;        
     p_offset_start =    p_vout->yuv.p_offset;                    
     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );
@@ -899,38 +999,12 @@ static void ConvertYUV420RGB8( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_
      * Perform conversion
      */
     i_scale_count = i_pic_height;
+    i_real_y = 0;
     for( i_y = 0; i_y < i_height; i_y++ )
     {
-        /* Mark beginnning of line for possible later line copy, and initialize
-         * buffer */
-        p_pic_start =   p_pic;
-        p_buffer =      b_horizontal_scaling ? p_buffer_start : p_pic;        
-
-        /* Do YUV conversion to buffer - YUV picture is always formed of 16
-         * pixels wide blocks */
-        for( i_x = i_width / 16; i_x--;  )
-        {
-            *p_buffer++ = p_vout->lookup[ ((*p_y++ - 8) >> 4) * 81 + ((*p_u)   >> 5) * 9 + ((*p_v)   >> 5) ];
-            *p_buffer++ = p_vout->lookup[ ((*p_y++ - 8) >> 4) * 81 + ((*p_u++) >> 5) * 9 + ((*p_v++) >> 5) ];
-            *p_buffer++ = p_vout->lookup[ ((*p_y++ - 8) >> 4) * 81 + ((*p_u)   >> 5) * 9 + ((*p_v)   >> 5) ];
-            *p_buffer++ = p_vout->lookup[ ((*p_y++ - 8) >> 4) * 81 + ((*p_u++) >> 5) * 9 + ((*p_v++) >> 5) ];
-            *p_buffer++ = p_vout->lookup[ ((*p_y++ - 8) >> 4) * 81 + ((*p_u)   >> 5) * 9 + ((*p_v)   >> 5) ];
-            *p_buffer++ = p_vout->lookup[ ((*p_y++ - 8) >> 4) * 81 + ((*p_u++) >> 5) * 9 + ((*p_v++) >> 5) ];
-            *p_buffer++ = p_vout->lookup[ ((*p_y++ - 8) >> 4) * 81 + ((*p_u)   >> 5) * 9 + ((*p_v)   >> 5) ];
-            *p_buffer++ = p_vout->lookup[ ((*p_y++ - 8) >> 4) * 81 + ((*p_u++) >> 5) * 9 + ((*p_v++) >> 5) ];
-            *p_buffer++ = p_vout->lookup[ ((*p_y++ - 8) >> 4) * 81 + ((*p_u)   >> 5) * 9 + ((*p_v)   >> 5) ];
-            *p_buffer++ = p_vout->lookup[ ((*p_y++ - 8) >> 4) * 81 + ((*p_u++) >> 5) * 9 + ((*p_v++) >> 5) ];
-            *p_buffer++ = p_vout->lookup[ ((*p_y++ - 8) >> 4) * 81 + ((*p_u)   >> 5) * 9 + ((*p_v)   >> 5) ];
-            *p_buffer++ = p_vout->lookup[ ((*p_y++ - 8) >> 4) * 81 + ((*p_u++) >> 5) * 9 + ((*p_v++) >> 5) ];
-            *p_buffer++ = p_vout->lookup[ ((*p_y++ - 8) >> 4) * 81 + ((*p_u)   >> 5) * 9 + ((*p_v)   >> 5) ];
-            *p_buffer++ = p_vout->lookup[ ((*p_y++ - 8) >> 4) * 81 + ((*p_u++) >> 5) * 9 + ((*p_v++) >> 5) ];
-            *p_buffer++ = p_vout->lookup[ ((*p_y++ - 8) >> 4) * 81 + ((*p_u)   >> 5) * 9 + ((*p_v)   >> 5) ];
-            *p_buffer++ = p_vout->lookup[ ((*p_y++ - 8) >> 4) * 81 + ((*p_u++) >> 5) * 9 + ((*p_v++) >> 5) ];
-        }             
-
         /* Do horizontal and vertical scaling */
-        SCALE_WIDTH;
-        SCALE_HEIGHT(420, 1);        
+        SCALE_WIDTH_DITHER( 420 );
+        SCALE_HEIGHT_DITHER( 420 );
     }
 }