1 /*****************************************************************************
2 * i420_rgb.h : YUV to bitmap RGB conversion module for vlc
3 *****************************************************************************
4 * Copyright (C) 2000 VideoLAN
5 * $Id: i420_rgb.h,v 1.1 2002/01/04 14:01:34 sam Exp $
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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
25 * chroma_sys_t: chroma method descriptor
26 *****************************************************************************
27 * This structure is part of the chroma transformation descriptor, it
28 * describes the yuv2rgb specific properties.
29 *****************************************************************************/
30 typedef struct chroma_sys_s
37 /*****************************************************************************
39 *****************************************************************************/
40 #ifdef MODULE_NAME_IS_chroma_i420_rgb
41 void _M( I420_RGB8 ) ( vout_thread_t *, picture_t *, picture_t * );
43 void _M( I420_RGB16 )( vout_thread_t *, picture_t *, picture_t * );
44 void _M( I420_RGB24 )( vout_thread_t *, picture_t *, picture_t * );
45 void _M( I420_RGB32 )( vout_thread_t *, picture_t *, picture_t * );
47 /*****************************************************************************
48 * CONVERT_*_PIXEL: pixel conversion macros
49 *****************************************************************************
50 * These conversion routines are used by YUV conversion functions.
51 * conversion are made from p_y, p_u, p_v, which are modified, to p_buffer,
52 * which is also modified. CONVERT_4YUV_PIXEL is used for 8bpp dithering,
53 * CONVERT_4YUV_PIXEL_SCALE does the same but also scales the output.
54 *****************************************************************************/
55 #define CONVERT_Y_PIXEL( BPP ) \
56 /* Only Y sample is present */ \
57 p_ybase = p_yuv + *p_y++; \
58 *p_buffer++ = p_ybase[RED_OFFSET-((V_RED_COEF*128)>>SHIFT) + i_red] | \
59 p_ybase[GREEN_OFFSET-(((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) \
60 + i_green ] | p_ybase[BLUE_OFFSET-((U_BLUE_COEF*128)>>SHIFT) + i_blue];
62 #define CONVERT_YUV_PIXEL( BPP ) \
63 /* Y, U and V samples are present */ \
66 i_red = (V_RED_COEF * i_vval) >> SHIFT; \
67 i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT; \
68 i_blue = (U_BLUE_COEF * i_uval) >> SHIFT; \
69 CONVERT_Y_PIXEL( BPP ) \
71 #define CONVERT_4YUV_PIXEL( CHROMA ) \
72 *p_pic++ = p_lookup[ \
73 (((*p_y++ + dither10[i_real_y]) >> 4) << 7) \
74 + ((*p_u + dither20[i_real_y]) >> 5) * 9 \
75 + ((*p_v + dither20[i_real_y]) >> 5) ]; \
76 *p_pic++ = p_lookup[ \
77 (((*p_y++ + dither11[i_real_y]) >> 4) << 7) \
78 + ((*p_u++ + dither21[i_real_y]) >> 5) * 9 \
79 + ((*p_v++ + dither21[i_real_y]) >> 5) ]; \
80 *p_pic++ = p_lookup[ \
81 (((*p_y++ + dither12[i_real_y]) >> 4) << 7) \
82 + ((*p_u + dither22[i_real_y]) >> 5) * 9 \
83 + ((*p_v + dither22[i_real_y]) >> 5) ]; \
84 *p_pic++ = p_lookup[ \
85 (((*p_y++ + dither13[i_real_y]) >> 4) << 7) \
86 + ((*p_u++ + dither23[i_real_y]) >> 5) * 9 \
87 + ((*p_v++ + dither23[i_real_y]) >> 5) ]; \
89 #define CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
90 *p_pic++ = p_lookup[ \
91 ( ((*p_y + dither10[i_real_y]) >> 4) << 7) \
92 + ((*p_u + dither20[i_real_y]) >> 5) * 9 \
93 + ((*p_v + dither20[i_real_y]) >> 5) ]; \
97 *p_pic++ = p_lookup[ \
98 ( ((*p_y + dither11[i_real_y]) >> 4) << 7) \
99 + ((*p_u + dither21[i_real_y]) >> 5) * 9 \
100 + ((*p_v + dither21[i_real_y]) >> 5) ]; \
101 p_y += *p_offset++; \
103 p_v += *p_offset++; \
104 *p_pic++ = p_lookup[ \
105 ( ((*p_y + dither12[i_real_y]) >> 4) << 7) \
106 + ((*p_u + dither22[i_real_y]) >> 5) * 9 \
107 + ((*p_v + dither22[i_real_y]) >> 5) ]; \
108 p_y += *p_offset++; \
110 p_v += *p_offset++; \
111 *p_pic++ = p_lookup[ \
112 ( ((*p_y + dither13[i_real_y]) >> 4) << 7) \
113 + ((*p_u + dither23[i_real_y]) >> 5) * 9 \
114 + ((*p_v + dither23[i_real_y]) >> 5) ]; \
115 p_y += *p_offset++; \
117 p_v += *p_offset++; \
119 /*****************************************************************************
120 * SCALE_WIDTH: scale a line horizontally
121 *****************************************************************************
122 * This macro scales a line using rendering buffer and offset array. It works
123 * for 1, 2 and 4 Bpp.
124 *****************************************************************************/
125 #define SCALE_WIDTH \
128 /* Horizontal scaling, conversion has been done to buffer. \
129 * Rewind buffer and offset, then copy and scale line */ \
130 p_buffer = p_buffer_start; \
131 p_offset = p_offset_start; \
132 for( i_x = p_vout->output.i_width / 16; i_x--; ) \
134 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
135 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
136 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
137 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
138 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
139 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
140 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
141 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
142 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
143 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
144 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
145 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
146 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
147 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
148 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
149 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
151 for( i_x = p_vout->output.i_width & 15; i_x--; ) \
153 *p_pic++ = *p_buffer; p_buffer += *p_offset++; \
155 p_pic += i_right_margin; \
159 /* No scaling, conversion has been done directly in picture memory. \
160 * Increment of picture pointer to end of line is still needed */ \
161 (u8*)p_pic += p_dest->p->i_pitch; \
164 /*****************************************************************************
165 * SCALE_WIDTH_DITHER: scale a line horizontally for dithered 8 bpp
166 *****************************************************************************
167 * This macro scales a line using an offset array.
168 *****************************************************************************/
169 #define SCALE_WIDTH_DITHER( CHROMA ) \
172 /* Horizontal scaling - we can't use a buffer due to dithering */ \
173 p_offset = p_offset_start; \
174 for( i_x = p_vout->output.i_width / 16; i_x--; ) \
176 CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
177 CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
178 CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
179 CONVERT_4YUV_PIXEL_SCALE( CHROMA ) \
184 for( i_x = p_vout->render.i_width / 16; i_x--; ) \
186 CONVERT_4YUV_PIXEL( CHROMA ) \
187 CONVERT_4YUV_PIXEL( CHROMA ) \
188 CONVERT_4YUV_PIXEL( CHROMA ) \
189 CONVERT_4YUV_PIXEL( CHROMA ) \
192 /* Increment of picture pointer to end of line is still needed */ \
193 p_pic += i_right_margin; \
195 /* Increment the Y coordinate in the matrix, modulo 4 */ \
196 i_real_y = (i_real_y + 1) & 0x3; \
198 /*****************************************************************************
199 * SCALE_HEIGHT: handle vertical scaling
200 *****************************************************************************
201 * This macro handle vertical scaling for a picture. CHROMA may be 420, 422 or
202 * 444 for RGB conversion, or 400 for gray conversion. It works for 1, 2, 3
204 *****************************************************************************/
205 #define SCALE_HEIGHT( CHROMA, BPP ) \
206 /* If line is odd, rewind 4:2:0 U and V samples */ \
207 if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
209 p_u -= i_chroma_width; \
210 p_v -= i_chroma_width; \
214 * Handle vertical scaling. The current line can be copied or next one \
219 case -1: /* vertical scaling factor is < 1 */ \
220 while( (i_scale_count -= p_vout->output.i_height) > 0 ) \
222 /* Height reduction: skip next source line */ \
223 p_y += p_vout->render.i_width; \
225 if( (CHROMA == 420) || (CHROMA == 422) ) \
229 p_u += i_chroma_width; \
230 p_v += i_chroma_width; \
233 else if( CHROMA == 444 ) \
235 p_u += p_vout->render.i_width; \
236 p_v += p_vout->render.i_width; \
239 i_scale_count += p_vout->render.i_height; \
241 case 1: /* vertical scaling factor is > 1 */ \
242 while( (i_scale_count -= p_vout->render.i_height) > 0 ) \
244 /* Height increment: copy previous picture line */ \
245 FAST_MEMCPY( p_pic, p_pic_start, p_vout->output.i_width * BPP ); \
246 (u8*)p_pic += p_dest->p->i_pitch; \
248 i_scale_count += p_vout->output.i_height; \
252 /*****************************************************************************
253 * SCALE_HEIGHT_DITHER: handle vertical scaling for dithered 8 bpp
254 *****************************************************************************
255 * This macro handles vertical scaling for a picture. CHROMA may be 420,
256 * 422 or 444 for RGB conversion, or 400 for gray conversion.
257 *****************************************************************************/
258 #define SCALE_HEIGHT_DITHER( CHROMA ) \
260 /* If line is odd, rewind 4:2:0 U and V samples */ \
261 if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) ) \
263 p_u -= i_chroma_width; \
264 p_v -= i_chroma_width; \
268 * Handle vertical scaling. The current line can be copied or next one \
274 case -1: /* vertical scaling factor is < 1 */ \
275 while( (i_scale_count -= p_vout->output.i_height) > 0 ) \
277 /* Height reduction: skip next source line */ \
278 p_y += p_vout->render.i_width; \
280 if( (CHROMA == 420) || (CHROMA == 422) ) \
284 p_u += i_chroma_width; \
285 p_v += i_chroma_width; \
288 else if( CHROMA == 444 ) \
290 p_u += p_vout->render.i_width; \
291 p_v += p_vout->render.i_width; \
294 i_scale_count += p_vout->render.i_height; \
296 case 1: /* vertical scaling factor is > 1 */ \
297 while( (i_scale_count -= p_vout->render.i_height) > 0 ) \
299 p_y -= p_vout->render.i_width; \
300 p_u -= i_chroma_width; \
301 p_v -= i_chroma_width; \
302 SCALE_WIDTH_DITHER( CHROMA ); \
304 i_scale_count += p_vout->output.i_height; \