FreeRDP
Loading...
Searching...
No Matches
prim_colors.c
1/* FreeRDP: A Remote Desktop Protocol Client
2 * Color conversion operations.
3 * vi:ts=4 sw=4:
4 *
5 * Copyright 2011 Stephen Erisman
6 * Copyright 2011 Norbert Federa <norbert.federa@thincast.com>
7 * Copyright 2011 Martin Fleisz <martin.fleisz@thincast.com>
8 * (c) Copyright 2012 Hewlett-Packard Development Company, L.P.
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License"); you may
11 * not use this file except in compliance with the License. You may obtain
12 * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
16 * or implied. See the License for the specific language governing
17 * permissions and limitations under the License.
18 */
19
20#include <math.h>
21
22#include <freerdp/config.h>
23#include <winpr/assert.h>
24#include <winpr/cast.h>
25
26#include <freerdp/types.h>
27#include <freerdp/primitives.h>
28#include <freerdp/codec/color.h>
29
30#include "prim_internal.h"
31#include "prim_colors.h"
32
33#ifndef MINMAX
34#define MINMAX(_v_, _l_, _h_) ((_v_) < (_l_) ? (_l_) : ((_v_) > (_h_) ? (_h_) : (_v_)))
35#endif /* !MINMAX */
36/* ------------------------------------------------------------------------- */
37
38/* pregenerated table for ycbcr constants: [0,27]
39 *
40 * rounded integer values derived from the following formula:
41 *
42 * { (1.402525f * 2^divisor), (0.714401f * 2^divisor), (0.343730f * 2^divisor), (1.769905f *
43 * 2^divisor) }
44 */
45
46static const INT32 ycbcr_constants[][4] = { { 1, 1, 0, 2 },
47 { 3, 1, 1, 4 },
48 { 6, 3, 1, 7 },
49 { 11, 6, 3, 14 },
50 { 22, 11, 5, 28 },
51 { 45, 23, 11, 57 },
52 { 90, 46, 22, 113 },
53 { 180, 91, 44, 227 },
54 { 359, 183, 88, 453 },
55 { 718, 366, 176, 906 },
56 { 1436, 732, 352, 1812 },
57 { 2872, 1463, 704, 3625 },
58 { 5745, 2926, 1408, 7250 },
59 { 11489, 5852, 2816, 14499 },
60 { 22979, 11705, 5632, 28998 },
61 { 45958, 23409, 11263, 57996 },
62 { 91916, 46819, 22527, 115992 },
63 { 183832, 93638, 45053, 231985 },
64 { 367664, 187276, 90107, 463970 },
65 { 735327, 374552, 180214, 927940 },
66 { 1470654, 749104, 360427, 1855880 },
67 { 2941308, 1498207, 720854, 3711760 },
68 { 5882616, 2996415, 1441708, 7423520 },
69 { 11765232, 5992830, 2883416, 14847039 },
70 { 23530465, 11985660, 5766832, 29694078 },
71 { 47060930, 23971320, 11533665, 59388157 },
72 { 94121859, 47942640, 23067330, 118776314 },
73 { 188243719, 95885279, 46134660, 237552628 },
74 { 376487438, 191770558, 92269319, 475105256 },
75 { 752974876, 383541116, 184538639, 950210512 },
76 { 1505949752, 767082233, 369077277, 1900421023 } };
77
78static pstatus_t general_yCbCrToRGB_16s8u_P3AC4R_BGRX(const INT16* WINPR_RESTRICT pSrc[3],
79 UINT32 srcStep, BYTE* WINPR_RESTRICT pDst,
80 UINT32 dstStep, UINT32 DstFormat,
81 const prim_size_t* WINPR_RESTRICT roi)
82{
83 BYTE* pRGB = pDst;
84 const INT16* pY = pSrc[0];
85 const INT16* pCb = pSrc[1];
86 const INT16* pCr = pSrc[2];
87 const size_t srcPad = (srcStep - (roi->width * 2)) / 2;
88 const size_t dstPad = (dstStep - (roi->width * 4));
89 const DWORD formatSize = FreeRDPGetBytesPerPixel(DstFormat);
90
91 for (UINT32 y = 0; y < roi->height; y++)
92 {
93 for (UINT32 x = 0; x < roi->width; x++)
94 {
95 const INT32 divisor = 16;
96 const INT32 Y = (INT32)((UINT32)((*pY++) + 4096) << divisor);
97 const INT32 Cb = (*pCb++);
98 const INT32 Cr = (*pCr++);
99
100 const INT32 CrR = WINPR_ASSERTING_INT_CAST(
101 int32_t, Cr* ycbcr_constants[divisor][0]); //(1.402525f * 2^divisor);
102 const INT32 CrG = WINPR_ASSERTING_INT_CAST(
103 int32_t, Cr* ycbcr_constants[divisor][1]); //(0.714401f * 2^divisor);
104 const INT32 CbG = WINPR_ASSERTING_INT_CAST(
105 int32_t, Cb* ycbcr_constants[divisor][2]); //(0.343730f * 2^divisor);
106 const INT32 CbB = WINPR_ASSERTING_INT_CAST(
107 int32_t, Cb* ycbcr_constants[divisor][3]); //(1.769905f * 2^divisor);
108 const INT16 R = WINPR_ASSERTING_INT_CAST(int16_t, ((CrR + Y) >> divisor) >> 5);
109 const INT16 G = WINPR_ASSERTING_INT_CAST(int16_t, ((Y - CbG - CrG) >> divisor) >> 5);
110 const INT16 B = WINPR_ASSERTING_INT_CAST(int16_t, ((CbB + Y) >> divisor) >> 5);
111 pRGB = writePixelBGRX(pRGB, formatSize, DstFormat, CLIP(R), CLIP(G), CLIP(B), 0);
112 }
113
114 pY += srcPad;
115 pCb += srcPad;
116 pCr += srcPad;
117 pRGB += dstPad;
118 }
119
120 return PRIMITIVES_SUCCESS;
121}
122
123static pstatus_t general_yCbCrToRGB_16s8u_P3AC4R_general(const INT16* WINPR_RESTRICT pSrc[3],
124 UINT32 srcStep, BYTE* WINPR_RESTRICT pDst,
125 UINT32 dstStep, UINT32 DstFormat,
126 const prim_size_t* WINPR_RESTRICT roi)
127{
128 BYTE* pRGB = pDst;
129 const INT16* pY = pSrc[0];
130 const INT16* pCb = pSrc[1];
131 const INT16* pCr = pSrc[2];
132 const size_t srcPad = (srcStep - (roi->width * 2)) / 2;
133 const size_t dstPad = (dstStep - (roi->width * 4));
134 const fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, FALSE);
135 const DWORD formatSize = FreeRDPGetBytesPerPixel(DstFormat);
136
137 for (UINT32 y = 0; y < roi->height; y++)
138 {
139 for (UINT32 x = 0; x < roi->width; x++)
140 {
141 const INT32 divisor = 16;
142 const INT32 Y = (INT32)((UINT32)((*pY++) + 4096) << divisor);
143 const INT32 Cb = (*pCb++);
144 const INT32 Cr = (*pCr++);
145 const INT32 CrR = Cr * ycbcr_constants[divisor][0];
146 const INT32 CrG = Cr * ycbcr_constants[divisor][1];
147 const INT32 CbG = Cb * ycbcr_constants[divisor][2];
148 const INT32 CbB = Cb * ycbcr_constants[divisor][3];
149 const INT32 R = (CrR + Y) >> (divisor + 5);
150 const INT32 G = (Y - CbG - CrG) >> (divisor + 5);
151 const INT32 B = (CbB + Y) >> (divisor + 5);
152 pRGB = writePixel(pRGB, formatSize, DstFormat, CLIP(R), CLIP(G), CLIP(B), 0);
153 }
154
155 pY += srcPad;
156 pCb += srcPad;
157 pCr += srcPad;
158 pRGB += dstPad;
159 }
160
161 return PRIMITIVES_SUCCESS;
162}
163
164static pstatus_t general_yCbCrToRGB_16s8u_P3AC4R(const INT16* WINPR_RESTRICT pSrc[3],
165 UINT32 srcStep, BYTE* WINPR_RESTRICT pDst,
166 UINT32 dstStep, UINT32 DstFormat,
167 const prim_size_t* WINPR_RESTRICT roi)
168{
169 switch (DstFormat)
170 {
171 case PIXEL_FORMAT_BGRA32:
172 case PIXEL_FORMAT_BGRX32:
173 return general_yCbCrToRGB_16s8u_P3AC4R_BGRX(pSrc, srcStep, pDst, dstStep, DstFormat,
174 roi);
175
176 default:
177 return general_yCbCrToRGB_16s8u_P3AC4R_general(pSrc, srcStep, pDst, dstStep, DstFormat,
178 roi);
179 }
180}
181
182/* ------------------------------------------------------------------------- */
183
184static pstatus_t
185general_yCbCrToRGB_16s16s_P3P3(const INT16* WINPR_RESTRICT pSrc[3], INT32 srcStep,
186 INT16* WINPR_RESTRICT pDst[3], INT32 dstStep,
187 const prim_size_t* WINPR_RESTRICT roi) /* region of interest */
188{
200 const INT16* yptr = pSrc[0];
201 const INT16* cbptr = pSrc[1];
202 const INT16* crptr = pSrc[2];
203 INT16* rptr = pDst[0];
204 INT16* gptr = pDst[1];
205 INT16* bptr = pDst[2];
206 UINT32 srcbump = (WINPR_ASSERTING_INT_CAST(uint32_t, srcStep) - (roi->width * sizeof(UINT16))) /
207 sizeof(UINT16);
208 UINT32 dstbump = (WINPR_ASSERTING_INT_CAST(uint32_t, dstStep) - (roi->width * sizeof(UINT16))) /
209 sizeof(UINT16);
210
211 for (UINT32 y = 0; y < roi->height; y++)
212 {
213 for (UINT32 x = 0; x < roi->width; ++x)
214 {
215 /* INT32 is used intentionally because we calculate
216 * with shifted factors!
217 */
218 INT32 cy = (INT32)(*yptr++);
219 INT32 cb = (INT32)(*cbptr++);
220 INT32 cr = (INT32)(*crptr++);
221 INT64 r = 0;
222 INT64 g = 0;
223 INT64 b = 0;
224 /*
225 * This is the slow floating point version kept here for reference.
226 * y = y + 4096; // 128<<5=4096 so that we can scale the sum by>>5
227 * r = y + cr*1.403f;
228 * g = y - cb*0.344f - cr*0.714f;
229 * b = y + cb*1.770f;
230 * y_r_buf[i] = CLIP(r>>5);
231 * cb_g_buf[i] = CLIP(g>>5);
232 * cr_b_buf[i] = CLIP(b>>5);
233 */
234 /*
235 * We scale the factors by << 16 into 32-bit integers in order to
236 * avoid slower floating point multiplications. Since the final
237 * result needs to be scaled by >> 5 we will extract only the
238 * upper 11 bits (>> 21) from the final sum.
239 * Hence we also have to scale the other terms of the sum by << 16.
240 * R: 1.403 << 16 = 91947
241 * G: 0.344 << 16 = 22544, 0.714 << 16 = 46792
242 * B: 1.770 << 16 = 115998
243 */
244 cy = (INT32)((UINT32)(cy + 4096) << 16);
245
246 r = 1LL * cy + 1LL * cr * ycbcr_constants[16][0];
247 g = 1LL * cy - 1LL * cb * ycbcr_constants[16][1] - 1LL * cr * ycbcr_constants[16][2];
248 b = 1LL * cy + 1LL * cb * ycbcr_constants[16][3];
249 *rptr++ = CLIP(r >> 21);
250 *gptr++ = CLIP(g >> 21);
251 *bptr++ = CLIP(b >> 21);
252 }
253
254 yptr += srcbump;
255 cbptr += srcbump;
256 crptr += srcbump;
257 rptr += dstbump;
258 gptr += dstbump;
259 bptr += dstbump;
260 }
261
262 return PRIMITIVES_SUCCESS;
263}
264
265/* ------------------------------------------------------------------------- */
266static pstatus_t
267general_RGBToYCbCr_16s16s_P3P3(const INT16* WINPR_RESTRICT pSrc[3], INT32 srcStep,
268 INT16* WINPR_RESTRICT pDst[3], INT32 dstStep,
269 const prim_size_t* WINPR_RESTRICT roi) /* region of interest */
270{
271 /* The encoded YCbCr coefficients are represented as 11.5 fixed-point
272 * numbers:
273 *
274 * 1 sign bit + 10 integer bits + 5 fractional bits
275 *
276 * However only 7 integer bits will be actually used since the value
277 * range is [-128.0, 127.0]. In other words, the encoded coefficients
278 * is scaled by << 5 when interpreted as INT16.
279 * It will be scaled down to original during the quantization phase.
280 */
281 const INT16* rptr = pSrc[0];
282 const INT16* gptr = pSrc[1];
283 const INT16* bptr = pSrc[2];
284 INT16* yptr = pDst[0];
285 INT16* cbptr = pDst[1];
286 INT16* crptr = pDst[2];
287 UINT32 srcbump = (WINPR_ASSERTING_INT_CAST(uint32_t, srcStep) - (roi->width * sizeof(UINT16))) /
288 sizeof(UINT16);
289 UINT32 dstbump = (WINPR_ASSERTING_INT_CAST(uint32_t, dstStep) - (roi->width * sizeof(UINT16))) /
290 sizeof(UINT16);
291
292 for (UINT32 y = 0; y < roi->height; y++)
293 {
294 for (UINT32 x = 0; x < roi->width; ++x)
295 {
296 /* INT32 is used intentionally because we calculate with
297 * shifted factors!
298 */
299 INT32 r = (INT32)(*rptr++);
300 INT32 g = (INT32)(*gptr++);
301 INT32 b = (INT32)(*bptr++);
302 /* We scale the factors by << 15 into 32-bit integers in order
303 * to avoid slower floating point multiplications. Since the
304 * terms need to be scaled by << 5 we simply scale the final
305 * sum by >> 10
306 *
307 * Y: 0.299000 << 15 = 9798, 0.587000 << 15 = 19235,
308 * 0.114000 << 15 = 3735
309 * Cb: 0.168935 << 15 = 5535, 0.331665 << 15 = 10868,
310 * 0.500590 << 15 = 16403
311 * Cr: 0.499813 << 15 = 16377, 0.418531 << 15 = 13714,
312 * 0.081282 << 15 = 2663
313 */
314 INT32 cy = (r * 9798 + g * 19235 + b * 3735) >> 10;
315 INT32 cb = (r * -5535 + g * -10868 + b * 16403) >> 10;
316 INT32 cr = (r * 16377 + g * -13714 + b * -2663) >> 10;
317 *yptr++ = (INT16)MINMAX(cy - 4096, -4096, 4095);
318 *cbptr++ = (INT16)MINMAX(cb, -4096, 4095);
319 *crptr++ = (INT16)MINMAX(cr, -4096, 4095);
320 }
321
322 yptr += srcbump;
323 cbptr += srcbump;
324 crptr += srcbump;
325 rptr += dstbump;
326 gptr += dstbump;
327 bptr += dstbump;
328 }
329
330 return PRIMITIVES_SUCCESS;
331}
332
333static INLINE void writeScanlineGeneric(BYTE* dst, DWORD formatSize, UINT32 DstFormat,
334 const INT16* r, const INT16* g, const INT16* b, DWORD width)
335{
336 fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, FALSE);
337
338 for (UINT32 x = 0; x < width; x++)
339 {
340 const INT16 pr = *r++;
341 const INT16 pg = *g++;
342 const INT16 pb = *b++;
343
344 dst =
345 writePixel(dst, formatSize, DstFormat, WINPR_ASSERTING_INT_CAST(UINT8, pr),
346 WINPR_ASSERTING_INT_CAST(UINT8, pg), WINPR_ASSERTING_INT_CAST(UINT8, pb), 0);
347 }
348}
349
350static INLINE void writeScanlineRGB(BYTE* dst, DWORD formatSize, UINT32 DstFormat, const INT16* r,
351 const INT16* g, const INT16* b, DWORD width)
352{
353 WINPR_UNUSED(formatSize);
354 WINPR_UNUSED(DstFormat);
355
356 for (UINT32 x = 0; x < width; x++)
357 {
358 const BYTE R = CLIP(*r++);
359 const BYTE G = CLIP(*g++);
360 const BYTE B = CLIP(*b++);
361 *dst++ = R;
362 *dst++ = G;
363 *dst++ = B;
364 }
365}
366
367static INLINE void writeScanlineBGR(BYTE* dst, DWORD formatSize, UINT32 DstFormat, const INT16* r,
368 const INT16* g, const INT16* b, DWORD width)
369{
370 WINPR_UNUSED(formatSize);
371 WINPR_UNUSED(DstFormat);
372
373 for (UINT32 x = 0; x < width; x++)
374 {
375 const BYTE R = CLIP(*r++);
376 const BYTE G = CLIP(*g++);
377 const BYTE B = CLIP(*b++);
378 *dst++ = B;
379 *dst++ = G;
380 *dst++ = R;
381 }
382}
383
384static INLINE void writeScanlineBGRX(BYTE* dst, DWORD formatSize, UINT32 DstFormat, const INT16* r,
385 const INT16* g, const INT16* b, DWORD width)
386{
387 WINPR_UNUSED(formatSize);
388 WINPR_UNUSED(DstFormat);
389
390 for (UINT32 x = 0; x < width; x++)
391 {
392 const BYTE R = CLIP(*r++);
393 const BYTE G = CLIP(*g++);
394 const BYTE B = CLIP(*b++);
395 *dst++ = B;
396 *dst++ = G;
397 *dst++ = R;
398 *dst++ = 0xFF;
399 }
400}
401
402static INLINE void writeScanlineRGBX(BYTE* dst, DWORD formatSize, UINT32 DstFormat, const INT16* r,
403 const INT16* g, const INT16* b, DWORD width)
404{
405 WINPR_UNUSED(formatSize);
406 WINPR_UNUSED(DstFormat);
407
408 for (UINT32 x = 0; x < width; x++)
409 {
410 const BYTE R = CLIP(*r++);
411 const BYTE G = CLIP(*g++);
412 const BYTE B = CLIP(*b++);
413 *dst++ = R;
414 *dst++ = G;
415 *dst++ = B;
416 *dst++ = 0xFF;
417 }
418}
419
420static INLINE void writeScanlineXBGR(BYTE* dst, DWORD formatSize, UINT32 DstFormat, const INT16* r,
421 const INT16* g, const INT16* b, DWORD width)
422{
423 WINPR_UNUSED(formatSize);
424 WINPR_UNUSED(DstFormat);
425
426 for (UINT32 x = 0; x < width; x++)
427 {
428 const BYTE R = CLIP(*r++);
429 const BYTE G = CLIP(*g++);
430 const BYTE B = CLIP(*b++);
431 *dst++ = 0xFF;
432 *dst++ = B;
433 *dst++ = G;
434 *dst++ = R;
435 }
436}
437
438static INLINE void writeScanlineXRGB(BYTE* dst, DWORD formatSize, UINT32 DstFormat, const INT16* r,
439 const INT16* g, const INT16* b, DWORD width)
440{
441 WINPR_UNUSED(formatSize);
442 WINPR_UNUSED(DstFormat);
443
444 for (UINT32 x = 0; x < width; x++)
445 {
446 const BYTE R = CLIP(*r++);
447 const BYTE G = CLIP(*g++);
448 const BYTE B = CLIP(*b++);
449 *dst++ = 0xFF;
450 *dst++ = R;
451 *dst++ = G;
452 *dst++ = B;
453 }
454}
455
456typedef void (*fkt_writeScanline)(BYTE*, DWORD, UINT32, const INT16*, const INT16*, const INT16*,
457 DWORD);
458
459static INLINE fkt_writeScanline getScanlineWriteFunction(DWORD format)
460{
461 switch (format)
462 {
463 case PIXEL_FORMAT_ARGB32:
464 case PIXEL_FORMAT_XRGB32:
465 return writeScanlineXRGB;
466
467 case PIXEL_FORMAT_ABGR32:
468 case PIXEL_FORMAT_XBGR32:
469 return writeScanlineXBGR;
470
471 case PIXEL_FORMAT_RGBA32:
472 case PIXEL_FORMAT_RGBX32:
473 return writeScanlineRGBX;
474
475 case PIXEL_FORMAT_BGRA32:
476 case PIXEL_FORMAT_BGRX32:
477 return writeScanlineBGRX;
478
479 case PIXEL_FORMAT_BGR24:
480 return writeScanlineBGR;
481
482 case PIXEL_FORMAT_RGB24:
483 return writeScanlineRGB;
484
485 default:
486 return writeScanlineGeneric;
487 }
488}
489
490/* ------------------------------------------------------------------------- */
491static pstatus_t general_RGBToRGB_16s8u_P3AC4R_general(
492 const INT16* WINPR_RESTRICT pSrc[3], /* 16-bit R,G, and B arrays */
493 UINT32 srcStep, /* bytes between rows in source data */
494 BYTE* WINPR_RESTRICT pDst, /* 32-bit interleaved ARGB (ABGR?) data */
495 UINT32 dstStep, /* bytes between rows in dest data */
496 UINT32 DstFormat, const prim_size_t* WINPR_RESTRICT roi) /* region of interest */
497{
498 const INT16* r = pSrc[0];
499 const INT16* g = pSrc[1];
500 const INT16* b = pSrc[2];
501 const DWORD srcAdd = srcStep / sizeof(INT16);
502 fkt_writeScanline writeScanline = getScanlineWriteFunction(DstFormat);
503 const DWORD formatSize = FreeRDPGetBytesPerPixel(DstFormat);
504
505 for (UINT32 y = 0; y < roi->height; ++y)
506 {
507 (*writeScanline)(pDst, formatSize, DstFormat, r, g, b, roi->width);
508 pDst += dstStep;
509 r += srcAdd;
510 g += srcAdd;
511 b += srcAdd;
512 }
513
514 return PRIMITIVES_SUCCESS;
515}
516
517static pstatus_t general_RGBToRGB_16s8u_P3AC4R_BGRX(
518 const INT16* WINPR_RESTRICT pSrc[3], /* 16-bit R,G, and B arrays */
519 UINT32 srcStep, /* bytes between rows in source data */
520 BYTE* WINPR_RESTRICT pDst, /* 32-bit interleaved ARGB (ABGR?) data */
521 UINT32 dstStep, /* bytes between rows in dest data */
522 UINT32 DstFormat, const prim_size_t* WINPR_RESTRICT roi) /* region of interest */
523{
524 const INT16* r = pSrc[0];
525 const INT16* g = pSrc[1];
526 const INT16* b = pSrc[2];
527 const DWORD srcAdd = srcStep / sizeof(INT16);
528 const DWORD formatSize = FreeRDPGetBytesPerPixel(DstFormat);
529
530 for (UINT32 y = 0; y < roi->height; ++y)
531 {
532 writeScanlineBGRX(pDst, formatSize, DstFormat, r, g, b, roi->width);
533 pDst += dstStep;
534 r += srcAdd;
535 g += srcAdd;
536 b += srcAdd;
537 }
538
539 return PRIMITIVES_SUCCESS;
540}
541
542static pstatus_t
543general_RGBToRGB_16s8u_P3AC4R(const INT16* WINPR_RESTRICT pSrc[3], /* 16-bit R,G, and B arrays */
544 UINT32 srcStep, /* bytes between rows in source data */
545 BYTE* WINPR_RESTRICT pDst, /* 32-bit interleaved ARGB (ABGR?) data */
546 UINT32 dstStep, /* bytes between rows in dest data */
547 UINT32 DstFormat,
548 const prim_size_t* WINPR_RESTRICT roi) /* region of interest */
549{
550 switch (DstFormat)
551 {
552 case PIXEL_FORMAT_BGRA32:
553 case PIXEL_FORMAT_BGRX32:
554 return general_RGBToRGB_16s8u_P3AC4R_BGRX(pSrc, srcStep, pDst, dstStep, DstFormat, roi);
555
556 default:
557 return general_RGBToRGB_16s8u_P3AC4R_general(pSrc, srcStep, pDst, dstStep, DstFormat,
558 roi);
559 }
560}
561/* ------------------------------------------------------------------------- */
562void primitives_init_colors(primitives_t* WINPR_RESTRICT prims)
563{
564 prims->yCbCrToRGB_16s8u_P3AC4R = general_yCbCrToRGB_16s8u_P3AC4R;
565 prims->yCbCrToRGB_16s16s_P3P3 = general_yCbCrToRGB_16s16s_P3P3;
566 prims->RGBToYCbCr_16s16s_P3P3 = general_RGBToYCbCr_16s16s_P3P3;
567 prims->RGBToRGB_16s8u_P3AC4R = general_RGBToRGB_16s8u_P3AC4R;
568}
569
570/* ------------------------------------------------------------------------- */
571void primitives_init_colors_opt(primitives_t* WINPR_RESTRICT prims)
572{
573 primitives_init_colors(prims);
574 primitives_init_colors_sse2(prims);
575 primitives_init_colors_neon(prims);
576}