@@ -123,3 +123,56 @@ void NV122RGB(const uint8_t *nv12, uint8_t *rgb, uint32_t width, uint32_t height
123123 }
124124 }
125125}
126+
127+ /*
128+ YU12 (I420) format has three planes:
129+ - Y plane: Full resolution luminance samples
130+ - U plane: 2x2 subsampled U (Cb) samples
131+ - V plane: 2x2 subsampled V (Cr) samples
132+
133+ Memory layout:
134+ YYYYYYYY
135+ YYYYYYYY
136+ YYYYYYYY
137+ YYYYYYYY
138+ UUUU
139+ UUUU
140+ VVVV
141+ VVVV
142+
143+ Each 2x2 Y block shares one U and one V value.
144+ */
145+ void YU122RGB (const uint8_t *yu12, uint8_t *rgb, uint32_t width, uint32_t height)
146+ {
147+ const uint8_t *y_plane = yu12;
148+ const uint8_t *u_plane = yu12 + (width * height);
149+ const uint8_t *v_plane = u_plane + (width * height / 4 );
150+
151+ for (uint32_t row = 0 ; row < height; row++)
152+ {
153+ for (uint32_t col = 0 ; col < width; col++)
154+ {
155+ // Get Y value for current pixel
156+ int16_t y = y_plane[row * width + col];
157+
158+ // Get U,V values (shared by 2x2 pixel blocks)
159+ uint32_t uv_row = row / 2 ;
160+ uint32_t uv_col = col / 2 ;
161+ uint32_t uv_index = uv_row * (width / 2 ) + uv_col;
162+
163+ int16_t u = u_plane[uv_index]; // Cb
164+ int16_t v = v_plane[uv_index]; // Cr
165+
166+ // Convert YUV to RGB using the same coefficients as YUYV
167+ int16_t yy = 19 * (y - 16 );
168+
169+ // Calculate RGB index
170+ uint32_t rgb_index = (row * width + col) * 3 ;
171+
172+ // R, G, B order (RGB24)
173+ rgb[rgb_index] = clamp ((yy + 26 * (v - 128 )) >> 4 );
174+ rgb[rgb_index + 1 ] = clamp ((yy - 13 * (v - 128 ) - 6 * (u - 128 )) >> 4 );
175+ rgb[rgb_index + 2 ] = clamp ((yy + 32 * (u - 128 )) >> 4 );
176+ }
177+ }
178+ }
0 commit comments