Commit 3a45b93f authored by Vincent Seguin's avatar Vincent Seguin

Scaling horizontal >=1

parent 01fcd5af
...@@ -293,8 +293,11 @@ ...@@ -293,8 +293,11 @@
#define VPAR_IDLE_SLEEP 100000 #define VPAR_IDLE_SLEEP 100000
/* Time to sleep when waiting for a buffer (from vout or the video fifo). */ /* Time to sleep when waiting for a buffer (from vout or the video fifo).
#define VPAR_OUTMEM_SLEEP 100000 * It should be approximately the time needed to perform a complete picture
* loop. Since it only happens when the video heap is full, it does not need
* to be too low, even if it blocks the decoder. */
#define VPAR_OUTMEM_SLEEP 50000
/* Optimization level, from 0 to 2 - 1 is generally a good compromise. Remember /* Optimization level, from 0 to 2 - 1 is generally a good compromise. Remember
* that raising this level dramatically lengthens the compilation time. */ * that raising this level dramatically lengthens the compilation time. */
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
* i_pic_width, i_pic_height picture extension * i_pic_width, i_pic_height picture extension
* i_pic_line_width picture total line width * i_pic_line_width picture total line width
* i_matrix_coefficients matrix coefficients * i_matrix_coefficients matrix coefficients
* Picture width and source dimensions must be multiples of 16.
*******************************************************************************/ *******************************************************************************/
typedef void (vout_yuv_convert_t)( p_vout_thread_t p_vout, void *p_pic, typedef void (vout_yuv_convert_t)( p_vout_thread_t p_vout, void *p_pic,
yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
......
...@@ -396,13 +396,13 @@ void vout_DestroySubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic ) ...@@ -396,13 +396,13 @@ void vout_DestroySubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic )
#endif #endif
} }
/****************************************************************************** /*******************************************************************************
* vout_DisplayPicture: display a picture * vout_DisplayPicture: display a picture
****************************************************************************** *******************************************************************************
* Remove the reservation flag of a picture, which will cause it to be ready for * Remove the reservation flag of a picture, which will cause it to be ready for
* display. The picture won't be displayed until vout_DatePicture has been * display. The picture won't be displayed until vout_DatePicture has been
* called. * called.
******************************************************************************/ *******************************************************************************/
void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic ) void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic )
{ {
vlc_mutex_lock( &p_vout->picture_lock ); vlc_mutex_lock( &p_vout->picture_lock );
...@@ -422,21 +422,24 @@ void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -422,21 +422,24 @@ void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic )
} }
#ifdef DEBUG_VIDEO #ifdef DEBUG_VIDEO
intf_DbgMsg("picture %p\n", p_pic ); intf_DbgMsg("picture %p\n", p_pic);
#endif #endif
vlc_mutex_unlock( &p_vout->picture_lock ); vlc_mutex_unlock( &p_vout->picture_lock );
} }
/****************************************************************************** /*******************************************************************************
* vout_DatePicture: date a picture * vout_DatePicture: date a picture
****************************************************************************** *******************************************************************************
* Remove the reservation flag of a picture, which will cause it to be ready for * Remove the reservation flag of a picture, which will cause it to be ready for
* display. The picture won't be displayed until vout_DisplayPicture has been * display. The picture won't be displayed until vout_DisplayPicture has been
* called. * called.
******************************************************************************/ *******************************************************************************/
void vout_DatePicture( vout_thread_t *p_vout, picture_t *p_pic, mtime_t date ) void vout_DatePicture( vout_thread_t *p_vout, picture_t *p_pic, mtime_t date )
{ {
#ifdef DEBUG_VIDEO
char psz_date[MSTRTIME_MAX_SIZE]; /* date */
#endif
vlc_mutex_lock( &p_vout->picture_lock ); vlc_mutex_lock( &p_vout->picture_lock );
p_pic->date = date; p_pic->date = date;
switch( p_pic->i_status ) switch( p_pic->i_status )
...@@ -455,9 +458,8 @@ void vout_DatePicture( vout_thread_t *p_vout, picture_t *p_pic, mtime_t date ) ...@@ -455,9 +458,8 @@ void vout_DatePicture( vout_thread_t *p_vout, picture_t *p_pic, mtime_t date )
} }
#ifdef DEBUG_VIDEO #ifdef DEBUG_VIDEO
intf_DbgMsg("picture %p\n", p_pic); intf_DbgMsg("picture %p, display date: %s\n", p_pic, mstrtime( psz_date, p_pic->date) );
#endif #endif
vlc_mutex_unlock( &p_vout->picture_lock ); vlc_mutex_unlock( &p_vout->picture_lock );
} }
...@@ -1265,10 +1267,9 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -1265,10 +1267,9 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic )
*/ */
if( p_pic != NULL ) if( p_pic != NULL )
{ {
/* Try horizontal scaling first */ /* Try horizontal scaling first - width must be a mutiple of 16 */
i_pic_width = ( p_vout->b_scale || (p_pic->i_width > i_vout_width)) ? i_pic_width = (( p_vout->b_scale || (p_pic->i_width > i_vout_width)) ?
i_vout_width : p_pic->i_width; i_vout_width : p_pic->i_width) & ~0xf;
i_pic_width = i_pic_width;
switch( p_pic->i_aspect_ratio ) switch( p_pic->i_aspect_ratio )
{ {
case AR_3_4_PICTURE: case AR_3_4_PICTURE:
...@@ -1287,7 +1288,8 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -1287,7 +1288,8 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic )
} }
/* If picture dimensions using horizontal scaling are too large, use /* If picture dimensions using horizontal scaling are too large, use
* vertical scaling */ * vertical scaling. Since width must be a multiple of 16, height is
* adjusted again after. */
if( i_pic_height > i_vout_height ) if( i_pic_height > i_vout_height )
{ {
i_pic_height = ( p_vout->b_scale || (p_pic->i_height > i_vout_height)) ? i_pic_height = ( p_vout->b_scale || (p_pic->i_height > i_vout_height)) ?
...@@ -1295,20 +1297,23 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -1295,20 +1297,23 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic )
switch( p_pic->i_aspect_ratio ) switch( p_pic->i_aspect_ratio )
{ {
case AR_3_4_PICTURE: case AR_3_4_PICTURE:
i_pic_width = i_pic_height * 4 / 3; i_pic_width = (i_pic_height * 4 / 3) & ~0xf;
i_pic_height = i_pic_width * 3 / 4;
break; break;
case AR_16_9_PICTURE: case AR_16_9_PICTURE:
i_pic_width = i_pic_height * 16 / 9; i_pic_width = (i_pic_height * 16 / 9) & ~0xf;
i_pic_height = i_pic_width * 9 / 16;
break; break;
case AR_221_1_PICTURE: case AR_221_1_PICTURE:
i_pic_width = i_pic_height * 221 / 100; i_pic_width = (i_pic_height * 221 / 100) & ~0xf;
i_pic_height = i_pic_width * 100 / 221;
break; break;
case AR_SQUARE_PICTURE: case AR_SQUARE_PICTURE:
default: default:
i_pic_width = p_pic->i_width * i_pic_height / p_pic->i_height; i_pic_width = (p_pic->i_width * i_pic_height / p_pic->i_height) & ~0xf;
i_pic_height = p_pic->i_height * i_pic_width / p_pic->i_width;
break; break;
} }
i_pic_width = i_pic_width;
} }
/* Set picture position */ /* Set picture position */
...@@ -1386,7 +1391,7 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -1386,7 +1391,7 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic )
#ifdef DEBUG_VIDEO #ifdef DEBUG_VIDEO
/* /*
* In DEBUG_VIDEO_MODE, draw white pixels at the beginning and the end of * In DEBUG_VIDEO mode, draw white pixels at the beginning and the end of
* the picture area. These pixels should not be erased by rendering functions, * the picture area. These pixels should not be erased by rendering functions,
* otherwise segmentation fault is menacing ! * otherwise segmentation fault is menacing !
*/ */
...@@ -1423,6 +1428,10 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -1423,6 +1428,10 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic )
******************************************************************************/ ******************************************************************************/
static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic ) static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
{ {
#ifdef DEBUG_VIDEO
char psz_date[MSTRTIME_MAX_SIZE]; /* picture date */
mtime_t render_time; /* picture rendering time */
#endif
vout_buffer_t * p_buffer; /* rendering buffer */ vout_buffer_t * p_buffer; /* rendering buffer */
byte_t * p_pic_data; /* convertion destination */ byte_t * p_pic_data; /* convertion destination */
...@@ -1431,6 +1440,9 @@ static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -1431,6 +1440,9 @@ static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
p_pic_data = p_buffer->p_data + p_pic_data = p_buffer->p_data +
p_buffer->i_pic_x * p_vout->i_bytes_per_pixel + p_buffer->i_pic_x * p_vout->i_bytes_per_pixel +
p_buffer->i_pic_y * p_vout->i_bytes_per_line; p_buffer->i_pic_y * p_vout->i_bytes_per_line;
#ifdef DEBUG_VIDEO
render_time = mdate();
#endif
/* /*
* Choose appropriate rendering function and render picture * Choose appropriate rendering function and render picture
...@@ -1467,6 +1479,12 @@ static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -1467,6 +1479,12 @@ static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
break; break;
#endif #endif
} }
#ifdef DEBUG_VIDEO
/* Print picture date and rendering time */
intf_DbgMsg("picture %p rendered (%ld us), display date: %s\n", p_pic,
(long) (mdate() - render_time), mstrtime( psz_date, p_pic->date ));
#endif
} }
/****************************************************************************** /******************************************************************************
......
...@@ -194,13 +194,12 @@ for (i_y = 0; i_y < i_height ; i_y++) \ ...@@ -194,13 +194,12 @@ for (i_y = 0; i_y < i_height ; i_y++) \
* CONVERT_YUV_PIXEL, CONVERT_Y_PIXEL: pixel convertion blocks * CONVERT_YUV_PIXEL, CONVERT_Y_PIXEL: pixel convertion blocks
******************************************************************************* *******************************************************************************
* These convertion routines are used by YUV convertion functions. * These convertion routines are used by YUV convertion functions.
* Convertion are made from p_y, p_u, p_v, which are modified, to p_pic, which * Convertion are made from p_y, p_u, p_v, which are modified, to i_dst. ??
* is also modified.
*******************************************************************************/ *******************************************************************************/
#define CONVERT_Y_PIXEL \ #define CONVERT_Y_PIXEL \
/* Only Y sample is present */ \ /* Only Y sample is present */ \
p_ybase = p_yuv + *(p_y++); \ p_ybase = p_yuv + *(p_y++); \
*(p_pic++) = p_ybase[1501 - ((V_RED_COEF*128)>>SHIFT) + i_red] | \ *p_pic++ = p_ybase[1501 - ((V_RED_COEF*128)>>SHIFT) + i_red] | \
p_ybase[135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + i_green ] | \ p_ybase[135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + i_green ] | \
p_ybase[818 - ((U_BLUE_COEF*128)>>SHIFT) + i_blue]; \ p_ybase[818 - ((U_BLUE_COEF*128)>>SHIFT) + i_blue]; \
...@@ -213,6 +212,14 @@ for (i_y = 0; i_y < i_height ; i_y++) \ ...@@ -213,6 +212,14 @@ for (i_y = 0; i_y < i_height ; i_y++) \
i_blue = (U_BLUE_COEF * i_uval) >> SHIFT; \ i_blue = (U_BLUE_COEF * i_uval) >> SHIFT; \
CONVERT_Y_PIXEL \ CONVERT_Y_PIXEL \
#define COPY_PIXEL \
/* Pixel may be copied, but only once */ \
while( (i_width_count -= i_width) > 0 ) \
{ \
*p_pic++ = *(p_pic - 1); \
} \
i_width_count += i_pic_width; \
/******************************************************************************* /*******************************************************************************
* vout_InitYUV: allocate and initialize translations tables * vout_InitYUV: allocate and initialize translations tables
******************************************************************************* *******************************************************************************
...@@ -386,7 +393,7 @@ static void SetYUV( vout_thread_t *p_vout ) ...@@ -386,7 +393,7 @@ static void SetYUV( vout_thread_t *p_vout )
switch( p_vout->i_screen_depth ) switch( p_vout->i_screen_depth )
{ {
case 15: case 15:
MaskToShift( &i_red_right, &i_red_left, 0x7c00 ); MaskToShift( &i_red_right, &i_red_left, 0xf800 );
MaskToShift( &i_green_right, &i_green_left, 0x03e0 ); MaskToShift( &i_green_right, &i_green_left, 0x03e0 );
MaskToShift( &i_blue_right, &i_blue_left, 0x001f ); MaskToShift( &i_blue_right, &i_blue_left, 0x001f );
break; break;
...@@ -625,52 +632,142 @@ static void ConvertYUV420RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t * ...@@ -625,52 +632,142 @@ static void ConvertYUV420RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *
CONVERT_YUV_RGB( 420, i_crv, i_cgv, i_cbu, i_cgu ); CONVERT_YUV_RGB( 420, i_crv, i_cgv, i_cbu, i_cgu );
#else #else
boolean_t b_inc_width, b_inc_height; /* width/heidth are increased */ int i_horizontal_scaling; /* horizontal scaling type */
int i_vertical_scaling; /* vertical scaling type */
int i_x, i_y; /* horizontal and vertical indexes */ int i_x, i_y; /* horizontal and vertical indexes */
int i_uval, i_vval; /* U and V samples */ int i_uval, i_vval; /* U and V samples */
int i_red, i_green, i_blue; /* U and V modified samples */ int i_red, i_green, i_blue; /* U and V modified samples */
int i_chroma_width; /* chroma width */ int i_chroma_width; /* chroma width */
int i_width_count; /* width modulo counter */
int i_height_count; /* height modulo counter */ int i_height_count; /* height modulo counter */
u16 * p_yuv; /* base convertion table */ u16 * p_yuv; /* base convertion table */
u16 * p_ybase; /* Y dependant convertion table */ u16 * p_ybase; /* Y dependant convertion table */
u16 * p_pic_start; /* beginning of the current line */ u16 * p_pic_start; /* beginning of the current line */
/* Initialize values */ /* Initialize values */
b_inc_width = i_width < i_pic_width;
b_inc_height = i_height < i_pic_height;
i_height_count = i_pic_height; i_height_count = i_pic_height;
i_chroma_width = i_width / 2; i_chroma_width = i_width / 2;
p_yuv = p_vout->yuv.yuv2.p_rgb16; p_yuv = p_vout->yuv.yuv2.p_rgb16;
/* Set scalings */
if( i_pic_width - i_width > 0 )
{
i_horizontal_scaling = 1;
}
else if( i_pic_width - i_width < 0 )
{
i_horizontal_scaling = -1;
}
else
{
i_horizontal_scaling = 0;
}
if( i_pic_height - i_height > 0 )
{
i_vertical_scaling = 1;
}
else if( i_pic_height - i_height < 0 )
{
i_vertical_scaling = -1;
}
else
{
i_vertical_scaling = 0;
}
/* /*
* Perform convertion * Perform convertion
*/ */
i_height_count = i_pic_height;
for( i_y = 0; i_y < i_height; i_y++ ) for( i_y = 0; i_y < i_height; i_y++ )
{ {
/* Mark beginnning of line */ /* Mark beginnning of line */
p_pic_start = p_pic; p_pic_start = p_pic;
/* Convert line using 16 pixels blocks, since picture come from 16 pixels width /* Convert line using 16 pixels blocks, since picture come from 16 pixels
* macroblocks */ * width macroblocks - several loops will be used, depending of the
for( i_x = i_width / 16; i_x--; ) * scaling type */
switch( i_horizontal_scaling )
{ {
CONVERT_YUV_PIXEL; case 1: /* horizontal scaling is > 1 */
CONVERT_Y_PIXEL; i_width_count = i_pic_width;
CONVERT_YUV_PIXEL; for( i_x = i_width / 16; i_x--; )
CONVERT_Y_PIXEL; {
CONVERT_YUV_PIXEL; CONVERT_YUV_PIXEL;
CONVERT_Y_PIXEL; COPY_PIXEL;
CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
CONVERT_Y_PIXEL; COPY_PIXEL;
CONVERT_YUV_PIXEL; CONVERT_YUV_PIXEL;
CONVERT_Y_PIXEL; COPY_PIXEL;
CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
CONVERT_Y_PIXEL; COPY_PIXEL;
CONVERT_YUV_PIXEL; CONVERT_YUV_PIXEL;
CONVERT_Y_PIXEL; COPY_PIXEL;
CONVERT_YUV_PIXEL; CONVERT_Y_PIXEL;
COPY_PIXEL;
CONVERT_YUV_PIXEL;
COPY_PIXEL;
CONVERT_Y_PIXEL;
COPY_PIXEL;
CONVERT_YUV_PIXEL;
COPY_PIXEL;
CONVERT_Y_PIXEL;
COPY_PIXEL;
CONVERT_YUV_PIXEL;
COPY_PIXEL;
CONVERT_Y_PIXEL;
COPY_PIXEL;
CONVERT_YUV_PIXEL;
COPY_PIXEL;
CONVERT_Y_PIXEL;
COPY_PIXEL;
CONVERT_YUV_PIXEL;
COPY_PIXEL;
CONVERT_Y_PIXEL;
COPY_PIXEL;
}
break;
case 0:
for( i_x = i_width / 16; i_x--; )
{
CONVERT_YUV_PIXEL;
CONVERT_Y_PIXEL;
CONVERT_YUV_PIXEL;
CONVERT_Y_PIXEL;
CONVERT_YUV_PIXEL;
CONVERT_Y_PIXEL;
CONVERT_YUV_PIXEL;
CONVERT_Y_PIXEL;
CONVERT_YUV_PIXEL;
CONVERT_Y_PIXEL;
CONVERT_YUV_PIXEL;
CONVERT_Y_PIXEL;
CONVERT_YUV_PIXEL;
CONVERT_Y_PIXEL;
CONVERT_YUV_PIXEL;
CONVERT_Y_PIXEL;
}
break;
case -1:
i_width_count = i_width;
/* {
while( (i_width_count -= i_pic_width) > 0)
{
p_y++;
p_u++;
}
i_width_count += i_width;
}
CONVERT_Y_PIXEL; CONVERT_Y_PIXEL;
} while( (i_width_count -= i_width) > 0)
{
*p_pic++ = *(p_pic - 1);
}
i_width_count += i_pic_width;
break;
*/
break;
}
/* If line is odd, rewind U and V samples */ /* If line is odd, rewind U and V samples */
if( i_y & 0x1 ) if( i_y & 0x1 )
...@@ -686,8 +783,22 @@ static void ConvertYUV420RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t * ...@@ -686,8 +783,22 @@ static void ConvertYUV420RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *
* Handle vertical scaling. The current line is copied or next one * Handle vertical scaling. The current line is copied or next one
* is ignored. * is ignored.
*/ */
if( b_inc_height ) switch( i_vertical_scaling )
{ {
case -1: /* vertical scaling factor is < 1 */
while( (i_height_count -= i_pic_height) >= 0 )
{
/* Height reduction: skip next source line */
p_y += i_width;
if( ! (++i_y & 0x1) )
{
p_u += i_chroma_width;
p_v += i_chroma_width;
}
}
i_height_count += i_height;
break;
case 1: /* vertical scaling factor is > 1 */
while( (i_height_count -= i_height) > 0 ) while( (i_height_count -= i_height) > 0 )
{ {
/* Height increment: copy previous picture line */ /* Height increment: copy previous picture line */
...@@ -702,21 +813,8 @@ static void ConvertYUV420RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t * ...@@ -702,21 +813,8 @@ static void ConvertYUV420RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *
p_pic_start += i_pic_line_width - i_pic_width; p_pic_start += i_pic_line_width - i_pic_width;
} }
i_height_count += i_pic_height; i_height_count += i_pic_height;
} break;
else }
{
while( (i_height_count -= i_pic_height) >= 0 )
{
/* Height reduction: skip next source line */
p_y += i_width;
if( ! (++i_y & 0x1) )
{
p_u += i_chroma_width;
p_v += i_chroma_width;
}
}
i_height_count += i_height;
}
} }
#endif #endif
} }
...@@ -826,60 +924,6 @@ static void ConvertYUV444RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t * ...@@ -826,60 +924,6 @@ static void ConvertYUV444RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *
* calculated to minimize the cache interactions of the 3 tables. * calculated to minimize the cache interactions of the 3 tables.
*/ */
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;
MaskToShift (&redRight, &redLeft, redMask);
MaskToShift (&greenRight, &greenLeft, greenMask);
MaskToShift (&blueRight, &blueLeft, blueMask);
/*
* 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], static int rgbTable32 (int table [1935],
int redMask, int greenMask, int blueMask, int redMask, int greenMask, int blueMask,
unsigned char gamma[256]) unsigned char gamma[256])
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment