]> git.sesse.net Git - vlc/commitdiff
. gestion du gamma en 8bpp grayscale
authorSam Hocevar <sam@videolan.org>
Tue, 8 Feb 2000 05:08:15 +0000 (05:08 +0000)
committerSam Hocevar <sam@videolan.org>
Tue, 8 Feb 2000 05:08:15 +0000 (05:08 +0000)
 . optimisations dans la YUV 8bpp
 . l'output framebuffer ne bloque plus la console
 . rajout d'une fonction dans la structure vout pour allouer une palette
 . r�initialisation de l'ancienne palette en quittant

bugs restant:
 . pas d'allocation de palette en 8bits sous X11
 . bugs du scaling en 8bits sous X11 (sans doute d� � l'alignement sur 1
  octet au lieu de 2)
 . l'output framebuffer est toujours p�t�e pour 16 et 32 bits
 . pas de correction gamma en 8bits couleur
 . c'est tout moche pendant la fraction de seconde du changement de palette

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

index cc23c514d4db4e9be8bc31112f0cb6153809fea2..288645b8d28de9a7e869fdf978717361abc746c7 100644 (file)
@@ -41,7 +41,7 @@ typedef struct vout_yuv_s
     vout_yuv_convert_t *        p_Convert444;          /* YUV 4:4:4 converter */
 
     /* Pre-calculated convertion tables */
-    void *              p_base;             /* base for all convertion tables */    
+    void *              p_base;             /* base for all conversion tables */
     union
     {
         u8 *            p_gray8;                         /* gray 8 bits table */
@@ -54,7 +54,7 @@ typedef struct vout_yuv_s
 
     /* Temporary convertion buffer and offset array */
     void *              p_buffer;                        /* convertion buffer */
-    int *               p_offset;                             /* offset array */    
+    int *               p_offset;                             /* offset array */
 } vout_yuv_t;
 
 /*******************************************************************************
@@ -85,6 +85,9 @@ typedef struct vout_buffer_s
  * is represented by a video output thread, and described using following 
  * structure.
  *******************************************************************************/
+typedef void (vout_set_palette_t)( p_vout_thread_t p_vout,
+                                   u16 *red, u16 *green, u16 *blue, u16 *transp );
+
 typedef struct vout_thread_s
 {
     /* Thread properties and lock */
@@ -123,15 +126,13 @@ typedef struct vout_thread_s
     u32                 i_black_pixel;                               /* black */
     u32                 i_gray_pixel;                                 /* gray */
     u32                 i_blue_pixel;                                 /* blue */
-    
-    /* Palette */
-    u8                  lookup[2176];       /* lookup table for 8 bpp palette */
 
     /* Pictures and rendering properties */
     boolean_t           b_grayscale;            /* color or grayscale display */
     boolean_t           b_info;             /* print additionnal informations */
     boolean_t           b_interface;                      /* render interface */
     boolean_t           b_scale;                     /* allow picture scaling */
+    vout_set_palette_t *p_set_palette;                   /* sets 8bpp palette */
 
     /* Idle screens management */
     mtime_t             last_display_date;      /* last non idle display date */
index c329d99feb036ff2e44b3bfc57d186c575af11fd..e56f03f80cd1421db60d2514d148f6a57336647c 100644 (file)
@@ -210,22 +210,23 @@ int intf_SelectChannel( intf_thread_t * p_intf, int i_channel )
     return( 1 );    
 }
 
-/*******************************************************************************
+/*****************************************************************************
  * intf_ProcessKey: process standard keys
- *******************************************************************************
+ *****************************************************************************
  * This function will process standard keys and return non 0 if the key was
  * unknown.
- *******************************************************************************/
+ *****************************************************************************/
 int intf_ProcessKey( intf_thread_t *p_intf, int i_key )
 {
     switch( i_key )
     {
-    case 'Q':                                                    /* quit order */
+    case 'Q':                                                  /* quit order */
     case 'q':
-    case 27: /* escape key */
+    case 27:                                                   /* escape key */
+    case 3:                                                            /* ^C */
         p_intf->b_die = 1;
         break;  
-    case '0':                                                 /* source change */
+    case '0':                                               /* source change */
     case '1':
     case '2':
     case '3':
@@ -239,17 +240,17 @@ int intf_ProcessKey( intf_thread_t *p_intf, int i_key )
          * its own error messages */
         intf_SelectChannel( p_intf, i_key - '0' );        
         break;
-    case '+':                                                      /* volume + */
+    case '+':                                                    /* volume + */
         // ??
         break;
-    case '-':                                                      /* volume - */
+    case '-':                                                    /* volume - */
         // ??
         break;
-    case 'M':                                                   /* toggle mute */
+    case 'M':                                                 /* toggle mute */
     case 'm':                    
         // ??
         break;     
-    case 'g':                                                       /* gamma - */
+    case 'g':                                                     /* gamma - */
         if( (p_intf->p_vout != NULL) && (p_intf->p_vout->f_gamma > -INTF_GAMMA_LIMIT) )
         {
             vlc_mutex_lock( &p_intf->p_vout->change_lock );
@@ -258,7 +259,7 @@ int intf_ProcessKey( intf_thread_t *p_intf, int i_key )
             vlc_mutex_unlock( &p_intf->p_vout->change_lock );
         }                    
         break;                                        
-    case 'G':                                                       /* gamma + */
+    case 'G':                                                     /* gamma + */
         if( (p_intf->p_vout != NULL) && (p_intf->p_vout->f_gamma < INTF_GAMMA_LIMIT) )
         {       
             vlc_mutex_lock( &p_intf->p_vout->change_lock );
@@ -267,7 +268,7 @@ int intf_ProcessKey( intf_thread_t *p_intf, int i_key )
             vlc_mutex_unlock( &p_intf->p_vout->change_lock );
         }                    
         break;  
-    case 'c':                                              /* toggle grayscale */
+    case 'c':                                            /* toggle grayscale */
         if( p_intf->p_vout != NULL )
         {
             vlc_mutex_lock( &p_intf->p_vout->change_lock );                        
@@ -276,7 +277,7 @@ int intf_ProcessKey( intf_thread_t *p_intf, int i_key )
             vlc_mutex_unlock( &p_intf->p_vout->change_lock );      
         }
         break;  
-    case ' ':                                              /* toggle interface */
+    case ' ':                                            /* toggle interface */
         if( p_intf->p_vout != NULL )
         {
             vlc_mutex_lock( &p_intf->p_vout->change_lock );                        
@@ -285,7 +286,7 @@ int intf_ProcessKey( intf_thread_t *p_intf, int i_key )
             vlc_mutex_unlock( &p_intf->p_vout->change_lock );      
         }
         break;                                
-    case 'i':                                                   /* toggle info */
+    case 'i':                                                 /* toggle info */
         if( p_intf->p_vout != NULL )
         {
             vlc_mutex_lock( &p_intf->p_vout->change_lock );                        
@@ -294,7 +295,7 @@ int intf_ProcessKey( intf_thread_t *p_intf, int i_key )
             vlc_mutex_unlock( &p_intf->p_vout->change_lock );      
         }
         break;                                
-    case 's':                                                 /* toggle scaling */
+    case 's':                                              /* toggle scaling */
         if( p_intf->p_vout != NULL )
         {
             vlc_mutex_lock( &p_intf->p_vout->change_lock );                        
@@ -303,7 +304,7 @@ int intf_ProcessKey( intf_thread_t *p_intf, int i_key )
             vlc_mutex_unlock( &p_intf->p_vout->change_lock );      
         }
         break;                                
-   default:                                                    /* unknown key */
+   default:                                                   /* unknown key */
         return( 1 );        
     }
 
index f2a2445ccca1483e41974817c8fe0cbbf39afcaf..217ef5dc6af813472ccea8f35364324a2400ee57 100644 (file)
@@ -67,8 +67,8 @@ typedef struct vout_sys_s
  ******************************************************************************/
 static int     FBOpenDisplay   ( vout_thread_t *p_vout );
 static void    FBCloseDisplay  ( vout_thread_t *p_vout );
-static void    FBInitBWPalette ( vout_thread_t *p_vout );
-static void    FBInitRGBPalette( vout_thread_t *p_vout );
+static void    FBSetPalette    ( p_vout_thread_t p_vout,
+                                 u16 *red, u16 *green, u16 *blue, u16 *transp );
 
 /******************************************************************************
  * vout_SysCreate: allocates FB video thread output method
@@ -101,6 +101,7 @@ int vout_SysCreate( vout_thread_t *p_vout, char *psz_display, int i_root_window
  ******************************************************************************/
 int vout_SysInit( vout_thread_t *p_vout )
 {
+    p_vout->p_set_palette       = FBSetPalette;
     return( 0 );
 }
 
@@ -230,8 +231,8 @@ static int FBOpenDisplay( vout_thread_t *p_vout )
         ioctl( p_vout->p_sys->i_fb_dev, FBIOGETCMAP, &p_vout->p_sys->fb_cmap );
 
         /* initializes black & white palette */
+        //FBInitRGBPalette( p_vout );
        //FBInitBWPalette( p_vout );
-        FBInitRGBPalette( p_vout );
 
         p_vout->i_bytes_per_pixel = 1;
         p_vout->i_bytes_per_line = p_vout->i_width;
@@ -301,116 +302,16 @@ static void FBCloseDisplay( vout_thread_t *p_vout )
     close( p_vout->p_sys->i_fb_dev );    
 }
 
-/*****************************************************************************
- * FBInitRGBPalette: initialize color palette for 8 bpp
- *****************************************************************************/
-static void FBInitRGBPalette( vout_thread_t *p_vout )
+/******************************************************************************
+ * FBSetPalette: sets an 8 bpp palette
+ ******************************************************************************
+ * This function is just a prototype that does nothing. Architectures that
+ * support palette allocation should override it.
+ ******************************************************************************/
+static void    FBSetPalette   ( p_vout_thread_t p_vout,
+                                u16 *red, u16 *green, u16 *blue, u16 *transp )
 {
-    #define SATURATE( x )    \
-    x = x + ( x >> 3 ) - 16; \
-    if( x < 0 ) x = 0;       \
-    if( x > 255 ) x = 255;
-
-    int y,u,v;
-    int r,g,b;
-    int uvRed, uvGreen, uvBlue;
-    unsigned int counter = 0;
-    unsigned int allocated = 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 = 0; u <= 256; u += 32 )
-        for ( v = 0; v <= 256; v += 32 )
-        {
-            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;
-            }
-        }
-        counter += 128-81;
-    }
-
-    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 );
-}
-
-/*****************************************************************************
- * FBInitBWPalette: initialize grayscale palette for 8 bpp
- *****************************************************************************/
-static void FBInitBWPalette( vout_thread_t *p_vout )
-{
-    unsigned int i;
-    unsigned short gamma[256], transp[256];
-    struct fb_cmap cmap = { 0, 256, gamma, gamma, gamma, transp };
-
-    for( i=0; i<256; i++ )
-    {
-        gamma[i] = i << 8;
-        transp[i] = 0;
-    }
-
     ioctl( p_vout->p_sys->i_fb_dev, FBIOPUTCMAP, &cmap );
 }
 
index ec4fa366996a3485a10b1453c25230a8c8844db3..f0c5414282edb3c302d515118cf26d86d15a4def 100644 (file)
@@ -54,6 +54,8 @@ static int      Manage            ( vout_thread_t *p_vout );
 static int      Align             ( vout_thread_t *p_vout, int *pi_x,
                                     int *pi_y, int i_width, int i_height,
                                     int i_h_align, int i_v_align );
+static void     SetPalette        ( p_vout_thread_t p_vout, u16 *red,
+                                    u16 *green, u16 *blue, u16 *transp );
 
 /******************************************************************************
  * vout_CreateThread: creates a new video output thread
@@ -101,6 +103,8 @@ vout_thread_t * vout_CreateThread               ( char *psz_display, int i_root_
     p_vout->b_info              = 0;    
     p_vout->b_interface         = 0;
     p_vout->b_scale             = 0;
+
+    p_vout->p_set_palette       = SetPalette;
     
     intf_DbgMsg("wished configuration: %dx%d, %d/%d bpp (%d Bpl)\n",
                 p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth,
@@ -146,12 +150,12 @@ vout_thread_t * vout_CreateThread               ( char *psz_display, int i_root_
     MaskToShift( &p_vout->i_green_lshift, &p_vout->i_green_rshift, p_vout->i_green_mask );
     MaskToShift( &p_vout->i_blue_lshift,  &p_vout->i_blue_rshift,  p_vout->i_blue_mask );
 
-    /* Set some usefull colors */
-    p_vout->i_white_pixel = RGB2PIXEL( p_vout, 255, 255, 255 );
+    /* Set some useful colors */
+/*    p_vout->i_white_pixel = RGB2PIXEL( p_vout, 255, 255, 255 );
     p_vout->i_black_pixel = RGB2PIXEL( p_vout, 0, 0, 0 );
     p_vout->i_gray_pixel  = RGB2PIXEL( p_vout, 128, 128, 128 );
     p_vout->i_blue_pixel  = RGB2PIXEL( p_vout, 0, 0, 50 );    
-
+*/
     /* Load fonts - fonts must be initialized after the systme method since
      * they may be dependant of screen depth and other thread properties */
     p_vout->p_default_font      = vout_LoadFont( VOUT_DEFAULT_FONT );    
@@ -1880,3 +1884,15 @@ static int Align( vout_thread_t *p_vout, int *pi_x, int *pi_y,
             (*pi_x + i_width > p_vout->i_width) || (*pi_y + i_height > p_vout->i_height) );    
 }
 
+/******************************************************************************
+ * SetPalette: sets an 8 bpp palette
+ ******************************************************************************
+ * This function is just a prototype that does nothing. Architectures that
+ * support palette allocation should override it.
+ ******************************************************************************/
+static void     SetPalette        ( p_vout_thread_t p_vout, u16 *red,
+                                    u16 *green, u16 *blue, u16 *transp )
+{
+    intf_ErrMsg( "SetPalette: method does not support palette changing\n" );
+}
+
index 900ffce8b5c35c72fb9a370d1667727766e988a3..61ca913839552c14bebb744bf67594af3428f462 100644 (file)
@@ -333,12 +333,12 @@ void vout_TextSize( vout_font_t *p_font, int i_style, const char *psz_text, int
     }
 }
 
-/*******************************************************************************
+/*****************************************************************************
  * vout_Print: low level printing function
 *******************************************************************************
- * This function prints a text, without clipping, in a buffer using a previously
- * loaded bitmap font.
- *******************************************************************************/
+ *****************************************************************************
+ * This function prints a text, without clipping, in a buffer using a
+ * previously loaded bitmap font.
+ *****************************************************************************/
 void vout_Print( vout_font_t *p_font, byte_t *p_pic, int i_bytes_per_pixel, int i_bytes_per_line, 
                  u32 i_char_color, u32 i_border_color, u32 i_bg_color, int i_style, const char *psz_text )
 {
index d5938880b94dc4dd2ba712753bfb49ccb40add54..5f752f2ea6bb78b0cb8f5a0bb163ef990ac99fac 100644 (file)
@@ -68,13 +68,15 @@ const int MATRIX_COEFFICIENTS_TABLE[8][4] =
 #define RED_MARGIN      178
 #define GREEN_MARGIN    135
 #define BLUE_MARGIN     224
-#define RED_OFFSET      1501                                   /* 1323 to 1935 */
-#define GREEN_OFFSET    135                                        /* 0 to 526 */
-#define BLUE_OFFSET     818                                     /* 594 to 1298 */
-#define RGB_TABLE_SIZE  1935                               /* total table size */
+#define RED_OFFSET      1501                                 /* 1323 to 1935 */
+#define GREEN_OFFSET    135                                      /* 0 to 526 */
+#define BLUE_OFFSET     818                                   /* 594 to 1298 */
+#define RGB_TABLE_SIZE  1935                             /* total table size */
 
 #define GRAY_MARGIN     384
-#define GRAY_TABLE_SIZE 1024                               /* total table size */
+#define GRAY_TABLE_SIZE 1024                             /* total table size */
+
+#define PALETTE_TABLE_SIZE 2176          /* YUV -> 8bpp palette lookup table */
 
 //??
 #define SHIFT 20
@@ -83,9 +85,9 @@ const int MATRIX_COEFFICIENTS_TABLE[8][4] =
 #define V_RED_COEF      ((int)(1.596 * (1<<SHIFT) / 1.164))
 #define V_GREEN_COEF    ((int)(-0.813 * (1<<SHIFT) / 1.164))
 
-/*******************************************************************************
+/*****************************************************************************
  * Local prototypes
- *******************************************************************************/
+ *****************************************************************************/
 static void     SetGammaTable     ( int *pi_table, double f_gamma );
 static void     SetYUV            ( vout_thread_t *p_vout );
 static void     SetOffset         ( int i_width, int i_height, int i_pic_width, int i_pic_height, 
@@ -169,56 +171,56 @@ static void     ConvertYUV444RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data
  * These macros dither 4 pixels in 8 bpp, with or without horiz. scaling
  *****************************************************************************/
 #define CONVERT_4YUV_PIXELS( CHROMA )                                         \
-    *p_pic++ = p_vout->lookup[                                                \
+    *p_pic++ = p_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_pic++ = p_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_pic++ = p_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_pic++ = p_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_pic++ = p_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;                                \
+    b_jump_uv = (b_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_u += *p_offset   & b_jump_uv;                                           \
+    p_v += *p_offset++ & b_jump_uv;                                           \
+    *p_pic++ = p_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;                                \
+    b_jump_uv = (b_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_u += *p_offset   & b_jump_uv;                                           \
+    p_v += *p_offset++ & b_jump_uv;                                           \
+    *p_pic++ = p_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;                                \
+    b_jump_uv = (b_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_u += *p_offset   & b_jump_uv;                                           \
+    p_v += *p_offset++ & b_jump_uv;                                           \
+    *p_pic++ = p_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;                                \
+    b_jump_uv = (b_jump_uv + *p_offset) & 0x1;                                \
     p_y += *p_offset;                                                         \
-    p_u += *p_offset   & i_jump_uv;                                           \
-    p_v += *p_offset++ & i_jump_uv;                                           \
+    p_u += *p_offset   & b_jump_uv;                                           \
+    p_v += *p_offset++ & b_jump_uv;                                           \
 
 /*****************************************************************************
  * SCALE_WIDTH: scale a line horizontally
@@ -272,7 +274,7 @@ static void     ConvertYUV444RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data
     {                                                                         \
         /* Horizontal scaling, but we can't use a buffer due to dither */     \
         p_offset = p_offset_start;                                            \
-       i_jump_uv = 0;                                                        \
+       b_jump_uv = 0;                                                        \
         for( i_x = i_pic_width / 16; i_x--; )                                 \
         {                                                                     \
             CONVERT_4YUV_PIXELS_SCALE( CHROMA )                               \
@@ -440,8 +442,7 @@ int vout_InitYUV( vout_thread_t *p_vout )
     switch( p_vout->i_bytes_per_pixel )
     {
     case 1:
-        /* nothing to allocate - will put the palette here afterwards */
-        tables_size = 1;
+        tables_size = sizeof( u8 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : PALETTE_TABLE_SIZE);
         break;        
     case 2:
         tables_size = sizeof( u16 ) * (p_vout->b_grayscale ? GRAY_TABLE_SIZE : RGB_TABLE_SIZE);
@@ -519,7 +520,7 @@ static void SetGammaTable( int *pi_table, double f_gamma )
     int         i_y;                                       /* base intensity */
 
     /* Use exp(gamma) instead of gamma */
-    f_gamma = exp(f_gamma );
+    f_gamma = exp( f_gamma );
 
     /* Build gamma table */
     for( i_y = 0; i_y < 256; i_y++ )
@@ -548,7 +549,30 @@ static void SetYUV( vout_thread_t *p_vout )
         switch( p_vout->i_bytes_per_pixel )
         {
         case 1:
-            break;        
+            {
+                u16 bright[256], transp[256];
+
+                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 ] = pi_gamma[ i_index ];
+                    bright[ i_index ] = i_index << 8;
+                    transp[ i_index ] = 0;
+                }
+                /* the colors have been allocated, we can set the palette */
+                p_vout->p_set_palette( p_vout, bright, bright, bright, transp );
+                p_vout->i_white_pixel = 0xff;
+                p_vout->i_black_pixel = 0x00;
+                p_vout->i_gray_pixel = 0x44;
+                p_vout->i_blue_pixel = 0x3b;
+
+                break;        
+            }
         case 2:
             p_vout->yuv.yuv.p_gray16 =  (u16 *)p_vout->yuv.p_base + GRAY_MARGIN;
             for( i_index = 0; i_index < GRAY_MARGIN; i_index++ )
@@ -582,7 +606,123 @@ static void SetYUV( vout_thread_t *p_vout )
         switch( p_vout->i_bytes_per_pixel )
         {
         case 1:
-            break;        
+            {
+                #define RGB_MIN 0
+                #define RGB_MAX 255
+                #define SATURATE( x )    \
+                x = x + ( x >> 3 ) - 16; \
+                if( x < 0 ) x = 0;       \
+                if( x > 255 ) x = 255;
+    
+                int y,u,v;
+                int r,g,b;
+                int uvr, uvg, uvb;
+                int i = 0, j = 0;
+                u16 red[256], green[256], blue[256], transp[256];
+                unsigned char lookup[PALETTE_TABLE_SIZE];
+    
+                p_vout->yuv.yuv.p_rgb8 = (u8 *)p_vout->yuv.p_base;
+    
+                /* this loop calculates the intersection of an YUV box
+                 * and the RGB cube. */
+                for ( y = 0; y <= 256; y += 16 )
+                {
+                    for ( u = 0; u <= 256; u += 32 )
+                    for ( v = 0; v <= 256; v += 32 )
+                    {
+                        uvr = (V_RED_COEF*(v-128)) >> SHIFT;
+                        uvg = (U_GREEN_COEF*(u-128) + V_GREEN_COEF*(v-128)) >> SHIFT;
+                        uvb = (U_BLUE_COEF*(u-128)) >> SHIFT;
+                        r = y + uvr;
+                        g = y + uvg;
+                        b = y + uvb;
+    
+                        if( r >= RGB_MIN && g >= RGB_MIN && b >= RGB_MIN
+                                && r <= RGB_MAX && g <= RGB_MAX && b <= RGB_MAX )
+                        {
+                            /* this one should never happen unless someone fscked up my code */
+                            if(j == 256) { intf_DbgMsg( "sorry, no colors left\n" ); exit( 1 ); }
+    
+                            /* saturate the colors */
+                            SATURATE( r );
+                            SATURATE( g );
+                            SATURATE( b );
+    
+                            red[j] = r << 8;
+                            green[j] = g << 8;
+                            blue[j] = b << 8;
+                            transp[j] = 0;
+    
+                            /* allocate color */
+                            lookup[i] = 1;
+                            p_vout->yuv.yuv.p_rgb8[i++] = j;
+                            j++;
+                        }
+                        else
+                        {
+                            lookup[i] = 0;
+                            p_vout->yuv.yuv.p_rgb8[i++] = 0;
+                        }
+                    }
+                    i += 128-81;
+                }
+
+                /* the colors have been allocated, we can set the palette */
+                /* there will eventually be a way to know which colors
+                 * couldn't be allocated and try to find a replacement */
+                p_vout->p_set_palette( p_vout, red, green, blue, transp );
+
+                p_vout->i_white_pixel = 0xff;
+                p_vout->i_black_pixel = 0x00;
+                p_vout->i_gray_pixel = 0x44;
+                p_vout->i_blue_pixel = 0x3b;
+
+                i = 0;
+                /* this loop allocates colors that got outside
+                 * the RGB cube */
+                for ( y = 0; y <= 256; y += 16 )
+                {
+                    for ( u = 0; u <= 256; u += 32 )
+                    for ( v = 0; v <= 256; v += 32 )
+                    {
+                        int u2, v2;
+                        int dist, mindist = 100000000;
+    
+                        if( lookup[i] || y==0)
+                        {
+                            i++;
+                            continue;
+                        }
+                                                                                                                   
+                        /* heavy. yeah. */
+                        for( u2 = 0; u2 <= 256; u2 += 32 )
+                        for( v2 = 0; v2 <= 256; v2 += 32 )
+                        {
+                            j = ((y>>4)<<7) + (u2>>5)*9 + (v2>>5);
+                            dist = (u-u2)*(u-u2) + (v-v2)*(v-v2);
+                            if( lookup[j] )
+                            /* find the nearest color */
+                            if( dist < mindist )
+                            {
+                                p_vout->yuv.yuv.p_rgb8[i] = p_vout->yuv.yuv.p_rgb8[j];
+                                mindist = dist;
+                            }
+                            j -= 128;
+                            if( lookup[j] )
+                            /* find the nearest color */
+                            if( dist + 128 < mindist )
+                            {
+                                p_vout->yuv.yuv.p_rgb8[i] = p_vout->yuv.yuv.p_rgb8[j];
+                                mindist = dist + 128;
+                            }
+                        }
+                        i++;
+                    }
+                    i += 128-81;
+                }
+
+                break;        
+            }
         case 2:
             p_vout->yuv.yuv.p_rgb16 = (u16 *)p_vout->yuv.p_base;
             for( i_index = 0; i_index < RED_MARGIN; i_index++ )
@@ -808,14 +948,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_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 */
@@ -965,8 +1105,9 @@ 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_jump_uv;
-    int         i_real_y;
+    int         b_jump_uv;                       /* should we jump u and v ? */
+    int         i_real_y;                                           /* y % 4 */
+    u8 *        p_lookup;                                    /* lookup table */
     int         i_chroma_width;                              /* chroma width */
     int *       p_offset_start;                        /* offset array start */
     int *       p_offset;                            /* offset array pointer */
@@ -980,6 +1121,7 @@ static void ConvertYUV420RGB8( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_
     int dither22[4] = { 0x06, 0x16, 0x02, 0x12 };
     int dither23[4] = { 0x1e, 0x0e, 0x1a, 0x0a };
 
+    /* other matrices that can be interesting, either for debugging or for effects */
     //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 } };
@@ -991,7 +1133,8 @@ static void ConvertYUV420RGB8( p_vout_thread_t p_vout, u8 *p_pic, yuv_data_t *p_
      */
     i_pic_line_width -= i_pic_width;
     i_chroma_width =    i_width / 2;
-    p_offset_start =    p_vout->yuv.p_offset;                    
+    p_offset_start =    p_vout->yuv.p_offset;
+    p_lookup =          p_vout->yuv.p_base;
     SetOffset( i_width, i_height, i_pic_width, i_pic_height, 
                &b_horizontal_scaling, &i_vertical_scaling, p_offset_start );