1 /*****************************************************************************
2 * i420_rgb8.c : YUV to bitmap RGB conversion module for vlc
3 *****************************************************************************
4 * Copyright (C) 2000 the VideoLAN team
7 * Authors: Samuel Hocevar <sam@zoy.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
32 #include <vlc_common.h>
33 #include <vlc_filter.h>
36 #include "i420_rgb_c.h"
38 static void SetOffset( int, int, int, int, bool *, int *, int * );
40 /*****************************************************************************
41 * I420_RGB8: color YUV 4:2:0 to RGB 8 bpp
42 *****************************************************************************/
43 void I420_RGB8( filter_t
*p_filter
, picture_t
*p_src
, picture_t
*p_dest
)
45 /* We got this one from the old arguments */
46 uint8_t *p_pic
= (uint8_t*)p_dest
->p
->p_pixels
;
47 uint8_t *p_y
= p_src
->Y_PIXELS
;
48 uint8_t *p_u
= p_src
->U_PIXELS
;
49 uint8_t *p_v
= p_src
->V_PIXELS
;
51 bool b_hscale
; /* horizontal scaling type */
52 int i_vscale
; /* vertical scaling type */
53 unsigned int i_x
, i_y
; /* horizontal and vertical indexes */
54 unsigned int i_real_y
; /* y % 4 */
56 int i_scale_count
; /* scale modulo counter */
57 unsigned int i_chroma_width
= p_filter
->fmt_in
.video
.i_width
/ 2;/* chroma width */
60 uint8_t * p_lookup
= p_filter
->p_sys
->p_base
;
62 /* Offset array pointer */
63 int * p_offset_start
= p_filter
->p_sys
->p_offset
;
66 const int i_source_margin
= p_src
->p
[0].i_pitch
67 - p_src
->p
[0].i_visible_pitch
;
68 const int i_source_margin_c
= p_src
->p
[1].i_pitch
69 - p_src
->p
[1].i_visible_pitch
;
71 /* The dithering matrices */
72 static const int dither10
[4] = { 0x0, 0x8, 0x2, 0xa };
73 static const int dither11
[4] = { 0xc, 0x4, 0xe, 0x6 };
74 static const int dither12
[4] = { 0x3, 0xb, 0x1, 0x9 };
75 static const int dither13
[4] = { 0xf, 0x7, 0xd, 0x5 };
77 static const int dither20
[4] = { 0x0, 0x10, 0x4, 0x14 };
78 static const int dither21
[4] = { 0x18, 0x8, 0x1c, 0xc };
79 static const int dither22
[4] = { 0x6, 0x16, 0x2, 0x12 };
80 static const int dither23
[4] = { 0x1e, 0xe, 0x1a, 0xa };
82 SetOffset( p_filter
->fmt_in
.video
.i_width
,
83 p_filter
->fmt_in
.video
.i_height
,
84 p_filter
->fmt_out
.video
.i_width
,
85 p_filter
->fmt_out
.video
.i_height
,
86 &b_hscale
, &i_vscale
, p_offset_start
);
88 i_right_margin
= p_dest
->p
->i_pitch
- p_dest
->p
->i_visible_pitch
;
93 i_scale_count
= ( i_vscale
== 1 ) ?
94 p_filter
->fmt_out
.video
.i_height
:
95 p_filter
->fmt_in
.video
.i_height
;
96 for( i_y
= 0, i_real_y
= 0; i_y
< p_filter
->fmt_in
.video
.i_height
; i_y
++ )
98 /* Do horizontal and vertical scaling */
99 SCALE_WIDTH_DITHER( 420 );
100 SCALE_HEIGHT_DITHER( 420 );
103 p_y
+= i_source_margin
;
106 p_u
+= i_source_margin_c
;
107 p_v
+= i_source_margin_c
;
111 /* Following functions are local */
113 /*****************************************************************************
114 * SetOffset: build offset array for conversion functions
115 *****************************************************************************
116 * This function will build an offset array used in later conversion functions.
117 * It will also set horizontal and vertical scaling indicators. The p_offset
118 * structure has interleaved Y and U/V offsets.
119 *****************************************************************************/
120 static void SetOffset( int i_width
, int i_height
, int i_pic_width
,
121 int i_pic_height
, bool *pb_hscale
,
122 int *pi_vscale
, int *p_offset
)
124 int i_x
; /* x position in destination */
125 int i_scale_count
; /* modulo counter */
128 * Prepare horizontal offset array
130 if( i_pic_width
- i_width
== 0 )
132 /* No horizontal scaling: YUV conversion is done directly to picture */
135 else if( i_pic_width
- i_width
> 0 )
139 /* Prepare scaling array for horizontal extension */
141 i_scale_count
= i_pic_width
;
142 for( i_x
= i_width
; i_x
--; )
144 while( (i_scale_count
-= i_width
) > 0 )
150 *p_offset
++ = i_dummy
;
151 i_dummy
= 1 - i_dummy
;
152 i_scale_count
+= i_pic_width
;
155 else /* if( i_pic_width - i_width < 0 ) */
160 /* Prepare scaling array for horizontal reduction */
162 i_scale_count
= i_width
;
163 for( i_x
= i_pic_width
; i_x
--; )
166 while( (i_scale_count
-= i_pic_width
) > 0 )
170 *p_offset
++ = i_jump
;
171 *p_offset
++ = ( i_jump
+= i_remainder
) >> 1;
172 i_remainder
= i_jump
& 1;
173 i_scale_count
+= i_width
;
178 * Set vertical scaling indicator
180 if( i_pic_height
- i_height
== 0 )
184 else if( i_pic_height
- i_height
> 0 )
188 else /* if( i_pic_height - i_height < 0 ) */