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