diff options
Diffstat (limited to 'src/decoder/test/codec_test.cc')
-rw-r--r-- | src/decoder/test/codec_test.cc | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/src/decoder/test/codec_test.cc b/src/decoder/test/codec_test.cc new file mode 100644 index 0000000..936eed3 --- /dev/null +++ b/src/decoder/test/codec_test.cc @@ -0,0 +1,181 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/decoder/codec.h" +#include "include/astc-codec/astc-codec.h" +#include "src/decoder/test/image_utils.h" + +#include <gtest/gtest.h> + +#include <string> + +namespace astc_codec { + +static void PrintTo(FootprintType footprint, std::ostream* os) { + switch (footprint) { + case FootprintType::k4x4: *os << "FootprintType::k4x4"; break; + case FootprintType::k5x4: *os << "FootprintType::k5x4"; break; + case FootprintType::k5x5: *os << "FootprintType::k5x5"; break; + case FootprintType::k6x5: *os << "FootprintType::k6x5"; break; + case FootprintType::k6x6: *os << "FootprintType::k6x6"; break; + case FootprintType::k8x5: *os << "FootprintType::k8x5"; break; + case FootprintType::k8x6: *os << "FootprintType::k8x6"; break; + case FootprintType::k10x5: *os << "FootprintType::k10x5"; break; + case FootprintType::k10x6: *os << "FootprintType::k10x6"; break; + case FootprintType::k8x8: *os << "FootprintType::k8x8"; break; + case FootprintType::k10x8: *os << "FootprintType::k10x8"; break; + case FootprintType::k10x10: *os << "FootprintType::k10x10"; break; + case FootprintType::k12x10: *os << "FootprintType::k12x10"; break; + case FootprintType::k12x12: *os << "FootprintType::k12x12"; break; + default: + *os << "<Unexpected FootprintType " + << static_cast<uint32_t>(footprint) << ">"; + } +} + +namespace { + +using ::testing::TestWithParam; +using ::testing::ValuesIn; + +ImageBuffer LoadGoldenImageWithAlpha(std::string basename) { + const std::string filename = + std::string("src/decoder/testdata/") + basename + ".bmp"; + ImageBuffer result; + LoadGoldenBmp(filename, &result); + EXPECT_EQ(result.BytesPerPixel(), 4); + return result; +} + +struct ImageTestParams { + std::string image_name; + FootprintType footprint; + size_t width; + size_t height; +}; + +static void PrintTo(const ImageTestParams& params, std::ostream* os) { + *os << "ImageTestParams(" << params.image_name << ", " << params.width << "x" + << params.height << ", "; + PrintTo(params.footprint, os); + *os << ")"; +} + +TEST(CodecTest, InvalidInput) { + const size_t valid_width = 16; + const size_t valid_height = 16; + const size_t valid_stride = valid_width * 4; + + const std::vector<uint8_t> data(256); + std::vector<uint8_t> output(valid_width * valid_height * 4); + + // Invalid footprint. + EXPECT_FALSE(ASTCDecompressToRGBA( + data.data(), data.size(), valid_width, valid_height, + FootprintType::kCount, output.data(), output.size(), valid_stride)); + + // Fail for 0 width or height. + EXPECT_FALSE(ASTCDecompressToRGBA(data.data(), data.size(), 0, valid_height, + FootprintType::k4x4, output.data(), + output.size(), valid_stride)); + EXPECT_FALSE(ASTCDecompressToRGBA(data.data(), data.size(), valid_width, 0, + FootprintType::k4x4, output.data(), + output.size(), valid_stride)); + + // Fail for data size that's not a multiple of block size. + EXPECT_FALSE(ASTCDecompressToRGBA( + data.data(), data.size() - 1, valid_width, valid_height, + FootprintType::k4x4, output.data(), output.size(), valid_stride)); + // Fail for data size that doesn't match the block count. + EXPECT_FALSE(ASTCDecompressToRGBA( + data.data(), data.size() - 16, valid_width, valid_height, + FootprintType::k4x4, output.data(), output.size(), valid_stride)); + + // Fail for invalid stride. + EXPECT_FALSE(ASTCDecompressToRGBA( + data.data(), data.size(), valid_width, valid_height, FootprintType::k4x4, + output.data(), output.size(), valid_stride - 1)); + + // Fail for invalid output size. + EXPECT_FALSE(ASTCDecompressToRGBA( + data.data(), data.size(), valid_width, valid_height, FootprintType::k4x4, + output.data(), output.size() - 1, valid_stride)); +} + +class CodecTest : public TestWithParam<ImageTestParams> {}; + +TEST_P(CodecTest, PublicAPI) { + const auto& params = GetParam(); + const std::string astc = LoadASTCFile(params.image_name); + + ImageBuffer our_decoded_image; + our_decoded_image.Allocate(params.width, params.height, 4); + ASSERT_TRUE(ASTCDecompressToRGBA( + reinterpret_cast<const uint8_t*>(astc.data()), astc.size(), params.width, + params.height, params.footprint, our_decoded_image.Data().data(), + our_decoded_image.DataSize(), our_decoded_image.Stride())); + + // Check that the decoded image is *very* similar to the library decoding + // of an ASTC texture. They may not be exact due to differences in how we + // convert a 16-bit float to an 8-bit integer. + ImageBuffer decoded_image = LoadGoldenImageWithAlpha(params.image_name); + CompareSumOfSquaredDifferences(decoded_image, our_decoded_image, 1.0); +} + +TEST_P(CodecTest, DecompressToImage) { + const auto& params = GetParam(); + + std::string error; + std::unique_ptr<ASTCFile> image_file = ASTCFile::LoadFile( + std::string("src/decoder/testdata/") + params.image_name + ".astc", + &error); + ASSERT_TRUE(image_file) << "Failed to load " << params.image_name << ": " + << error; + + ASSERT_TRUE(image_file->GetFootprint()); + EXPECT_EQ(params.footprint, image_file->GetFootprint().value().Type()); + + ImageBuffer our_decoded_image; + our_decoded_image.Allocate(image_file->GetWidth(), image_file->GetHeight(), + 4); + + ASSERT_TRUE(DecompressToImage(*image_file, our_decoded_image.Data().data(), + our_decoded_image.DataSize(), + our_decoded_image.Stride())); + + // Check that the decoded image is *very* similar to the library decoding + // of an ASTC texture. They may not be exact due to differences in how we + // convert a 16-bit float to an 8-bit integer. + ImageBuffer decoded_image = LoadGoldenImageWithAlpha(params.image_name); + CompareSumOfSquaredDifferences(decoded_image, our_decoded_image, 1.0); +} + +// Test to make sure that reading out color values from blocks in a real-world +// image isn't terribly wrong, either. +std::vector<ImageTestParams> GetTransparentImageTestParams() { + return { + // image_name astc footprint width height + { "atlas_small_4x4", FootprintType::k4x4, 256, 256 }, + { "atlas_small_5x5", FootprintType::k5x5, 256, 256 }, + { "atlas_small_6x6", FootprintType::k6x6, 256, 256 }, + { "atlas_small_8x8", FootprintType::k8x8, 256, 256 }, + }; +} + +INSTANTIATE_TEST_CASE_P(Transparent, CodecTest, + ValuesIn(GetTransparentImageTestParams())); + +} // namespace + +} // namespace astc_codec |