// Copyright 2014 Google Inc. All Rights Reserved. // // Use of this source code is governed by a BSD-style license // that can be found in the COPYING file in the root of the source // tree. An additional intellectual property rights grant can be found // in the file PATENTS. All contributing project authors may // be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // YUV->RGB conversion functions // // Author: Skal (pascal.massimino@gmail.com)
//----------------------------------------------------------------------------- // Convert spans of 32 pixels to various RGB formats for the fancy upsampler.
// These constants are 14b fixed-point version of ITU-R BT.601 constants. // R = (19077 * y + 26149 * v - 14234) >> 6 // G = (19077 * y - 6419 * u - 13320 * v + 8708) >> 6 // B = (19077 * y + 33050 * u - 17685) >> 6 staticvoid ConvertYUV444ToRGB_SSE2(const __m128i* const Y0, const __m128i* const U0, const __m128i* const V0,
__m128i* const R,
__m128i* const G,
__m128i* const B) { const __m128i k19077 = _mm_set1_epi16(19077); const __m128i k26149 = _mm_set1_epi16(26149); const __m128i k14234 = _mm_set1_epi16(14234); // 33050 doesn't fit in a signed short: only use this with unsigned arithmetic const __m128i k33050 = _mm_set1_epi16((short)33050); const __m128i k17685 = _mm_set1_epi16(17685); const __m128i k6419 = _mm_set1_epi16(6419); const __m128i k13320 = _mm_set1_epi16(13320); const __m128i k8708 = _mm_set1_epi16(8708);
// Pack the planar buffers // rrrr... rrrr... gggg... gggg... bbbb... bbbb.... // triplet by triplet in the output buffer rgb as rgbrgbrgbrgb ... static WEBP_INLINE void PlanarTo24b_SSE2(__m128i* const in0, __m128i* const in1,
__m128i* const in2, __m128i* const in3,
__m128i* const in4, __m128i* const in5,
uint8_t* WEBP_RESTRICT const rgb) { // The input is 6 registers of sixteen 8b but for the sake of explanation, // let's take 6 registers of four 8b values. // To pack, we will keep taking one every two 8b integer and move it // around as follows: // Input: // r0r1r2r3 | r4r5r6r7 | g0g1g2g3 | g4g5g6g7 | b0b1b2b3 | b4b5b6b7 // Split the 6 registers in two sets of 3 registers: the first set as the even // 8b bytes, the second the odd ones: // r0r2r4r6 | g0g2g4g6 | b0b2b4b6 | r1r3r5r7 | g1g3g5g7 | b1b3b5b7 // Repeat the same permutations twice more: // r0r4g0g4 | b0b4r1r5 | g1g5b1b5 | r2r6g2g6 | b2b6r3r7 | g3g7b3b7 // r0g0b0r1 | g1b1r2g2 | b2r3g3b3 | r4g4b4r5 | g5b5r6g6 | b6r7g7b7
VP8PlanarTo24b_SSE2(in0, in1, in2, in3, in4, in5);
void VP8YuvToRgba32_SSE2(const uint8_t* WEBP_RESTRICT y, const uint8_t* WEBP_RESTRICT u, const uint8_t* WEBP_RESTRICT v,
uint8_t* WEBP_RESTRICT dst) { const __m128i kAlpha = _mm_set1_epi16(255); int n; for (n = 0; n < 32; n += 8, dst += 32) {
__m128i R, G, B;
YUV444ToRGB_SSE2(y + n, u + n, v + n, &R, &G, &B);
PackAndStore4_SSE2(&R, &G, &B, &kAlpha, dst);
}
}
void VP8YuvToBgra32_SSE2(const uint8_t* WEBP_RESTRICT y, const uint8_t* WEBP_RESTRICT u, const uint8_t* WEBP_RESTRICT v,
uint8_t* WEBP_RESTRICT dst) { const __m128i kAlpha = _mm_set1_epi16(255); int n; for (n = 0; n < 32; n += 8, dst += 32) {
__m128i R, G, B;
YUV444ToRGB_SSE2(y + n, u + n, v + n, &R, &G, &B);
PackAndStore4_SSE2(&B, &G, &R, &kAlpha, dst);
}
}
void VP8YuvToArgb32_SSE2(const uint8_t* WEBP_RESTRICT y, const uint8_t* WEBP_RESTRICT u, const uint8_t* WEBP_RESTRICT v,
uint8_t* WEBP_RESTRICT dst) { const __m128i kAlpha = _mm_set1_epi16(255); int n; for (n = 0; n < 32; n += 8, dst += 32) {
__m128i R, G, B;
YUV444ToRGB_SSE2(y + n, u + n, v + n, &R, &G, &B);
PackAndStore4_SSE2(&kAlpha, &R, &G, &B, dst);
}
}
void VP8YuvToRgba444432_SSE2(const uint8_t* WEBP_RESTRICT y, const uint8_t* WEBP_RESTRICT u, const uint8_t* WEBP_RESTRICT v,
uint8_t* WEBP_RESTRICT dst) { const __m128i kAlpha = _mm_set1_epi16(255); int n; for (n = 0; n < 32; n += 8, dst += 16) {
__m128i R, G, B;
YUV444ToRGB_SSE2(y + n, u + n, v + n, &R, &G, &B);
PackAndStore4444_SSE2(&R, &G, &B, &kAlpha, dst);
}
}
void VP8YuvToRgb56532_SSE2(const uint8_t* WEBP_RESTRICT y, const uint8_t* WEBP_RESTRICT u, const uint8_t* WEBP_RESTRICT v,
uint8_t* WEBP_RESTRICT dst) { int n; for (n = 0; n < 32; n += 8, dst += 16) {
__m128i R, G, B;
YUV444ToRGB_SSE2(y + n, u + n, v + n, &R, &G, &B);
PackAndStore565_SSE2(&R, &G, &B, dst);
}
}
y += 32;
u += 16;
v += 16;
} for (; n < len; ++n) { // Finish off
VP8YuvToRgb(y[0], u[0], v[0], dst);
dst += 3;
y += 1;
u += (n & 1);
v += (n & 1);
}
}
staticvoid YuvToBgrRow_SSE2(const uint8_t* WEBP_RESTRICT y, const uint8_t* WEBP_RESTRICT u, const uint8_t* WEBP_RESTRICT v,
uint8_t* WEBP_RESTRICT dst, int len) { int n; for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) {
__m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3;
__m128i bgr0, bgr1, bgr2, bgr3, bgr4, bgr5;
YUV420ToRGB_SSE2(y + 0, u + 0, v + 0, &R0, &G0, &B0);
YUV420ToRGB_SSE2(y + 8, u + 4, v + 4, &R1, &G1, &B1);
YUV420ToRGB_SSE2(y + 16, u + 8, v + 8, &R2, &G2, &B2);
YUV420ToRGB_SSE2(y + 24, u + 12, v + 12, &R3, &G3, &B3);
// Cast to 8b and store as BBBBGGGGRRRR.
bgr0 = _mm_packus_epi16(B0, B1);
bgr1 = _mm_packus_epi16(B2, B3);
bgr2 = _mm_packus_epi16(G0, G1);
bgr3 = _mm_packus_epi16(G2, G3);
bgr4 = _mm_packus_epi16(R0, R1);
bgr5 = _mm_packus_epi16(R2, R3);
y += 32;
u += 16;
v += 16;
} for (; n < len; ++n) { // Finish off
VP8YuvToBgr(y[0], u[0], v[0], dst);
dst += 3;
y += 1;
u += (n & 1);
v += (n & 1);
}
}
//------------------------------------------------------------------------------ // Entry point
// Load eight 16b-words from *src. #define LOAD_16(src) _mm_loadu_si128((const __m128i*)(src)) // Store either 16b-words into *dst #define STORE_16(V, dst) _mm_storeu_si128((__m128i*)(dst), (V))
// Function that inserts a value of the second half of the in buffer in between // every two char of the first half. static WEBP_INLINE void RGB24PackedToPlanarHelper_SSE2( const __m128i* const in /*in[6]*/, __m128i* const out /*out[6]*/) {
out[0] = _mm_unpacklo_epi8(in[0], in[3]);
out[1] = _mm_unpackhi_epi8(in[0], in[3]);
out[2] = _mm_unpacklo_epi8(in[1], in[4]);
out[3] = _mm_unpackhi_epi8(in[1], in[4]);
out[4] = _mm_unpacklo_epi8(in[2], in[5]);
out[5] = _mm_unpackhi_epi8(in[2], in[5]);
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.14Bemerkung:
(vorverarbeitet am 2026-09-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.