1 // Copyright 2023 Google LLC
2 // SPDX-License-Identifier: BSD-2-Clause
3
4 #include <vector>
5
6 #include "avif/avif.h"
7 #include "aviftest_helpers.h"
8 #include "gtest/gtest.h"
9
10 namespace avif {
11 namespace {
12
13 constexpr uint8_t kWidth = 4;
14 constexpr uint8_t kHeight = 4;
15 constexpr uint8_t kPlaneSize = 16;
16 constexpr uint8_t kUOffset = 16;
17 constexpr uint8_t kVOffset = 32;
18 constexpr uint8_t kYuv[][kPlaneSize * 4] = {
19 // White
20 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
21 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
22 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
23 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80},
24 // Red
25 {0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
26 0x4c, 0x4c, 0x4c, 0x4c, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
27 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0xff, 0xff, 0xff, 0xff,
28 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
29 // Mixed
30 {0x88, 0x88, 0x88, 0x88, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c,
31 0x88, 0x88, 0x88, 0x88, 0xa4, 0xa4, 0xa4, 0xa4, 0x72, 0x72, 0x72, 0x72,
32 0x72, 0x72, 0x72, 0x72, 0xa4, 0xa4, 0xa4, 0xa4, 0x7a, 0x7a, 0x7a, 0x7a,
33 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0x7a, 0x7a, 0x7a, 0x7a}};
34
35 constexpr uint8_t kRgb[][kWidth * kHeight * 4] = {
36 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
37 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
38 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
39 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
40 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
41 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
42 {0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
43 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
44 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
45 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
46 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
47 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff},
48 {0x80, 0x80, 0xc8, 0xff, 0x80, 0x80, 0xc8, 0xff, 0x80, 0x80, 0xc8,
49 0xff, 0x80, 0x80, 0xc8, 0xff, 0xe5, 0x4b, 0x63, 0xff, 0xe5, 0x4b,
50 0x63, 0xff, 0xe5, 0x4b, 0x63, 0xff, 0xe5, 0x4b, 0x63, 0xff, 0xe5,
51 0x4b, 0x63, 0xff, 0xe5, 0x4b, 0x63, 0xff, 0xe5, 0x4b, 0x63, 0xff,
52 0xe5, 0x4b, 0x63, 0xff, 0x80, 0x80, 0xc8, 0xff, 0x80, 0x80, 0xc8,
53 0xff, 0x80, 0x80, 0xc8, 0xff, 0x80, 0x80, 0xc8, 0xff}};
54
TEST(AvifDecodeTest,YUVToRGBConversion)55 TEST(AvifDecodeTest, YUVToRGBConversion) {
56 for (int p = 0; p < 3; ++p) {
57 ImagePtr image(
58 avifImageCreate(kWidth, kHeight, 8, AVIF_PIXEL_FORMAT_YUV444));
59 ASSERT_NE(image, nullptr);
60 ASSERT_EQ(avifImageAllocatePlanes(image.get(), AVIF_PLANES_YUV),
61 AVIF_RESULT_OK);
62 memcpy(image->yuvPlanes[0], kYuv[p], kPlaneSize);
63 memcpy(image->yuvPlanes[1], kYuv[p] + kUOffset, kPlaneSize);
64 memcpy(image->yuvPlanes[2], kYuv[p] + kVOffset, kPlaneSize);
65 avifRGBImage rgb;
66 avifRGBImageSetDefaults(&rgb, image.get());
67 std::vector<uint8_t> rgb_pixels(kWidth * kHeight * 4);
68 rgb.pixels = rgb_pixels.data();
69 rgb.rowBytes = kWidth * 4;
70 ASSERT_EQ(avifImageYUVToRGB(image.get(), &rgb), AVIF_RESULT_OK);
71 for (int i = 0; i < rgb_pixels.size(); ++i) {
72 EXPECT_EQ(rgb.pixels[i], kRgb[p][i]);
73 }
74 avifImageFreePlanes(image.get(), AVIF_PLANES_YUV);
75 }
76 }
77
78 } // namespace
79 } // namespace avif
80
main(int argc,char ** argv)81 int main(int argc, char** argv) {
82 ::testing::InitGoogleTest(&argc, argv);
83 return RUN_ALL_TESTS();
84 }
85