28 #include <SFML/Graphics/Image.hpp> 29 #include <SFML/Graphics/ImageLoader.hpp> 30 #include <SFML/Graphics/RenderWindow.hpp> 31 #include <SFML/Graphics/GraphicsContext.hpp> 50 myNeedTextureUpdate(false),
51 myNeedArrayUpdate (false)
62 myWidth (Copy.myWidth),
63 myHeight (Copy.myHeight),
64 myTextureWidth (Copy.myTextureWidth),
65 myTextureHeight (Copy.myTextureHeight),
67 myIsSmooth (Copy.myIsSmooth),
68 myPixels (Copy.myPixels),
69 myNeedTextureUpdate(false),
70 myNeedArrayUpdate (false)
86 myNeedTextureUpdate(false),
87 myNeedArrayUpdate (false)
89 Create(Width, Height, Col);
96 Image::Image(
unsigned int Width,
unsigned int Height,
const Uint8* Data) :
103 myNeedTextureUpdate(false),
104 myNeedArrayUpdate (false)
126 bool Success = priv::ImageLoader::GetInstance().LoadImageFromFile(Filename, myPixels, myWidth, myHeight);
148 if (!Data || (SizeInBytes == 0))
150 std::cerr <<
"Failed to image font from memory, no data provided" << std::endl;
155 bool Success = priv::ImageLoader::GetInstance().LoadImageFromMemory(Data, SizeInBytes, myPixels, myWidth, myHeight);
183 const Color* Ptr =
reinterpret_cast<const Color*
>(Data);
184 myPixels.assign(Ptr, Ptr + Width * Height);
201 return Create(Width, Height,
Color(255, 255, 255, 255));
215 return priv::ImageLoader::GetInstance().SaveImageToFile(Filename, myPixels, myWidth, myHeight);
230 myPixels.resize(Width * Height, Col);
255 Color NewColor(ColorKey.
r, ColorKey.
g, ColorKey.
b, Alpha);
258 std::replace(myPixels.begin(), myPixels.end(), ColorKey, NewColor);
261 myNeedTextureUpdate =
true;
273 if ((Source.myWidth == 0) || (Source.myHeight == 0) || (myWidth == 0) || (myHeight == 0))
278 Source.EnsureArrayUpdate();
286 SrcRect.
Right = Source.myWidth;
287 SrcRect.
Bottom = Source.myHeight;
291 if (SrcRect.
Left < 0) SrcRect.
Left = 0;
292 if (SrcRect.
Top < 0) SrcRect.
Top = 0;
293 if (SrcRect.
Right > static_cast<int>(Source.myWidth)) SrcRect.
Right = Source.myWidth;
294 if (SrcRect.
Bottom > static_cast<int>(Source.myHeight)) SrcRect.
Bottom = Source.myHeight;
300 if (DestX + Width > myWidth) Width = myWidth - DestX;
301 if (DestY + Height > myHeight) Height = myHeight - DestY;
304 if ((Width <= 0) || (Height <= 0))
308 int Pitch = Width * 4;
310 int SrcStride = Source.myWidth * 4;
311 int DstStride = myWidth * 4;
312 const Uint8* SrcPixels = Source.
GetPixelsPtr() + (SrcRect.
Left + SrcRect.
Top * Source.myWidth) * 4;
313 Uint8* DstPixels =
reinterpret_cast<Uint8*
>(&myPixels[0]) + (DestX + DestY * myWidth) * 4;
319 for (
int i = 0; i < Rows; ++i)
321 for (
int j = 0; j < Width; ++j)
324 const Uint8* Src = SrcPixels + j * 4;
325 Uint8* Dst = DstPixels + j * 4;
328 Uint8 Alpha = Src[3];
329 Dst[0] = (Src[0] * Alpha + Dst[0] * (255 - Alpha)) / 255;
330 Dst[1] = (Src[1] * Alpha + Dst[1] * (255 - Alpha)) / 255;
331 Dst[2] = (Src[2] * Alpha + Dst[2] * (255 - Alpha)) / 255;
334 SrcPixels += SrcStride;
335 DstPixels += DstStride;
341 for (
int i = 0; i < Rows; ++i)
343 memcpy(DstPixels, SrcPixels, Pitch);
344 SrcPixels += SrcStride;
345 DstPixels += DstStride;
350 myNeedTextureUpdate =
true;
371 if (SrcRect.
Left < 0) SrcRect.
Left = 0;
372 if (SrcRect.
Top < 0) SrcRect.
Top = 0;
384 GLint PreviousTexture;
385 GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &PreviousTexture));
387 GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
388 GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, SrcRect.
Left, SrcRect.
Top, myWidth, myHeight));
390 GLCheck(glBindTexture(GL_TEXTURE_2D, PreviousTexture));
392 myNeedTextureUpdate =
false;
393 myNeedArrayUpdate =
true;
414 if ((X >= myWidth) || (Y >= myHeight))
416 std::cerr <<
"Cannot set pixel (" << X <<
"," << Y <<
") for image " 417 <<
"(width = " << myWidth <<
", height = " << myHeight <<
")" << std::endl;
421 myPixels[X + Y * myWidth] = Col;
424 myNeedTextureUpdate =
true;
437 if ((X >= myWidth) || (Y >= myHeight))
439 std::cerr <<
"Cannot get pixel (" << X <<
"," << Y <<
") for image " 440 <<
"(width = " << myWidth <<
", height = " << myHeight <<
")" << std::endl;
444 return myPixels[X + Y * myWidth];
458 if (!myPixels.empty())
460 return reinterpret_cast<const Uint8*
>(&myPixels[0]);
464 std::cerr <<
"Trying to access the pixels of an empty image" << std::endl;
476 EnsureTextureUpdate();
481 GLCheck(glEnable(GL_TEXTURE_2D));
482 GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
492 if (Smooth != myIsSmooth)
499 priv::GraphicsContext Ctx;
501 GLint PreviousTexture;
502 GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &PreviousTexture));
504 GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
505 GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST));
506 GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST));
508 GLCheck(glBindTexture(GL_TEXTURE_2D, PreviousTexture));
547 float Width =
static_cast<float>(myTextureWidth);
548 float Height =
static_cast<float>(myTextureHeight);
563 priv::GraphicsContext Ctx;
565 if (glewIsSupported(
"GL_ARB_texture_non_power_of_two") != 0)
573 unsigned int PowerOfTwo = 1;
574 while (PowerOfTwo < Size)
589 std::swap(myWidth, Temp.myWidth);
590 std::swap(myHeight, Temp.myHeight);
591 std::swap(myTextureWidth, Temp.myTextureWidth);
592 std::swap(myTextureHeight, Temp.myTextureHeight);
593 std::swap(myTexture, Temp.myTexture);
594 std::swap(myIsSmooth, Temp.myIsSmooth);
595 std::swap(myNeedArrayUpdate, Temp.myNeedArrayUpdate);
596 std::swap(myNeedTextureUpdate, Temp.myNeedTextureUpdate);
597 myPixels.swap(Temp.myPixels);
606 bool Image::CreateTexture()
609 if (!myWidth || !myHeight)
613 priv::GraphicsContext Ctx;
621 GLCheck(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxSize));
622 if ((TextureWidth > static_cast<unsigned int>(MaxSize)) || (TextureHeight > static_cast<unsigned int>(MaxSize)))
624 std::cerr <<
"Failed to create image, its internal size is too high (" << TextureWidth <<
"x" << TextureHeight <<
")" << std::endl;
629 if ((TextureWidth != myTextureWidth) || (TextureHeight != myTextureHeight))
632 myTextureWidth = TextureWidth;
633 myTextureHeight = TextureHeight;
639 GLint PreviousTexture;
640 GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &PreviousTexture));
643 GLCheck(glGenTextures(1, &Texture));
644 GLCheck(glBindTexture(GL_TEXTURE_2D, Texture));
645 GLCheck(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, myTextureWidth, myTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
646 GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP));
647 GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP));
648 GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST));
649 GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST));
650 myTexture =
static_cast<unsigned int>(Texture);
652 GLCheck(glBindTexture(GL_TEXTURE_2D, PreviousTexture));
655 myNeedTextureUpdate =
true;
665 void Image::EnsureTextureUpdate()
const 667 if (myNeedTextureUpdate)
670 if (myTexture && !myPixels.empty())
672 GLint PreviousTexture;
673 GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &PreviousTexture));
676 GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
677 GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myWidth, myHeight, GL_RGBA, GL_UNSIGNED_BYTE, &myPixels[0]));
679 GLCheck(glBindTexture(GL_TEXTURE_2D, PreviousTexture));
682 myNeedTextureUpdate =
false;
691 void Image::EnsureArrayUpdate()
const 693 if (myNeedArrayUpdate)
696 GLint PreviousTexture;
697 GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &PreviousTexture));
700 myPixels.resize(myWidth * myHeight);
702 if ((myWidth == myTextureWidth) && (myHeight == myTextureHeight))
707 GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
708 GLCheck(glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &myPixels[0]));
715 std::vector<Color> AllPixels(myTextureWidth * myTextureHeight);
716 GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
717 GLCheck(glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &AllPixels[0]));
720 const Color* Src = &AllPixels[0];
721 Color* Dst = &myPixels[0];
722 for (
unsigned int i = 0; i < myHeight; ++i)
724 std::copy(Src, Src + myWidth, Dst);
725 Src += myTextureWidth;
731 GLCheck(glBindTexture(GL_TEXTURE_2D, PreviousTexture));
733 myNeedArrayUpdate =
false;
751 myNeedTextureUpdate =
false;
752 myNeedArrayUpdate =
false;
760 void Image::DestroyTexture()
766 priv::GraphicsContext Ctx;
768 GLuint Texture =
static_cast<GLuint
>(myTexture);
769 GLCheck(glDeleteTextures(1, &Texture));
771 myNeedTextureUpdate =
false;
772 myNeedArrayUpdate =
false;
void CreateMaskFromColor(Color ColorKey, Uint8 Alpha=0)
Create transparency mask from a specified colorkey.
void SetSmooth(bool Smooth)
Enable or disable image smooth filter.
Image()
Default constructor.
const Color & GetPixel(unsigned int X, unsigned int Y) const
Get a pixel from the image.
Base class for every resource that needs to notify dependent classes about its destruction.
static const Color Black
Black predefined color.
Simple wrapper for sf::Window that allows easy 2D rendering.
T Right
Right coordinate of the rectangle.
Image is the low-level class for loading and manipulating images.
bool IsSmooth() const
Tells whether the smooth filtering is enabled or not.
T GetHeight() const
Get the height of the rectangle.
void SetPixel(unsigned int X, unsigned int Y, const Color &Col)
Change the color of a pixel.
bool CopyScreen(RenderWindow &Window, const IntRect &SourceRect=IntRect(0, 0, 0, 0))
Create the image from the current contents of the given window.
bool LoadFromFile(const std::string &Filename)
Load the image from a file.
bool SaveToFile(const std::string &Filename) const
Save the content of the image to a file.
const Uint8 * GetPixelsPtr() const
Get a read-only pointer to the array of pixels (RGBA 8 bits integers components) Array size is GetWid...
unsigned int GetWidth() const
Get the width of the rendering region of the window.
unsigned int GetWidth() const
Return the width of the image.
bool SetActive(bool Active=true) const
Activate of deactivate the window as the current target for rendering.
Window is a rendering window ; it can create a new window or connect to an existing one...
void Bind() const
Bind the image for rendering.
bool LoadFromMemory(const char *Data, std::size_t SizeInBytes)
Load the image from a file in memory.
Image & operator=(const Image &Other)
Assignment operator.
static unsigned int GetValidTextureSize(unsigned int Size)
Get a valid texture size according to hardware support.
Color is an utility class for manipulating 32-bits RGBA colors.
bool LoadFromPixels(unsigned int Width, unsigned int Height, const Uint8 *Data)
Load the image directly from an array of pixels.
T Bottom
Bottom coordinate of the rectangle.
unsigned int GetHeight() const
Get the height of the rendering region of the window.
T GetWidth() const
Get the width of the rectangle.
FloatRect GetTexCoords(const IntRect &Rect) const
Convert a subrect expressed in pixels, into float texture coordinates.
void Copy(const Image &Source, unsigned int DestX, unsigned int DestY, const IntRect &SourceRect=IntRect(0, 0, 0, 0), bool ApplyAlpha=false)
Copy pixels from another image onto this one.
bool Create(unsigned int Width, unsigned int Height, Color Col=Color(0, 0, 0, 255))
Create an empty image.
unsigned int GetHeight() const
Return the height of the image.
T Top
Top coordinate of the rectangle.
T Left
Left coordinate of the rectangle.