/*******************************************************************************
* Preamble
*******************************************************************************/
-#include <errno.h>
+#include <errno.h>
+#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
* not change much for two different loops. This macro allows to change slightly
* the content of the loop without having to copy and paste code. It is used in
* RenderYUVPicture function. */
-#define YUV_GRAYSCALE( TRANS_RED, TRANS_GREEN, TRANS_BLUE, P_PIC ) \
+#define YUV_GRAYSCALE( TRANS_GRAY, P_PIC ) \
/* Main loop */ \
for (i_pic_y=0; i_pic_y < p_pic->i_height ; i_pic_y++) \
{ \
- for (i_pic_x=0; i_pic_x< p_pic->i_width; i_pic_x++) \
+ for (i_pic_x=0; i_pic_x< p_pic->i_width; i_pic_x+=16) \
{ \
- i_y = *p_y++; \
- *P_PIC++ = TRANS_RED[i_y] | TRANS_GREEN[i_y] | TRANS_BLUE[i_y]; \
+ /* Convert 16 pixels (width is always multiple of 16 */ \
+ *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \
+ *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \
+ *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \
+ *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \
+ *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \
+ *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \
+ *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \
+ *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \
+ *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \
+ *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \
+ *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \
+ *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \
+ *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \
+ *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \
+ *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \
+ *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \
} \
/* Skip until beginning of next line */ \
P_PIC += i_eol_offset; \
/* Main loop */ \
for (i_pic_y=0; i_pic_y < p_pic->i_height ; i_pic_y++) \
{ \
- for (i_pic_x=0; i_pic_x< p_pic->i_width; i_pic_x+=2) \
+ for (i_pic_x=0; i_pic_x< p_pic->i_width; i_pic_x+=2 ) \
{ \
/* First sample (complete) */ \
i_y = 76309 * *p_y++ - 1188177; \
* i_width, i_height: frames dimensions (pixels)
* i_ypitch, i_vpitch: Y and V lines sizes (bytes)
* i_aspect: vertical aspect factor
- * pi_pic: RGB frame
+ * p_pic: RGB frame
* i_dci_offset: ?? x offset for left image border
* i_offset_to_line_0: ?? x offset for left image border
* i_pitch: RGB line size (bytes)
void vout_YUV420_16_MMX( u8* p_y, u8* p_u, u8 *p_v,
unsigned int i_width, unsigned int i_height,
unsigned int i_ypitch, unsigned int i_vpitch,
- unsigned int i_aspect, u8 *pi_pic,
+ unsigned int i_aspect, u8 *p_pic,
u32 i_dci_offset, u32 i_offset_to_line_0,
int CCOPitch, int i_colortype );
#endif
static void RunThread ( vout_thread_t *p_vout );
static void ErrorThread ( vout_thread_t *p_vout );
static void EndThread ( vout_thread_t *p_vout );
+static void BuildTables ( vout_thread_t *p_vout );
static void RenderPicture ( vout_thread_t *p_vout, picture_t *p_pic );
static void RenderYUVGrayPicture ( vout_thread_t *p_vout, picture_t *p_pic );
static void RenderYUV16Picture ( vout_thread_t *p_vout, picture_t *p_pic );
p_vout->i_bytes_per_pixel = 2;
p_vout->f_x_ratio = 1;
p_vout->f_y_ratio = 1;
+ p_vout->f_gamma = VOUT_GAMMA;
intf_DbgMsg("wished configuration: %dx%d,%d (%d bytes/pixel, %d bytes/line), ratio %.2f:%.2f, gray=%d\n",
p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth,
p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
p_vout->c_idle_loops = 0;
p_vout->c_fps_samples = 0;
#endif
+ p_vout->b_gamma_change = 0;
+ p_vout->i_new_width = p_vout->i_width;
+ p_vout->i_new_height = p_vout->i_height;
/* Create thread and set locks */
vlc_mutex_init( &p_vout->lock );
static int InitThread( vout_thread_t *p_vout )
{
int i_index; /* generic index */
- int i_pixel_size; /* pixel size, in bytes, for translations tables */
/* Update status */
*p_vout->pi_status = THREAD_START;
}
/* Allocate translation tables */
- switch( p_vout->i_bytes_per_pixel )
+ p_vout->p_trans_base = malloc( 4 * 1024 * p_vout->i_bytes_per_pixel );
+ if( p_vout->p_trans_base == NULL )
{
- case 2: /* 15 or 16 bpp, use 16 bits translations tables */
- i_pixel_size = sizeof( u16 );
- break;
- case 3: /* 24 or 32 bpp, use 32 bits translations tables */
- case 4:
-#ifndef DEBUG
- default:
-#endif
- i_pixel_size = sizeof( u32 );
- break;
-#ifdef DEBUG
- default:
- intf_DbgMsg("error: invalid bytes_per_pixel %d\n", p_vout->i_bytes_per_pixel );
- i_pixel_size = sizeof( u32 );
- break;
-#endif
+ intf_ErrMsg("error: %s\n", strerror(ENOMEM));
+ return( 1 );
}
- p_vout->pi_trans32_red = (u32 *)p_vout->pi_trans16_red =
- (u16 *)malloc( 1024 * i_pixel_size );
- p_vout->pi_trans32_green = (u32 *)p_vout->pi_trans16_green =
- (u16 *)malloc( 1024 * i_pixel_size );
- p_vout->pi_trans32_blue = (u32 *)p_vout->pi_trans16_blue =
- (u16 *)malloc( 1024 * i_pixel_size );
- if( (p_vout->pi_trans16_red == NULL) ||
- (p_vout->pi_trans16_green == NULL ) ||
- (p_vout->pi_trans16_blue == NULL ) )
- {
- intf_ErrMsg("error: %s\n", strerror(ENOMEM) );
- *p_vout->pi_status = THREAD_ERROR;
- if( p_vout->pi_trans16_red != NULL )
- {
- free( p_vout->pi_trans16_red );
- }
- if( p_vout->pi_trans16_green != NULL )
- {
- free( p_vout->pi_trans16_green );
- }
- if( p_vout->pi_trans16_blue != NULL )
- {
- free( p_vout->pi_trans16_blue );
- }
- return( 1 );
- }
+ p_vout->p_trans_red = p_vout->p_trans_base + 384 *p_vout->i_bytes_per_pixel;
+ p_vout->p_trans_green = p_vout->p_trans_base + ( 1024 + 384)*p_vout->i_bytes_per_pixel;
+ p_vout->p_trans_blue = p_vout->p_trans_base + (2*1024 + 384)*p_vout->i_bytes_per_pixel;
+ p_vout->p_trans_gray = p_vout->p_trans_base + (3*1024 + 384)*p_vout->i_bytes_per_pixel;
- /* Translate translation tables */
- p_vout->pi_trans16_red += 384;
- p_vout->pi_trans16_green += 384;
- p_vout->pi_trans16_blue += 384;
- p_vout->pi_trans32_red += 384;
- p_vout->pi_trans32_green += 384;
- p_vout->pi_trans32_blue += 384;
-
/* Build translation tables */
- switch( p_vout->i_screen_depth )
- {
- case 15:
- for( i_index = -384; i_index < 640; i_index++)
- {
- p_vout->pi_trans16_red[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<7;
- p_vout->pi_trans16_green[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<2;
- p_vout->pi_trans16_blue[i_index] = CLIP_BYTE( i_index ) >> 3;
- }
- break;
- case 16:
- for( i_index = -384; i_index < 640; i_index++)
- {
- p_vout->pi_trans16_red[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<8;
- p_vout->pi_trans16_green[i_index] = (CLIP_BYTE( i_index ) & 0xfc)<<3;
- p_vout->pi_trans16_blue[i_index] = CLIP_BYTE( i_index ) >> 3;
- }
- break;
- case 24:
- case 32:
- for( i_index = -384; i_index < 640; i_index++)
- {
- p_vout->pi_trans32_red[i_index] = CLIP_BYTE( i_index ) <<16;
- p_vout->pi_trans32_green[i_index] = CLIP_BYTE( i_index ) <<8;
- p_vout->pi_trans32_blue[i_index] = CLIP_BYTE( i_index ) ;
- }
- break;
-#ifdef DEBUG
- default:
- intf_DbgMsg("error: invalid screen depth %d\n", p_vout->i_screen_depth );
- break;
-#endif
- }
+ BuildTables( p_vout );
/* Mark thread as running and return */
p_vout->b_active = 1;
}
}
+ /*
+ * Rebuild tables if gamma has changed
+ */
+ if( p_vout->b_gamma_change )
+ {
+ p_vout->b_gamma_change = 0;
+ BuildTables( p_vout );
+ }
+
/*
* Check events, sleep and display picture
*/
}
}
- /* Destroy translation tables - remeber these tables are translated */
- free( p_vout->pi_trans16_red - 384 );
- free( p_vout->pi_trans16_green - 384 );
- free( p_vout->pi_trans16_blue - 384 );
+ /* Destroy translation tables */
+ free( p_vout->p_trans_base );
/* Destroy thread structures allocated by InitThread */
vout_SysEnd( p_vout );
*pi_status = THREAD_OVER;
}
+/*******************************************************************************
+ * BuildTables: build YUV translation tables
+ *******************************************************************************
+ * This function will build translations tables according to pixel width and
+ * gamma.
+ *******************************************************************************/
+static void BuildTables( vout_thread_t *p_vout )
+{
+ u16 * p_trans16_red = (u16 *) p_vout->p_trans_red;
+ u16 * p_trans16_green = (u16 *) p_vout->p_trans_green;
+ u16 * p_trans16_blue = (u16 *) p_vout->p_trans_blue;
+ u16 * p_trans16_gray = (u16 *) p_vout->p_trans_gray;
+ u32 * p_trans32_red = (u32 *) p_vout->p_trans_red;
+ u32 * p_trans32_green = (u32 *) p_vout->p_trans_green;
+ u32 * p_trans32_blue = (u32 *) p_vout->p_trans_blue;
+ u32 * p_trans32_gray = (u32 *) p_vout->p_trans_gray;
+ u8 i_gamma[256]; /* gamma table */
+ int i_index; /* index in tables */
+
+ /* Build gamma table */
+ for( i_index = 0; i_index < 256; i_index++ )
+ {
+ i_gamma[i_index] = 255. * pow( (double)i_index / 255., p_vout->f_gamma );
+ }
+
+ /* Build red, green, blue and gray tables */
+ switch( p_vout->i_screen_depth )
+ {
+ case 15:
+ for( i_index = -384; i_index < 640; i_index++)
+ {
+ p_trans16_red[i_index] = (i_gamma[CLIP_BYTE( i_index )] & 0xf8)<<7;
+ p_trans16_green[i_index] = (i_gamma[CLIP_BYTE( i_index )] & 0xf8)<<2;
+ p_trans16_blue[i_index] = i_gamma[CLIP_BYTE( i_index )] >> 3;
+ p_trans16_gray[i_index] = p_trans16_red[i_index] |
+ p_trans16_green[i_index] | p_trans16_blue[i_index];
+ }
+ break;
+ case 16:
+ for( i_index = -384; i_index < 640; i_index++)
+ {
+ p_trans16_red[i_index] = (i_gamma[CLIP_BYTE( i_index )] & 0xf8)<<8;
+ p_trans16_green[i_index] = (i_gamma[CLIP_BYTE( i_index )] & 0xfc)<<3;
+ p_trans16_blue[i_index] = i_gamma[CLIP_BYTE( i_index )] >> 3;
+ p_trans16_gray[i_index] = p_trans16_red[i_index] |
+ p_trans16_green[i_index] | p_trans16_blue[i_index];
+ }
+ break;
+ case 32:
+ for( i_index = -384; i_index < 640; i_index++)
+ {
+ p_trans32_red[i_index] = i_gamma[CLIP_BYTE( i_index )] <<16;
+ p_trans32_green[i_index] = i_gamma[CLIP_BYTE( i_index )] <<8;
+ p_trans32_blue[i_index] = i_gamma[CLIP_BYTE( i_index )] ;
+ p_trans32_gray[i_index] = p_trans32_red[i_index] |
+ p_trans32_green[i_index] | p_trans32_blue[i_index];
+ }
+ break;
+#ifdef DEBUG
+ default:
+ intf_DbgMsg("error: invalid screen depth %d\n", p_vout->i_screen_depth );
+ break;
+#endif
+ }
+}
+
/*******************************************************************************
* RenderPicture: render a picture
*******************************************************************************
{
RenderYUV16Picture( p_vout, p_pic );
}
- else /* color 24 or 32 bpp */
+ else if( p_vout->i_bytes_per_pixel == 4 ) /* color 32 bpp */
{
RenderYUV32Picture( p_vout, p_pic );
}
}
/*******************************************************************************
- * RenderYUVGrayPicture: render a 15, 16, 24 or 32 bpp YUV picture in grayscale
+ * RenderYUVGrayPicture: render YUV picture in grayscale
*******************************************************************************
* Performs the YUV convertion. The picture sent to this function should only
* have YUV_420, YUV_422 or YUV_444 types.
int i_width, i_height; /* picture size */
int i_eol_offset; /* pixels from end of line to next line */
yuv_data_t *p_y; /* Y data base adress */
- yuv_data_t i_y; /* Y sample */
- u16 * pi_pic16; /* destination picture, 15 or 16 bpp */
- u32 * pi_pic32; /* destination picture, 24 or 32 bpp */
- u16 * pi_trans16_red; /* red transformation table */
- u16 * pi_trans16_green; /* green transformation table */
- u16 * pi_trans16_blue; /* blue transformation table */
- u32 * pi_trans32_red; /* red transformation table */
- u32 * pi_trans32_green; /* green transformation table */
- u32 * pi_trans32_blue; /* blue transformation table */
+ u16 * p_pic16; /* destination picture, 15 or 16 bpp */
+ u32 * p_pic32; /* destination picture, 32 bpp */
+ u16 * p_trans16_gray; /* transformation table, 15 or 16 bpp */
+ u32 * p_trans32_gray; /* transformation table, 32 bpp */
/* Set the base pointers and transformation parameters */
p_y = p_pic->p_y;
{
case 15:
case 16:
- pi_trans16_red = p_vout->pi_trans16_red;
- pi_trans16_green = p_vout->pi_trans16_green;
- pi_trans16_blue = p_vout->pi_trans16_blue;
- pi_pic16 = (u16 *) vout_SysGetPicture( p_vout );
-
- YUV_GRAYSCALE( pi_trans16_red, pi_trans16_green, pi_trans16_blue,
- pi_pic16 );
+ p_trans16_gray = (u16 *) p_vout->p_trans_gray;
+ p_pic16 = (u16 *) vout_SysGetPicture( p_vout );
+ YUV_GRAYSCALE( p_trans16_gray, p_pic16 );
break;
- case 24:
case 32:
- pi_trans32_red = p_vout->pi_trans32_red;
- pi_trans32_green = p_vout->pi_trans32_green;
- pi_trans32_blue = p_vout->pi_trans32_blue;
- pi_pic32 = (u32 *) vout_SysGetPicture( p_vout );
-
- YUV_GRAYSCALE( pi_trans32_red, pi_trans32_green, pi_trans32_blue,
- pi_pic32 );
+ p_trans32_gray = (u32 *) p_vout->p_trans_gray;
+ p_pic32 = (u32 *) vout_SysGetPicture( p_vout );
+ YUV_GRAYSCALE( p_trans32_gray, p_pic32 );
break;
#ifdef DEBUG
default:
yuv_data_t *p_y; /* Y data base adress */
yuv_data_t *p_u; /* U data base adress */
yuv_data_t *p_v; /* V data base adress */
- u16 * pi_pic; /* base adress for destination picture */
- u16 * pi_trans_red; /* red transformation table */
- u16 * pi_trans_green; /* green transformation table */
- u16 * pi_trans_blue; /* blue transformation table */
+ u16 * p_data; /* base adress for destination picture */
+ u16 * p_trans_red; /* red transformation table */
+ u16 * p_trans_green; /* green transformation table */
+ u16 * p_trans_blue; /* blue transformation table */
/* Choose transformation matrix coefficients */
i_crv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][0];
i_cgu = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][2];
i_cgv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][3];
- /* Choose the conversions tables */
- pi_trans_red = p_vout->pi_trans16_red;
- pi_trans_green = p_vout->pi_trans16_green;
- pi_trans_blue = p_vout->pi_trans16_blue;
+ /* Choose the conversions tables and picture address */
+ p_trans_red = (u16 *) p_vout->p_trans_red;
+ p_trans_green = (u16 *) p_vout->p_trans_green;
+ p_trans_blue = (u16 *) p_vout->p_trans_blue;
+ p_data = (u16 *) vout_SysGetPicture( p_vout );
/* Set the base pointers and transformation parameters */
p_y = p_pic->p_y;
i_chroma_width = i_width / 2;
i_eol_offset = p_vout->i_bytes_per_line / 2 - i_width;
- /* Get base adress for destination image */
- pi_pic = (u16 *)vout_SysGetPicture( p_vout );
-
/* Do YUV transformation - the loops are repeated for optimization */
switch( p_pic->i_type )
{
vout_YUV420_16_MMX( p_y, p_u, p_v,
i_width, i_height,
i_width, i_chroma_width,
- 0, (u8 *) pi_pic,
+ 0, p_data,
0, 0, p_vout->i_bytes_per_line,
p_vout->i_screen_depth == 15 );
#else
YUV_TRANSFORM( 420,
- pi_trans_red,
- pi_trans_green,
- pi_trans_blue,
- pi_pic );
+ p_trans_red,
+ p_trans_green,
+ p_trans_blue,
+ p_data );
#endif
break;
case YUV_422_PICTURE: /* 15 or 16 bpp 422 transformation */
YUV_TRANSFORM( 422,
- pi_trans_red,
- pi_trans_green,
- pi_trans_blue,
- pi_pic );
+ p_trans_red,
+ p_trans_green,
+ p_trans_blue,
+ p_data );
break;
case YUV_444_PICTURE: /* 15 or 16 bpp 444 transformation */
YUV_TRANSFORM( 444,
- pi_trans_red,
- pi_trans_green,
- pi_trans_blue,
- pi_pic );
+ p_trans_red,
+ p_trans_green,
+ p_trans_blue,
+ p_data );
break;
}
}
/*******************************************************************************
- * RenderYUV32Picture: render a 24 or 32 bpp YUV picture
+ * RenderYUV32Picture: render a 32 bpp YUV picture
*******************************************************************************
* Performs the YUV convertion. The picture sent to this function should only
* have YUV_420, YUV_422 or YUV_444 types.
yuv_data_t *p_y; /* Y data base adress */
yuv_data_t *p_u; /* U data base adress */
yuv_data_t *p_v; /* V data base adress */
- u32 * pi_pic; /* base adress for destination picture */
- u32 * pi_trans_red; /* red transformation table */
- u32 * pi_trans_green; /* green transformation table */
- u32 * pi_trans_blue; /* blue transformation table */
+ u32 * p_data; /* base adress for destination picture */
+ u32 * p_trans_red; /* red transformation table */
+ u32 * p_trans_green; /* green transformation table */
+ u32 * p_trans_blue; /* blue transformation table */
/* Choose transformation matrix coefficients */
i_crv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][0];
i_cgu = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][2];
i_cgv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][3];
- /* Choose the conversions tables */
- pi_trans_red = p_vout->pi_trans32_red;
- pi_trans_green = p_vout->pi_trans32_green;
- pi_trans_blue = p_vout->pi_trans32_blue;
+ /* Choose the conversions tables and picture address */
+ p_trans_red = (u32 *) p_vout->p_trans_red;
+ p_trans_green = (u32 *) p_vout->p_trans_green;
+ p_trans_blue = (u32 *) p_vout->p_trans_blue;
+ p_data = (u32 *) vout_SysGetPicture( p_vout );
/* Set the base pointers and transformation parameters */
p_y = p_pic->p_y;
i_chroma_width = i_width / 2;
i_eol_offset = p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel - i_width;
- /* Get base adress for destination image */
- pi_pic = (u32 *)vout_SysGetPicture( p_vout );
-
/* Do YUV transformation - the loops are repeated for optimization */
switch( p_pic->i_type )
{
- case YUV_420_PICTURE: /* 24 or 32 bpp 420 transformation */
+ case YUV_420_PICTURE: /* 32 bpp 420 transformation */
YUV_TRANSFORM( 420,
- pi_trans_red,
- pi_trans_green,
- pi_trans_blue,
- pi_pic );
+ p_trans_red,
+ p_trans_green,
+ p_trans_blue,
+ p_data );
break;
- case YUV_422_PICTURE: /* 24 or 32 bpp 422 transformation */
+ case YUV_422_PICTURE: /* 32 bpp 422 transformation */
YUV_TRANSFORM( 422,
- pi_trans_red,
- pi_trans_green,
- pi_trans_blue,
- pi_pic );
+ p_trans_red,
+ p_trans_green,
+ p_trans_blue,
+ p_data );
break;
- case YUV_444_PICTURE: /* 24 or 32 bpp 444 transformation */
+ case YUV_444_PICTURE: /* 32 bpp 444 transformation */
YUV_TRANSFORM( 444,
- pi_trans_red,
- pi_trans_green,
- pi_trans_blue,
- pi_pic );
+ p_trans_red,
+ p_trans_green,
+ p_trans_blue,
+ p_data );
break;
}
}
}
/* Print statistics in upper left corner */
- sprintf( psz_buffer, "%ld frames (%.1f %% idle)", p_vout->c_fps_samples,
- p_vout->c_loops ?
+ sprintf( psz_buffer, "gamma=%.2f %ld frames (%.1f %% idle)",
+ p_vout->f_gamma, p_vout->c_fps_samples, p_vout->c_loops ?
(double ) p_vout->c_idle_loops * 100 / p_vout->c_loops : 100. );
vout_SysPrint( p_vout, 0, 0, -1, -1, psz_buffer );
#endif
--- /dev/null
+/*******************************************************************************
+ * video_yuv_c.c: YUV transformation, optimized
+ * (c)1999 VideoLAN
+ *******************************************************************************
+ * Provides optimized functions to perform the YUV conversion.
+ *******************************************************************************/
+
+#include <stdlib.h> /* malloc */
+
+#include "convert.h"
+
+static int binaryLog (int i)
+{
+ int log;
+
+ log = 0;
+ if (i & 0xffff0000) log = 16;
+ if (i & 0xff00ff00) log += 8;
+ if (i & 0xf0f0f0f0) log += 4;
+ if (i & 0xcccccccc) log += 2;
+ if (i & 0xaaaaaaaa) log++;
+ if (i != (1 << log))
+ return -1;
+
+ return log;
+}
+
+static int colorMaskToShift (int * right, int * left, int mask)
+{
+ int low;
+ int high;
+
+ low = mask & (- mask); /* lower bit of the mask */
+ high = mask + low; /* higher bit of the mask */
+
+ low = binaryLog (low);
+ high = binaryLog (high);
+ if ((low == -1) || (high == -1))
+ return 1;
+
+ *left = low;
+ *right = (8 - high + low);
+
+ return 0;
+}
+
+
+/*
+ * YUV to RGB routines.
+ *
+ * these routines calculate r, g and b values from each pixel's y, u and v.
+ * these r, g an b values are then passed thru a table lookup to take the
+ * gamma curve into account and find the corresponding pixel value.
+ *
+ * the table must store more than 3*256 values because of the possibility
+ * of overflow in the yuv->rgb calculation. actually the calculated r,g,b
+ * values are in the following intervals :
+ * -176 to 255+176 for red
+ * -133 to 255+133 for green
+ * -222 to 255+222 for blue
+ *
+ * If the input y,u,v values are right, the r,g,b results are not expected
+ * to move out of the 0 to 255 interval but who knows what will happen in
+ * real use...
+ *
+ * the red, green and blue conversion tables are stored in a single 1935-entry
+ * array. The respective positions of each component in the array have been
+ * calculated to minimize the cache interactions of the 3 tables.
+ */
+
+static int rgbTable16 (short table [1935],
+ int redMask, int greenMask, int blueMask,
+ unsigned char gamma[256])
+{
+ int redRight;
+ int redLeft;
+ int greenRight;
+ int greenLeft;
+ int blueRight;
+ int blueLeft;
+ short * redTable;
+ short * greenTable;
+ short * blueTable;
+ int i;
+ int y;
+
+ if (colorMaskToShift (&redRight, &redLeft, redMask) ||
+ colorMaskToShift (&greenRight, &greenLeft, greenMask) ||
+ colorMaskToShift (&blueRight, &blueLeft, blueMask))
+ return 1;
+
+ /*
+ * green blue red +- 2 just to be sure
+ * green = 0-525 [151-370]
+ * blue = 594-1297 [834-1053] <834-29>
+ * red = 1323-1934 [1517-1736] <493-712>
+ */
+
+ redTable = table + 1501;
+ greenTable = table + 135;
+ blueTable = table + 818;
+
+ for (i = 0; i < 178; i++) {
+ redTable[i-178] = 0;
+ redTable[i+256] = redMask;
+ }
+ for (i = 0; i < 135; i++) {
+ greenTable[i-135] = 0;
+ greenTable[i+256] = greenMask;
+ }
+ for (i = 0; i < 224; i++) {
+ blueTable[i-224] = 0;
+ blueTable[i+256] = blueMask;
+ }
+
+ for (i = 0; i < 256; i++) {
+ y = gamma[i];
+ redTable[i] = ((y >> redRight) << redLeft);
+ greenTable[i] = ((y >> greenRight) << greenLeft);
+ blueTable[i] = ((y >> blueRight) << blueLeft);
+ }
+
+ return 0;
+}
+
+static int rgbTable32 (int table [1935],
+ int redMask, int greenMask, int blueMask,
+ unsigned char gamma[256])
+{
+ int redRight;
+ int redLeft;
+ int greenRight;
+ int greenLeft;
+ int blueRight;
+ int blueLeft;
+ int * redTable;
+ int * greenTable;
+ int * blueTable;
+ int i;
+ int y;
+
+ if (colorMaskToShift (&redRight, &redLeft, redMask) ||
+ colorMaskToShift (&greenRight, &greenLeft, greenMask) ||
+ colorMaskToShift (&blueRight, &blueLeft, blueMask))
+ return 1;
+
+ /*
+ * green blue red +- 2 just to be sure
+ * green = 0-525 [151-370]
+ * blue = 594-1297 [834-1053] <834-29>
+ * red = 1323-1934 [1517-1736] <493-712>
+ */
+
+ redTable = table + 1501;
+ greenTable = table + 135;
+ blueTable = table + 818;
+
+ for (i = 0; i < 178; i++) {
+ redTable[i-178] = 0;
+ redTable[i+256] = redMask;
+ }
+ for (i = 0; i < 135; i++) {
+ greenTable[i-135] = 0;
+ greenTable[i+256] = greenMask;
+ }
+ for (i = 0; i < 224; i++) {
+ blueTable[i-224] = 0;
+ blueTable[i+256] = blueMask;
+ }
+
+ for (i = 0; i < 256; i++) {
+ y = gamma[i];
+ redTable[i] = ((y >> redRight) << redLeft);
+ greenTable[i] = ((y >> greenRight) << greenLeft);
+ blueTable[i] = ((y >> blueRight) << blueLeft);
+ }
+
+ return 0;
+}
+
+#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))
+
+static void yuvToRgb16 (unsigned char * Y,
+ unsigned char * U, unsigned char * V,
+ short * dest, short table[1935], int width)
+{
+ int i;
+ int u;
+ int v;
+ int uvRed;
+ int uvGreen;
+ int uvBlue;
+ short * tableY;
+
+ i = width >> 4;
+ while (i--) {
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+ }
+
+ i = (width & 15) >> 1;
+ while (i--) {
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+ }
+
+ if (width & 1) {
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+ }
+}
+
+static void yuvToRgb24 (unsigned char * Y,
+ unsigned char * U, unsigned char * V,
+ char * dest, int table[1935], int width)
+{
+ int i;
+ int u;
+ int v;
+ int uvRed;
+ int uvGreen;
+ int uvBlue;
+ int * tableY;
+ int tmp24;
+
+ i = width >> 3;
+ while (i--) {
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+ *(dest++) = tmp24;
+ *(dest++) = tmp24 >> 8;
+ *(dest++) = tmp24 >> 16;
+
+ tableY = table + *(Y++);
+ tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+ *(dest++) = tmp24;
+ *(dest++) = tmp24 >> 8;
+ *(dest++) = tmp24 >> 16;
+
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+ *(dest++) = tmp24;
+ *(dest++) = tmp24 >> 8;
+ *(dest++) = tmp24 >> 16;
+
+ tableY = table + *(Y++);
+ tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+ *(dest++) = tmp24;
+ *(dest++) = tmp24 >> 8;
+ *(dest++) = tmp24 >> 16;
+
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+ *(dest++) = tmp24;
+ *(dest++) = tmp24 >> 8;
+ *(dest++) = tmp24 >> 16;
+
+ tableY = table + *(Y++);
+ tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+ *(dest++) = tmp24;
+ *(dest++) = tmp24 >> 8;
+ *(dest++) = tmp24 >> 16;
+
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+ *(dest++) = tmp24;
+ *(dest++) = tmp24 >> 8;
+ *(dest++) = tmp24 >> 16;
+
+ tableY = table + *(Y++);
+ tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+ *(dest++) = tmp24;
+ *(dest++) = tmp24 >> 8;
+ *(dest++) = tmp24 >> 16;
+ }
+
+ i = (width & 7) >> 1;
+ while (i--) {
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+ *(dest++) = tmp24;
+ *(dest++) = tmp24 >> 8;
+ *(dest++) = tmp24 >> 16;
+
+ tableY = table + *(Y++);
+ tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+ *(dest++) = tmp24;
+ *(dest++) = tmp24 >> 8;
+ *(dest++) = tmp24 >> 16;
+ }
+
+ if (width & 1) {
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+ *(dest++) = tmp24;
+ *(dest++) = tmp24 >> 8;
+ *(dest++) = tmp24 >> 16;
+ }
+}
+
+static void yuvToRgb32 (unsigned char * Y,
+ unsigned char * U, unsigned char * V,
+ int * dest, int table[1935], int width)
+{
+ int i;
+ int u;
+ int v;
+ int uvRed;
+ int uvGreen;
+ int uvBlue;
+ int * tableY;
+
+ i = width >> 4;
+ while (i--) {
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+ }
+
+ i = (width & 15) >> 1;
+ while (i--) {
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+ }
+
+ if (width & 1) {
+ u = *(U++);
+ v = *(V++);
+ uvRed = (V_RED_COEF*v) >> SHIFT;
+ uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT;
+ uvBlue = (U_BLUE_COEF*u) >> SHIFT;
+
+ tableY = table + *(Y++);
+ *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] |
+ tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) +
+ uvGreen] |
+ tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]);
+ }
+}
+
+/* API routines */
+
+int convertGrey (CONVERTER * convert, DISPLAY * disp)
+{
+ if ((convert == NULL) || (disp == NULL))
+ return 1;
+
+ if (greyRgbTable (disp))
+ return 1;
+
+ switch (disp->bytesPerPixel) {
+ case 2:
+ convert->convert = &greyToRgb16;
+ break;
+ case 3:
+ convert->convert = &greyToRgb24;
+ break;
+ case 4:
+ convert->convert = &greyToRgb32;
+ break;
+ default:
+ return 1;
+ }
+ convert->table = disp->greyRgbTable;
+ return 0;
+}
+
+static void * greyRgbTable (DISP_COLORS * colors, unsigned char gamma[256])
+{
+ /* FIXME could avoid recalculating the same table */
+ void * table;
+
+ for (i = 0; i < 16; i++)
+ gamma[i] = 0;
+#define Y_COEF ((int)(1.164 * 65536))
+ for (; i <= 235; i++)
+ gamma[i] = (Y_COEF * i - Y_COEF * 16) >> 16;
+#undef Y_COEF
+ for (; i < 256; i++)
+ gamma[i] = 255;
+ }
+
+ switch (colors->bytesPerPixel) {
+ case 2:
+ table = malloc (256 * sizeof (short));
+ if (table == NULL)
+ break;
+ if (greyRgb16Table (table,
+ colors->redMask,
+ colors->greenMask,
+ colors->blueMask,
+ gamma))
+ goto error;
+ return table;
+ case 3:
+ case 4:
+ table = malloc (256 * sizeof (int));
+ if (table == NULL)
+ break;
+ if (greyRgb32Table (table,
+ colors->redMask,
+ colors->greenMask,
+ colors->blueMask,
+ gamma))
+ goto error;
+ return table;
+ error:
+ free (table);
+ }
+
+ return NULL;
+}
+
+static void * rgbTable (DISP_COLORS * colors, unsigned char gamma[256])
+{
+ /* FIXME could avoid recalculating the same table */
+ void * table;
+
+ switch (colors->bytesPerPixel) {
+ case 2:
+ table = malloc (1935 * sizeof (short));
+ if (table == NULL)
+ break;
+ if (rgbTable16 (table,
+ colors->redMask, colors->greenMask, colors->blueMask,
+ gamma))
+ goto error;
+ return table;
+ case 3:
+ case 4:
+ table = malloc (1935 * sizeof (int));
+ if (table == NULL)
+ break;
+ if (rgbTable32 (table,
+ colors->redMask, colors->greenMask, colors->blueMask,
+ gamma))
+ goto error;
+ return table;
+ error:
+ free (table);
+ }
+
+ return NULL;
+}