Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Downsizing image without quality loss  (Read 2274 times)

0 Members and 1 Guest are viewing this topic.

Richy19

  • Full Member
  • ***
  • Posts: 190
    • View Profile
Downsizing image without quality loss
« 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:



But i didnt  know if SFML had anything like it

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Downsizing image without quality loss
« Reply #1 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.
Laurent Gomila - SFML developer

ndrsbhm

  • Newbie
  • *
  • Posts: 1
    • View Profile
    • http://www.ndrsbhm.de
Downsizing image without quality loss
« Reply #2 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.

Richy19

  • Full Member
  • ***
  • Posts: 190
    • View Profile
Downsizing image without quality loss
« Reply #3 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?

 

anything