SFML community forums

Help => Graphics => Topic started by: Richy19 on April 23, 2011, 07:48:54 pm

Title: Downsizing image without quality loss
Post by: Richy19 on April 23, 2011, 07:48:54 pm
Just wondering if theres anything in SFML that allows you to downsize without loosing quality.
In VS/XNA i use the generate mipmaps option in the content importer:

(http://img194.imageshack.us/img194/3139/unledgx.png)

But i didnt  know if SFML had anything like it
Title: Downsizing image without quality loss
Post by: Laurent on April 23, 2011, 10:35:32 pm
Quote
Just wondering if theres anything in SFML that allows you to downsize without loosing quality.

That doesn't make sense, downsizing always looses quality since you have less pixels. The only thing that you can choose is how to loose the quality (ie. which scale filter to apply). In SFML you can play with Image::SetSmooth to modify that. With smoothing on, you get bilinear filtering. With smoothing off, you get nearest pixel filtering.

Quote
In VS/XNA i use the generate mipmaps option in the content importer:

Generating mipmaps doesn't help, the important thing is (again) what filter you apply, either when you generate the mipmap levels, or when you perform texture lookup.
Title: Downsizing image without quality loss
Post by: ndrsbhm on July 06, 2011, 07:30:30 pm
Downsizing doesn't use mipmaps. (Edit: Nah, it does...) You need to zoom the view to use them. Here is a small test I made, using SFML2:

Code: [Select]

#include <SFML/Graphics.hpp>
#include <SFML/OpenGL.hpp>
#define GL_GENERATE_MIPMAP 0x8191
#include <math.h>
#define USEMIPMAPS true

inline float fRand() { return rand() / float(RAND_MAX + 1); };
inline float fRand(float upperLimit) { return fRand() * upperLimit; };
inline unsigned int uRand(unsigned int upperLimit) { return unsigned int(fRand() * upperLimit); };

int main()
{
sf::ContextSettings cs;
cs.AntialiasingLevel = 8;
sf::RenderWindow App(sf::VideoMode(800, 800), "SFML window", sf::Style::Default, cs);

sf::Image image;
image.Create(1600, 1600);
image.SetSmooth(true);
if(USEMIPMAPS)
{
 image.Bind();
 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    }
   
for(int y=0; y<1600; y++)
{
   for(int x=0; x<1600; x++)
   {
       int c = uRand(256);
       image.SetPixel(x, y, sf::Color(c,c,c));
   }
    }

sf::Sprite sprite;
sprite.SetImage(image);
sprite.SetOrigin(image.GetWidth()/2, image.GetHeight()/2);
sprite.SetPosition(App.GetWidth()/2, App.GetHeight()/2);

int counter = 0;
sf::View view;
    view.SetCenter(App.GetWidth()/2, App.GetHeight()/2);

while (App.IsOpened())
{
sf::Event Event;
while (App.PollEvent(Event))
{
if (Event.Type == sf::Event::Closed)
App.Close();
if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape))
App.Close();
}

      counter++;
      double scale = (sin(double(counter*0.01))+1)*6400+200;
      view.SetSize(scale, scale);
      App.SetView(view);

App.Clear();
App.Draw(sprite);

App.Display();
sf::Sleep(20);

}
return EXIT_SUCCESS;
}


I get this error: "An internal OpenGL call failed in Renderer.cpp (104) : GL_INVALID_ENUM, an unacceptable value has been specified for an enumerated argument". But it works and it looks much better. Try setting USEMIPMAPS to false to see the difference.

If you really need to downsize a sprite, you probably must create your mipmaps yourself and switch the sprite's image when appropriate.

Edit: I don't know why I didn't get the same results in the first place. Now I can change the lines

Code: [Select]
double scale = (sin(double(counter*0.01))+1)*6400+200;
view.SetSize(scale, scale);

to
Code: [Select]
double scale = (sin(double(counter*0.01))+1)*4;
sprite.SetScale(sf::Vector2f(scale, scale));

and it still works.
Title: Downsizing image without quality loss
Post by: Richy19 on August 18, 2011, 10:32:06 pm
Sorry to bump this but I only just saw that last comment.
Would it be really necessarily to do all of that with the view?

Could it not just be done by creating the images 2,3 or 5 times bigger than needed and then just downsizing the sprite?