SFML community forums

General => Feature requests => Topic started by: dk123 on December 31, 2018, 03:57:49 am

Title: sf Image resize
Post by: dk123 on December 31, 2018, 03:57:49 am
Hi, I feel that resizing an image is a concept that's very common. It would be nice if sf Image, and sf Texture could have functions to actually resize its pixel dimensions.

I've seen threads that recommend pasting things into a rendertexture, window, etc. through a sprite, but this feels way too cumbersome for a concept that should just be simple.

With SFML's first S being 'simple', I feel this would be not only a very useful, but fitting small extension.
Title: Re: sf Image resize
Post by: Laurent on December 31, 2018, 08:51:47 am
Why would you like to resize a texture or an image? What's your use case?
Title: Re: sf Image resize
Post by: dk123 on December 31, 2018, 04:50:13 pm
Use cases

a. Saving original textures / images to image files of different size

Is probably the largest use case.

I might say have a screenshot of the screen I want to scale down to a different size upon saving.
Or I might be using the image as a canvas for drawing and may want to resize the canvas at some point.

b. Loading original textures / image to textures of different size

Would be another that comes up often.
For example I might have a button with different images for untouched, touched, clicked.
I'd want to keep each image at the same display size when rendering,
but rather than calculating how much scaling would be needed each user interaction,
it would just make calculations easier if I could resize and cache the images on load,
and then use uniform scale factors for all states.

In terms of API

.resize( width, height )

would be simplest.

If one wants to become pedantic, or SFML wants to add options

.resize( width, height, stretch_method: linear, etc. )

would be nice, but not necessary.
Title: Re: sf Image resize
Post by: Hapax on January 02, 2019, 03:17:03 pm
a. Saving original textures / images to image files of different size

Is probably the largest use case.

I might say have a screenshot of the screen I want to scale down to a different size upon saving.
Or I might be using the image as a canvas for drawing and may want to resize the canvas at some point.
Two approaches are:
1) draw to a render texture, then converting that texture to an image and saving that (as you already touched on but seems simple enough; it uses OpenGL to do the work),
2) resize the pixel data within an image
The second is image manipulation and seems "out-of-scope" for SFML, especially as it can be done manually or requires specific approaches.

b. Loading original textures / image to textures of different size
It's usually better to resize the images before saving to the file and then you can just use the image as is.
Of course, if you need a scaleable image, as you mentioned, too many different image files might be needed.

For example I might have a button with different images for untouched, touched, clicked.
I'd want to keep each image at the same display size when rendering,
but rather than calculating how much scaling would be needed each user interaction,
it would just make calculations easier if I could resize and cache the images on load,
and then use uniform scale factors for all states.
This is a bit of a strange example.
To fit an image (or part of an image) in a specified rectangular area, use an sf::Rectangle, set its position and size, then set its texture rectangle to cover the part of the texture needed. No scaling necessary.


Since "simple" is the thing you focus on the most, I presume you find it the most important.
So, here's a simple example of how to resize an image:
void resizeImage(const sf::Image& originalImage, sf::Image& resizedImage)
{
    const sf::Vector2u originalImageSize{ originalImage.getSize() };
    const sf::Vector2u resizedImageSize{ resizedImage.getSize() };
    for (unsigned int y{ 0u }; y < resizedImageSize.y; ++y)
    {
        for (unsigned int x{ 0u }; x < resizedImageSize.x; ++x)
        {
            unsigned int origX{ static_cast<unsigned int>(static_cast<double>(x) / resizedImageSize.x * originalImageSize.x) };
            unsigned int origY{ static_cast<unsigned int>(static_cast<double>(y) / resizedImageSize.y * originalImageSize.y) };
            resizedImage.setPixel(x, y, originalImage.getPixel(origX, origY));
        }
    }
}
This fills the second image (at its current size) with the first image, stretched or squashed to fit the second. So, you can just create (or re-create) the second image to whatever size you need before using the function.

EDIT: added simple image resizing example
Title: Re: sf Image resize
Post by: dk123 on January 02, 2019, 08:44:02 pm
Hi Hapax,

Thanks for the code and comments! I'd just like to clarify my rationale though.
I'm not necessarily stating I don't know how to get the specific examples done in SFML,
it's that I feel that the resize function seems simple, conained, and common enough that I'm suugesting
an addition to the API.

As you've just shown with the code example, this does seem like a function
that could be given to users with a single function.
Title: Re: sf Image resize
Post by: Nexus on January 02, 2019, 09:12:25 pm
Since resizing comes at a loss of data (except for exact multiples), I'm not sure if it's such a often-needed functionality -- at least on the sf::Image level.

As already suggested, I would render an sf::Sprite using the desired image to a sf::RenderTexture. This also allows you to specify a lot of other options, and chances are that you need related features like image cropping.
Title: Re: sf Image resize
Post by: FRex on January 04, 2019, 10:08:03 pm
It would be kinda convenient but then people would come out of the woodwork with all the different ways of scaling/resampling images up and down when they aren't powers-of-two scales and other software image features or even software drawing.

You're better off writing a few helper functions on your own or using a proper software image library if you really need that, especially since this isn't something where SFML prevents you from doing your own thing easily and in fully portable code and isn't that common or straight forward.