• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/decoder/codec.h"
16 #include "include/astc-codec/astc-codec.h"
17 #include "src/decoder/test/image_utils.h"
18 
19 #include <gtest/gtest.h>
20 
21 #include <string>
22 
23 namespace astc_codec {
24 
PrintTo(FootprintType footprint,std::ostream * os)25 static void PrintTo(FootprintType footprint, std::ostream* os) {
26     switch (footprint) {
27         case FootprintType::k4x4:   *os << "FootprintType::k4x4";   break;
28         case FootprintType::k5x4:   *os << "FootprintType::k5x4";   break;
29         case FootprintType::k5x5:   *os << "FootprintType::k5x5";   break;
30         case FootprintType::k6x5:   *os << "FootprintType::k6x5";   break;
31         case FootprintType::k6x6:   *os << "FootprintType::k6x6";   break;
32         case FootprintType::k8x5:   *os << "FootprintType::k8x5";   break;
33         case FootprintType::k8x6:   *os << "FootprintType::k8x6";   break;
34         case FootprintType::k10x5:  *os << "FootprintType::k10x5";  break;
35         case FootprintType::k10x6:  *os << "FootprintType::k10x6";  break;
36         case FootprintType::k8x8:   *os << "FootprintType::k8x8";   break;
37         case FootprintType::k10x8:  *os << "FootprintType::k10x8";  break;
38         case FootprintType::k10x10: *os << "FootprintType::k10x10"; break;
39         case FootprintType::k12x10: *os << "FootprintType::k12x10"; break;
40         case FootprintType::k12x12: *os << "FootprintType::k12x12"; break;
41         default:
42           *os << "<Unexpected FootprintType "
43               << static_cast<uint32_t>(footprint) << ">";
44     }
45 }
46 
47 namespace {
48 
49 using ::testing::TestWithParam;
50 using ::testing::ValuesIn;
51 
LoadGoldenImageWithAlpha(std::string basename)52 ImageBuffer LoadGoldenImageWithAlpha(std::string basename) {
53   const std::string filename =
54       std::string("src/decoder/testdata/") + basename + ".bmp";
55   ImageBuffer result;
56   LoadGoldenBmp(filename, &result);
57   EXPECT_EQ(result.BytesPerPixel(), 4);
58   return result;
59 }
60 
61 struct ImageTestParams {
62   std::string image_name;
63   FootprintType footprint;
64   size_t width;
65   size_t height;
66 };
67 
PrintTo(const ImageTestParams & params,std::ostream * os)68 static void PrintTo(const ImageTestParams& params, std::ostream* os) {
69   *os << "ImageTestParams(" << params.image_name << ", " << params.width << "x"
70       << params.height << ", ";
71   PrintTo(params.footprint, os);
72   *os << ")";
73 }
74 
TEST(CodecTest,InvalidInput)75 TEST(CodecTest, InvalidInput) {
76   const size_t valid_width = 16;
77   const size_t valid_height = 16;
78   const size_t valid_stride = valid_width * 4;
79 
80   const std::vector<uint8_t> data(256);
81   std::vector<uint8_t> output(valid_width * valid_height * 4);
82 
83   // Invalid footprint.
84   EXPECT_FALSE(ASTCDecompressToRGBA(
85       data.data(), data.size(), valid_width, valid_height,
86       FootprintType::kCount, output.data(), output.size(), valid_stride));
87 
88   // Fail for 0 width or height.
89   EXPECT_FALSE(ASTCDecompressToRGBA(data.data(), data.size(), 0, valid_height,
90                                     FootprintType::k4x4, output.data(),
91                                     output.size(), valid_stride));
92   EXPECT_FALSE(ASTCDecompressToRGBA(data.data(), data.size(), valid_width, 0,
93                                     FootprintType::k4x4, output.data(),
94                                     output.size(), valid_stride));
95 
96   // Fail for data size that's not a multiple of block size.
97   EXPECT_FALSE(ASTCDecompressToRGBA(
98       data.data(), data.size() - 1, valid_width, valid_height,
99       FootprintType::k4x4, output.data(), output.size(), valid_stride));
100   // Fail for data size that doesn't match the block count.
101   EXPECT_FALSE(ASTCDecompressToRGBA(
102       data.data(), data.size() - 16, valid_width, valid_height,
103       FootprintType::k4x4, output.data(), output.size(), valid_stride));
104 
105   // Fail for invalid stride.
106   EXPECT_FALSE(ASTCDecompressToRGBA(
107       data.data(), data.size(), valid_width, valid_height, FootprintType::k4x4,
108       output.data(), output.size(), valid_stride - 1));
109 
110   // Fail for invalid output size.
111   EXPECT_FALSE(ASTCDecompressToRGBA(
112       data.data(), data.size(), valid_width, valid_height, FootprintType::k4x4,
113       output.data(), output.size() - 1, valid_stride));
114 }
115 
116 class CodecTest : public TestWithParam<ImageTestParams> {};
117 
TEST_P(CodecTest,PublicAPI)118 TEST_P(CodecTest, PublicAPI) {
119   const auto& params = GetParam();
120   const std::string astc = LoadASTCFile(params.image_name);
121 
122   ImageBuffer our_decoded_image;
123   our_decoded_image.Allocate(params.width, params.height, 4);
124   ASSERT_TRUE(ASTCDecompressToRGBA(
125       reinterpret_cast<const uint8_t*>(astc.data()), astc.size(), params.width,
126       params.height, params.footprint, our_decoded_image.Data().data(),
127       our_decoded_image.DataSize(), our_decoded_image.Stride()));
128 
129   // Check that the decoded image is *very* similar to the library decoding
130   // of an ASTC texture. They may not be exact due to differences in how we
131   // convert a 16-bit float to an 8-bit integer.
132   ImageBuffer decoded_image = LoadGoldenImageWithAlpha(params.image_name);
133   CompareSumOfSquaredDifferences(decoded_image, our_decoded_image, 1.0);
134 }
135 
TEST_P(CodecTest,DecompressToImage)136 TEST_P(CodecTest, DecompressToImage) {
137   const auto& params = GetParam();
138 
139   std::string error;
140   std::unique_ptr<ASTCFile> image_file = ASTCFile::LoadFile(
141       std::string("src/decoder/testdata/") + params.image_name + ".astc",
142       &error);
143   ASSERT_TRUE(image_file) << "Failed to load " << params.image_name << ": "
144                           << error;
145 
146   ASSERT_TRUE(image_file->GetFootprint());
147   EXPECT_EQ(params.footprint, image_file->GetFootprint().value().Type());
148 
149   ImageBuffer our_decoded_image;
150   our_decoded_image.Allocate(image_file->GetWidth(), image_file->GetHeight(),
151                              4);
152 
153   ASSERT_TRUE(DecompressToImage(*image_file, our_decoded_image.Data().data(),
154                                 our_decoded_image.DataSize(),
155                                 our_decoded_image.Stride()));
156 
157   // Check that the decoded image is *very* similar to the library decoding
158   // of an ASTC texture. They may not be exact due to differences in how we
159   // convert a 16-bit float to an 8-bit integer.
160   ImageBuffer decoded_image = LoadGoldenImageWithAlpha(params.image_name);
161   CompareSumOfSquaredDifferences(decoded_image, our_decoded_image, 1.0);
162 }
163 
164 // Test to make sure that reading out color values from blocks in a real-world
165 // image isn't terribly wrong, either.
GetTransparentImageTestParams()166 std::vector<ImageTestParams> GetTransparentImageTestParams() {
167   return {
168     // image_name         astc footprint        width    height
169     { "atlas_small_4x4",  FootprintType::k4x4,  256,     256 },
170     { "atlas_small_5x5",  FootprintType::k5x5,  256,     256 },
171     { "atlas_small_6x6",  FootprintType::k6x6,  256,     256 },
172     { "atlas_small_8x8",  FootprintType::k8x8,  256,     256 },
173   };
174 }
175 
176 INSTANTIATE_TEST_CASE_P(Transparent, CodecTest,
177                         ValuesIn(GetTransparentImageTestParams()));
178 
179 }  // namespace
180 
181 }  // namespace astc_codec
182