00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00024
00026
00028 #include <SFML/Graphics/Image.hpp>
00029 #include <SFML/Graphics/ImageLoader.hpp>
00030 #include <SFML/Graphics/GraphicsDevice.hpp>
00031 #include <SFML/Graphics/OpenGL.hpp>
00032 #include <SFML/Window/OpenGLCaps.hpp>
00033 #include <algorithm>
00034 #include <iostream>
00035 #include <vector>
00036
00037
00041 sfImage::sfImage() :
00042 myWidth (0),
00043 myHeight (0),
00044 myTextureWidth (0),
00045 myTextureHeight(0),
00046 myGLTexture (0)
00047 {
00048
00049 }
00050
00051
00055 sfImage::sfImage(const sfImage& Copy) :
00056 myWidth (Copy.myWidth),
00057 myHeight (Copy.myHeight),
00058 myTextureWidth (Copy.myTextureWidth),
00059 myTextureHeight(Copy.myTextureHeight),
00060 myPixels (Copy.myPixels),
00061 myGLTexture (0)
00062 {
00063 CreateTexture();
00064 }
00065
00066
00070 sfImage::sfImage(unsigned int Width, unsigned int Height, const sfColor& Color) :
00071 myWidth (0),
00072 myHeight (0),
00073 myTextureWidth (0),
00074 myTextureHeight(0),
00075 myGLTexture (0)
00076 {
00077 Create(Width, Height, Color);
00078 }
00079
00080
00084 sfImage::sfImage(unsigned int Width, unsigned int Height, const void* Data) :
00085 myWidth (0),
00086 myHeight (0),
00087 myTextureWidth (0),
00088 myTextureHeight(0),
00089 myGLTexture (0)
00090 {
00091 LoadFromMemory(Width, Height, Data);
00092 }
00093
00094
00098 sfImage::~sfImage()
00099 {
00100
00101 DestroyVideoResources();
00102 }
00103
00104
00108 bool sfImage::LoadFromFile(const std::string& Filename)
00109 {
00110
00111 bool Success = sf_private::sfImageLoader::GetInstance().LoadImageFromFile(Filename, myPixels, myWidth, myHeight);
00112
00113 if (Success)
00114 {
00115
00116 CreateTexture();
00117
00118 return true;
00119 }
00120 else
00121 {
00122
00123 myWidth = 0;
00124 myHeight = 0;
00125 myTextureWidth = 0;
00126 myTextureHeight = 0;
00127 myGLTexture = 0;
00128 myPixels.clear();
00129
00130 return false;
00131 }
00132 }
00133
00134
00138 bool sfImage::SaveToFile(const std::string& Filename) const
00139 {
00140
00141 return sf_private::sfImageLoader::GetInstance().SaveImageToFile(Filename, myPixels, myWidth, myHeight);
00142 }
00143
00144
00148 void sfImage::Create(unsigned int Width, unsigned int Height, const sfColor& Color)
00149 {
00150
00151 myWidth = Width;
00152 myHeight = Height;
00153
00154
00155 myPixels.clear();
00156 myPixels.resize(Width * Height, Color.ToRGBA());
00157
00158
00159 CreateTexture();
00160 }
00161
00162
00166 void sfImage::LoadFromMemory(unsigned int Width, unsigned int Height, const void* Data)
00167 {
00168 if (Data)
00169 {
00170
00171 myWidth = Width;
00172 myHeight = Height;
00173
00174
00175 const sfUint32* Ptr = reinterpret_cast<const sfUint32*>(Data);
00176 myPixels.assign(Ptr, Ptr + Width * Height);
00177
00178
00179 CreateTexture();
00180 }
00181 else
00182 {
00183
00184 Create(Width, Height, sfColor(255, 255, 255, 255));
00185 }
00186 }
00187
00188
00192 void sfImage::CreateMaskFromColor(const sfColor& ColorKey)
00193 {
00194
00195 sfUint32 OldColor = ColorKey.ToRGBA();
00196 sfUint32 NewColor = OldColor & 0x00FFFFFF;
00197
00198
00199 std::replace(myPixels.begin(), myPixels.end(), OldColor, NewColor);
00200
00201
00202 Update();
00203 }
00204
00205
00210 void sfImage::Resize(unsigned int Width, unsigned int Height, const sfColor& Color)
00211 {
00212
00213 if ((Width == 0) || (Height == 0))
00214 {
00215 std::cerr << "Invalid new size for image (width = " << Width << ", height = " << Height << ")" << std::endl;
00216 return;
00217 }
00218
00219
00220 std::vector<sfUint32> Pixels(Width * Height, Color.ToRGBA());
00221
00222
00223 for (unsigned int i = 0; i < std::min(Width, myWidth); ++i)
00224 for (unsigned int j = 0; j < std::min(Height, myHeight); ++j)
00225 Pixels[i + j * Width] = myPixels[i + j * myWidth];
00226 Pixels.swap(myPixels);
00227
00228
00229 myWidth = Width;
00230 myHeight = Height;
00231
00232
00233 CreateTexture();
00234 }
00235
00236
00241 void sfImage::SetPixel(unsigned int X, unsigned int Y, const sfColor& Color)
00242 {
00243
00244 if ((X >= myWidth) || (Y >= myHeight))
00245 {
00246 std::cerr << "Cannot set pixel (" << X << "," << Y << ") for image "
00247 << "(width = " << myWidth << ", height = " << myHeight << ")" << std::endl;
00248 return;
00249 }
00250
00251 myPixels[X + Y * myWidth] = Color.ToRGBA();
00252 }
00253
00254
00258 sfColor sfImage::GetPixel(unsigned int X, unsigned int Y) const
00259 {
00260
00261 if ((X >= myWidth) || (Y >= myHeight))
00262 {
00263 std::cerr << "Cannot get pixel (" << X << "," << Y << ") for image "
00264 << "(width = " << myWidth << ", height = " << myHeight << ")" << std::endl;
00265 return sfColor::Black;
00266 }
00267
00268 return sfColor(myPixels[X + Y * myWidth]);
00269 }
00270
00271
00277 const sfUint32* sfImage::GetPixelsPtr() const
00278 {
00279 if (!myPixels.empty())
00280 {
00281 return &myPixels[0];
00282 }
00283 else
00284 {
00285 std::cerr << "Trying to access the pixels of an empty image" << std::endl;
00286 return NULL;
00287 }
00288 }
00289
00290
00294 void sfImage::Update()
00295 {
00296 if (myGLTexture && myWidth && myHeight && !myPixels.empty())
00297 {
00298
00299 sfGLCheck(glBindTexture(GL_TEXTURE_2D, myGLTexture));
00300 sfGLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myWidth, myHeight, GL_RGBA, GL_UNSIGNED_BYTE, &myPixels[0]));
00301 sfGLCheck(glBindTexture(GL_TEXTURE_2D, 0));
00302 }
00303 }
00304
00305
00309 void sfImage::Bind() const
00310 {
00311
00312 if (myGLTexture)
00313 sfGLCheck(glBindTexture(GL_TEXTURE_2D, myGLTexture));
00314 }
00315
00316
00320 void sfImage::SetSmooth(bool Smooth) const
00321 {
00322 if (myGLTexture)
00323 {
00324
00325 sfGLCheck(glBindTexture(GL_TEXTURE_2D, myGLTexture));
00326 sfGLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Smooth ? GL_LINEAR : GL_NEAREST));
00327 sfGLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Smooth ? GL_LINEAR : GL_NEAREST));
00328 sfGLCheck(glBindTexture(GL_TEXTURE_2D, 0));
00329 }
00330 }
00331
00332
00337 void sfImage::SetRepeat(bool Repeat) const
00338 {
00339 if (myGLTexture)
00340 {
00341
00342 sfGLCheck(glBindTexture(GL_TEXTURE_2D, myGLTexture));
00343 sfGLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, Repeat ? GL_REPEAT : GL_CLAMP));
00344 sfGLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, Repeat ? GL_REPEAT : GL_CLAMP));
00345 sfGLCheck(glBindTexture(GL_TEXTURE_2D, 0));
00346 }
00347 }
00348
00349
00353 unsigned int sfImage::GetWidth() const
00354 {
00355 return myWidth;
00356 }
00357
00358
00362 unsigned int sfImage::GetHeight() const
00363 {
00364 return myHeight;
00365 }
00366
00367
00372 sfFloatRect sfImage::GetTexCoords(const sfIntRect& Rect) const
00373 {
00374 return sfFloatRect((Rect.Left + 0.5f) / myTextureWidth,
00375 (Rect.Top + 0.5f) / myTextureHeight,
00376 (Rect.Right - 0.5f) / myTextureWidth,
00377 (Rect.Bottom - 0.5f) / myTextureHeight);
00378 }
00379
00380
00384 unsigned int sfImage::GetValidTextureSize(unsigned int Size)
00385 {
00386 if (sfOpenGLCaps::CheckExtension("GL_ARB_texture_non_power_of_two"))
00387 {
00388
00389 return Size;
00390 }
00391 else
00392 {
00393
00394 unsigned int PowerOfTwo = 1;
00395 while (PowerOfTwo < Size)
00396 PowerOfTwo *= 2;
00397
00398 return PowerOfTwo;
00399 }
00400 }
00401
00402
00406 sfImage& sfImage::operator =(const sfImage& Other)
00407 {
00408 sfImage Temp(Other);
00409
00410 std::swap(myWidth, Temp.myWidth);
00411 std::swap(myHeight, Temp.myHeight);
00412 std::swap(myTextureWidth, Temp.myTextureWidth);
00413 std::swap(myTextureHeight, Temp.myTextureHeight);
00414 std::swap(myGLTexture, Temp.myGLTexture);
00415 myPixels.swap(Temp.myPixels);
00416
00417 return *this;
00418 }
00419
00420
00424 void sfImage::CreateTexture()
00425 {
00426
00427 if (!myWidth || !myHeight || myPixels.empty())
00428 return;
00429
00430
00431 if (myGLTexture)
00432 {
00433 sfGLCheck(glDeleteTextures(1, &myGLTexture));
00434 myGLTexture = 0;
00435 }
00436
00437
00438 myTextureWidth = GetValidTextureSize(myWidth);
00439 myTextureHeight = GetValidTextureSize(myHeight);
00440
00441
00442 sfGLCheck(glGenTextures(1, &myGLTexture));
00443 sfGLCheck(glBindTexture(GL_TEXTURE_2D, myGLTexture));
00444 sfGLCheck(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, myTextureWidth, myTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
00445
00446
00447 sfGLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
00448 sfGLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT));
00449 sfGLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
00450 sfGLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
00451
00452
00453 Update();
00454 }
00455
00456
00460 void sfImage::DestroyVideoResources()
00461 {
00462
00463 if (myGLTexture)
00464 {
00465 sfGLCheck(glDeleteTextures(1, &myGLTexture));
00466 myGLTexture = 0;
00467 }
00468 }