bf4f48eaba093b9fb7a1ef31d987bbc435b87003
[platform/upstream/SDL.git] / src / video / yuv2rgb / yuv_rgb_std_func.h
1 // Copyright 2016 Adrien Descamps
2 // Distributed under BSD 3-Clause License
3
4 /* You need to define the following macros before including this file:
5         STD_FUNCTION_NAME
6         YUV_FORMAT
7         RGB_FORMAT
8 */
9
10 #if RGB_FORMAT == RGB_FORMAT_RGB565
11
12 #define PACK_PIXEL(rgb_ptr) \
13         *(Uint16 *)rgb_ptr = \
14                 ((((Uint16)clampU8(y_tmp+r_tmp)) << 8 ) & 0xF800) | \
15                 ((((Uint16)clampU8(y_tmp+g_tmp)) << 3) & 0x07E0) | \
16                 (((Uint16)clampU8(y_tmp+b_tmp)) >> 3); \
17         rgb_ptr += 2; \
18
19 #elif RGB_FORMAT == RGB_FORMAT_RGB24
20
21 #define PACK_PIXEL(rgb_ptr) \
22         rgb_ptr[0] = clampU8(y_tmp+r_tmp); \
23         rgb_ptr[1] = clampU8(y_tmp+g_tmp); \
24         rgb_ptr[2] = clampU8(y_tmp+b_tmp); \
25         rgb_ptr += 3; \
26
27 #elif RGB_FORMAT == RGB_FORMAT_RGBA
28
29 #define PACK_PIXEL(rgb_ptr) \
30         *(Uint32 *)rgb_ptr = \
31                 (((Uint32)clampU8(y_tmp+r_tmp)) << 24) | \
32                 (((Uint32)clampU8(y_tmp+g_tmp)) << 16) | \
33                 (((Uint32)clampU8(y_tmp+b_tmp)) << 8) | \
34                 0x000000FF; \
35         rgb_ptr += 4; \
36
37 #elif RGB_FORMAT == RGB_FORMAT_BGRA
38
39 #define PACK_PIXEL(rgb_ptr) \
40         *(Uint32 *)rgb_ptr = \
41                 (((Uint32)clampU8(y_tmp+b_tmp)) << 24) | \
42                 (((Uint32)clampU8(y_tmp+g_tmp)) << 16) | \
43                 (((Uint32)clampU8(y_tmp+r_tmp)) << 8) | \
44                 0x000000FF; \
45         rgb_ptr += 4; \
46
47 #elif RGB_FORMAT == RGB_FORMAT_ARGB
48
49 #define PACK_PIXEL(rgb_ptr) \
50         *(Uint32 *)rgb_ptr = \
51                 0xFF000000 | \
52                 (((Uint32)clampU8(y_tmp+r_tmp)) << 16) | \
53                 (((Uint32)clampU8(y_tmp+g_tmp)) << 8) | \
54                 (((Uint32)clampU8(y_tmp+b_tmp)) << 0); \
55         rgb_ptr += 4; \
56
57 #elif RGB_FORMAT == RGB_FORMAT_ABGR
58
59 #define PACK_PIXEL(rgb_ptr) \
60         *(Uint32 *)rgb_ptr = \
61                 0xFF000000 | \
62                 (((Uint32)clampU8(y_tmp+b_tmp)) << 16) | \
63                 (((Uint32)clampU8(y_tmp+g_tmp)) << 8) | \
64                 (((Uint32)clampU8(y_tmp+r_tmp)) << 0); \
65         rgb_ptr += 4; \
66
67 #else
68 #error PACK_PIXEL unimplemented
69 #endif
70
71
72 void STD_FUNCTION_NAME(
73         uint32_t width, uint32_t height, 
74         const uint8_t *Y, const uint8_t *U, const uint8_t *V, uint32_t Y_stride, uint32_t UV_stride, 
75         uint8_t *RGB, uint32_t RGB_stride, 
76         YCbCrType yuv_type)
77 {
78         const YUV2RGBParam *const param = &(YUV2RGB[yuv_type]);
79 #if YUV_FORMAT == YUV_FORMAT_420
80         const int y_pixel_stride = 1;
81         const int uv_pixel_stride = 1;
82         const int uv_x_sample_interval = 2;
83         const int uv_y_sample_interval = 2;
84 #elif YUV_FORMAT == YUV_FORMAT_422
85         const int y_pixel_stride = 2;
86         const int uv_pixel_stride = 4;
87         const int uv_x_sample_interval = 2;
88         const int uv_y_sample_interval = 1;
89 #elif YUV_FORMAT == YUV_FORMAT_NV12
90         const int y_pixel_stride = 1;
91         const int uv_pixel_stride = 2;
92         const int uv_x_sample_interval = 2;
93         const int uv_y_sample_interval = 2;
94 #endif
95
96         uint32_t x, y;
97         for(y=0; y<(height-(uv_y_sample_interval-1)); y+=uv_y_sample_interval)
98         {
99                 const uint8_t *y_ptr1=Y+y*Y_stride,
100                         *y_ptr2=Y+(y+1)*Y_stride,
101                         *u_ptr=U+(y/uv_y_sample_interval)*UV_stride,
102                         *v_ptr=V+(y/uv_y_sample_interval)*UV_stride;
103                 
104                 uint8_t *rgb_ptr1=RGB+y*RGB_stride,
105                         *rgb_ptr2=RGB+(y+1)*RGB_stride;
106                 
107                 for(x=0; x<(width-(uv_x_sample_interval-1)); x+=uv_x_sample_interval)
108                 {
109                         // Compute U and V contributions, common to the four pixels
110                         
111                         int32_t u_tmp = ((*u_ptr)-128);
112                         int32_t v_tmp = ((*v_ptr)-128);
113                         
114                         int32_t r_tmp = (v_tmp*param->v_r_factor);
115                         int32_t g_tmp = (u_tmp*param->u_g_factor + v_tmp*param->v_g_factor);
116                         int32_t b_tmp = (u_tmp*param->u_b_factor);
117                         
118                         // Compute the Y contribution for each pixel
119                         
120                         int32_t y_tmp = ((y_ptr1[0]-param->y_shift)*param->y_factor);
121                         PACK_PIXEL(rgb_ptr1);
122                         
123                         y_tmp = ((y_ptr1[y_pixel_stride]-param->y_shift)*param->y_factor);
124                         PACK_PIXEL(rgb_ptr1);
125                         
126                         if (uv_y_sample_interval > 1) {
127                                 y_tmp = ((y_ptr2[0]-param->y_shift)*param->y_factor);
128                                 PACK_PIXEL(rgb_ptr2);
129                                 
130                                 y_tmp = ((y_ptr2[y_pixel_stride]-param->y_shift)*param->y_factor);
131                                 PACK_PIXEL(rgb_ptr2);
132                         }
133
134                         y_ptr1+=2*y_pixel_stride;
135                         y_ptr2+=2*y_pixel_stride;
136                         u_ptr+=2*uv_pixel_stride/uv_x_sample_interval;
137                         v_ptr+=2*uv_pixel_stride/uv_x_sample_interval;
138                 }
139
140                 /* Catch the last pixel, if needed */
141                 if (uv_x_sample_interval == 2 && x == (width-1))
142                 {
143                         // Compute U and V contributions, common to the four pixels
144                         
145                         int32_t u_tmp = ((*u_ptr)-128);
146                         int32_t v_tmp = ((*v_ptr)-128);
147                         
148                         int32_t r_tmp = (v_tmp*param->v_r_factor);
149                         int32_t g_tmp = (u_tmp*param->u_g_factor + v_tmp*param->v_g_factor);
150                         int32_t b_tmp = (u_tmp*param->u_b_factor);
151                         
152                         // Compute the Y contribution for each pixel
153                         
154                         int32_t y_tmp = ((y_ptr1[0]-param->y_shift)*param->y_factor);
155                         PACK_PIXEL(rgb_ptr1);
156                         
157                         if (uv_y_sample_interval > 1) {
158                                 y_tmp = ((y_ptr2[0]-param->y_shift)*param->y_factor);
159                                 PACK_PIXEL(rgb_ptr2);
160                         }
161                 }
162         }
163
164         /* Catch the last line, if needed */
165         if (uv_y_sample_interval == 2 && y == (height-1))
166         {
167                 const uint8_t *y_ptr1=Y+y*Y_stride,
168                         *u_ptr=U+(y/uv_y_sample_interval)*UV_stride,
169                         *v_ptr=V+(y/uv_y_sample_interval)*UV_stride;
170                 
171                 uint8_t *rgb_ptr1=RGB+y*RGB_stride;
172                 
173                 for(x=0; x<(width-(uv_x_sample_interval-1)); x+=uv_x_sample_interval)
174                 {
175                         // Compute U and V contributions, common to the four pixels
176                         
177                         int32_t u_tmp = ((*u_ptr)-128);
178                         int32_t v_tmp = ((*v_ptr)-128);
179                         
180                         int32_t r_tmp = (v_tmp*param->v_r_factor);
181                         int32_t g_tmp = (u_tmp*param->u_g_factor + v_tmp*param->v_g_factor);
182                         int32_t b_tmp = (u_tmp*param->u_b_factor);
183                         
184                         // Compute the Y contribution for each pixel
185                         
186                         int32_t y_tmp = ((y_ptr1[0]-param->y_shift)*param->y_factor);
187                         PACK_PIXEL(rgb_ptr1);
188                         
189                         y_tmp = ((y_ptr1[y_pixel_stride]-param->y_shift)*param->y_factor);
190                         PACK_PIXEL(rgb_ptr1);
191                         
192                         y_ptr1+=2*y_pixel_stride;
193                         u_ptr+=2*uv_pixel_stride/uv_x_sample_interval;
194                         v_ptr+=2*uv_pixel_stride/uv_x_sample_interval;
195                 }
196
197                 /* Catch the last pixel, if needed */
198                 if (uv_x_sample_interval == 2 && x == (width-1))
199                 {
200                         // Compute U and V contributions, common to the four pixels
201                         
202                         int32_t u_tmp = ((*u_ptr)-128);
203                         int32_t v_tmp = ((*v_ptr)-128);
204                         
205                         int32_t r_tmp = (v_tmp*param->v_r_factor);
206                         int32_t g_tmp = (u_tmp*param->u_g_factor + v_tmp*param->v_g_factor);
207                         int32_t b_tmp = (u_tmp*param->u_b_factor);
208                         
209                         // Compute the Y contribution for each pixel
210                         
211                         int32_t y_tmp = ((y_ptr1[0]-param->y_shift)*param->y_factor);
212                         PACK_PIXEL(rgb_ptr1);
213                 }
214         }
215 }
216
217 #undef STD_FUNCTION_NAME
218 #undef YUV_FORMAT
219 #undef RGB_FORMAT
220 #undef PACK_PIXEL