#### /Avc/yuv420rgb8888c.cpp

C++ | 187 lines | 103 code | 10 blank | 74 comment | 15 complexity | 111c1d66dbb4323ba2eaba9345fc5f62 MD5 | raw file
```  1/* YUV-> RGB conversion code.
2 *
3 * Copyright (C) 2011 Robin Watts (robin@wss.co.uk) for Pinknoise
4 * Productions Ltd.
5 *
6 * Licensed under the BSD license. See 'COPYING' for details of
7 * (non-)warranty.
8 *
9 *
10 * The algorithm used here is based heavily on one created by Sophie Wilson
11 * of Acorn/e-14/Broadcomm. Many thanks.
12 *
13 * Additional tweaks (in the fast fixup code) are from Paul Gardiner.
14 *
15 * The old implementation of YUV -> RGB did:
16 *
17 * R = CLAMP((Y-16)*1.164 +           1.596*V)
18 * G = CLAMP((Y-16)*1.164 - 0.391*U - 0.813*V)
19 * B = CLAMP((Y-16)*1.164 + 2.018*U          )
20 *
21 * We're going to bend that here as follows:
22 *
23 * R = CLAMP(y +           1.596*V)
24 * G = CLAMP(y - 0.383*U - 0.813*V)
25 * B = CLAMP(y + 1.976*U          )
26 *
27 * where y = 0               for       Y <=  16,
28 *       y = (  Y-16)*1.164, for  16 < Y <= 239,
29 *       y = (239-16)*1.164, for 239 < Y
30 *
31 * i.e. We clamp Y to the 16 to 239 range (which it is supposed to be in
32 * anyway). We then pick the B_U factor so that B never exceeds 511. We then
33 * shrink the G_U factor in line with that to avoid a colour shift as much as
34 * possible.
35 *
36 * We're going to use tables to do it faster, but rather than doing it using
37 * 5 tables as as the above suggests, we're going to do it using just 3.
38 *
39 * We do this by working in parallel within a 32 bit word, and using one
40 * table each for Y U and V.
41 *
42 * Source Y values are    0 to 255, so    0.. 260 after scaling
43 * Source U values are -128 to 127, so  -49.. 49(G), -253..251(B) after
44 * Source V values are -128 to 127, so -204..203(R), -104..103(G) after
45 *
46 * So total summed values:
47 * -223 <= R <= 481, -173 <= G <= 431, -253 <= B < 511
48 *
49 * We need to pack R G and B into a 32 bit word, and because of Bs range we
50 * need 2 bits above the valid range of B to detect overflow, and another one
51 * to detect the sense of the overflow. We therefore adopt the following
52 * representation:
53 *
54 * osGGGGGgggggosBBBBBbbbosRRRRRrrr
55 *
56 * Each such word breaks down into 3 ranges.
57 *
58 * osGGGGGggggg   osBBBBBbbb   osRRRRRrrr
59 *
60 * Thus we have 8 bits for each B and R table entry, and 10 bits for G (good
61 * as G is the most noticable one). The s bit for each represents the sign,
62 * and o represents the overflow.
63 *
64 * For R and B we pack the table by taking the 11 bit representation of their
65 * values, and toggling bit 10 in the U and V tables.
66 *
67 * For the green case we calculate 4*G (thus effectively using 10 bits for the
68 * valid range) truncate to 12 bits. We toggle bit 11 in the Y table.
69 */
70
71#include "yuv2rgb.h"
72
73enum
74{
75    FLAGS         = 0x40080100
76};
77
78#define READUV(U,V) (tables[256 + (U)] + tables[512 + (V)])
80#define FIXUP(Y)                 \
81do {                             \
82    int tmp = (Y) & FLAGS;       \
83    if (tmp != 0)                \
84    {                            \
85        tmp  -= tmp>>8;          \
86        (Y)  |= tmp;             \
87        tmp   = FLAGS & ~(Y>>1); \
88        (Y)  += tmp>>8;          \
89    }                            \
90} while (0 == 1)
91
92#define STORE(Y,DSTPTR)     \
93do {                        \
94    (DSTPTR) = (Y & 0xFF) | (0xFF00 & (Y>>14)) | (0xFF0000 & (Y<<5)) ;\
95} while (0 == 1)
96
97void yuv420_2_rgb8888(uint8_t  *dst_ptr_,
98                const uint8_t  *y_ptr,
99                const uint8_t  *u_ptr,
100                const uint8_t  *v_ptr,
101                      int32_t   width,
102                      int32_t   height,
103                      int32_t   y_span,
104                      int32_t   uv_span,
105                      int32_t   dst_span,
106                const uint32_t *tables,
107                      int32_t   dither)
108{
109    uint32_t *dst_ptr = (uint32_t *)(void *)dst_ptr_;
110    dst_span >>= 2;
111
112    height -= 1;
113    while (height > 0)
114    {
115        height -= width<<16;
116        height += 1<<16;
117        while (height < 0)
118        {
119            /* Do 2 column pairs */
120            uint32_t uv, y0, y1;
121
123            y1  = uv + READY(y_ptr[y_span]);
124            y0  = uv + READY(*y_ptr++);
125            FIXUP(y1);
126            FIXUP(y0);
127            STORE(y1, dst_ptr[dst_span]);
128            STORE(y0, *dst_ptr++);
129            y1  = uv + READY(y_ptr[y_span]);
130            y0  = uv + READY(*y_ptr++);
131            FIXUP(y1);
132            FIXUP(y0);
133            STORE(y1, dst_ptr[dst_span]);
134            STORE(y0, *dst_ptr++);
135            height += (2<<16);
136        }
137        if ((height>>16) == 0)
138        {
139            /* Trailing column pair */
140            uint32_t uv, y0, y1;
141
143            y1 = uv + READY(y_ptr[y_span]);
144            y0 = uv + READY(*y_ptr++);
145            FIXUP(y1);
146            FIXUP(y0);
147            STORE(y0, dst_ptr[dst_span]);
148            STORE(y1, *dst_ptr++);
149        }
150        dst_ptr += dst_span*2-width;
151        y_ptr   += y_span*2-width;
152        u_ptr   += uv_span-(width>>1);
153        v_ptr   += uv_span-(width>>1);
154        height = (height<<16)>>16;
155        height -= 2;
156    }
157    if (height == 0)
158    {
159        /* Trail row */
160        height -= width<<16;
161        height += 1<<16;
162        while (height < 0)
163        {
164            /* Do a row pair */
165            uint32_t uv, y0, y1;
166
168            y1  = uv + READY(*y_ptr++);
169            y0  = uv + READY(*y_ptr++);
170            FIXUP(y1);
171            FIXUP(y0);
172            STORE(y1, *dst_ptr++);
173            STORE(y0, *dst_ptr++);
174            height += (2<<16);
175        }
176        if ((height>>16) == 0)
177        {
178            /* Trailing pix */
179            uint32_t uv, y0;
180