Skip to content

Commit

Permalink
Remove default empty state of sf::Image
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisThrasher committed May 19, 2024
1 parent add6422 commit 0ac278b
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 250 deletions.
6 changes: 4 additions & 2 deletions examples/vulkan/Vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1801,14 +1801,16 @@ class VulkanExample
void setupTextureImage()
{
// Load the image data
sf::Image imageData;
const auto maybeImageData = sf::Image::loadFromFile("resources/logo.png");

if (!imageData.loadFromFile("resources/logo.png"))
if (!maybeImageData)
{
vulkanAvailable = false;
return;
}

const auto& imageData = *maybeImageData;

// Create a staging buffer to transfer the data with
const VkDeviceSize imageSize = imageData.getSize().x * imageData.getSize().y * 4;

Expand Down
33 changes: 18 additions & 15 deletions include/SFML/Graphics/Image.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,16 @@ class SFML_GRAPHICS_API Image
{
public:
////////////////////////////////////////////////////////////
/// \brief Create the image and fill it with a unique color
/// \brief Construct the image and fill it with a unique color
///
/// \param size Width and height of the image
/// \param color Fill color
///
////////////////////////////////////////////////////////////
void create(const Vector2u& size, const Color& color = Color::Black);
explicit Image(const Vector2u& size, const Color& color = Color::Black);

////////////////////////////////////////////////////////////
/// \brief Create the image from an array of pixels
/// \brief Construct the image from an array of pixels
///
/// The \a pixel array is assumed to contain 32-bits RGBA pixels,
/// and have the given \a width and \a height. If not, this is
Expand All @@ -75,7 +75,7 @@ class SFML_GRAPHICS_API Image
/// \param pixels Array of pixels to copy to the image
///
////////////////////////////////////////////////////////////
void create(const Vector2u& size, const std::uint8_t* pixels);
Image(const Vector2u& size, const std::uint8_t* pixels);

////////////////////////////////////////////////////////////
/// \brief Load the image from a file on disk
Expand All @@ -87,12 +87,12 @@ class SFML_GRAPHICS_API Image
///
/// \param filename Path of the image file to load
///
/// \return True if loading was successful
/// \return Image if loading was successful, `std::nullopt` otherwise
///
/// \see loadFromMemory, loadFromStream, saveToFile
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromFile(const std::filesystem::path& filename);
[[nodiscard]] static std::optional<Image> loadFromFile(const std::filesystem::path& filename);

////////////////////////////////////////////////////////////
/// \brief Load the image from a file in memory
Expand All @@ -105,12 +105,12 @@ class SFML_GRAPHICS_API Image
/// \param data Pointer to the file data in memory
/// \param size Size of the data to load, in bytes
///
/// \return True if loading was successful
/// \return Image if loading was successful, `std::nullopt` otherwise
///
/// \see loadFromFile, loadFromStream
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromMemory(const void* data, std::size_t size);
[[nodiscard]] static std::optional<Image> loadFromMemory(const void* data, std::size_t size);

////////////////////////////////////////////////////////////
/// \brief Load the image from a custom stream
Expand All @@ -122,12 +122,12 @@ class SFML_GRAPHICS_API Image
///
/// \param stream Source stream to read from
///
/// \return True if loading was successful
/// \return Image if loading was successful, `std::nullopt` otherwise
///
/// \see loadFromFile, loadFromMemory
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromStream(InputStream& stream);
[[nodiscard]] static std::optional<Image> loadFromStream(InputStream& stream);

////////////////////////////////////////////////////////////
/// \brief Save the image to a file on disk
Expand Down Expand Up @@ -281,6 +281,12 @@ class SFML_GRAPHICS_API Image
void flipVertically();

private:
////////////////////////////////////////////////////////////
/// \brief Directly initialize data members
///
////////////////////////////////////////////////////////////
Image(Vector2u size, std::vector<std::uint8_t>&& pixels);

////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -316,13 +322,10 @@ class SFML_GRAPHICS_API Image
/// Usage example:
/// \code
/// // Load an image file from a file
/// sf::Image background;
/// if (!background.loadFromFile("background.jpg"))
/// return -1;
/// const auto background = sf::Image::loadFromFile("background.jpg").value();
///
/// // Create a 20x20 image filled with black color
/// sf::Image image;
/// image.create({20, 20}, sf::Color::Black);
/// sf::Image image({20, 20}, sf::Color::Black);
///
/// // Copy background on image at position (10, 10)
/// if (!image.copy(background, {10, 10}))
Expand Down
27 changes: 0 additions & 27 deletions include/SFML/Graphics/Texture.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,6 @@ class SFML_GRAPHICS_API Texture : GlResource
////////////////////////////////////////////////////////////
/// \brief Load the texture from a file on disk
///
/// This function is a shortcut for the following code:
/// \code
/// sf::Image image;
/// if (!image.loadFromFile(filename))
/// return false;
/// if (!texture.loadFromImage(image, area))
/// return false;
/// \endcode
///
/// The \a area argument can be used to load only a sub-rectangle
/// of the whole image. If you want the entire image then leave
/// the default value (which is an empty IntRect).
Expand All @@ -143,15 +134,6 @@ class SFML_GRAPHICS_API Texture : GlResource
////////////////////////////////////////////////////////////
/// \brief Load the texture from a file in memory
///
/// This function is a shortcut for the following code:
/// \code
/// sf::Image image;
/// if (!image.loadFromMemory(data, size))
/// return false;
/// if (!texture.loadFromImage(image, area))
/// return false;
/// \endcode
///
/// The \a area argument can be used to load only a sub-rectangle
/// of the whole image. If you want the entire image then leave
/// the default value (which is an empty IntRect).
Expand All @@ -177,15 +159,6 @@ class SFML_GRAPHICS_API Texture : GlResource
////////////////////////////////////////////////////////////
/// \brief Load the texture from a custom stream
///
/// This function is a shortcut for the following code:
/// \code
/// sf::Image image;
/// if (!image.loadFromStream(stream))
/// return false;
/// if (!texture.loadFromImage(image, area))
/// return false;
/// \endcode
///
/// The \a area argument can be used to load only a sub-rectangle
/// of the whole image. If you want the entire image then leave
/// the default value (which is an empty IntRect).
Expand Down
3 changes: 1 addition & 2 deletions src/SFML/Graphics/Font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -784,8 +784,7 @@ bool Font::setCurrentSize(unsigned int characterSize) const
Font::Page::Page(bool smooth)
{
// Make sure that the texture is initialized by default
Image image;
image.create({128, 128}, Color::Transparent);
Image image({128, 128}, Color::Transparent);

// Reserve a 2x2 white square for texturing underlines
for (unsigned int x = 0; x < 2; ++x)
Expand Down
59 changes: 19 additions & 40 deletions src/SFML/Graphics/Image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ using StbPtr = std::unique_ptr<stbi_uc, StbDeleter>;
namespace sf
{
////////////////////////////////////////////////////////////
void Image::create(const Vector2u& size, const Color& color)
Image::Image(const Vector2u& size, const Color& color)
{
if (size.x && size.y)
{
Expand Down Expand Up @@ -131,7 +131,7 @@ void Image::create(const Vector2u& size, const Color& color)


////////////////////////////////////////////////////////////
void Image::create(const Vector2u& size, const std::uint8_t* pixels)
Image::Image(const Vector2u& size, const std::uint8_t* pixels)
{
if (pixels && size.x && size.y)
{
Expand All @@ -156,7 +156,13 @@ void Image::create(const Vector2u& size, const std::uint8_t* pixels)


////////////////////////////////////////////////////////////
bool Image::loadFromFile(const std::filesystem::path& filename)
Image::Image(Vector2u size, std::vector<std::uint8_t>&& pixels) : m_size(size), m_pixels(std::move(pixels))
{
}


////////////////////////////////////////////////////////////
std::optional<Image> Image::loadFromFile(const std::filesystem::path& filename)
{
#ifdef SFML_SYSTEM_ANDROID

Expand All @@ -168,9 +174,6 @@ bool Image::loadFromFile(const std::filesystem::path& filename)

#endif

// Clear the array (just in case)
m_pixels.clear();

// Load the image and get a pointer to the pixels in memory
int width = 0;
int height = 0;
Expand All @@ -179,34 +182,25 @@ bool Image::loadFromFile(const std::filesystem::path& filename)

if (ptr)
{
// Assign the image properties
m_size = Vector2u(Vector2i(width, height));

// Copy the loaded pixels to the pixel buffer
m_pixels.assign(ptr.get(), ptr.get() + width * height * 4);

return true;
return Image(Vector2u(Vector2i(width, height)), {ptr.get(), ptr.get() + width * height * 4});
}
else
{
// Error, failed to load the image
err() << "Failed to load image\n"
<< formatDebugPathInfo(filename) << "\nReason: " << stbi_failure_reason() << std::endl;

return false;
return std::nullopt;
}
}


////////////////////////////////////////////////////////////
bool Image::loadFromMemory(const void* data, std::size_t size)
std::optional<Image> Image::loadFromMemory(const void* data, std::size_t size)
{
// Check input parameters
if (data && size)
{
// Clear the array (just in case)
m_pixels.clear();

// Load the image and get a pointer to the pixels in memory
int width = 0;
int height = 0;
Expand All @@ -217,41 +211,32 @@ bool Image::loadFromMemory(const void* data, std::size_t size)

if (ptr)
{
// Assign the image properties
m_size = Vector2u(Vector2i(width, height));

// Copy the loaded pixels to the pixel buffer
m_pixels.assign(ptr.get(), ptr.get() + width * height * 4);

return true;
return Image(Vector2u(Vector2i(width, height)), {ptr.get(), ptr.get() + width * height * 4});
}
else
{
// Error, failed to load the image
err() << "Failed to load image from memory. Reason: " << stbi_failure_reason() << std::endl;

return false;
return std::nullopt;
}
}
else
{
err() << "Failed to load image from memory, no data provided" << std::endl;
return false;
return std::nullopt;
}
}


////////////////////////////////////////////////////////////
bool Image::loadFromStream(InputStream& stream)
std::optional<Image> Image::loadFromStream(InputStream& stream)
{
// Clear the array (just in case)
m_pixels.clear();

// Make sure that the stream's reading position is at the beginning
if (stream.seek(0) == -1)
{
err() << "Failed to seek image stream" << std::endl;
return false;
return std::nullopt;
}

// Setup the stb_image callbacks
Expand All @@ -268,19 +253,13 @@ bool Image::loadFromStream(InputStream& stream)

if (ptr)
{
// Assign the image properties
m_size = Vector2u(Vector2i(width, height));

// Copy the loaded pixels to the pixel buffer
m_pixels.assign(ptr.get(), ptr.get() + width * height * 4);

return true;
return Image(Vector2u(Vector2i(width, height)), {ptr.get(), ptr.get() + width * height * 4});
}
else
{
// Error, failed to load the image
err() << "Failed to load image from stream. Reason: " << stbi_failure_reason() << std::endl;
return false;
return std::nullopt;
}
}

Expand Down
27 changes: 14 additions & 13 deletions src/SFML/Graphics/Texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,24 +265,30 @@ bool Texture::create(const Vector2u& size)
////////////////////////////////////////////////////////////
bool Texture::loadFromFile(const std::filesystem::path& filename, const IntRect& area)
{
Image image;
return image.loadFromFile(filename) && loadFromImage(image, area);
const auto image = sf::Image::loadFromFile(filename);
if (!image)
return false;
return loadFromImage(*image, area);
}


////////////////////////////////////////////////////////////
bool Texture::loadFromMemory(const void* data, std::size_t size, const IntRect& area)
{
Image image;
return image.loadFromMemory(data, size) && loadFromImage(image, area);
const auto image = sf::Image::loadFromMemory(data, size);
if (!image)
return false;
return loadFromImage(*image, area);
}


////////////////////////////////////////////////////////////
bool Texture::loadFromStream(InputStream& stream, const IntRect& area)
{
Image image;
return image.loadFromStream(stream) && loadFromImage(image, area);
const auto image = sf::Image::loadFromStream(stream);
if (!image)
return false;
return loadFromImage(*image, area);
}


Expand Down Expand Up @@ -364,8 +370,7 @@ Vector2u Texture::getSize() const
Image Texture::copyToImage() const
{
// Easy case: empty texture
if (!m_texture)
return {};
assert(m_texture && "Texture::copyToImage Cannot copy empty texture to image");

const TransientContextLock lock;

Expand Down Expand Up @@ -456,11 +461,7 @@ Image Texture::copyToImage() const

#endif // SFML_OPENGL_ES

// Create the image
Image image;
image.create(m_size, pixels.data());

return image;
return {m_size, pixels.data()};
}


Expand Down

0 comments on commit 0ac278b

Please sign in to comment.