1 // Copyright 2016 Adrien Descamps 2 // Distributed under BSD 3-Clause License 3 4 // Provide optimized functions to convert images from 8bits yuv420 to rgb24 format 5 6 // There are a few slightly different variations of the YCbCr color space with different parameters that 7 // change the conversion matrix. 8 // The three most common YCbCr color space, defined by BT.601, BT.709 and JPEG standard are implemented here. 9 // See the respective standards for details 10 // The matrix values used are derived from http://www.equasys.de/colorconversion.html 11 12 // YUV420 is stored as three separate channels, with U and V (Cb and Cr) subsampled by a 2 factor 13 // For conversion from yuv to rgb, no interpolation is done, and the same UV value are used for 4 rgb pixels. This 14 // is suboptimal for image quality, but by far the fastest method. 15 16 // For all methods, width and height should be even, if not, the last row/column of the result image won't be affected. 17 // For sse methods, if the width if not divisable by 32, the last (width%32) pixels of each line won't be affected. 18 19 #include "SDL_stdinc.h" 20 /*#include <stdint.h>*/ 21 22 typedef enum 23 { 24 YCBCR_JPEG, 25 YCBCR_601, 26 YCBCR_709 27 } YCbCrType; 28 29 // yuv to rgb, standard c implementation 30 void yuv420_rgb565_std( 31 uint32_t width, uint32_t height, 32 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 33 uint8_t *rgb, uint32_t rgb_stride, 34 YCbCrType yuv_type); 35 36 void yuv420_rgb24_std( 37 uint32_t width, uint32_t height, 38 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 39 uint8_t *rgb, uint32_t rgb_stride, 40 YCbCrType yuv_type); 41 42 void yuv420_rgba_std( 43 uint32_t width, uint32_t height, 44 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 45 uint8_t *rgb, uint32_t rgb_stride, 46 YCbCrType yuv_type); 47 48 void yuv420_bgra_std( 49 uint32_t width, uint32_t height, 50 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 51 uint8_t *rgb, uint32_t rgb_stride, 52 YCbCrType yuv_type); 53 54 void yuv420_argb_std( 55 uint32_t width, uint32_t height, 56 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 57 uint8_t *rgb, uint32_t rgb_stride, 58 YCbCrType yuv_type); 59 60 void yuv420_abgr_std( 61 uint32_t width, uint32_t height, 62 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 63 uint8_t *rgb, uint32_t rgb_stride, 64 YCbCrType yuv_type); 65 66 void yuv422_rgb565_std( 67 uint32_t width, uint32_t height, 68 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 69 uint8_t *rgb, uint32_t rgb_stride, 70 YCbCrType yuv_type); 71 72 void yuv422_rgb24_std( 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 void yuv422_rgba_std( 79 uint32_t width, uint32_t height, 80 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 81 uint8_t *rgb, uint32_t rgb_stride, 82 YCbCrType yuv_type); 83 84 void yuv422_bgra_std( 85 uint32_t width, uint32_t height, 86 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 87 uint8_t *rgb, uint32_t rgb_stride, 88 YCbCrType yuv_type); 89 90 void yuv422_argb_std( 91 uint32_t width, uint32_t height, 92 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 93 uint8_t *rgb, uint32_t rgb_stride, 94 YCbCrType yuv_type); 95 96 void yuv422_abgr_std( 97 uint32_t width, uint32_t height, 98 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 99 uint8_t *rgb, uint32_t rgb_stride, 100 YCbCrType yuv_type); 101 102 void yuvnv12_rgb565_std( 103 uint32_t width, uint32_t height, 104 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 105 uint8_t *rgb, uint32_t rgb_stride, 106 YCbCrType yuv_type); 107 108 void yuvnv12_rgb24_std( 109 uint32_t width, uint32_t height, 110 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 111 uint8_t *rgb, uint32_t rgb_stride, 112 YCbCrType yuv_type); 113 114 void yuvnv12_rgba_std( 115 uint32_t width, uint32_t height, 116 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 117 uint8_t *rgb, uint32_t rgb_stride, 118 YCbCrType yuv_type); 119 120 void yuvnv12_bgra_std( 121 uint32_t width, uint32_t height, 122 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 123 uint8_t *rgb, uint32_t rgb_stride, 124 YCbCrType yuv_type); 125 126 void yuvnv12_argb_std( 127 uint32_t width, uint32_t height, 128 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 129 uint8_t *rgb, uint32_t rgb_stride, 130 YCbCrType yuv_type); 131 132 void yuvnv12_abgr_std( 133 uint32_t width, uint32_t height, 134 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 135 uint8_t *rgb, uint32_t rgb_stride, 136 YCbCrType yuv_type); 137 138 // yuv to rgb, sse implementation 139 // pointers must be 16 byte aligned, and strides must be divisable by 16 140 void yuv420_rgb565_sse( 141 uint32_t width, uint32_t height, 142 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 143 uint8_t *rgb, uint32_t rgb_stride, 144 YCbCrType yuv_type); 145 146 void yuv420_rgb24_sse( 147 uint32_t width, uint32_t height, 148 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 149 uint8_t *rgb, uint32_t rgb_stride, 150 YCbCrType yuv_type); 151 152 void yuv420_rgba_sse( 153 uint32_t width, uint32_t height, 154 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 155 uint8_t *rgb, uint32_t rgb_stride, 156 YCbCrType yuv_type); 157 158 void yuv420_bgra_sse( 159 uint32_t width, uint32_t height, 160 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 161 uint8_t *rgb, uint32_t rgb_stride, 162 YCbCrType yuv_type); 163 164 void yuv420_argb_sse( 165 uint32_t width, uint32_t height, 166 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 167 uint8_t *rgb, uint32_t rgb_stride, 168 YCbCrType yuv_type); 169 170 void yuv420_abgr_sse( 171 uint32_t width, uint32_t height, 172 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 173 uint8_t *rgb, uint32_t rgb_stride, 174 YCbCrType yuv_type); 175 176 void yuv422_rgb565_sse( 177 uint32_t width, uint32_t height, 178 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 179 uint8_t *rgb, uint32_t rgb_stride, 180 YCbCrType yuv_type); 181 182 void yuv422_rgb24_sse( 183 uint32_t width, uint32_t height, 184 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 185 uint8_t *rgb, uint32_t rgb_stride, 186 YCbCrType yuv_type); 187 188 void yuv422_rgba_sse( 189 uint32_t width, uint32_t height, 190 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 191 uint8_t *rgb, uint32_t rgb_stride, 192 YCbCrType yuv_type); 193 194 void yuv422_bgra_sse( 195 uint32_t width, uint32_t height, 196 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 197 uint8_t *rgb, uint32_t rgb_stride, 198 YCbCrType yuv_type); 199 200 void yuv422_argb_sse( 201 uint32_t width, uint32_t height, 202 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 203 uint8_t *rgb, uint32_t rgb_stride, 204 YCbCrType yuv_type); 205 206 void yuv422_abgr_sse( 207 uint32_t width, uint32_t height, 208 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 209 uint8_t *rgb, uint32_t rgb_stride, 210 YCbCrType yuv_type); 211 212 void yuvnv12_rgb565_sse( 213 uint32_t width, uint32_t height, 214 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 215 uint8_t *rgb, uint32_t rgb_stride, 216 YCbCrType yuv_type); 217 218 void yuvnv12_rgb24_sse( 219 uint32_t width, uint32_t height, 220 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 221 uint8_t *rgb, uint32_t rgb_stride, 222 YCbCrType yuv_type); 223 224 void yuvnv12_rgba_sse( 225 uint32_t width, uint32_t height, 226 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 227 uint8_t *rgb, uint32_t rgb_stride, 228 YCbCrType yuv_type); 229 230 void yuvnv12_bgra_sse( 231 uint32_t width, uint32_t height, 232 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 233 uint8_t *rgb, uint32_t rgb_stride, 234 YCbCrType yuv_type); 235 236 void yuvnv12_argb_sse( 237 uint32_t width, uint32_t height, 238 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 239 uint8_t *rgb, uint32_t rgb_stride, 240 YCbCrType yuv_type); 241 242 void yuvnv12_abgr_sse( 243 uint32_t width, uint32_t height, 244 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 245 uint8_t *rgb, uint32_t rgb_stride, 246 YCbCrType yuv_type); 247 248 // yuv to rgb, sse implementation 249 // pointers do not need to be 16 byte aligned 250 void yuv420_rgb565_sseu( 251 uint32_t width, uint32_t height, 252 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 253 uint8_t *rgb, uint32_t rgb_stride, 254 YCbCrType yuv_type); 255 256 void yuv420_rgb24_sseu( 257 uint32_t width, uint32_t height, 258 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 259 uint8_t *rgb, uint32_t rgb_stride, 260 YCbCrType yuv_type); 261 262 void yuv420_rgba_sseu( 263 uint32_t width, uint32_t height, 264 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 265 uint8_t *rgb, uint32_t rgb_stride, 266 YCbCrType yuv_type); 267 268 void yuv420_bgra_sseu( 269 uint32_t width, uint32_t height, 270 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 271 uint8_t *rgb, uint32_t rgb_stride, 272 YCbCrType yuv_type); 273 274 void yuv420_argb_sseu( 275 uint32_t width, uint32_t height, 276 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 277 uint8_t *rgb, uint32_t rgb_stride, 278 YCbCrType yuv_type); 279 280 void yuv420_abgr_sseu( 281 uint32_t width, uint32_t height, 282 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 283 uint8_t *rgb, uint32_t rgb_stride, 284 YCbCrType yuv_type); 285 286 void yuv422_rgb565_sseu( 287 uint32_t width, uint32_t height, 288 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 289 uint8_t *rgb, uint32_t rgb_stride, 290 YCbCrType yuv_type); 291 292 void yuv422_rgb24_sseu( 293 uint32_t width, uint32_t height, 294 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 295 uint8_t *rgb, uint32_t rgb_stride, 296 YCbCrType yuv_type); 297 298 void yuv422_rgba_sseu( 299 uint32_t width, uint32_t height, 300 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 301 uint8_t *rgb, uint32_t rgb_stride, 302 YCbCrType yuv_type); 303 304 void yuv422_bgra_sseu( 305 uint32_t width, uint32_t height, 306 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 307 uint8_t *rgb, uint32_t rgb_stride, 308 YCbCrType yuv_type); 309 310 void yuv422_argb_sseu( 311 uint32_t width, uint32_t height, 312 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 313 uint8_t *rgb, uint32_t rgb_stride, 314 YCbCrType yuv_type); 315 316 void yuv422_abgr_sseu( 317 uint32_t width, uint32_t height, 318 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 319 uint8_t *rgb, uint32_t rgb_stride, 320 YCbCrType yuv_type); 321 322 void yuvnv12_rgb565_sseu( 323 uint32_t width, uint32_t height, 324 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 325 uint8_t *rgb, uint32_t rgb_stride, 326 YCbCrType yuv_type); 327 328 void yuvnv12_rgb24_sseu( 329 uint32_t width, uint32_t height, 330 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 331 uint8_t *rgb, uint32_t rgb_stride, 332 YCbCrType yuv_type); 333 334 void yuvnv12_rgba_sseu( 335 uint32_t width, uint32_t height, 336 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 337 uint8_t *rgb, uint32_t rgb_stride, 338 YCbCrType yuv_type); 339 340 void yuvnv12_bgra_sseu( 341 uint32_t width, uint32_t height, 342 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 343 uint8_t *rgb, uint32_t rgb_stride, 344 YCbCrType yuv_type); 345 346 void yuvnv12_argb_sseu( 347 uint32_t width, uint32_t height, 348 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 349 uint8_t *rgb, uint32_t rgb_stride, 350 YCbCrType yuv_type); 351 352 void yuvnv12_abgr_sseu( 353 uint32_t width, uint32_t height, 354 const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 355 uint8_t *rgb, uint32_t rgb_stride, 356 YCbCrType yuv_type); 357 358 359 // rgb to yuv, standard c implementation 360 void rgb24_yuv420_std( 361 uint32_t width, uint32_t height, 362 const uint8_t *rgb, uint32_t rgb_stride, 363 uint8_t *y, uint8_t *u, uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 364 YCbCrType yuv_type); 365 366 // rgb to yuv, sse implementation 367 // pointers must be 16 byte aligned, and strides must be divisible by 16 368 void rgb24_yuv420_sse( 369 uint32_t width, uint32_t height, 370 const uint8_t *rgb, uint32_t rgb_stride, 371 uint8_t *y, uint8_t *u, uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 372 YCbCrType yuv_type); 373 374 // rgb to yuv, sse implementation 375 // pointers do not need to be 16 byte aligned 376 void rgb24_yuv420_sseu( 377 uint32_t width, uint32_t height, 378 const uint8_t *rgb, uint32_t rgb_stride, 379 uint8_t *y, uint8_t *u, uint8_t *v, uint32_t y_stride, uint32_t uv_stride, 380 YCbCrType yuv_type); 381 382