Reviewed all sf::Image functions to make the behaviour always well-defined and robust
git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/branches/sfml2@1764 4e206d99-4929-0410-ac5d-dfc041789085
This commit is contained in:
parent
8eebd71fcc
commit
87b207edc7
@ -79,6 +79,7 @@ public :
|
|||||||
/// like progressive jpeg.
|
/// like progressive jpeg.
|
||||||
/// The maximum size for an image depends on the graphics
|
/// The maximum size for an image depends on the graphics
|
||||||
/// driver and can be retrieve with the GetMaximumSize function.
|
/// driver and can be retrieve with the GetMaximumSize function.
|
||||||
|
/// If this function fails, the image is left unchanged.
|
||||||
///
|
///
|
||||||
/// \param filename Path of the image file to load
|
/// \param filename Path of the image file to load
|
||||||
///
|
///
|
||||||
@ -97,6 +98,7 @@ public :
|
|||||||
/// like progressive jpeg.
|
/// like progressive jpeg.
|
||||||
/// The maximum size for an image depends on the graphics
|
/// The maximum size for an image depends on the graphics
|
||||||
/// driver and can be retrieve with the GetMaximumSize function.
|
/// driver and can be retrieve with the GetMaximumSize function.
|
||||||
|
/// If this function fails, the image is left unchanged.
|
||||||
///
|
///
|
||||||
/// \param data Pointer to the file data in memory
|
/// \param data Pointer to the file data in memory
|
||||||
/// \param size Size of the data to load, in bytes
|
/// \param size Size of the data to load, in bytes
|
||||||
@ -113,9 +115,8 @@ public :
|
|||||||
///
|
///
|
||||||
/// The \a pixels argument must point to an array of 32 bits
|
/// The \a pixels argument must point to an array of 32 bits
|
||||||
/// RGBA pixels. In other words, the pixel array must have
|
/// RGBA pixels. In other words, the pixel array must have
|
||||||
/// this memory layout:
|
/// this memory layout: [r0 g0 b0 a0 r1 g1 b1 a1 r2...]
|
||||||
///
|
/// If this function fails, the image is left unchanged.
|
||||||
/// [r0 g0 b0 a0 r1 g1 b1 a1 r2...]
|
|
||||||
///
|
///
|
||||||
/// \param width Width of the image
|
/// \param width Width of the image
|
||||||
/// \param height Height of the image
|
/// \param height Height of the image
|
||||||
@ -134,7 +135,7 @@ public :
|
|||||||
/// The format of the image is automatically deduced from
|
/// The format of the image is automatically deduced from
|
||||||
/// the extension. The supported image formats are bmp, png,
|
/// the extension. The supported image formats are bmp, png,
|
||||||
/// tga and jpg. The destination file is overwritten
|
/// tga and jpg. The destination file is overwritten
|
||||||
/// if it already exists.
|
/// if it already exists. This function fails if the image is empty.
|
||||||
///
|
///
|
||||||
/// \param filename Path of the file to save
|
/// \param filename Path of the file to save
|
||||||
///
|
///
|
||||||
@ -148,6 +149,8 @@ public :
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Create the image and fill it with a unique color
|
/// \brief Create the image and fill it with a unique color
|
||||||
///
|
///
|
||||||
|
/// If this function fails, the image is left unchanged.
|
||||||
|
///
|
||||||
/// \param width Width of the image
|
/// \param width Width of the image
|
||||||
/// \param height Height of the image
|
/// \param height Height of the image
|
||||||
/// \param color Fill color
|
/// \param color Fill color
|
||||||
@ -198,6 +201,7 @@ public :
|
|||||||
/// If \a sourceRect is empty, the whole window is copied.
|
/// If \a sourceRect is empty, the whole window is copied.
|
||||||
/// Warning: this is a slow operation, if you need to draw
|
/// Warning: this is a slow operation, if you need to draw
|
||||||
/// dynamic contents to an image then use sf::RenderImage.
|
/// dynamic contents to an image then use sf::RenderImage.
|
||||||
|
/// If this function fails, the image is left unchanged.
|
||||||
///
|
///
|
||||||
/// \param window Window to capture
|
/// \param window Window to capture
|
||||||
/// \param sourceRect Sub-rectangle of the screen to copy
|
/// \param sourceRect Sub-rectangle of the screen to copy
|
||||||
@ -243,9 +247,10 @@ public :
|
|||||||
///
|
///
|
||||||
/// The returned value points to an array of RGBA pixels made of
|
/// The returned value points to an array of RGBA pixels made of
|
||||||
/// 8 bits integers components. The size of the array is
|
/// 8 bits integers components. The size of the array is
|
||||||
/// width * height * 4.
|
/// GetWidth() * GetHeight() * 4.
|
||||||
/// Warning: the returned pointer may become invalid if you
|
/// Warning: the returned pointer may become invalid if you
|
||||||
/// modify the image, so you should never store it for too long.
|
/// modify the image, so you should never store it for too long.
|
||||||
|
/// If the image is empty, a null pointer is returned.
|
||||||
///
|
///
|
||||||
/// \return Const pointer to the array of pixels
|
/// \return Const pointer to the array of pixels
|
||||||
///
|
///
|
||||||
@ -259,6 +264,7 @@ public :
|
|||||||
/// the image, and to store RGBA 32 bits pixels.
|
/// the image, and to store RGBA 32 bits pixels.
|
||||||
/// See the other overload of this function to update only
|
/// See the other overload of this function to update only
|
||||||
/// a sub-rectangle of the image.
|
/// a sub-rectangle of the image.
|
||||||
|
/// This function does nothing if \a pixels is null.
|
||||||
///
|
///
|
||||||
/// \param pixels Array of pixels to write to the image
|
/// \param pixels Array of pixels to write to the image
|
||||||
///
|
///
|
||||||
@ -273,6 +279,7 @@ public :
|
|||||||
/// perform any check; thus you're responsible of ensuring that
|
/// perform any check; thus you're responsible of ensuring that
|
||||||
/// \a rectangle does not exceed the image size, and that
|
/// \a rectangle does not exceed the image size, and that
|
||||||
/// \a pixels contains enough elements.
|
/// \a pixels contains enough elements.
|
||||||
|
/// This function does nothing if \a pixels is null.
|
||||||
/// See the other overload of this function to update the
|
/// See the other overload of this function to update the
|
||||||
/// whole image.
|
/// whole image.
|
||||||
///
|
///
|
||||||
@ -398,10 +405,15 @@ private :
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Create the OpenGL texture
|
/// \brief Create the OpenGL texture
|
||||||
///
|
///
|
||||||
/// \return True if texture has been successfully created
|
/// If this function fails, the image's members are left unchanged.
|
||||||
|
///
|
||||||
|
/// \param width Texture width
|
||||||
|
/// \param height Texture height
|
||||||
|
///
|
||||||
|
/// \return True if texture was successfully created, false if it failed
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool CreateTexture();
|
bool CreateTexture(unsigned int width, unsigned int height);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Make sure that the texture in video memory is
|
/// \brief Make sure that the texture in video memory is
|
||||||
@ -423,18 +435,6 @@ private :
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Use() const;
|
void Use() const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Reset the image attributes and leave a clean empty image
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void Reset();
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Destroy the OpenGL texture
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void DestroyTexture();
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Types
|
// Types
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
@ -74,7 +74,7 @@ Resource<Image>()
|
|||||||
myPixelsFlipped = copy.myPixelsFlipped;
|
myPixelsFlipped = copy.myPixelsFlipped;
|
||||||
|
|
||||||
// Create the texture
|
// Create the texture
|
||||||
CreateTexture();
|
CreateTexture(myWidth, myHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -82,26 +82,32 @@ Resource<Image>()
|
|||||||
Image::~Image()
|
Image::~Image()
|
||||||
{
|
{
|
||||||
// Destroy the OpenGL texture
|
// Destroy the OpenGL texture
|
||||||
DestroyTexture();
|
if (myTexture)
|
||||||
|
{
|
||||||
|
GLuint Texture = static_cast<GLuint>(myTexture);
|
||||||
|
GLCheck(glDeleteTextures(1, &Texture));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool Image::LoadFromFile(const std::string& filename)
|
bool Image::LoadFromFile(const std::string& filename)
|
||||||
{
|
{
|
||||||
// Let the image loader load the image into our pixel array
|
// Forward the job to the image loader
|
||||||
bool success = priv::ImageLoader::GetInstance().LoadImageFromFile(filename, myPixels, myWidth, myHeight);
|
std::vector<Uint8> pixels;
|
||||||
|
unsigned int width;
|
||||||
if (success)
|
unsigned int height;
|
||||||
|
if (priv::ImageLoader::GetInstance().LoadImageFromFile(filename, pixels, width, height))
|
||||||
{
|
{
|
||||||
// Loading succeeded : we can create the texture
|
// Loading succeeded : we can create the texture
|
||||||
if (CreateTexture())
|
if (CreateTexture(width, height))
|
||||||
|
{
|
||||||
|
// Copy the pixels
|
||||||
|
myPixels.swap(pixels);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Oops... something failed
|
|
||||||
Reset();
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,26 +115,21 @@ bool Image::LoadFromFile(const std::string& filename)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool Image::LoadFromMemory(const void* data, std::size_t size)
|
bool Image::LoadFromMemory(const void* data, std::size_t size)
|
||||||
{
|
{
|
||||||
// Check parameters
|
// Forward the job to the image loader
|
||||||
if (!data || (size == 0))
|
std::vector<Uint8> pixels;
|
||||||
{
|
unsigned int width;
|
||||||
Err() << "Failed to image font from memory, no data provided" << std::endl;
|
unsigned int height;
|
||||||
return false;
|
if (priv::ImageLoader::GetInstance().LoadImageFromMemory(data, size, pixels, width, height))
|
||||||
}
|
|
||||||
|
|
||||||
// Let the image loader load the image into our pixel array
|
|
||||||
bool success = priv::ImageLoader::GetInstance().LoadImageFromMemory(data, size, myPixels, myWidth, myHeight);
|
|
||||||
|
|
||||||
if (success)
|
|
||||||
{
|
{
|
||||||
// Loading succeeded : we can create the texture
|
// Loading succeeded : we can create the texture
|
||||||
if (CreateTexture())
|
if (CreateTexture(width, height))
|
||||||
|
{
|
||||||
|
// Copy the pixels
|
||||||
|
myPixels.swap(pixels);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Oops... something failed
|
|
||||||
Reset();
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,23 +139,17 @@ bool Image::LoadFromPixels(unsigned int width, unsigned int height, const Uint8*
|
|||||||
{
|
{
|
||||||
if (data)
|
if (data)
|
||||||
{
|
{
|
||||||
// Store the texture dimensions
|
// Create the internal texture
|
||||||
myWidth = width;
|
if (CreateTexture(width, height))
|
||||||
myHeight = height;
|
|
||||||
|
|
||||||
// Fill the pixel buffer with the specified raw data
|
|
||||||
myPixels.resize(width * height * 4);
|
|
||||||
std::memcpy(&myPixels[0], data, myPixels.size());
|
|
||||||
|
|
||||||
// We can create the texture
|
|
||||||
if (CreateTexture())
|
|
||||||
{
|
{
|
||||||
|
// Copy the pixels
|
||||||
|
std::size_t size = width * height * 4;
|
||||||
|
myPixels.resize(size);
|
||||||
|
std::memcpy(&myPixels[0], data, size); // faster than vector::assign
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Oops... something failed
|
|
||||||
Reset();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -180,33 +175,27 @@ bool Image::SaveToFile(const std::string& filename) const
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool Image::Create(unsigned int width, unsigned int height, const Color& color)
|
bool Image::Create(unsigned int width, unsigned int height, const Color& color)
|
||||||
{
|
{
|
||||||
// Store the texture dimensions
|
// First create the texture
|
||||||
myWidth = width;
|
if (CreateTexture(width, height))
|
||||||
myHeight = height;
|
|
||||||
|
|
||||||
// Resize the pixel buffer
|
|
||||||
myPixels.resize(myWidth * myHeight * 4);
|
|
||||||
|
|
||||||
// Fill it with the specified color
|
|
||||||
Uint8* p = &myPixels[0];
|
|
||||||
Uint8* end = p + myWidth * myHeight * 4;
|
|
||||||
while (p < end)
|
|
||||||
{
|
{
|
||||||
*p++ = color.r;
|
// Resize the pixel buffer
|
||||||
*p++ = color.g;
|
myPixels.resize(width * height * 4);
|
||||||
*p++ = color.b;
|
|
||||||
*p++ = color.a;
|
// Fill it with the specified color
|
||||||
}
|
Uint8* ptr = &*myPixels.begin();
|
||||||
|
Uint8* end = &*myPixels.end();
|
||||||
|
while (ptr < end)
|
||||||
|
{
|
||||||
|
*ptr++ = color.r;
|
||||||
|
*ptr++ = color.g;
|
||||||
|
*ptr++ = color.b;
|
||||||
|
*ptr++ = color.a;
|
||||||
|
}
|
||||||
|
|
||||||
// We can create the texture
|
|
||||||
if (CreateTexture())
|
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Oops... something failed
|
|
||||||
Reset();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -215,32 +204,32 @@ bool Image::Create(unsigned int width, unsigned int height, const Color& color)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Image::CreateMaskFromColor(const Color& color, Uint8 alpha)
|
void Image::CreateMaskFromColor(const Color& color, Uint8 alpha)
|
||||||
{
|
{
|
||||||
// No pixels to replace
|
|
||||||
if (myPixels.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Check if the array of pixels needs to be updated
|
// Check if the array of pixels needs to be updated
|
||||||
EnsureArrayUpdate();
|
EnsureArrayUpdate();
|
||||||
|
|
||||||
// Replace the alpha of the pixels that match the transparent color
|
// Make sure that the image is not empty
|
||||||
Uint8* p = &myPixels[0];
|
if (!myPixels.empty())
|
||||||
Uint8* end = p + myWidth * myHeight * 4;
|
|
||||||
while (p < end)
|
|
||||||
{
|
{
|
||||||
if ((p[0] == color.r) && (p[1] == color.g) && (p[2] == color.b) && (p[3] == color.a))
|
// Replace the alpha of the pixels that match the transparent color
|
||||||
p[3] = alpha;
|
Uint8* ptr = &*myPixels.begin();
|
||||||
p += 4;
|
Uint8* end = &*myPixels.end();
|
||||||
}
|
while (ptr < end)
|
||||||
|
{
|
||||||
|
if ((ptr[0] == color.r) && (ptr[1] == color.g) && (ptr[2] == color.b) && (ptr[3] == color.a))
|
||||||
|
ptr[3] = alpha;
|
||||||
|
ptr += 4;
|
||||||
|
}
|
||||||
|
|
||||||
// The texture will need to be updated
|
// The texture will need to be updated
|
||||||
myTextureUpdated = false;
|
myTextureUpdated = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Image::Copy(const Image& source, unsigned int destX, unsigned int destY, const IntRect& sourceRect, bool applyAlpha)
|
void Image::Copy(const Image& source, unsigned int destX, unsigned int destY, const IntRect& sourceRect, bool applyAlpha)
|
||||||
{
|
{
|
||||||
// Make sure both images are valid
|
// Make sure that both images are valid
|
||||||
if ((source.myWidth == 0) || (source.myHeight == 0) || (myWidth == 0) || (myHeight == 0))
|
if ((source.myWidth == 0) || (source.myHeight == 0) || (myWidth == 0) || (myHeight == 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -343,12 +332,8 @@ bool Image::CopyScreen(RenderWindow& window, const IntRect& sourceRect)
|
|||||||
if (srcRect.Height > static_cast<int>(window.GetHeight())) srcRect.Height = window.GetHeight();
|
if (srcRect.Height > static_cast<int>(window.GetHeight())) srcRect.Height = window.GetHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the texture dimensions
|
|
||||||
myWidth = srcRect.Width;
|
|
||||||
myHeight = srcRect.Height;
|
|
||||||
|
|
||||||
// We can then create the texture
|
// We can then create the texture
|
||||||
if (window.SetActive() && CreateTexture())
|
if (window.SetActive() && CreateTexture(srcRect.Width, srcRect.Height))
|
||||||
{
|
{
|
||||||
GLint previous;
|
GLint previous;
|
||||||
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
|
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
|
||||||
@ -366,7 +351,6 @@ bool Image::CopyScreen(RenderWindow& window, const IntRect& sourceRect)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Reset();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -424,17 +408,20 @@ const Uint8* Image::GetPixelsPtr() const
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Image::UpdatePixels(const Uint8* pixels)
|
void Image::UpdatePixels(const Uint8* pixels)
|
||||||
{
|
{
|
||||||
GLint previous;
|
if (pixels && myTexture)
|
||||||
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
|
{
|
||||||
|
GLint previous;
|
||||||
|
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
|
||||||
|
|
||||||
// Update the texture from the array of pixels
|
// Update the texture from the array of pixels
|
||||||
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
|
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
|
||||||
GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myWidth, myHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
|
GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myWidth, myHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
|
||||||
|
|
||||||
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
|
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
|
||||||
|
|
||||||
myArrayUpdated = false;
|
myArrayUpdated = false;
|
||||||
myTextureUpdated = true;
|
myTextureUpdated = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -444,17 +431,20 @@ void Image::UpdatePixels(const Uint8* pixels, const IntRect& rectangle)
|
|||||||
// Make sure that the texture is up-to-date
|
// Make sure that the texture is up-to-date
|
||||||
EnsureTextureUpdate();
|
EnsureTextureUpdate();
|
||||||
|
|
||||||
GLint previous;
|
if (pixels && myTexture)
|
||||||
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
|
{
|
||||||
|
GLint previous;
|
||||||
|
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
|
||||||
|
|
||||||
// Update the texture from the array of pixels
|
// Update the texture from the array of pixels
|
||||||
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
|
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
|
||||||
GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
|
GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
|
||||||
|
|
||||||
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
|
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
|
||||||
|
|
||||||
// The pixel cache is no longer up-to-date
|
// The pixel cache is no longer up-to-date
|
||||||
myArrayUpdated = false;
|
myArrayUpdated = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -596,27 +586,33 @@ unsigned int Image::GetValidSize(unsigned int size)
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool Image::CreateTexture()
|
bool Image::CreateTexture(unsigned int width, unsigned int height)
|
||||||
{
|
{
|
||||||
// Check if texture parameters are valid before creating it
|
// Check if texture parameters are valid before creating it
|
||||||
if (!myWidth || !myHeight)
|
if (!width || !height)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Adjust internal texture dimensions depending on NPOT textures support
|
// Compute the internal texture dimensions depending on NPOT textures support
|
||||||
myTextureWidth = GetValidSize(myWidth);
|
unsigned int textureWidth = GetValidSize(width);
|
||||||
myTextureHeight = GetValidSize(myHeight);
|
unsigned int textureHeight = GetValidSize(height);
|
||||||
|
|
||||||
// Check the maximum texture size
|
// Check the maximum texture size
|
||||||
unsigned int maxSize = GetMaximumSize();
|
unsigned int maxSize = GetMaximumSize();
|
||||||
if ((myTextureWidth > maxSize) || (myTextureHeight > maxSize))
|
if ((textureWidth > maxSize) || (textureHeight > maxSize))
|
||||||
{
|
{
|
||||||
Err() << "Failed to create image, its internal size is too high "
|
Err() << "Failed to create image, its internal size is too high "
|
||||||
<< "(" << myTextureWidth << "x" << myTextureHeight << ", "
|
<< "(" << textureWidth << "x" << textureHeight << ", "
|
||||||
<< "maximum is " << maxSize << "x" << maxSize << ")"
|
<< "maximum is " << maxSize << "x" << maxSize << ")"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// All the validity checks passed, we can store the new texture settings
|
||||||
|
myWidth = width;
|
||||||
|
myHeight = height;
|
||||||
|
myTextureWidth = textureWidth;
|
||||||
|
myTextureHeight = textureHeight;
|
||||||
|
|
||||||
// Create the OpenGL texture if it doesn't exist yet
|
// Create the OpenGL texture if it doesn't exist yet
|
||||||
if (!myTexture)
|
if (!myTexture)
|
||||||
{
|
{
|
||||||
@ -729,37 +725,4 @@ void Image::Use() const
|
|||||||
EnsureTextureUpdate();
|
EnsureTextureUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void Image::Reset()
|
|
||||||
{
|
|
||||||
DestroyTexture();
|
|
||||||
|
|
||||||
myWidth = 0;
|
|
||||||
myHeight = 0;
|
|
||||||
myTextureWidth = 0;
|
|
||||||
myTextureHeight = 0;
|
|
||||||
myTexture = 0;
|
|
||||||
myIsSmooth = true;
|
|
||||||
myTextureUpdated = true;
|
|
||||||
myArrayUpdated = true;
|
|
||||||
myPixelsFlipped = false;
|
|
||||||
myPixels.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void Image::DestroyTexture()
|
|
||||||
{
|
|
||||||
// Destroy the internal texture
|
|
||||||
if (myTexture)
|
|
||||||
{
|
|
||||||
GLuint Texture = static_cast<GLuint>(myTexture);
|
|
||||||
GLCheck(glDeleteTextures(1, &Texture));
|
|
||||||
myTexture = 0;
|
|
||||||
myTextureUpdated = true;
|
|
||||||
myArrayUpdated = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -87,7 +87,7 @@ bool ImageLoader::LoadImageFromFile(const std::string& filename, std::vector<Uin
|
|||||||
int imgWidth, imgHeight, imgChannels;
|
int imgWidth, imgHeight, imgChannels;
|
||||||
unsigned char* ptr = stbi_load(filename.c_str(), &imgWidth, &imgHeight, &imgChannels, STBI_rgb_alpha);
|
unsigned char* ptr = stbi_load(filename.c_str(), &imgWidth, &imgHeight, &imgChannels, STBI_rgb_alpha);
|
||||||
|
|
||||||
if (ptr)
|
if (ptr && imgWidth && imgHeight)
|
||||||
{
|
{
|
||||||
// Assign the image properties
|
// Assign the image properties
|
||||||
width = imgWidth;
|
width = imgWidth;
|
||||||
@ -115,34 +115,43 @@ bool ImageLoader::LoadImageFromFile(const std::string& filename, std::vector<Uin
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool ImageLoader::LoadImageFromMemory(const void* data, std::size_t size, std::vector<Uint8>& pixels, unsigned int& width, unsigned int& height)
|
bool ImageLoader::LoadImageFromMemory(const void* data, std::size_t size, std::vector<Uint8>& pixels, unsigned int& width, unsigned int& height)
|
||||||
{
|
{
|
||||||
// Clear the array (just in case)
|
// Check input parameters
|
||||||
pixels.clear();
|
if (data && size)
|
||||||
|
|
||||||
// Load the image and get a pointer to the pixels in memory
|
|
||||||
int imgWidth, imgHeight, imgChannels;
|
|
||||||
const unsigned char* buffer = static_cast<const unsigned char*>(data);
|
|
||||||
unsigned char* ptr = stbi_load_from_memory(buffer, static_cast<int>(size), &imgWidth, &imgHeight, &imgChannels, STBI_rgb_alpha);
|
|
||||||
|
|
||||||
if (ptr)
|
|
||||||
{
|
{
|
||||||
// Assign the image properties
|
// Clear the array (just in case)
|
||||||
width = imgWidth;
|
pixels.clear();
|
||||||
height = imgHeight;
|
|
||||||
|
|
||||||
// Copy the loaded pixels to the pixel buffer
|
// Load the image and get a pointer to the pixels in memory
|
||||||
pixels.resize(width * height * 4);
|
int imgWidth, imgHeight, imgChannels;
|
||||||
memcpy(&pixels[0], ptr, pixels.size());
|
const unsigned char* buffer = static_cast<const unsigned char*>(data);
|
||||||
|
unsigned char* ptr = stbi_load_from_memory(buffer, static_cast<int>(size), &imgWidth, &imgHeight, &imgChannels, STBI_rgb_alpha);
|
||||||
|
|
||||||
// Free the loaded pixels (they are now in our own pixel buffer)
|
if (ptr && imgWidth && imgHeight)
|
||||||
stbi_image_free(ptr);
|
{
|
||||||
|
// Assign the image properties
|
||||||
|
width = imgWidth;
|
||||||
|
height = imgHeight;
|
||||||
|
|
||||||
return true;
|
// Copy the loaded pixels to the pixel buffer
|
||||||
|
pixels.resize(width * height * 4);
|
||||||
|
memcpy(&pixels[0], ptr, pixels.size());
|
||||||
|
|
||||||
|
// Free the loaded pixels (they are now in our own pixel buffer)
|
||||||
|
stbi_image_free(ptr);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Error, failed to load the image
|
||||||
|
Err() << "Failed to load image from memory. Reason : " << stbi_failure_reason() << std::endl;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Error, failed to load the image
|
Err() << "Failed to load image from memory, no data provided" << std::endl;
|
||||||
Err() << "Failed to load image from memory. Reason : " << stbi_failure_reason() << std::endl;
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -151,35 +160,39 @@ bool ImageLoader::LoadImageFromMemory(const void* data, std::size_t size, std::v
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool ImageLoader::SaveImageToFile(const std::string& filename, const std::vector<Uint8>& pixels, unsigned int width, unsigned int height)
|
bool ImageLoader::SaveImageToFile(const std::string& filename, const std::vector<Uint8>& pixels, unsigned int width, unsigned int height)
|
||||||
{
|
{
|
||||||
// Deduce the image type from its extension
|
// Make sure the image is not empty
|
||||||
if (filename.size() > 3)
|
if (!pixels.empty() && width && height)
|
||||||
{
|
{
|
||||||
// Extract the extension
|
// Deduce the image type from its extension
|
||||||
std::string extension = filename.substr(filename.size() - 3);
|
if (filename.size() > 3)
|
||||||
|
{
|
||||||
|
// Extract the extension
|
||||||
|
std::string extension = filename.substr(filename.size() - 3);
|
||||||
|
|
||||||
if (ToLower(extension) == "bmp")
|
if (ToLower(extension) == "bmp")
|
||||||
{
|
{
|
||||||
// BMP format
|
// BMP format
|
||||||
if (stbi_write_bmp(filename.c_str(), width, height, 4, &pixels[0]))
|
if (stbi_write_bmp(filename.c_str(), width, height, 4, &pixels[0]))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (ToLower(extension) == "tga")
|
else if (ToLower(extension) == "tga")
|
||||||
{
|
{
|
||||||
// TGA format
|
// TGA format
|
||||||
if (stbi_write_tga(filename.c_str(), width, height, 4, &pixels[0]))
|
if (stbi_write_tga(filename.c_str(), width, height, 4, &pixels[0]))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if(ToLower(extension) == "png")
|
else if(ToLower(extension) == "png")
|
||||||
{
|
{
|
||||||
// PNG format
|
// PNG format
|
||||||
if (stbi_write_png(filename.c_str(), width, height, 4, &pixels[0], 0))
|
if (stbi_write_png(filename.c_str(), width, height, 4, &pixels[0], 0))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (ToLower(extension) == "jpg")
|
else if (ToLower(extension) == "jpg")
|
||||||
{
|
{
|
||||||
// JPG format
|
// JPG format
|
||||||
if (WriteJpg(filename, pixels, width, height))
|
if (WriteJpg(filename, pixels, width, height))
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user