]> git.sesse.net Git - vlc/blob - plugins/yuv/transforms_yuv.h
da658b47c111879a59bba4ef1230072f47dc8980
[vlc] / plugins / yuv / transforms_yuv.h
1 /*****************************************************************************
2  * transforms_yuv.h: C specific YUV transformation macros
3  *****************************************************************************
4  * Copyright (C) 1999, 2000 VideoLAN
5  *
6  * Authors:
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public
19  * License along with this program; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * CONVERT_4YUV_PIXELS: dither 4 pixels in 8 bpp
26  *****************************************************************************
27  * These macros dither 4 pixels in 8 bpp
28  *****************************************************************************/
29 #define CONVERT_4YUV_PIXELS( CHROMA )                                         \
30     *p_pic++ = p_lookup[                                                      \
31         (((*p_y++ + dither10[i_real_y]) >> 4) << 7)                           \
32       + ((*p_u + dither20[i_real_y]) >> 5) * 9                                \
33       + ((*p_v + dither20[i_real_y]) >> 5) ];                                 \
34     *p_pic++ = p_lookup[                                                      \
35         (((*p_y++ + dither11[i_real_y]) >> 4) << 7)                           \
36       + ((*p_u++ + dither21[i_real_y]) >> 5) * 9                              \
37       + ((*p_v++ + dither21[i_real_y]) >> 5) ];                               \
38     *p_pic++ = p_lookup[                                                      \
39         (((*p_y++ + dither12[i_real_y]) >> 4) << 7)                           \
40       + ((*p_u + dither22[i_real_y]) >> 5) * 9                                \
41       + ((*p_v + dither22[i_real_y]) >> 5) ];                                 \
42     *p_pic++ = p_lookup[                                                      \
43         (((*p_y++ + dither13[i_real_y]) >> 4) << 7)                           \
44       + ((*p_u++ + dither23[i_real_y]) >> 5) * 9                              \
45       + ((*p_v++ + dither23[i_real_y]) >> 5) ];                               \
46
47 /*****************************************************************************
48  * CONVERT_4YUV_PIXELS_SCALE: dither and scale 4 pixels in 8 bpp
49  *****************************************************************************
50  * These macros dither 4 pixels in 8 bpp, with horizontal scaling
51  *****************************************************************************/
52 #define CONVERT_4YUV_PIXELS_SCALE( CHROMA )                                   \
53     *p_pic++ = p_lookup[                                                      \
54         ( ((*p_y + dither10[i_real_y]) >> 4) << 7)                            \
55         + ((*p_u + dither20[i_real_y]) >> 5) * 9                              \
56         + ((*p_v + dither20[i_real_y]) >> 5) ];                               \
57     p_y += *p_offset++;                                                       \
58     p_u += *p_offset;                                                         \
59     p_v += *p_offset++;                                                       \
60     *p_pic++ = p_lookup[                                                      \
61         ( ((*p_y + dither11[i_real_y]) >> 4) << 7)                            \
62         + ((*p_u + dither21[i_real_y]) >> 5) * 9                              \
63         + ((*p_v + dither21[i_real_y]) >> 5) ];                               \
64     p_y += *p_offset++;                                                       \
65     p_u += *p_offset;                                                         \
66     p_v += *p_offset++;                                                       \
67     *p_pic++ = p_lookup[                                                      \
68         ( ((*p_y + dither12[i_real_y]) >> 4) << 7)                            \
69         + ((*p_u + dither22[i_real_y]) >> 5) * 9                              \
70         + ((*p_v + dither22[i_real_y]) >> 5) ];                               \
71     p_y += *p_offset++;                                                       \
72     p_u += *p_offset;                                                         \
73     p_v += *p_offset++;                                                       \
74     *p_pic++ = p_lookup[                                                      \
75         ( ((*p_y + dither13[i_real_y]) >> 4) << 7)                            \
76         + ((*p_u + dither23[i_real_y]) >> 5) * 9                              \
77         + ((*p_v + dither23[i_real_y]) >> 5) ];                               \
78     p_y += *p_offset++;                                                       \
79     p_u += *p_offset;                                                         \
80     p_v += *p_offset++;                                                       \
81
82 /*****************************************************************************
83  * SCALE_WIDTH_DITHER: scale a line horizontally for dithered 8 bpp
84  *****************************************************************************
85  * This macro scales a line using an offset array.
86  *****************************************************************************/
87 #define SCALE_WIDTH_DITHER( CHROMA )                                          \
88     if( b_horizontal_scaling )                                                \
89     {                                                                         \
90         /* Horizontal scaling - we can't use a buffer due to dithering */     \
91         p_offset = p_offset_start;                                            \
92         for( i_x = i_pic_width / 16; i_x--; )                                 \
93         {                                                                     \
94             CONVERT_4YUV_PIXELS_SCALE( CHROMA )                               \
95             CONVERT_4YUV_PIXELS_SCALE( CHROMA )                               \
96             CONVERT_4YUV_PIXELS_SCALE( CHROMA )                               \
97             CONVERT_4YUV_PIXELS_SCALE( CHROMA )                               \
98         }                                                                     \
99     }                                                                         \
100     else                                                                      \
101     {                                                                         \
102         for( i_x = i_width / 16; i_x--;  )                                    \
103         {                                                                     \
104             CONVERT_4YUV_PIXELS( CHROMA )                                     \
105             CONVERT_4YUV_PIXELS( CHROMA )                                     \
106             CONVERT_4YUV_PIXELS( CHROMA )                                     \
107             CONVERT_4YUV_PIXELS( CHROMA )                                     \
108         }                                                                     \
109     }                                                                         \
110     /* Increment of picture pointer to end of line is still needed */         \
111     p_pic += i_pic_line_width;                                                \
112                                                                               \
113     /* Increment the Y coordinate in the matrix, modulo 4 */                  \
114     i_real_y = (i_real_y + 1) & 0x3;                                          \
115
116 /*****************************************************************************
117  * SCALE_HEIGHT_DITHER: handle vertical scaling for dithered 8 bpp
118  *****************************************************************************
119  * This macro handles vertical scaling for a picture. CHROMA may be 420,
120  * 422 or 444 for RGB conversion, or 400 for gray conversion.
121  *****************************************************************************/
122 #define SCALE_HEIGHT_DITHER( CHROMA )                                         \
123                                                                               \
124     /* If line is odd, rewind 4:2:0 U and V samples */                        \
125     if( ((CHROMA == 420) || (CHROMA == 422)) && !(i_y & 0x1) )                \
126     {                                                                         \
127         p_u -= i_chroma_width;                                                \
128         p_v -= i_chroma_width;                                                \
129     }                                                                         \
130                                                                               \
131     /*                                                                        \
132      * Handle vertical scaling. The current line can be copied or next one    \
133      * can be ignored.                                                        \
134      */                                                                       \
135                                                                               \
136     switch( i_vertical_scaling )                                              \
137     {                                                                         \
138     case -1:                             /* vertical scaling factor is < 1 */ \
139         while( (i_scale_count -= i_pic_height) > 0 )                          \
140         {                                                                     \
141             /* Height reduction: skip next source line */                     \
142             p_y += i_width;                                                   \
143             i_y++;                                                            \
144             if( (CHROMA == 420) || (CHROMA == 422) )                          \
145             {                                                                 \
146                 if( i_y & 0x1 )                                               \
147                 {                                                             \
148                     p_u += i_chroma_width;                                    \
149                     p_v += i_chroma_width;                                    \
150                 }                                                             \
151             }                                                                 \
152             else if( CHROMA == 444 )                                          \
153             {                                                                 \
154                 p_u += i_width;                                               \
155                 p_v += i_width;                                               \
156             }                                                                 \
157         }                                                                     \
158         i_scale_count += i_height;                                            \
159         break;                                                                \
160     case 1:                              /* vertical scaling factor is > 1 */ \
161         while( (i_scale_count -= i_height) > 0 )                              \
162         {                                                                     \
163             p_y -= i_width;                                                   \
164             p_u -= i_chroma_width;                                            \
165             p_v -= i_chroma_width;                                            \
166             SCALE_WIDTH_DITHER( CHROMA );                                     \
167         }                                                                     \
168         i_scale_count += i_pic_height;                                        \
169         break;                                                                \
170     }                                                                         \
171