mirror of
https://chromium.googlesource.com/libyuv/libyuv
synced 2026-07-30 16:26:19 +08:00
[libyuv] Fix color matrix constants in RAWToI420
RAW format in libyuv is Red-first ([R, G, B] in memory), whereas RGB24 is Blue-first ([B, G, R] in memory). RGBToYMatrixRow and RGBToUVMatrixRow internally expand 3-byte input into 4-byte [byte0, byte1, byte2, 255]. For RAW, this buffer becomes [R, G, B, 255] (matching ABGR byte order). RAWToI420 previously passed &kArgbI601Constants (which expects [B, G, R, 255]) instead of &kAbgrI601Constants, causing Red and Blue channels to be swapped. Pass &kAbgrI601Constants in RAWToI420, fix parameter names in source/convert.cc, and add a unit test. Test: libyuv_unittest --gtest_filter=*RAWToI420* Bug: libyuv:537503370 TAG=agy CONV=2c54c4b5-f515-421b-80b3-079caa9f948b Change-Id: Ic72470813eaf15e80046c2c01cf804cb827039ab Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8133048 Reviewed-by: richard winterton <rrwinterton@gmail.com>
This commit is contained in:
parent
666b4ee514
commit
1e06475900
@ -2862,8 +2862,8 @@ int RGB24ToJ420(const uint8_t* src_rgb24,
|
||||
|
||||
// Convert RAW to I420.
|
||||
LIBYUV_API
|
||||
int RAWToI420(const uint8_t* src_rgb24,
|
||||
int src_stride_rgb24,
|
||||
int RAWToI420(const uint8_t* src_raw,
|
||||
int src_stride_raw,
|
||||
uint8_t* dst_y,
|
||||
int dst_stride_y,
|
||||
uint8_t* dst_u,
|
||||
@ -2925,31 +2925,31 @@ int RAWToI420(const uint8_t* src_rgb24,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!src_rgb24 || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0 ||
|
||||
if (!src_raw || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0 ||
|
||||
height == INT_MIN) {
|
||||
return -1;
|
||||
}
|
||||
// Negative height means invert the image.
|
||||
if (height < 0) {
|
||||
height = -height;
|
||||
src_rgb24 = src_rgb24 + (ptrdiff_t)(height - 1) * src_stride_rgb24;
|
||||
src_stride_rgb24 = -src_stride_rgb24;
|
||||
src_raw = src_raw + (ptrdiff_t)(height - 1) * src_stride_raw;
|
||||
src_stride_raw = -src_stride_raw;
|
||||
}
|
||||
|
||||
for (y = 0; y < height - 1; y += 2) {
|
||||
RGBToUVMatrixRow(src_rgb24, src_stride_rgb24, dst_u, dst_v, width,
|
||||
&kArgbI601Constants);
|
||||
RGBToYMatrixRow(src_rgb24, dst_y, width, &kArgbI601Constants);
|
||||
RGBToYMatrixRow(src_rgb24 + src_stride_rgb24, dst_y + dst_stride_y, width,
|
||||
&kArgbI601Constants);
|
||||
src_rgb24 += src_stride_rgb24 * 2;
|
||||
RGBToUVMatrixRow(src_raw, src_stride_raw, dst_u, dst_v, width,
|
||||
&kAbgrI601Constants);
|
||||
RGBToYMatrixRow(src_raw, dst_y, width, &kAbgrI601Constants);
|
||||
RGBToYMatrixRow(src_raw + src_stride_raw, dst_y + dst_stride_y, width,
|
||||
&kAbgrI601Constants);
|
||||
src_raw += src_stride_raw * 2;
|
||||
dst_y += dst_stride_y * 2;
|
||||
dst_u += dst_stride_u;
|
||||
dst_v += dst_stride_v;
|
||||
}
|
||||
if (height & 1) {
|
||||
RGBToYMatrixRow(src_rgb24, dst_y, width, &kArgbI601Constants);
|
||||
RGBToUVMatrixRow(src_rgb24, 0, dst_u, dst_v, width, &kArgbI601Constants);
|
||||
RGBToYMatrixRow(src_raw, dst_y, width, &kAbgrI601Constants);
|
||||
RGBToUVMatrixRow(src_raw, 0, dst_u, dst_v, width, &kAbgrI601Constants);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2176,6 +2176,46 @@ TEST_F(LibYUVConvertTest, TestABGRToI420Matrix) {
|
||||
free_aligned_buffer_page_end(ref_v);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVConvertTest, TestRAWToI420) {
|
||||
const int kWidth = 16;
|
||||
const int kHeight = 16;
|
||||
align_buffer_page_end(src_raw, kWidth * kHeight * 3);
|
||||
align_buffer_page_end(dst_y, kWidth * kHeight);
|
||||
align_buffer_page_end(dst_u, kWidth / 2 * kHeight / 2);
|
||||
align_buffer_page_end(dst_v, kWidth / 2 * kHeight / 2);
|
||||
align_buffer_page_end(src_argb, kWidth * kHeight * 4);
|
||||
align_buffer_page_end(ref_y, kWidth * kHeight);
|
||||
align_buffer_page_end(ref_u, kWidth / 2 * kHeight / 2);
|
||||
align_buffer_page_end(ref_v, kWidth / 2 * kHeight / 2);
|
||||
|
||||
MemRandomize(src_raw, kWidth * kHeight * 3);
|
||||
|
||||
RAWToI420(src_raw, kWidth * 3, dst_y, kWidth, dst_u, kWidth / 2, dst_v,
|
||||
kWidth / 2, kWidth, kHeight);
|
||||
|
||||
// Verify against RAWToARGB + ARGBToI420
|
||||
RAWToARGB(src_raw, kWidth * 3, src_argb, kWidth * 4, kWidth, kHeight);
|
||||
ARGBToI420(src_argb, kWidth * 4, ref_y, kWidth, ref_u, kWidth / 2, ref_v,
|
||||
kWidth / 2, kWidth, kHeight);
|
||||
|
||||
for (int i = 0; i < kWidth * kHeight; ++i) {
|
||||
ASSERT_EQ(dst_y[i], ref_y[i]);
|
||||
}
|
||||
for (int i = 0; i < kWidth / 2 * kHeight / 2; ++i) {
|
||||
ASSERT_EQ(dst_u[i], ref_u[i]);
|
||||
ASSERT_EQ(dst_v[i], ref_v[i]);
|
||||
}
|
||||
|
||||
free_aligned_buffer_page_end(src_raw);
|
||||
free_aligned_buffer_page_end(dst_y);
|
||||
free_aligned_buffer_page_end(dst_u);
|
||||
free_aligned_buffer_page_end(dst_v);
|
||||
free_aligned_buffer_page_end(src_argb);
|
||||
free_aligned_buffer_page_end(ref_y);
|
||||
free_aligned_buffer_page_end(ref_u);
|
||||
free_aligned_buffer_page_end(ref_v);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVConvertTest, TestARGBToNV12Matrix) {
|
||||
const int kWidth = 16;
|
||||
const int kHeight = 16;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user