diff --git a/include/SFML/Graphics/Image.hpp b/include/SFML/Graphics/Image.hpp index f2a7518b0..0296403d0 100644 --- a/include/SFML/Graphics/Image.hpp +++ b/include/SFML/Graphics/Image.hpp @@ -155,6 +155,24 @@ public: //////////////////////////////////////////////////////////// bool saveToFile(const std::string& filename) const; + //////////////////////////////////////////////////////////// + /// \brief Save the image to a buffer in memory + /// + /// The format of the image must be specified. + /// The supported image formats are bmp, png, tga and jpg. + /// This function fails if the image is empty, or if + /// the format was invalid. + /// + /// \param output Buffer to fill with encoded data + /// \param format Encoding format to use + /// + /// \return True if saving was successful + /// + /// \see create, loadFromFile, loadFromMemory, saveToFile + /// + //////////////////////////////////////////////////////////// + bool saveToMemory(std::vector& output, const std::string& format) const; + //////////////////////////////////////////////////////////// /// \brief Return the size (width and height) of the image /// diff --git a/src/SFML/Graphics/Image.cpp b/src/SFML/Graphics/Image.cpp index bb791d66f..64e13a8bf 100644 --- a/src/SFML/Graphics/Image.cpp +++ b/src/SFML/Graphics/Image.cpp @@ -153,6 +153,12 @@ bool Image::saveToFile(const std::string& filename) const return priv::ImageLoader::getInstance().saveImageToFile(filename, m_pixels, m_size); } +//////////////////////////////////////////////////////////// +bool Image::saveToMemory(std::vector& output, const std::string& format) const +{ + return priv::ImageLoader::getInstance().saveImageToMemory(format, output, m_pixels, m_size); +} + //////////////////////////////////////////////////////////// Vector2u Image::getSize() const diff --git a/src/SFML/Graphics/ImageLoader.cpp b/src/SFML/Graphics/ImageLoader.cpp index d0e7ac9ef..cc4981492 100644 --- a/src/SFML/Graphics/ImageLoader.cpp +++ b/src/SFML/Graphics/ImageLoader.cpp @@ -33,6 +33,7 @@ #define STB_IMAGE_WRITE_IMPLEMENTATION #include #include +#include namespace @@ -61,6 +62,14 @@ namespace sf::InputStream* stream = static_cast(user); return stream->tell() >= stream->getSize(); } + + // stb_image callback for constructing a buffer + void bufferFromCallback(void* context, void* data, int size) + { + sf::Uint8* source = static_cast(data); + std::vector* dest = static_cast*>(context); + std::copy(source, source + size, std::back_inserter(*dest)); + } } @@ -272,6 +281,46 @@ bool ImageLoader::saveImageToFile(const std::string& filename, const std::vector return false; } +//////////////////////////////////////////////////////////// +bool ImageLoader::saveImageToMemory(const std::string& format, std::vector& output, const std::vector& pixels, const Vector2u& size) +{ + // Make sure the image is not empty + if (!pixels.empty() && (size.x > 0) && (size.y > 0)) + { + // Choose function based on format + + std::string specified = toLower(format); + + if (specified == "bmp") + { + // BMP format + if (stbi_write_bmp_to_func(&bufferFromCallback, &output, size.x, size.y, 4, &pixels[0])) + return true; + } + else if (specified == "tga") + { + // TGA format + if (stbi_write_tga_to_func(&bufferFromCallback, &output, size.x, size.y, 4, &pixels[0])) + return true; + } + else if (specified == "png") + { + // PNG format + if (stbi_write_png_to_func(&bufferFromCallback, &output, size.x, size.y, 4, &pixels[0], 0)) + return true; + } + else if (specified == "jpg" || specified == "jpeg") + { + // JPG format + if (stbi_write_jpg_to_func(&bufferFromCallback, &output, size.x, size.y, 4, &pixels[0], 90)) + return true; + } + } + + err() << "Failed to save image with format \"" << format << "\"" << std::endl; + return false; +} + } // namespace priv } // namespace sf diff --git a/src/SFML/Graphics/ImageLoader.hpp b/src/SFML/Graphics/ImageLoader.hpp index c178cb7ab..d800f42c5 100644 --- a/src/SFML/Graphics/ImageLoader.hpp +++ b/src/SFML/Graphics/ImageLoader.hpp @@ -105,6 +105,19 @@ public: //////////////////////////////////////////////////////////// bool saveImageToFile(const std::string& filename, const std::vector& pixels, const Vector2u& size); + //////////////////////////////////////////////////////////// + /// \brief Save an array of pixels as an encoded image buffer + /// + /// \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 size Size of image to save, in pixels + /// + /// \return True if saving was successful + /// + //////////////////////////////////////////////////////////// + bool saveImageToMemory(const std::string& format, std::vector& output, const std::vector& pixels, const Vector2u& size); + private: ////////////////////////////////////////////////////////////