Remove output parameter from sf::Image::saveToMemory

This commit is contained in:
Chris Thrasher 2023-10-26 16:23:27 -06:00
parent 0fcd1dd0f1
commit 5cf740fd93
5 changed files with 44 additions and 44 deletions

View File

@ -33,6 +33,7 @@
#include <SFML/Graphics/Rect.hpp> #include <SFML/Graphics/Rect.hpp>
#include <filesystem> #include <filesystem>
#include <optional>
#include <string_view> #include <string_view>
#include <vector> #include <vector>
@ -148,15 +149,15 @@ public:
/// This function fails if the image is empty, or if /// This function fails if the image is empty, or if
/// the format was invalid. /// the format was invalid.
/// ///
/// \param output Buffer to fill with encoded data
/// \param format Encoding format to use /// \param format Encoding format to use
/// ///
/// \return True if saving was successful /// \return Buffer with encoded data if saving was successful,
/// otherwise std::nullopt
/// ///
/// \see create, loadFromFile, loadFromMemory, saveToFile /// \see create, loadFromFile, loadFromMemory, saveToFile
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
[[nodiscard]] bool saveToMemory(std::vector<std::uint8_t>& output, std::string_view format) const; [[nodiscard]] std::optional<std::vector<std::uint8_t>> saveToMemory(std::string_view format) const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Return the size (width and height) of the image /// \brief Return the size (width and height) of the image

View File

@ -141,9 +141,9 @@ bool Image::saveToFile(const std::filesystem::path& filename) const
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool Image::saveToMemory(std::vector<std::uint8_t>& output, std::string_view format) const std::optional<std::vector<std::uint8_t>> Image::saveToMemory(std::string_view format) const
{ {
return priv::ImageLoader::getInstance().saveImageToMemory(std::string(format), output, m_pixels, m_size); return priv::ImageLoader::getInstance().saveImageToMemory(std::string(format), m_pixels, m_size);
} }

View File

@ -282,47 +282,47 @@ bool ImageLoader::saveImageToFile(const std::filesystem::path& filename,
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool ImageLoader::saveImageToMemory(const std::string& format, std::optional<std::vector<std::uint8_t>> ImageLoader::saveImageToMemory(const std::string& format,
std::vector<std::uint8_t>& output, const std::vector<std::uint8_t>& pixels,
const std::vector<std::uint8_t>& pixels, const Vector2u& size)
const Vector2u& size)
{ {
// Make sure the image is not empty // Make sure the image is not empty
if (!pixels.empty() && (size.x > 0) && (size.y > 0)) if (!pixels.empty() && (size.x > 0) && (size.y > 0))
{ {
// Choose function based on format // Choose function based on format
const std::string specified = toLower(format); const std::string specified = toLower(format);
const Vector2i convertedSize = Vector2i(size); const Vector2i convertedSize = Vector2i(size);
std::vector<std::uint8_t> buffer;
if (specified == "bmp") if (specified == "bmp")
{ {
// BMP format // BMP format
if (stbi_write_bmp_to_func(&bufferFromCallback, &output, convertedSize.x, convertedSize.y, 4, pixels.data())) if (stbi_write_bmp_to_func(bufferFromCallback, &buffer, convertedSize.x, convertedSize.y, 4, pixels.data()))
return true; return buffer;
} }
else if (specified == "tga") else if (specified == "tga")
{ {
// TGA format // TGA format
if (stbi_write_tga_to_func(&bufferFromCallback, &output, convertedSize.x, convertedSize.y, 4, pixels.data())) if (stbi_write_tga_to_func(&bufferFromCallback, &buffer, convertedSize.x, convertedSize.y, 4, pixels.data()))
return true; return buffer;
} }
else if (specified == "png") else if (specified == "png")
{ {
// PNG format // PNG format
if (stbi_write_png_to_func(&bufferFromCallback, &output, convertedSize.x, convertedSize.y, 4, pixels.data(), 0)) if (stbi_write_png_to_func(&bufferFromCallback, &buffer, convertedSize.x, convertedSize.y, 4, pixels.data(), 0))
return true; return buffer;
} }
else if (specified == "jpg" || specified == "jpeg") else if (specified == "jpg" || specified == "jpeg")
{ {
// JPG format // JPG format
if (stbi_write_jpg_to_func(&bufferFromCallback, &output, convertedSize.x, convertedSize.y, 4, pixels.data(), 90)) if (stbi_write_jpg_to_func(&bufferFromCallback, &buffer, convertedSize.x, convertedSize.y, 4, pixels.data(), 90))
return true; return buffer;
} }
} }
err() << "Failed to save image with format " << std::quoted(format) << std::endl; err() << "Failed to save image with format " << std::quoted(format) << std::endl;
return false; return std::nullopt;
} }
} // namespace sf::priv } // namespace sf::priv

View File

@ -32,6 +32,7 @@
#include <SFML/System/Vector2.hpp> #include <SFML/System/Vector2.hpp>
#include <filesystem> #include <filesystem>
#include <optional>
#include <string> #include <string>
#include <vector> #include <vector>
@ -122,17 +123,15 @@ public:
/// \brief Save an array of pixels as an encoded image buffer /// \brief Save an array of pixels as an encoded image buffer
/// ///
/// \param format Must be "bmp", "png", "tga" or "jpg"/"jpeg". /// \param format Must be "bmp", "png", "tga" or "jpg"/"jpeg".
/// \param output Buffer to fill with encoded data
/// \param pixels Array of pixels to save to image /// \param pixels Array of pixels to save to image
/// \param size Size of image to save, in pixels /// \param size Size of image to save, in pixels
/// ///
/// \return True if saving was successful /// \return Buffer with encoded data if saving was successful
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool saveImageToMemory(const std::string& format, std::optional<std::vector<std::uint8_t>> saveImageToMemory(const std::string& format,
std::vector<std::uint8_t>& output, const std::vector<std::uint8_t>& pixels,
const std::vector<std::uint8_t>& pixels, const Vector2u& size);
const Vector2u& size);
private: private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -207,48 +207,44 @@ TEST_CASE("[Graphics] sf::Image")
SECTION("saveToMemory()") SECTION("saveToMemory()")
{ {
sf::Image image; sf::Image image;
std::vector<std::uint8_t> output;
SECTION("Empty") SECTION("Empty")
{ {
CHECK(!image.saveToMemory(output, "test.jpg")); CHECK(!image.saveToMemory("test.jpg"));
CHECK(output.empty());
} }
SECTION("Invalid size") SECTION("Invalid size")
{ {
image.create({10, 0}, sf::Color::Magenta); image.create({10, 0}, sf::Color::Magenta);
CHECK(!image.saveToMemory(output, "test.jpg")); CHECK(!image.saveToMemory("test.jpg"));
CHECK(output.empty());
image.create({0, 10}, sf::Color::Magenta); image.create({0, 10}, sf::Color::Magenta);
CHECK(!image.saveToMemory(output, "test.jpg")); CHECK(!image.saveToMemory("test.jpg"));
CHECK(output.empty());
} }
image.create({16, 16}, sf::Color::Magenta); image.create({16, 16}, sf::Color::Magenta);
SECTION("No extension") SECTION("No extension")
{ {
CHECK(!image.saveToMemory(output, "")); CHECK(!image.saveToMemory(""));
CHECK(output.empty());
} }
SECTION("Invalid extension") SECTION("Invalid extension")
{ {
CHECK(!image.saveToMemory(output, ".")); CHECK(!image.saveToMemory("."));
CHECK(output.empty()); CHECK(!image.saveToMemory("gif"));
CHECK(!image.saveToMemory(output, "gif")); CHECK(!image.saveToMemory(".jpg")); // Supposed to be "jpg"
CHECK(output.empty());
CHECK(!image.saveToMemory(output, ".jpg")); // Supposed to be "jpg"
CHECK(output.empty());
} }
SECTION("Successful save") SECTION("Successful save")
{ {
std::optional<std::vector<std::uint8_t>> maybeOutput;
SECTION("To bmp") SECTION("To bmp")
{ {
REQUIRE(image.saveToMemory(output, "bmp")); maybeOutput = image.saveToMemory("bmp");
REQUIRE(maybeOutput.has_value());
const auto& output = *maybeOutput;
REQUIRE(output.size() == 1146); REQUIRE(output.size() == 1146);
CHECK(output[0] == 66); CHECK(output[0] == 66);
CHECK(output[1] == 77); CHECK(output[1] == 77);
@ -262,7 +258,9 @@ TEST_CASE("[Graphics] sf::Image")
SECTION("To tga") SECTION("To tga")
{ {
REQUIRE(image.saveToMemory(output, "tga")); maybeOutput = image.saveToMemory("tga");
REQUIRE(maybeOutput.has_value());
const auto& output = *maybeOutput;
REQUIRE(output.size() == 98); REQUIRE(output.size() == 98);
CHECK(output[0] == 0); CHECK(output[0] == 0);
CHECK(output[1] == 0); CHECK(output[1] == 0);
@ -272,7 +270,9 @@ TEST_CASE("[Graphics] sf::Image")
SECTION("To png") SECTION("To png")
{ {
REQUIRE(image.saveToMemory(output, "png")); maybeOutput = image.saveToMemory("png");
REQUIRE(maybeOutput.has_value());
const auto& output = *maybeOutput;
REQUIRE(output.size() == 92); REQUIRE(output.size() == 92);
CHECK(output[0] == 137); CHECK(output[0] == 137);
CHECK(output[1] == 80); CHECK(output[1] == 80);