summaryrefslogtreecommitdiff
path: root/src/SFML/Graphics/Image.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/SFML/Graphics/Image.cpp')
-rwxr-xr-xsrc/SFML/Graphics/Image.cpp215
1 files changed, 123 insertions, 92 deletions
diff --git a/src/SFML/Graphics/Image.cpp b/src/SFML/Graphics/Image.cpp
index 3a2e3f8..c2d0325 100755
--- a/src/SFML/Graphics/Image.cpp
+++ b/src/SFML/Graphics/Image.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
+// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -27,9 +27,7 @@
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/ImageLoader.hpp>
-#include <SFML/Graphics/GraphicsDevice.hpp>
-#include <SFML/Graphics/OpenGL.hpp>
-#include <SFML/Window/OpenGLCaps.hpp>
+#include <SFML/Graphics/Renderer.hpp>
#include <algorithm>
#include <iostream>
#include <vector>
@@ -45,7 +43,8 @@ myWidth (0),
myHeight (0),
myTextureWidth (0),
myTextureHeight(0),
-myGLTexture (0),
+myTexture (0),
+myIsSmooth (true),
myUpdated (false)
{
@@ -62,7 +61,8 @@ myHeight (Copy.myHeight),
myTextureWidth (Copy.myTextureWidth),
myTextureHeight(Copy.myTextureHeight),
myPixels (Copy.myPixels),
-myGLTexture (0),
+myTexture (0),
+myIsSmooth (Copy.myIsSmooth),
myUpdated (false)
{
CreateTexture();
@@ -77,7 +77,8 @@ myWidth (0),
myHeight (0),
myTextureWidth (0),
myTextureHeight(0),
-myGLTexture (0),
+myTexture (0),
+myIsSmooth (true),
myUpdated (false)
{
Create(Width, Height, Col);
@@ -92,7 +93,8 @@ myWidth (0),
myHeight (0),
myTextureWidth (0),
myTextureHeight(0),
-myGLTexture (0),
+myTexture (0),
+myIsSmooth (true),
myUpdated (false)
{
LoadFromPixels(Width, Height, Data);
@@ -132,10 +134,17 @@ bool Image::LoadFromFile(const std::string& Filename)
////////////////////////////////////////////////////////////
-/// Load the surface from a file in memory
+/// Load the image from a file in memory
////////////////////////////////////////////////////////////
bool Image::LoadFromMemory(const char* Data, std::size_t SizeInBytes)
{
+ // Check parameters
+ if (!Data || (SizeInBytes == 0))
+ {
+ std::cerr << "Failed to image font from memory, no data provided" << std::endl;
+ return false;
+ }
+
// Let the image loader load the image into our pixel array
bool Success = priv::ImageLoader::GetInstance().LoadImageFromMemory(Data, SizeInBytes, myPixels, myWidth, myHeight);
@@ -201,7 +210,7 @@ bool Image::SaveToFile(const std::string& Filename) const
////////////////////////////////////////////////////////////
/// Create an empty image
////////////////////////////////////////////////////////////
-bool Image::Create(unsigned int Width, unsigned int Height, const Color& Col)
+bool Image::Create(unsigned int Width, unsigned int Height, Color Col)
{
// Store the texture dimensions
myWidth = Width;
@@ -228,7 +237,7 @@ bool Image::Create(unsigned int Width, unsigned int Height, const Color& Col)
////////////////////////////////////////////////////////////
/// Create transparency mask from a specified colorkey
////////////////////////////////////////////////////////////
-void Image::CreateMaskFromColor(const Color& ColorKey, Uint8 Alpha)
+void Image::CreateMaskFromColor(Color ColorKey, Uint8 Alpha)
{
// Calculate the new color (old color with no alpha)
Color NewColor(ColorKey.r, ColorKey.g, ColorKey.b, Alpha);
@@ -243,9 +252,9 @@ void Image::CreateMaskFromColor(const Color& ColorKey, Uint8 Alpha)
////////////////////////////////////////////////////////////
/// Resize the image - warning : this function does not scale the image,
-/// it just ajdusts size (add padding or remove pixels)
+/// it just adjusts its size (add padding or remove pixels)
////////////////////////////////////////////////////////////
-bool Image::Resize(unsigned int Width, unsigned int Height, const Color& Col)
+bool Image::Resize(unsigned int Width, unsigned int Height, Color Col)
{
// Check size
if ((Width == 0) || (Height == 0))
@@ -320,7 +329,7 @@ const Color& Image::GetPixel(unsigned int X, unsigned int Y) const
////////////////////////////////////////////////////////////
-/// Get a read-only pointer to the array of pixels (8 bits integers RGBA)
+/// Get a read-only pointer to the array of pixels (RGBA 8 bits integers components)
/// Array size is GetWidth() x GetHeight() x 4
/// This pointer becomes invalid if you reload or resize the image
////////////////////////////////////////////////////////////
@@ -343,15 +352,15 @@ const Uint8* Image::GetPixelsPtr() const
////////////////////////////////////////////////////////////
void Image::Bind() const
{
- if (myGLTexture)
- {
- // Check if the texture needs to be updated
- if (!myUpdated)
- Update();
+ // First check if the texture needs to be updated
+ if (!myUpdated)
+ const_cast<Image*>(this)->Update();
- // Bind it
+ // Bind it
+ if (myTexture)
+ {
GLCheck(glEnable(GL_TEXTURE_2D));
- GLCheck(glBindTexture(GL_TEXTURE_2D, myGLTexture));
+ GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
}
}
@@ -359,32 +368,20 @@ void Image::Bind() const
////////////////////////////////////////////////////////////
/// Enable or disable image smoothing filter
////////////////////////////////////////////////////////////
-void Image::SetSmooth(bool Smooth) const
+void Image::SetSmooth(bool Smooth)
{
- if (myGLTexture)
+ myIsSmooth = Smooth;
+
+ if (myTexture)
{
- // Change OpenGL texture filter
- GLCheck(glBindTexture(GL_TEXTURE_2D, myGLTexture));
- GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Smooth ? GL_LINEAR : GL_NEAREST));
- GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Smooth ? GL_LINEAR : GL_NEAREST));
- GLCheck(glBindTexture(GL_TEXTURE_2D, 0));
- }
-}
+ GLint PreviousTexture;
+ GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &PreviousTexture));
+ GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
+ GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST));
+ GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST));
-////////////////////////////////////////////////////////////
-/// Enable or disable image repeat mode
-/// (ie. how to define pixels outside the texture range)
-////////////////////////////////////////////////////////////
-void Image::SetRepeat(bool Repeat) const
-{
- if (myGLTexture)
- {
- // Change OpenGL texture wrap mode
- GLCheck(glBindTexture(GL_TEXTURE_2D, myGLTexture));
- GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, Repeat ? GL_REPEAT : GL_CLAMP));
- GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, Repeat ? GL_REPEAT : GL_CLAMP));
- GLCheck(glBindTexture(GL_TEXTURE_2D, 0));
+ GLCheck(glBindTexture(GL_TEXTURE_2D, PreviousTexture));
}
}
@@ -408,16 +405,37 @@ unsigned int Image::GetHeight() const
////////////////////////////////////////////////////////////
+/// Tells whether the smooth filtering is enabled or not
+////////////////////////////////////////////////////////////
+bool Image::IsSmooth() const
+{
+ return myIsSmooth;
+}
+
+
+////////////////////////////////////////////////////////////
/// Convert a subrect expressed in pixels, into float
/// texture coordinates
////////////////////////////////////////////////////////////
FloatRect Image::GetTexCoords(const IntRect& Rect, bool Adjust) const
{
- float Offset = Adjust ? 0.5f : 0.f;
- return FloatRect((Rect.Left + Offset) / myTextureWidth,
- (Rect.Top + Offset) / myTextureHeight,
- (Rect.Right - Offset) / myTextureWidth,
- (Rect.Bottom - Offset) / myTextureHeight);
+ float Width = static_cast<float>(myTextureWidth);
+ float Height = static_cast<float>(myTextureHeight);
+
+ if (Adjust && myIsSmooth)
+ {
+ return FloatRect((Rect.Left + 0.5f) / Width,
+ (Rect.Top + 0.5f) / Height,
+ (Rect.Right - 0.5f) / Width,
+ (Rect.Bottom - 0.5f) / Height);
+ }
+ else
+ {
+ return FloatRect(Rect.Left / Width,
+ Rect.Top / Height,
+ Rect.Right / Width,
+ Rect.Bottom / Height);
+ }
}
@@ -426,7 +444,7 @@ FloatRect Image::GetTexCoords(const IntRect& Rect, bool Adjust) const
////////////////////////////////////////////////////////////
unsigned int Image::GetValidTextureSize(unsigned int Size)
{
- if (OpenGLCaps::CheckExtension("GL_ARB_texture_non_power_of_two"))
+ if (glewIsSupported("GL_ARB_texture_non_power_of_two") != 0)
{
// If hardware supports NPOT textures, then just return the unmodified size
return Size;
@@ -454,7 +472,8 @@ Image& Image::operator =(const Image& Other)
std::swap(myHeight, Temp.myHeight);
std::swap(myTextureWidth, Temp.myTextureWidth);
std::swap(myTextureHeight, Temp.myTextureHeight);
- std::swap(myGLTexture, Temp.myGLTexture);
+ std::swap(myTexture, Temp.myTexture);
+ std::swap(myIsSmooth, Temp.myIsSmooth);
std::swap(myUpdated, Temp.myUpdated);
myPixels.swap(Temp.myPixels);
@@ -469,45 +488,33 @@ bool Image::CreateTexture()
{
// Check if texture parameters are valid before creating it
if (!myWidth || !myHeight || myPixels.empty())
- {
- Reset();
return false;
- }
-
- // Destroy previous OpenGL texture if it was loaded
- if (myGLTexture)
- {
- GLCheck(glDeleteTextures(1, (GLuint*)&myGLTexture));
- myGLTexture = 0;
- }
// Adjust internal texture dimensions depending on NPOT textures support
- myTextureWidth = GetValidTextureSize(myWidth);
- myTextureHeight = GetValidTextureSize(myHeight);
+ unsigned int TextureWidth = GetValidTextureSize(myWidth);
+ unsigned int TextureHeight = GetValidTextureSize(myHeight);
- // Check maximum texture size
- unsigned int MaxSize = static_cast<unsigned int>(OpenGLCaps::GetMaxTextureSize());
- if ((myTextureWidth >= MaxSize) || (myTextureHeight >= MaxSize))
+ // Check the maximum texture size
+ GLint MaxSize;
+ GLCheck(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxSize));
+ if ((TextureWidth > static_cast<unsigned int>(MaxSize)) || (TextureHeight > static_cast<unsigned int>(MaxSize)))
{
- std::cerr << "Failed to create image, it's internal size is too high ("
- << myWidth << "x" << myTextureHeight << ")" << std::endl;
- Reset();
+ std::cerr << "Failed to create image, its internal size is too high (" << TextureWidth << "x" << TextureHeight << ")" << std::endl;
return false;
}
- // Create the OpenGL texture
- GLCheck(glGenTextures(1, (GLuint*)&myGLTexture));
- GLCheck(glBindTexture(GL_TEXTURE_2D, myGLTexture));
- GLCheck(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, myTextureWidth, myTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
-
- // Set texture parameters for 2D rendering
- GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
- GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT));
- GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
- GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+ // Destroy the previous OpenGL texture if it already exists with another size
+ if ((TextureWidth != myTextureWidth) || (TextureHeight != myTextureHeight))
+ {
+ DestroyVideoResources();
+ myTextureWidth = TextureWidth;
+ myTextureHeight = TextureHeight;
+ }
- // Copy the pixel buffer to the OpenGL texture
- Update();
+ // We don't actually create the OpenGL texture, to allow loading sf::Image instances
+ // without the need for a valid OpenGL context ()
+ // Creation is done in Image::Update()
+ myUpdated = false;
return true;
}
@@ -516,16 +523,36 @@ bool Image::CreateTexture()
////////////////////////////////////////////////////////////
/// Update the whole image in video memory
////////////////////////////////////////////////////////////
-void Image::Update() const
+void Image::Update()
{
- if (myGLTexture && myWidth && myHeight && !myPixels.empty())
+ GLint PreviousTexture;
+ GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &PreviousTexture));
+
+ // Create the OpenGL texture if it doesn't exist
+ // Texture creation is delayed on purpose (see Image::CreateTexture())
+ if (!myTexture)
+ {
+ GLuint Texture = 0;
+ GLCheck(glGenTextures(1, &Texture));
+ GLCheck(glBindTexture(GL_TEXTURE_2D, Texture));
+ GLCheck(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, myTextureWidth, myTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
+ GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP));
+ GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP));
+ GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST));
+ GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST));
+ myTexture = static_cast<unsigned int>(Texture);
+ }
+
+ // Copy the pixels
+ if (myTexture)
{
- // Update texture pixels
- GLCheck(glBindTexture(GL_TEXTURE_2D, myGLTexture));
- GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myWidth, myHeight, GL_RGBA, GL_UNSIGNED_BYTE, &myPixels[0]));
- GLCheck(glBindTexture(GL_TEXTURE_2D, 0));
+ const Uint8* Pixels = reinterpret_cast<const Uint8*>(&myPixels[0]);
+ GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
+ GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myWidth, myHeight, GL_RGBA, GL_UNSIGNED_BYTE, Pixels));
}
+ GLCheck(glBindTexture(GL_TEXTURE_2D, PreviousTexture));
+
myUpdated = true;
}
@@ -535,11 +562,14 @@ void Image::Update() const
////////////////////////////////////////////////////////////
void Image::Reset()
{
+ DestroyVideoResources();
+
myWidth = 0;
myHeight = 0;
myTextureWidth = 0;
myTextureHeight = 0;
- myGLTexture = 0;
+ myTexture = 0;
+ myIsSmooth = true;
myUpdated = false;
myPixels.clear();
}
@@ -550,12 +580,13 @@ void Image::Reset()
////////////////////////////////////////////////////////////
void Image::DestroyVideoResources()
{
- // Destroy textures
- if (myGLTexture)
+ // Destroy the internal texture
+ if (myTexture)
{
- GLCheck(glDeleteTextures(1, (GLuint*)&myGLTexture));
- myGLTexture = 0;
- myUpdated = false;
+ GLuint Texture = static_cast<GLuint>(myTexture);
+ GLCheck(glDeleteTextures(1, &Texture));
+ myTexture = 0;
+ myUpdated = false;
}
}