2022-06-18 01:03:21 +08:00
|
|
|
#include <SFML/Graphics/Image.hpp>
|
|
|
|
|
2023-11-17 01:03:29 +08:00
|
|
|
// Other 1st party headers
|
2024-08-21 05:30:38 +08:00
|
|
|
#include <SFML/System/Exception.hpp>
|
2023-11-17 01:03:29 +08:00
|
|
|
#include <SFML/System/FileInputStream.hpp>
|
|
|
|
|
2023-01-18 12:51:08 +08:00
|
|
|
#include <catch2/catch_test_macros.hpp>
|
2022-06-18 01:03:21 +08:00
|
|
|
|
2022-07-05 00:20:58 +08:00
|
|
|
#include <GraphicsUtil.hpp>
|
|
|
|
#include <array>
|
2022-07-25 14:36:05 +08:00
|
|
|
#include <type_traits>
|
|
|
|
|
2022-07-05 13:51:18 +08:00
|
|
|
TEST_CASE("[Graphics] sf::Image")
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2023-01-18 12:51:08 +08:00
|
|
|
SECTION("Type traits")
|
|
|
|
{
|
|
|
|
STATIC_CHECK(std::is_copy_constructible_v<sf::Image>);
|
|
|
|
STATIC_CHECK(std::is_copy_assignable_v<sf::Image>);
|
|
|
|
STATIC_CHECK(std::is_nothrow_move_constructible_v<sf::Image>);
|
|
|
|
STATIC_CHECK(std::is_nothrow_move_assignable_v<sf::Image>);
|
|
|
|
}
|
|
|
|
|
2024-05-19 03:07:26 +08:00
|
|
|
SECTION("Construction")
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2024-07-06 10:24:00 +08:00
|
|
|
SECTION("Default constructor")
|
|
|
|
{
|
|
|
|
const sf::Image image;
|
|
|
|
CHECK(image.getSize() == sf::Vector2u());
|
|
|
|
CHECK(image.getPixelsPtr() == nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("File constructor")
|
|
|
|
{
|
|
|
|
SECTION("Invalid file")
|
|
|
|
{
|
2024-08-21 05:30:38 +08:00
|
|
|
CHECK_THROWS_AS(sf::Image("."), sf::Exception);
|
|
|
|
CHECK_THROWS_AS(sf::Image("this/does/not/exist.jpg"), sf::Exception);
|
2024-07-06 10:24:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Successful load")
|
|
|
|
{
|
|
|
|
SECTION("bmp")
|
|
|
|
{
|
|
|
|
const sf::Image image("Graphics/sfml-logo-big.bmp");
|
|
|
|
CHECK(image.getPixel({0, 0}) == sf::Color::White);
|
|
|
|
CHECK(image.getPixel({200, 150}) == sf::Color(144, 208, 62));
|
|
|
|
CHECK(image.getSize() == sf::Vector2u(1001, 304));
|
|
|
|
CHECK(image.getPixelsPtr() != nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("png")
|
|
|
|
{
|
|
|
|
const sf::Image image("Graphics/sfml-logo-big.png");
|
|
|
|
CHECK(image.getPixel({0, 0}) == sf::Color(255, 255, 255, 0));
|
|
|
|
CHECK(image.getPixel({200, 150}) == sf::Color(144, 208, 62));
|
|
|
|
CHECK(image.getSize() == sf::Vector2u(1001, 304));
|
|
|
|
CHECK(image.getPixelsPtr() != nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("jpg")
|
|
|
|
{
|
|
|
|
const sf::Image image("Graphics/sfml-logo-big.jpg");
|
|
|
|
CHECK(image.getPixel({0, 0}) == sf::Color::White);
|
|
|
|
CHECK(image.getPixel({200, 150}) == sf::Color(144, 208, 62));
|
|
|
|
CHECK(image.getSize() == sf::Vector2u(1001, 304));
|
|
|
|
CHECK(image.getPixelsPtr() != nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("gif")
|
|
|
|
{
|
|
|
|
const sf::Image image("Graphics/sfml-logo-big.gif");
|
|
|
|
CHECK(image.getPixel({0, 0}) == sf::Color::White);
|
|
|
|
CHECK(image.getPixel({200, 150}) == sf::Color(146, 210, 62));
|
|
|
|
CHECK(image.getSize() == sf::Vector2u(1001, 304));
|
|
|
|
CHECK(image.getPixelsPtr() != nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("psd")
|
|
|
|
{
|
|
|
|
const sf::Image image("Graphics/sfml-logo-big.psd");
|
|
|
|
CHECK(image.getPixel({0, 0}) == sf::Color::White);
|
|
|
|
CHECK(image.getPixel({200, 150}) == sf::Color(144, 208, 62));
|
|
|
|
CHECK(image.getSize() == sf::Vector2u(1001, 304));
|
|
|
|
CHECK(image.getPixelsPtr() != nullptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Memory constructor")
|
|
|
|
{
|
|
|
|
SECTION("Invalid pointer")
|
|
|
|
{
|
2024-08-21 05:30:38 +08:00
|
|
|
CHECK_THROWS_AS(sf::Image(nullptr, 1), sf::Exception);
|
2024-07-06 10:24:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Invalid size")
|
|
|
|
{
|
|
|
|
const std::byte testByte{0xAB};
|
2024-08-21 05:30:38 +08:00
|
|
|
CHECK_THROWS_AS(sf::Image(&testByte, 0), sf::Exception);
|
2024-07-06 10:24:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Failed load")
|
|
|
|
{
|
|
|
|
std::vector<std::uint8_t> memory;
|
|
|
|
|
|
|
|
SECTION("Empty")
|
|
|
|
{
|
|
|
|
memory.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Junk data")
|
|
|
|
{
|
|
|
|
memory = {1, 2, 3, 4};
|
|
|
|
}
|
|
|
|
|
2024-08-21 05:30:38 +08:00
|
|
|
CHECK_THROWS_AS(sf::Image(memory.data(), memory.size()), sf::Exception);
|
2024-07-06 10:24:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Successful load")
|
|
|
|
{
|
|
|
|
const auto memory = sf::Image({24, 24}, sf::Color::Green).saveToMemory("png").value();
|
|
|
|
const sf::Image image(memory.data(), memory.size());
|
|
|
|
CHECK(image.getSize() == sf::Vector2u(24, 24));
|
|
|
|
CHECK(image.getPixelsPtr() != nullptr);
|
|
|
|
CHECK(image.getPixel({0, 0}) == sf::Color::Green);
|
|
|
|
CHECK(image.getPixel({23, 23}) == sf::Color::Green);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Stream constructor")
|
|
|
|
{
|
|
|
|
sf::FileInputStream stream("Graphics/sfml-logo-big.png");
|
|
|
|
const sf::Image image(stream);
|
|
|
|
CHECK(image.getSize() == sf::Vector2u(1001, 304));
|
|
|
|
CHECK(image.getPixelsPtr() != nullptr);
|
|
|
|
CHECK(image.getPixel({0, 0}) == sf::Color(255, 255, 255, 0));
|
|
|
|
CHECK(image.getPixel({200, 150}) == sf::Color(144, 208, 62));
|
|
|
|
}
|
|
|
|
|
2024-05-19 03:07:26 +08:00
|
|
|
SECTION("Vector2 constructor")
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2024-05-19 03:07:26 +08:00
|
|
|
const sf::Image image(sf::Vector2u(10, 10));
|
2022-06-18 01:03:21 +08:00
|
|
|
CHECK(image.getSize() == sf::Vector2u(10, 10));
|
|
|
|
CHECK(image.getPixelsPtr() != nullptr);
|
|
|
|
|
2022-09-13 04:17:27 +08:00
|
|
|
for (std::uint32_t i = 0; i < 10; ++i)
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2022-09-13 04:17:27 +08:00
|
|
|
for (std::uint32_t j = 0; j < 10; ++j)
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2023-03-20 03:43:04 +08:00
|
|
|
CHECK(image.getPixel(sf::Vector2u(i, j)) == sf::Color::Black);
|
2022-06-18 01:03:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-19 03:07:26 +08:00
|
|
|
SECTION("Vector2 and color constructor")
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2024-05-19 03:07:26 +08:00
|
|
|
const sf::Image image(sf::Vector2u(10, 10), sf::Color::Red);
|
2022-06-18 01:03:21 +08:00
|
|
|
CHECK(image.getSize() == sf::Vector2u(10, 10));
|
|
|
|
CHECK(image.getPixelsPtr() != nullptr);
|
|
|
|
|
2022-09-13 04:17:27 +08:00
|
|
|
for (std::uint32_t i = 0; i < 10; ++i)
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2022-09-13 04:17:27 +08:00
|
|
|
for (std::uint32_t j = 0; j < 10; ++j)
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
|
|
|
CHECK(image.getPixel(sf::Vector2u(i, j)) == sf::Color::Red);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-19 03:07:26 +08:00
|
|
|
SECTION("Vector2 and std::uint8_t* constructor")
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2024-06-12 23:00:04 +08:00
|
|
|
// 10 x 10, with 4 color channels array
|
2023-10-18 02:48:03 +08:00
|
|
|
std::array<std::uint8_t, 400> pixels{};
|
2022-06-18 01:03:21 +08:00
|
|
|
for (std::size_t i = 0; i < pixels.size(); i += 4)
|
|
|
|
{
|
2022-07-05 00:20:58 +08:00
|
|
|
pixels[i] = 255; // r
|
2022-06-18 01:03:21 +08:00
|
|
|
pixels[i + 1] = 0; // g
|
|
|
|
pixels[i + 2] = 0; // b
|
|
|
|
pixels[i + 3] = 255; // a
|
|
|
|
}
|
|
|
|
|
2024-05-19 03:07:26 +08:00
|
|
|
const sf::Image image(sf::Vector2u(10, 10), pixels.data());
|
2022-06-18 01:03:21 +08:00
|
|
|
CHECK(image.getSize() == sf::Vector2u(10, 10));
|
|
|
|
CHECK(image.getPixelsPtr() != nullptr);
|
|
|
|
|
2022-09-13 04:17:27 +08:00
|
|
|
for (std::uint32_t i = 0; i < 10; ++i)
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2022-09-13 04:17:27 +08:00
|
|
|
for (std::uint32_t j = 0; j < 10; ++j)
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
|
|
|
CHECK(image.getPixel(sf::Vector2u(i, j)) == sf::Color::Red);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-06 09:38:32 +08:00
|
|
|
SECTION("Resize")
|
|
|
|
{
|
|
|
|
SECTION("resize(Vector2)")
|
|
|
|
{
|
|
|
|
sf::Image image;
|
|
|
|
image.resize(sf::Vector2u(10, 10));
|
|
|
|
CHECK(image.getSize() == sf::Vector2u(10, 10));
|
|
|
|
CHECK(image.getPixelsPtr() != nullptr);
|
|
|
|
|
|
|
|
for (std::uint32_t i = 0; i < 10; ++i)
|
|
|
|
{
|
|
|
|
for (std::uint32_t j = 0; j < 10; ++j)
|
|
|
|
{
|
|
|
|
CHECK(image.getPixel(sf::Vector2u(i, j)) == sf::Color::Black);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("resize(Vector2, Color)")
|
|
|
|
{
|
|
|
|
sf::Image image;
|
|
|
|
image.resize(sf::Vector2u(10, 10), sf::Color::Red);
|
|
|
|
|
|
|
|
CHECK(image.getSize() == sf::Vector2u(10, 10));
|
|
|
|
CHECK(image.getPixelsPtr() != nullptr);
|
|
|
|
|
|
|
|
for (std::uint32_t i = 0; i < 10; ++i)
|
|
|
|
{
|
|
|
|
for (std::uint32_t j = 0; j < 10; ++j)
|
|
|
|
{
|
|
|
|
CHECK(image.getPixel(sf::Vector2u(i, j)) == sf::Color::Red);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("resize(Vector2, std::uint8_t*)")
|
|
|
|
{
|
|
|
|
// 10 x 10, with 4 colour channels array
|
|
|
|
std::array<std::uint8_t, 400> pixels{};
|
|
|
|
for (std::size_t i = 0; i < pixels.size(); i += 4)
|
|
|
|
{
|
|
|
|
pixels[i] = 255; // r
|
|
|
|
pixels[i + 1] = 0; // g
|
|
|
|
pixels[i + 2] = 0; // b
|
|
|
|
pixels[i + 3] = 255; // a
|
|
|
|
}
|
|
|
|
|
|
|
|
sf::Image image;
|
|
|
|
image.resize(sf::Vector2u(10, 10), pixels.data());
|
|
|
|
|
|
|
|
CHECK(image.getSize() == sf::Vector2u(10, 10));
|
|
|
|
CHECK(image.getPixelsPtr() != nullptr);
|
|
|
|
|
|
|
|
for (std::uint32_t i = 0; i < 10; ++i)
|
|
|
|
{
|
|
|
|
for (std::uint32_t j = 0; j < 10; ++j)
|
|
|
|
{
|
|
|
|
CHECK(image.getPixel(sf::Vector2u(i, j)) == sf::Color::Red);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-05 06:28:40 +08:00
|
|
|
SECTION("loadFromFile()")
|
|
|
|
{
|
2024-07-06 09:38:32 +08:00
|
|
|
sf::Image image;
|
|
|
|
|
2023-10-27 07:37:11 +08:00
|
|
|
SECTION("Invalid file")
|
2023-08-05 06:28:40 +08:00
|
|
|
{
|
2024-07-06 09:38:32 +08:00
|
|
|
CHECK(!image.loadFromFile("."));
|
|
|
|
CHECK(!image.loadFromFile("this/does/not/exist.jpg"));
|
|
|
|
|
|
|
|
CHECK(image.getSize() == sf::Vector2u(0, 0));
|
|
|
|
CHECK(image.getPixelsPtr() == nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Successful load")
|
|
|
|
{
|
|
|
|
SECTION("bmp")
|
|
|
|
{
|
|
|
|
REQUIRE(image.loadFromFile("Graphics/sfml-logo-big.bmp"));
|
|
|
|
CHECK(image.getPixel({0, 0}) == sf::Color::White);
|
|
|
|
CHECK(image.getPixel({200, 150}) == sf::Color(144, 208, 62));
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("png")
|
|
|
|
{
|
|
|
|
REQUIRE(image.loadFromFile("Graphics/sfml-logo-big.png"));
|
|
|
|
CHECK(image.getPixel({0, 0}) == sf::Color(255, 255, 255, 0));
|
|
|
|
CHECK(image.getPixel({200, 150}) == sf::Color(144, 208, 62));
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("jpg")
|
|
|
|
{
|
|
|
|
REQUIRE(image.loadFromFile("Graphics/sfml-logo-big.jpg"));
|
|
|
|
CHECK(image.getPixel({0, 0}) == sf::Color::White);
|
|
|
|
CHECK(image.getPixel({200, 150}) == sf::Color(144, 208, 62));
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("gif")
|
|
|
|
{
|
|
|
|
REQUIRE(image.loadFromFile("Graphics/sfml-logo-big.gif"));
|
|
|
|
CHECK(image.getPixel({0, 0}) == sf::Color::White);
|
|
|
|
CHECK(image.getPixel({200, 150}) == sf::Color(146, 210, 62));
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("psd")
|
|
|
|
{
|
|
|
|
REQUIRE(image.loadFromFile("Graphics/sfml-logo-big.psd"));
|
|
|
|
CHECK(image.getPixel({0, 0}) == sf::Color::White);
|
|
|
|
CHECK(image.getPixel({200, 150}) == sf::Color(144, 208, 62));
|
|
|
|
}
|
|
|
|
|
|
|
|
CHECK(image.getSize() == sf::Vector2u(1001, 304));
|
|
|
|
CHECK(image.getPixelsPtr() != nullptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("loadFromMemory()")
|
|
|
|
{
|
|
|
|
sf::Image image;
|
|
|
|
|
|
|
|
SECTION("Invalid pointer")
|
|
|
|
{
|
|
|
|
CHECK(!image.loadFromMemory(nullptr, 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Invalid size")
|
|
|
|
{
|
|
|
|
const std::byte testByte{0xAB};
|
|
|
|
CHECK(!image.loadFromMemory(&testByte, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Failed load")
|
|
|
|
{
|
|
|
|
std::vector<std::uint8_t> memory;
|
|
|
|
|
|
|
|
SECTION("Empty")
|
|
|
|
{
|
|
|
|
memory.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Junk data")
|
|
|
|
{
|
|
|
|
memory = {1, 2, 3, 4};
|
|
|
|
}
|
|
|
|
|
|
|
|
CHECK(!image.loadFromMemory(memory.data(), memory.size()));
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Successful load")
|
|
|
|
{
|
|
|
|
const auto memory = []()
|
|
|
|
{
|
|
|
|
sf::Image savedImage;
|
|
|
|
savedImage.resize({24, 24}, sf::Color::Green);
|
|
|
|
return savedImage.saveToMemory("png").value();
|
|
|
|
}();
|
|
|
|
|
|
|
|
CHECK(image.loadFromMemory(memory.data(), memory.size()));
|
|
|
|
CHECK(image.getSize() == sf::Vector2u(24, 24));
|
|
|
|
CHECK(image.getPixelsPtr() != nullptr);
|
|
|
|
CHECK(image.getPixel({0, 0}) == sf::Color::Green);
|
|
|
|
CHECK(image.getPixel({23, 23}) == sf::Color::Green);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("loadFromStream()")
|
|
|
|
{
|
|
|
|
sf::Image image;
|
|
|
|
sf::FileInputStream stream;
|
|
|
|
|
|
|
|
SECTION("Invalid stream")
|
|
|
|
{
|
|
|
|
CHECK(!image.loadFromStream(stream));
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Successful load")
|
|
|
|
{
|
|
|
|
CHECK(stream.open("Graphics/sfml-logo-big.png"));
|
|
|
|
REQUIRE(image.loadFromStream(stream));
|
|
|
|
CHECK(image.getSize() == sf::Vector2u(1001, 304));
|
|
|
|
CHECK(image.getPixelsPtr() != nullptr);
|
|
|
|
CHECK(image.getPixel({0, 0}) == sf::Color(255, 255, 255, 0));
|
|
|
|
CHECK(image.getPixel({200, 150}) == sf::Color(144, 208, 62));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-21 07:05:06 +08:00
|
|
|
SECTION("saveToFile()")
|
|
|
|
{
|
|
|
|
SECTION("Invalid size")
|
|
|
|
{
|
2024-05-19 03:07:26 +08:00
|
|
|
CHECK(!sf::Image({10, 0}, sf::Color::Magenta).saveToFile("test.jpg"));
|
|
|
|
CHECK(!sf::Image({0, 10}, sf::Color::Magenta).saveToFile("test.jpg"));
|
2023-10-21 07:05:06 +08:00
|
|
|
}
|
|
|
|
|
2024-05-19 03:07:26 +08:00
|
|
|
const sf::Image image({256, 256}, sf::Color::Magenta);
|
2023-10-21 07:05:06 +08:00
|
|
|
|
|
|
|
SECTION("No extension")
|
|
|
|
{
|
|
|
|
CHECK(!image.saveToFile("wheresmyextension"));
|
|
|
|
CHECK(!image.saveToFile("pls/add/extension"));
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Invalid extension")
|
|
|
|
{
|
|
|
|
CHECK(!image.saveToFile("test.ps"));
|
|
|
|
CHECK(!image.saveToFile("test.foo"));
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Successful save")
|
|
|
|
{
|
|
|
|
auto filename = std::filesystem::temp_directory_path();
|
|
|
|
|
|
|
|
SECTION("To .bmp")
|
|
|
|
{
|
|
|
|
filename /= "test.bmp";
|
|
|
|
CHECK(image.saveToFile(filename));
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("To .tga")
|
|
|
|
{
|
|
|
|
filename /= "test.tga";
|
|
|
|
CHECK(image.saveToFile(filename));
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("To .png")
|
|
|
|
{
|
|
|
|
filename /= "test.png";
|
|
|
|
CHECK(image.saveToFile(filename));
|
|
|
|
}
|
|
|
|
|
2023-10-27 07:28:40 +08:00
|
|
|
// Cannot test JPEG encoding due to it triggering UB in stbiw__jpg_writeBits
|
2023-10-21 07:05:06 +08:00
|
|
|
|
2024-07-06 10:24:00 +08:00
|
|
|
const sf::Image loadedImage(filename);
|
2023-10-22 00:29:01 +08:00
|
|
|
CHECK(loadedImage.getSize() == sf::Vector2u(256, 256));
|
|
|
|
CHECK(loadedImage.getPixelsPtr() != nullptr);
|
2023-10-21 07:05:06 +08:00
|
|
|
|
|
|
|
CHECK(std::filesystem::remove(filename));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-27 06:05:40 +08:00
|
|
|
SECTION("saveToMemory()")
|
|
|
|
{
|
|
|
|
SECTION("Invalid size")
|
|
|
|
{
|
2024-05-19 03:07:26 +08:00
|
|
|
CHECK(!sf::Image({10, 0}, sf::Color::Magenta).saveToMemory("test.jpg"));
|
|
|
|
CHECK(!sf::Image({0, 10}, sf::Color::Magenta).saveToMemory("test.jpg"));
|
2023-10-27 06:05:40 +08:00
|
|
|
}
|
|
|
|
|
2024-05-19 03:07:26 +08:00
|
|
|
const sf::Image image({16, 16}, sf::Color::Magenta);
|
2023-10-27 06:05:40 +08:00
|
|
|
|
|
|
|
SECTION("No extension")
|
|
|
|
{
|
2023-10-27 06:23:27 +08:00
|
|
|
CHECK(!image.saveToMemory(""));
|
2023-10-27 06:05:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Invalid extension")
|
|
|
|
{
|
2023-10-27 06:23:27 +08:00
|
|
|
CHECK(!image.saveToMemory("."));
|
|
|
|
CHECK(!image.saveToMemory("gif"));
|
|
|
|
CHECK(!image.saveToMemory(".jpg")); // Supposed to be "jpg"
|
2023-10-27 06:05:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Successful save")
|
|
|
|
{
|
2023-10-27 06:23:27 +08:00
|
|
|
std::optional<std::vector<std::uint8_t>> maybeOutput;
|
|
|
|
|
2023-10-27 06:05:40 +08:00
|
|
|
SECTION("To bmp")
|
|
|
|
{
|
2023-10-27 06:23:27 +08:00
|
|
|
maybeOutput = image.saveToMemory("bmp");
|
|
|
|
REQUIRE(maybeOutput.has_value());
|
|
|
|
const auto& output = *maybeOutput;
|
2023-10-27 06:05:40 +08:00
|
|
|
REQUIRE(output.size() == 1146);
|
|
|
|
CHECK(output[0] == 66);
|
|
|
|
CHECK(output[1] == 77);
|
|
|
|
CHECK(output[2] == 122);
|
|
|
|
CHECK(output[3] == 4);
|
|
|
|
CHECK(output[1000] == 255);
|
|
|
|
CHECK(output[1001] == 255);
|
|
|
|
CHECK(output[1002] == 255);
|
|
|
|
CHECK(output[1003] == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("To tga")
|
|
|
|
{
|
2023-10-27 06:23:27 +08:00
|
|
|
maybeOutput = image.saveToMemory("tga");
|
|
|
|
REQUIRE(maybeOutput.has_value());
|
|
|
|
const auto& output = *maybeOutput;
|
2023-10-27 06:05:40 +08:00
|
|
|
REQUIRE(output.size() == 98);
|
|
|
|
CHECK(output[0] == 0);
|
|
|
|
CHECK(output[1] == 0);
|
|
|
|
CHECK(output[2] == 10);
|
|
|
|
CHECK(output[3] == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("To png")
|
|
|
|
{
|
2023-10-27 06:23:27 +08:00
|
|
|
maybeOutput = image.saveToMemory("png");
|
|
|
|
REQUIRE(maybeOutput.has_value());
|
|
|
|
const auto& output = *maybeOutput;
|
2023-10-27 06:05:40 +08:00
|
|
|
REQUIRE(output.size() == 92);
|
|
|
|
CHECK(output[0] == 137);
|
|
|
|
CHECK(output[1] == 80);
|
|
|
|
CHECK(output[2] == 78);
|
|
|
|
CHECK(output[3] == 71);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Cannot test JPEG encoding due to it triggering UB in stbiw__jpg_writeBits
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-18 12:51:08 +08:00
|
|
|
SECTION("Set/get pixel")
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2024-05-19 03:07:26 +08:00
|
|
|
sf::Image image(sf::Vector2u(10, 10), sf::Color::Green);
|
2022-06-18 01:03:21 +08:00
|
|
|
CHECK(image.getPixel(sf::Vector2u(2, 2)) == sf::Color::Green);
|
|
|
|
|
|
|
|
image.setPixel(sf::Vector2u(2, 2), sf::Color::Blue);
|
|
|
|
CHECK(image.getPixel(sf::Vector2u(2, 2)) == sf::Color::Blue);
|
|
|
|
}
|
|
|
|
|
2023-01-18 12:51:08 +08:00
|
|
|
SECTION("Copy from Image")
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2023-01-18 12:51:08 +08:00
|
|
|
SECTION("Copy (Image, Vector2u)")
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2024-05-19 03:07:26 +08:00
|
|
|
const sf::Image image1(sf::Vector2u(10, 10), sf::Color::Blue);
|
|
|
|
sf::Image image2(sf::Vector2u(10, 10));
|
2022-06-21 21:33:50 +08:00
|
|
|
CHECK(image2.copy(image1, sf::Vector2u(0, 0)));
|
2022-06-18 01:03:21 +08:00
|
|
|
|
2022-09-13 04:17:27 +08:00
|
|
|
for (std::uint32_t i = 0; i < 10; ++i)
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2022-09-13 04:17:27 +08:00
|
|
|
for (std::uint32_t j = 0; j < 10; ++j)
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
|
|
|
CHECK(image1.getPixel(sf::Vector2u(i, j)) == image2.getPixel(sf::Vector2u(i, j)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-18 12:51:08 +08:00
|
|
|
SECTION("Copy (Image, Vector2u, IntRect)")
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2024-05-19 03:07:26 +08:00
|
|
|
const sf::Image image1(sf::Vector2u(5, 5), sf::Color::Blue);
|
|
|
|
sf::Image image2(sf::Vector2u(10, 10));
|
2022-06-21 21:33:50 +08:00
|
|
|
CHECK(image2.copy(image1, sf::Vector2u(0, 0), sf::IntRect(sf::Vector2i(0, 0), sf::Vector2i(5, 5))));
|
2022-06-18 01:03:21 +08:00
|
|
|
|
2022-09-13 04:17:27 +08:00
|
|
|
for (std::uint32_t i = 0; i < 10; ++i)
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2022-09-13 04:17:27 +08:00
|
|
|
for (std::uint32_t j = 0; j < 10; ++j)
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
|
|
|
if (i <= 4 && j <= 4)
|
|
|
|
CHECK(image2.getPixel(sf::Vector2u(i, j)) == sf::Color::Blue);
|
|
|
|
else
|
2023-03-20 03:43:04 +08:00
|
|
|
CHECK(image2.getPixel(sf::Vector2u(i, j)) == sf::Color::Black);
|
2022-06-18 01:03:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-18 12:51:08 +08:00
|
|
|
SECTION("Copy (Image, Vector2u, IntRect, bool)")
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
|
|
|
const sf::Color dest(255, 0, 0, 255);
|
|
|
|
const sf::Color source(5, 255, 78, 232);
|
|
|
|
|
2024-06-12 23:00:04 +08:00
|
|
|
// Create the composited color for via the alpha composite over operation
|
2022-09-04 04:15:24 +08:00
|
|
|
const auto a = static_cast<std::uint8_t>(source.a + (dest.a * (255 - source.a)) / 255);
|
|
|
|
const auto r = static_cast<std::uint8_t>(
|
2023-07-12 15:14:51 +08:00
|
|
|
((source.r * source.a) + ((dest.r * dest.a) * (255 - source.a)) / 255) / a);
|
2022-09-04 04:15:24 +08:00
|
|
|
const auto g = static_cast<std::uint8_t>(
|
2023-07-12 15:14:51 +08:00
|
|
|
((source.g * source.a) + ((dest.g * dest.a) * (255 - source.a)) / 255) / a);
|
2022-09-04 04:15:24 +08:00
|
|
|
const auto b = static_cast<std::uint8_t>(
|
2023-07-12 15:14:51 +08:00
|
|
|
((source.b * source.a) + ((dest.b * dest.a) * (255 - source.a)) / 255) / a);
|
2022-06-18 01:03:21 +08:00
|
|
|
const sf::Color composite(r, g, b, a);
|
|
|
|
|
2024-05-19 03:07:26 +08:00
|
|
|
sf::Image image1(sf::Vector2u(10, 10), dest);
|
|
|
|
const sf::Image image2(sf::Vector2u(10, 10), source);
|
2022-06-21 21:33:50 +08:00
|
|
|
CHECK(image1.copy(image2, sf::Vector2u(0, 0), sf::IntRect(sf::Vector2i(0, 0), sf::Vector2i(10, 10)), true));
|
2022-06-18 01:03:21 +08:00
|
|
|
|
2022-09-13 04:17:27 +08:00
|
|
|
for (std::uint32_t i = 0; i < 10; ++i)
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2022-09-13 04:17:27 +08:00
|
|
|
for (std::uint32_t j = 0; j < 10; ++j)
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
|
|
|
CHECK(image1.getPixel(sf::Vector2u(i, j)) == composite);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-18 12:51:08 +08:00
|
|
|
SECTION("Copy (Out of bounds sourceRect)")
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2024-05-19 03:07:26 +08:00
|
|
|
const sf::Image image1(sf::Vector2u(5, 5), sf::Color::Blue);
|
|
|
|
sf::Image image2(sf::Vector2u(10, 10), sf::Color::Red);
|
2022-06-21 21:33:50 +08:00
|
|
|
CHECK(!image2.copy(image1, sf::Vector2u(0, 0), sf::IntRect(sf::Vector2i(5, 5), sf::Vector2i(9, 9))));
|
2022-06-18 01:03:21 +08:00
|
|
|
|
2022-09-13 04:17:27 +08:00
|
|
|
for (std::uint32_t i = 0; i < 10; ++i)
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2022-09-13 04:17:27 +08:00
|
|
|
for (std::uint32_t j = 0; j < 10; ++j)
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
|
|
|
CHECK(image2.getPixel(sf::Vector2u(i, j)) == sf::Color::Red);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-18 12:51:08 +08:00
|
|
|
SECTION("Create mask from color")
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2023-01-18 12:51:08 +08:00
|
|
|
SECTION("createMaskFromColor(Color)")
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2024-05-19 03:07:26 +08:00
|
|
|
sf::Image image(sf::Vector2u(10, 10), sf::Color::Blue);
|
2022-06-18 01:03:21 +08:00
|
|
|
image.createMaskFromColor(sf::Color::Blue);
|
|
|
|
|
2022-09-13 04:17:27 +08:00
|
|
|
for (std::uint32_t i = 0; i < 10; ++i)
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2022-09-13 04:17:27 +08:00
|
|
|
for (std::uint32_t j = 0; j < 10; ++j)
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
|
|
|
CHECK(image.getPixel(sf::Vector2u(i, j)) == sf::Color(0, 0, 255, 0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-18 12:51:08 +08:00
|
|
|
SECTION("createMaskFromColor(Color, std::uint8_t)")
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2024-05-19 03:07:26 +08:00
|
|
|
sf::Image image(sf::Vector2u(10, 10), sf::Color::Blue);
|
2022-06-18 01:03:21 +08:00
|
|
|
image.createMaskFromColor(sf::Color::Blue, 100);
|
|
|
|
|
2022-09-13 04:17:27 +08:00
|
|
|
for (std::uint32_t i = 0; i < 10; ++i)
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2022-09-13 04:17:27 +08:00
|
|
|
for (std::uint32_t j = 0; j < 10; ++j)
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
|
|
|
CHECK(image.getPixel(sf::Vector2u(i, j)) == sf::Color(0, 0, 255, 100));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-18 12:51:08 +08:00
|
|
|
SECTION("Flip horizontally")
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2024-05-19 03:07:26 +08:00
|
|
|
sf::Image image(sf::Vector2u(10, 10), sf::Color::Red);
|
2022-06-18 01:03:21 +08:00
|
|
|
image.setPixel(sf::Vector2u(0, 0), sf::Color::Green);
|
|
|
|
image.flipHorizontally();
|
|
|
|
|
|
|
|
CHECK(image.getPixel(sf::Vector2u(9, 0)) == sf::Color::Green);
|
|
|
|
}
|
|
|
|
|
2023-01-18 12:51:08 +08:00
|
|
|
SECTION("Flip vertically")
|
2022-06-18 01:03:21 +08:00
|
|
|
{
|
2024-05-19 03:07:26 +08:00
|
|
|
sf::Image image(sf::Vector2u(10, 10), sf::Color::Red);
|
2022-06-18 01:03:21 +08:00
|
|
|
image.setPixel(sf::Vector2u(0, 0), sf::Color::Green);
|
|
|
|
image.flipVertically();
|
|
|
|
|
|
|
|
CHECK(image.getPixel(sf::Vector2u(0, 9)) == sf::Color::Green);
|
|
|
|
}
|
|
|
|
}
|