Atlas - testyuv_cvt.c

Home / ext / SDL2 / test Lines: 1 | Size: 8503 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Copyright (C) 1997-2018 Sam Lantinga <[email protected]> 3 4 This software is provided 'as-is', without any express or implied 5 warranty. In no event will the authors be held liable for any damages 6 arising from the use of this software. 7 8 Permission is granted to anyone to use this software for any purpose, 9 including commercial applications, and to alter it and redistribute it 10 freely. 11*/ 12 13#include "SDL.h" 14 15#include "testyuv_cvt.h" 16 17 18static float clip3(float x, float y, float z) 19{ 20 return ((z < x) ? x : ((z > y) ? y : z)); 21} 22 23static void RGBtoYUV(Uint8 * rgb, int *yuv, SDL_YUV_CONVERSION_MODE mode, int monochrome, int luminance) 24{ 25 if (mode == SDL_YUV_CONVERSION_JPEG) { 26 /* Full range YUV */ 27 yuv[0] = (int)(0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2]); 28 yuv[1] = (int)((rgb[2] - yuv[0]) * 0.565 + 128); 29 yuv[2] = (int)((rgb[0] - yuv[0]) * 0.713 + 128); 30 } else { 31 // This formula is from Microsoft's documentation: 32 // https://msdn.microsoft.com/en-us/library/windows/desktop/dd206750(v=vs.85).aspx 33 // L = Kr * R + Kb * B + (1 - Kr - Kb) * G 34 // Y = floor(2^(M-8) * (219*(L-Z)/S + 16) + 0.5); 35 // U = clip3(0, (2^M)-1, floor(2^(M-8) * (112*(B-L) / ((1-Kb)*S) + 128) + 0.5)); 36 // V = clip3(0, (2^M)-1, floor(2^(M-8) * (112*(R-L) / ((1-Kr)*S) + 128) + 0.5)); 37 float S, Z, R, G, B, L, Kr, Kb, Y, U, V; 38 39 if (mode == SDL_YUV_CONVERSION_BT709) { 40 /* BT.709 */ 41 Kr = 0.2126f; 42 Kb = 0.0722f; 43 } else { 44 /* BT.601 */ 45 Kr = 0.299f; 46 Kb = 0.114f; 47 } 48 49 S = 255.0f; 50 Z = 0.0f; 51 R = rgb[0]; 52 G = rgb[1]; 53 B = rgb[2]; 54 L = Kr * R + Kb * B + (1 - Kr - Kb) * G; 55 Y = (Uint8)SDL_floorf((219*(L-Z)/S + 16) + 0.5f); 56 U = (Uint8)clip3(0, 255, SDL_floorf((112.0f*(B-L) / ((1.0f-Kb)*S) + 128) + 0.5f)); 57 V = (Uint8)clip3(0, 255, SDL_floorf((112.0f*(R-L) / ((1.0f-Kr)*S) + 128) + 0.5f)); 58 59 yuv[0] = (Uint8)Y; 60 yuv[1] = (Uint8)U; 61 yuv[2] = (Uint8)V; 62 } 63 64 if (monochrome) { 65 yuv[1] = 128; 66 yuv[2] = 128; 67 } 68 69 if (luminance != 100) { 70 yuv[0] = yuv[0] * luminance / 100; 71 if (yuv[0] > 255) 72 yuv[0] = 255; 73 } 74} 75 76static void ConvertRGBtoPlanar2x2(Uint32 format, Uint8 *src, int pitch, Uint8 *out, int w, int h, SDL_YUV_CONVERSION_MODE mode, int monochrome, int luminance) 77{ 78 int x, y; 79 int yuv[4][3]; 80 Uint8 *Y1, *Y2, *U, *V; 81 Uint8 *rgb1, *rgb2; 82 int rgb_row_advance = (pitch - w*3) + pitch; 83 int UV_advance; 84 85 rgb1 = src; 86 rgb2 = src + pitch; 87 88 Y1 = out; 89 Y2 = Y1 + w; 90 switch (format) { 91 case SDL_PIXELFORMAT_YV12: 92 V = (Y1 + h * w); 93 U = V + ((h + 1)/2)*((w + 1)/2); 94 UV_advance = 1; 95 break; 96 case SDL_PIXELFORMAT_IYUV: 97 U = (Y1 + h * w); 98 V = U + ((h + 1)/2)*((w + 1)/2); 99 UV_advance = 1; 100 break; 101 case SDL_PIXELFORMAT_NV12: 102 U = (Y1 + h * w); 103 V = U + 1; 104 UV_advance = 2; 105 break; 106 case SDL_PIXELFORMAT_NV21: 107 V = (Y1 + h * w); 108 U = V + 1; 109 UV_advance = 2; 110 break; 111 default: 112 SDL_assert(!"Unsupported planar YUV format"); 113 return; 114 } 115 116 for (y = 0; y < (h - 1); y += 2) { 117 for (x = 0; x < (w - 1); x += 2) { 118 RGBtoYUV(rgb1, yuv[0], mode, monochrome, luminance); 119 rgb1 += 3; 120 *Y1++ = (Uint8)yuv[0][0]; 121 122 RGBtoYUV(rgb1, yuv[1], mode, monochrome, luminance); 123 rgb1 += 3; 124 *Y1++ = (Uint8)yuv[1][0]; 125 126 RGBtoYUV(rgb2, yuv[2], mode, monochrome, luminance); 127 rgb2 += 3; 128 *Y2++ = (Uint8)yuv[2][0]; 129 130 RGBtoYUV(rgb2, yuv[3], mode, monochrome, luminance); 131 rgb2 += 3; 132 *Y2++ = (Uint8)yuv[3][0]; 133 134 *U = (Uint8)SDL_floorf((yuv[0][1] + yuv[1][1] + yuv[2][1] + yuv[3][1])/4.0f + 0.5f); 135 U += UV_advance; 136 137 *V = (Uint8)SDL_floorf((yuv[0][2] + yuv[1][2] + yuv[2][2] + yuv[3][2])/4.0f + 0.5f); 138 V += UV_advance; 139 } 140 /* Last column */ 141 if (x == (w - 1)) { 142 RGBtoYUV(rgb1, yuv[0], mode, monochrome, luminance); 143 rgb1 += 3; 144 *Y1++ = (Uint8)yuv[0][0]; 145 146 RGBtoYUV(rgb2, yuv[2], mode, monochrome, luminance); 147 rgb2 += 3; 148 *Y2++ = (Uint8)yuv[2][0]; 149 150 *U = (Uint8)SDL_floorf((yuv[0][1] + yuv[2][1])/2.0f + 0.5f); 151 U += UV_advance; 152 153 *V = (Uint8)SDL_floorf((yuv[0][2] + yuv[2][2])/2.0f + 0.5f); 154 V += UV_advance; 155 } 156 Y1 += w; 157 Y2 += w; 158 rgb1 += rgb_row_advance; 159 rgb2 += rgb_row_advance; 160 } 161 /* Last row */ 162 if (y == (h - 1)) { 163 for (x = 0; x < (w - 1); x += 2) { 164 RGBtoYUV(rgb1, yuv[0], mode, monochrome, luminance); 165 rgb1 += 3; 166 *Y1++ = (Uint8)yuv[0][0]; 167 168 RGBtoYUV(rgb1, yuv[1], mode, monochrome, luminance); 169 rgb1 += 3; 170 *Y1++ = (Uint8)yuv[1][0]; 171 172 *U = (Uint8)SDL_floorf((yuv[0][1] + yuv[1][1])/2.0f + 0.5f); 173 U += UV_advance; 174 175 *V = (Uint8)SDL_floorf((yuv[0][2] + yuv[1][2])/2.0f + 0.5f); 176 V += UV_advance; 177 } 178 /* Last column */ 179 if (x == (w - 1)) { 180 RGBtoYUV(rgb1, yuv[0], mode, monochrome, luminance); 181 *Y1++ = (Uint8)yuv[0][0]; 182 183 *U = (Uint8)yuv[0][1]; 184 U += UV_advance; 185 186 *V = (Uint8)yuv[0][2]; 187 V += UV_advance; 188 } 189 } 190} 191 192static void ConvertRGBtoPacked4(Uint32 format, Uint8 *src, int pitch, Uint8 *out, int w, int h, SDL_YUV_CONVERSION_MODE mode, int monochrome, int luminance) 193{ 194 int x, y; 195 int yuv[2][3]; 196 Uint8 *Y1, *Y2, *U, *V; 197 Uint8 *rgb; 198 int rgb_row_advance = (pitch - w*3); 199 200 rgb = src; 201 202 switch (format) { 203 case SDL_PIXELFORMAT_YUY2: 204 Y1 = out; 205 U = out+1; 206 Y2 = out+2; 207 V = out+3; 208 break; 209 case SDL_PIXELFORMAT_UYVY: 210 U = out; 211 Y1 = out+1; 212 V = out+2; 213 Y2 = out+3; 214 break; 215 case SDL_PIXELFORMAT_YVYU: 216 Y1 = out; 217 V = out+1; 218 Y2 = out+2; 219 U = out+3; 220 break; 221 default: 222 SDL_assert(!"Unsupported packed YUV format"); 223 return; 224 } 225 226 for (y = 0; y < h; ++y) { 227 for (x = 0; x < (w - 1); x += 2) { 228 RGBtoYUV(rgb, yuv[0], mode, monochrome, luminance); 229 rgb += 3; 230 *Y1 = (Uint8)yuv[0][0]; 231 Y1 += 4; 232 233 RGBtoYUV(rgb, yuv[1], mode, monochrome, luminance); 234 rgb += 3; 235 *Y2 = (Uint8)yuv[1][0]; 236 Y2 += 4; 237 238 *U = (Uint8)SDL_floorf((yuv[0][1] + yuv[1][1])/2.0f + 0.5f); 239 U += 4; 240 241 *V = (Uint8)SDL_floorf((yuv[0][2] + yuv[1][2])/2.0f + 0.5f); 242 V += 4; 243 } 244 /* Last column */ 245 if (x == (w - 1)) { 246 RGBtoYUV(rgb, yuv[0], mode, monochrome, luminance); 247 rgb += 3; 248 *Y2 = *Y1 = (Uint8)yuv[0][0]; 249 Y1 += 4; 250 Y2 += 4; 251 252 *U = (Uint8)yuv[0][1]; 253 U += 4; 254 255 *V = (Uint8)yuv[0][2]; 256 V += 4; 257 } 258 rgb += rgb_row_advance; 259 } 260} 261 262SDL_bool ConvertRGBtoYUV(Uint32 format, Uint8 *src, int pitch, Uint8 *out, int w, int h, SDL_YUV_CONVERSION_MODE mode, int monochrome, int luminance) 263{ 264 switch (format) 265 { 266 case SDL_PIXELFORMAT_YV12: 267 case SDL_PIXELFORMAT_IYUV: 268 case SDL_PIXELFORMAT_NV12: 269 case SDL_PIXELFORMAT_NV21: 270 ConvertRGBtoPlanar2x2(format, src, pitch, out, w, h, mode, monochrome, luminance); 271 return SDL_TRUE; 272 case SDL_PIXELFORMAT_YUY2: 273 case SDL_PIXELFORMAT_UYVY: 274 case SDL_PIXELFORMAT_YVYU: 275 ConvertRGBtoPacked4(format, src, pitch, out, w, h, mode, monochrome, luminance); 276 return SDL_TRUE; 277 default: 278 return SDL_FALSE; 279 } 280} 281 282int CalculateYUVPitch(Uint32 format, int width) 283{ 284 switch (format) 285 { 286 case SDL_PIXELFORMAT_YV12: 287 case SDL_PIXELFORMAT_IYUV: 288 case SDL_PIXELFORMAT_NV12: 289 case SDL_PIXELFORMAT_NV21: 290 return width; 291 case SDL_PIXELFORMAT_YUY2: 292 case SDL_PIXELFORMAT_UYVY: 293 case SDL_PIXELFORMAT_YVYU: 294 return 4*((width + 1)/2); 295 default: 296 return 0; 297 } 298} 299 300/* vi: set ts=4 sw=4 expandtab: */ 301
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.