]> git.sesse.net Git - vlc/blob - plugins/chroma/transforms.h
43e577d3ed3eb782dfa255556d09d197ab2773fe
[vlc] / plugins / chroma / transforms.h
1 /*****************************************************************************
2  * transforms_common.h: Chroma transformation macros
3  *****************************************************************************
4  * Copyright (C) 1999, 2000, 2001 VideoLAN
5  * $Id: transforms.h,v 1.1 2001/12/16 16:18:36 sam Exp $
6  *
7  * Authors: Vincent Seguin <seguin@via.ecp.fr>
8  *          Samuel Hocevar <sam@zoy.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public
21  * License along with this program; if not, write to the
22  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23  * Boston, MA 02111-1307, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * CONVERT_*_PIXEL: pixel conversion macros
28  *****************************************************************************
29  * These conversion routines are used by YUV conversion functions.
30  * conversion are made from p_y, p_u, p_v, which are modified, to p_buffer,
31  * which is also modified. CONVERT_4YUV_PIXEL is used for 8bpp dithering,
32  * CONVERT_4YUV_PIXEL_SCALE does the same but also scales the output.
33  *****************************************************************************/
34 #define CONVERT_Y_PIXEL( BPP )                                                \
35     /* Only Y sample is present */                                            \
36     p_ybase = p_yuv + *p_y++;                                                 \
37     *p_buffer++ = p_ybase[RED_OFFSET-((V_RED_COEF*128)>>SHIFT) + i_red] |     \
38         p_ybase[GREEN_OFFSET-(((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT)       \
39         + i_green ] | p_ybase[BLUE_OFFSET-((U_BLUE_COEF*128)>>SHIFT) + i_blue];
40
41 #define CONVERT_YUV_PIXEL( BPP )                                              \
42     /* Y, U and V samples are present */                                      \
43     i_uval =    *p_u++;                                                       \
44     i_vval =    *p_v++;                                                       \
45     i_red =     (V_RED_COEF * i_vval) >> SHIFT;                               \
46     i_green =   (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT;     \
47     i_blue =    (U_BLUE_COEF * i_uval) >> SHIFT;                              \
48     CONVERT_Y_PIXEL( BPP )                                                    \
49
50 #define CONVERT_4YUV_PIXEL( CHROMA )                                         \
51     *p_pic++ = p_lookup[                                                      \
52         (((*p_y++ + dither10[i_real_y]) >> 4) << 7)                           \
53       + ((*p_u + dither20[i_real_y]) >> 5) * 9                                \
54       + ((*p_v + dither20[i_real_y]) >> 5) ];                                 \
55     *p_pic++ = p_lookup[                                                      \
56         (((*p_y++ + dither11[i_real_y]) >> 4) << 7)                           \
57       + ((*p_u++ + dither21[i_real_y]) >> 5) * 9                              \
58       + ((*p_v++ + dither21[i_real_y]) >> 5) ];                               \
59     *p_pic++ = p_lookup[                                                      \
60         (((*p_y++ + dither12[i_real_y]) >> 4) << 7)                           \
61       + ((*p_u + dither22[i_real_y]) >> 5) * 9                                \
62       + ((*p_v + dither22[i_real_y]) >> 5) ];                                 \
63     *p_pic++ = p_lookup[                                                      \
64         (((*p_y++ + dither13[i_real_y]) >> 4) << 7)                           \
65       + ((*p_u++ + dither23[i_real_y]) >> 5) * 9                              \
66       + ((*p_v++ + dither23[i_real_y]) >> 5) ];                               \
67
68 #define CONVERT_4YUV_PIXEL_SCALE( CHROMA )                                   \
69     *p_pic++ = p_lookup[                                                      \
70         ( ((*p_y + dither10[i_real_y]) >> 4) << 7)                            \
71         + ((*p_u + dither20[i_real_y]) >> 5) * 9                              \
72         + ((*p_v + dither20[i_real_y]) >> 5) ];                               \
73     p_y += *p_offset++;                                                       \
74     p_u += *p_offset;                                                         \
75     p_v += *p_offset++;                                                       \
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_y += *p_offset++;                                                       \
81     p_u += *p_offset;                                                         \
82     p_v += *p_offset++;                                                       \
83     *p_pic++ = p_lookup[                                                      \
84         ( ((*p_y + dither12[i_real_y]) >> 4) << 7)                            \
85         + ((*p_u + dither22[i_real_y]) >> 5) * 9                              \
86         + ((*p_v + dither22[i_real_y]) >> 5) ];                               \
87     p_y += *p_offset++;                                                       \
88     p_u += *p_offset;                                                         \
89     p_v += *p_offset++;                                                       \
90     *p_pic++ = p_lookup[                                                      \
91         ( ((*p_y + dither13[i_real_y]) >> 4) << 7)                            \
92         + ((*p_u + dither23[i_real_y]) >> 5) * 9                              \
93         + ((*p_v + dither23[i_real_y]) >> 5) ];                               \
94     p_y += *p_offset++;                                                       \
95     p_u += *p_offset;                                                         \
96     p_v += *p_offset++;                                                       \
97
98 /*****************************************************************************
99  * SCALE_WIDTH: scale a line horizontally
100  *****************************************************************************
101  * This macro scales a line using rendering buffer and offset array. It works
102  * for 1, 2 and 4 Bpp.
103  *****************************************************************************/
104 #define SCALE_WIDTH                                                           \
105     if( b_horizontal_scaling )                                                \
106     {                                                                         \
107         /* Horizontal scaling, conversion has been done to buffer.            \
108          * Rewind buffer and offset, then copy and scale line */              \
109         p_buffer = p_buffer_start;                                            \
110         p_offset = p_offset_start;                                            \
111         for( i_x = i_pic_width / 16; i_x--; )                                 \
112         {                                                                     \
113             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
114             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
115             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
116             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
117             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
118             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
119             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
120             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
121             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
122             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
123             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
124             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
125             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
126             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
127             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
128             *p_pic++ = *p_buffer;   p_buffer += *p_offset++;                  \
129         }                                                                     \
130         p_pic += i_pic_line_width;                                            \
131     }                                                                         \
132     else                                                                      \
133     {                                                                         \
134         /* No scaling, conversion has been done directly in picture memory.   \
135          * Increment of picture pointer to end of line is still needed */     \
136         p_pic += i_pic_width + i_pic_line_width;                              \
137     }                                                                         \
138
139 /*****************************************************************************
140  * SCALE_WIDTH_DITHER: scale a line horizontally for dithered 8 bpp
141  *****************************************************************************
142  * This macro scales a line using an offset array.
143  *****************************************************************************/
144 #define SCALE_WIDTH_DITHER( CHROMA )                                          \
145     if( b_horizontal_scaling )                                                \
146     {                                                                         \
147         /* Horizontal scaling - we can't use a buffer due to dithering */     \
148         p_offset = p_offset_start;                                            \
149         for( i_x = i_pic_width / 16; i_x--; )                                 \
150         {                                                                     \
151             CONVERT_4YUV_PIXEL_SCALE( CHROMA )                               \
152             CONVERT_4YUV_PIXEL_SCALE( CHROMA )                               \
153             CONVERT_4YUV_PIXEL_SCALE( CHROMA )                               \
154             CONVERT_4YUV_PIXEL_SCALE( CHROMA )                               \
155         }                                                                     \
156     }                                                                         \
157     else                                                                      \
158     {                                                                         \
159         for( i_x = i_width / 16; i_x--;  )                                    \
160         {                                                                     \
161             CONVERT_4YUV_PIXEL( CHROMA )                                     \
162             CONVERT_4YUV_PIXEL( CHROMA )                                     \
163             CONVERT_4YUV_PIXEL( CHROMA )                                     \
164             CONVERT_4YUV_PIXEL( CHROMA )                                     \
165         }                                                                     \
166     }                                                                         \
167     /* Increment of picture pointer to end of line is still needed */         \
168     p_pic += i_pic_line_width;                                                \
169                                                                               \
170     /* Increment the Y coordinate in the matrix, modulo 4 */                  \
171     i_real_y = (i_real_y + 1) & 0x3;                                          \
172
173 /*****************************************************************************
174  * SCALE_HEIGHT: handle vertical scaling
175  *****************************************************************************
176  * This macro handle vertical scaling for a picture. CHROMA may be 420, 422 or
177  * 444 for RGB conversion, or 400 for gray conversion. It works for 1, 2, 3
178  * and 4 Bpp.
179  *****************************************************************************/
180 #define SCALE_HEIGHT( CHROMA, BPP )                                           \
181     /* If line is odd, rewind 4:2:0 U and V samples */                        \
182     if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) )                \
183     {                                                                         \
184         p_u -= i_chroma_width;                                                \
185         p_v -= i_chroma_width;                                                \
186     }                                                                         \
187                                                                               \
188     /*                                                                        \
189      * Handle vertical scaling. The current line can be copied or next one    \
190      * can be ignored.                                                        \
191      */                                                                       \
192     switch( i_vertical_scaling )                                              \
193     {                                                                         \
194     case -1:                             /* vertical scaling factor is < 1 */ \
195         while( (i_scale_count -= i_pic_height) > 0 )                          \
196         {                                                                     \
197             /* Height reduction: skip next source line */                     \
198             p_y += i_width;                                                   \
199             i_y++;                                                            \
200             if( (CHROMA == 420) || (CHROMA == 422) )                          \
201             {                                                                 \
202                 if( i_y & 0x1 )                                               \
203                 {                                                             \
204                     p_u += i_chroma_width;                                    \
205                     p_v += i_chroma_width;                                    \
206                 }                                                             \
207             }                                                                 \
208             else if( CHROMA == 444 )                                          \
209             {                                                                 \
210                 p_u += i_width;                                               \
211                 p_v += i_width;                                               \
212             }                                                                 \
213         }                                                                     \
214         i_scale_count += i_height;                                            \
215         break;                                                                \
216     case 1:                              /* vertical scaling factor is > 1 */ \
217         while( (i_scale_count -= i_height) > 0 )                              \
218         {                                                                     \
219             /* Height increment: copy previous picture line */                \
220             for( i_x = i_pic_width / 16; i_x--; )                             \
221             {                                                                 \
222                 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );           \
223                 *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );           \
224                 if( BPP > 1 )                               /* 2, 3, 4 Bpp */ \
225                 {                                                             \
226                     *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );       \
227                     *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );       \
228                 }                                                             \
229                 if( BPP > 2 )                                  /* 3, 4 Bpp */ \
230                 {                                                             \
231                     *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );       \
232                     *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );       \
233                 }                                                             \
234                 if( BPP > 3 )                                     /* 4 Bpp */ \
235                 {                                                             \
236                     *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );       \
237                     *(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );       \
238                 }                                                             \
239             }                                                                 \
240             p_pic +=        i_pic_line_width;                                 \
241             p_pic_start +=  i_pic_line_width;                                 \
242         }                                                                     \
243         i_scale_count += i_pic_height;                                        \
244         break;                                                                \
245     }                                                                         \
246
247 /*****************************************************************************
248  * SCALE_HEIGHT_DITHER: handle vertical scaling for dithered 8 bpp
249  *****************************************************************************
250  * This macro handles vertical scaling for a picture. CHROMA may be 420,
251  * 422 or 444 for RGB conversion, or 400 for gray conversion.
252  *****************************************************************************/
253 #define SCALE_HEIGHT_DITHER( CHROMA )                                         \
254                                                                               \
255     /* If line is odd, rewind 4:2:0 U and V samples */                        \
256     if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) )                \
257     {                                                                         \
258         p_u -= i_chroma_width;                                                \
259         p_v -= i_chroma_width;                                                \
260     }                                                                         \
261                                                                               \
262     /*                                                                        \
263      * Handle vertical scaling. The current line can be copied or next one    \
264      * can be ignored.                                                        \
265      */                                                                       \
266                                                                               \
267     switch( i_vertical_scaling )                                              \
268     {                                                                         \
269     case -1:                             /* vertical scaling factor is < 1 */ \
270         while( (i_scale_count -= i_pic_height) > 0 )                          \
271         {                                                                     \
272             /* Height reduction: skip next source line */                     \
273             p_y += i_width;                                                   \
274             i_y++;                                                            \
275             if( (CHROMA == 420) || (CHROMA == 422) )                          \
276             {                                                                 \
277                 if( i_y & 0x1 )                                               \
278                 {                                                             \
279                     p_u += i_chroma_width;                                    \
280                     p_v += i_chroma_width;                                    \
281                 }                                                             \
282             }                                                                 \
283             else if( CHROMA == 444 )                                          \
284             {                                                                 \
285                 p_u += i_width;                                               \
286                 p_v += i_width;                                               \
287             }                                                                 \
288         }                                                                     \
289         i_scale_count += i_height;                                            \
290         break;                                                                \
291     case 1:                              /* vertical scaling factor is > 1 */ \
292         while( (i_scale_count -= i_height) > 0 )                              \
293         {                                                                     \
294             p_y -= i_width;                                                   \
295             p_u -= i_chroma_width;                                            \
296             p_v -= i_chroma_width;                                            \
297             SCALE_WIDTH_DITHER( CHROMA );                                     \
298         }                                                                     \
299         i_scale_count += i_pic_height;                                        \
300         break;                                                                \
301     }                                                                         \
302