SFML Image.saveToFile access violation - c++

So I am working on a program that generates images with shapes of random selected colors. and I want to save an image of the output so I can use shaders on the image like blurring, as well as have an output file for any purpose. Here is my main loop for the window.
while (window.isOpen())
{
Event event;
while (window.pollEvent(event))
{
if (event.type == Event::Closed)
window.close();
}
window.clear(Color::Black);
for (int i = 0; i < rectangles.size(); i++)
window.draw(rectangles[i]);
Texture outputTexture;
outputTexture.create(width, height);
outputTexture.update(window);
Image output;
output.create(width, height);
output = outputTexture.copyToImage();
output.saveToFile("output.png");
Sprite sprite;
sprite.setTexture(outputTexture);
window.clear();
window.draw(sprite);
window.display();
}
I have tested this with the sprite and the window draws the sprite correctly. However I am getting an error here
output.saveToFile("output.png");
Exception thrown at 0x00007FF8D1527190 (sfml-graphics-2.dll) in name.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
I can't seem to figure out the issue, I really need to be able to save images to a file. Thanks all for help

I came across the same problem, the solution was to change "sfml-xxx.lib" to "sfml-xxx-d.lib" in "Additional Dependencies" property in Visual Studio.

Related

Changing the world origin in C++ SFML

I've recently gotten into SFML and as an exercise to get more comfortable (and have fun), I started translating some Coding Challenges done by Daniel Shiffman on his Youtube channel, The Coding Train. Upon attempting to translate a star field effect in SFML, I started searching for the right function in SFML that would change the world origin from the top-left of the screen to the center. The closest thing I found to this was the setOrigin function, but that only works for sprites and not the whole window/screen. If you didn't understand my description of this function, it would be the equivalent of the translate(x, y) function in Processing. Any help would be appreciated.
You need to use sf::View
https://www.sfml-dev.org/tutorials/2.5/graphics-view.php
Here is a small implementation example:
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(300, 300), "");
sf::Vector2u size = window.getSize();
sf::View view(sf::Vector2f(0, 0), sf::Vector2f(size.x, size.y));
window.setView(view);
sf::CircleShape cir(10);
cir.setOrigin(10, 10);
while(window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
if (event.type == sf::Event::Closed)
window.close();
window.clear();
window.draw(cir);
window.display();
}
return 0;
}

SFML Anti-Aliasing - lines look dotted and moving objects smear

Several months ago I made a Fourier Transform program using SFML 2.0. I used anti-aliasing level 8 and it looked perfectly fine. Just recently however (not quite sure when the problem began since I have not touched it in a while), it seems to have broken.
Whenever I draw a line it looks dotted and whenever something moves, it flashes between two states and it doesn't completely clear after calling window.clear(). It's not just that program however. Anytime I use any level of anti-aliasing greater than 0, even in SFML 2.5.1, the same problem occurs.
Here is the some sample code which does not work as it should on my computer:
#include <SFML/Graphics.hpp>
int main()
{
sf::Vertex line[2] =
{
sf::Vertex(sf::Vector2f(0, 0)),
sf::Vertex(sf::Vector2f(800, 0))
};
sf::ContextSettings settings;
settings.antialiasingLevel = 8.0;
sf::RenderWindow window(sf::VideoMode(800, 600), "Test", sf::Style::Close, settings);
window.setVerticalSyncEnabled(true);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
line[1].position.y += 1.0;
window.clear();
window.draw(line, 2, sf::Lines);
window.display();
}
return 0;
}
When the line finishes sweeping, it looks
like this
As this used to not be a problem, I don't think it's SFML's fault. I am using Windows 10 and my computer uses an integrated Intel UHD Graphics 620 graphics card, both of which have not changed since before the problem started happening. On a side note, I have not noticed any other programs on my computer break, only the ones I made.

Why the texture appears only in the first quadrant

What's wrong with this code using SFML?
In the code below, I have this image (1000x1000) and I want to show it in a window (500x500) using sf::RenderTexture.
However, only part of the image appears in the first quadrant:
#include <SFML/Graphics.hpp>
using namespace sf;
int main()
{
RenderWindow window({500, 500}, "SFML Views", Style::Close);
View camera;
camera.setSize(Vector2f(window.getSize()));
Texture background;
background.loadFromFile("numeros.png");
Sprite numeros (background);
RenderTexture texture;
texture.create(window.getSize().x, window.getSize().y);
Sprite content;
content.setTexture(texture.getTexture());
texture.draw(numeros);
texture.display();
while (window.isOpen())
{
for (Event event; window.pollEvent(event);)
if (event.type == Event::Closed)
window.close();
window.clear();
window.setView(camera);
window.draw(content);
window.display();
}
return EXIT_SUCCESS;
}
As far as I can understand, the code should generate the original image (1000x1000) automatically adjusted to 500x500.
Could anyone tell you what is wrong?
You're facing, in fact, two distinct problems:
First one:
As far as I can understand, the code should generate the original
image (1000x1000) automatically adjusted to 500x500.
This is not really true. SFML handles the sprites with the real size of the texture. If your image is 1000x1000, but you want representing it as 500x500, you should assign the texture to a sprite, as you do:
Sprite numeros(background);
and then scale this sprite to fit in a 500x500 window, this is:
numeros.setScale(0.5, 0.5);
With this change you should view the whole image, but...
Second one:
You're messing with the view of the window. If we check SFML documentation, we can see that sf::View expects:
A sf::FloatRect: this is, a coordinate (x,y) - in this case the top-left corner - and a size(width, height)
or
Two sf::Vector2f: one corresponding to the coordinates of the center and the other corresponding to the size of the view.
Assuming you want to use the second one, you're missing the first parameter, the center coordinates, but this is not really necessary. If you simply don't apply the view, the image should be shown in the whole window.
So you simply need to remove:
window.setView(camera);
The code I've tried:
int main()
{
RenderWindow window({ 500, 500 }, "SFML Views", Style::Close);
View camera;
camera.setSize(Vector2f(window.getSize()));
Texture background;
background.loadFromFile("numeros.png");
Sprite numeros(background);
numeros.setScale(0.5, 0.5); // <-- Add this
RenderTexture texture;
texture.create(window.getSize().x, window.getSize().y);
Sprite content;
content.setTexture(texture.getTexture());
texture.draw(numeros);
texture.display();
while (window.isOpen())
{
for (Event event; window.pollEvent(event);)
if (event.type == Event::Closed)
window.close();
window.clear();
//window.setView(camera); <-- Remove this
window.draw(content);
window.display();
}
return EXIT_SUCCESS;
}
And my result:
Just to add another option to #alseether 's excellent response, I realized that the whole issue consisted of that bad View initialization.
This way you can also set the size of the view = to the size of the background image (1000,1000) and finally set the center of the view to the windows's upper left corner.
As the view is larger than the window size (500,500) it will automatically be adjusted to this new size.
In short, the section to be changed would be:
View camera;
camera.setSize(Vector2f(background.getSize().x, background.getSize().y));
camera.setCenter(Vector2f(window.getSize()));

SFML graphics Draw Texture in Window- Black Screen

I just tried to write a chess engine, and what is important to me is that I get a nice visual representation of the game. I tried to implement the Code in a Visual Studio project - the problem is that the program only shows me a black screen instead of the texture I loaded.
My Code is the following:
#include <SFML/Graphics.hpp>
#include <time.h>
using namespace sf;
int main(){
RenderWindow window(VideoMode(1000, 1000), "MattseChess!");
Texture t1;
t1.loadFromFile("images/board.png");
Sprite s(t1);
while (window.isOpen())
{
Event e;
while (window.pollEvent(e)) {
if (e.type == Event::Closed)
window.close();
//Draw
window.clear();
window.draw(s);
window.display();
}
}
return 0;
}
Do you have any idea of what I did wrong?
Make sure to put your drawing code outside your event loop. Otherwise you're only drawing whenever there's some event happening (such as cursor movement).
That code works. I am pretty sure you did not put your board.png into the images directory in your execution path.
Make sure this image is available:
t1.loadFromFile("images/board.png");

Slight pause/delay when moving

I've been working on this little framework for my game today and realized that moving delays when moving around. I've used SFML before and have had the same problem, but never bothered to fix it. I'm wondering if anyone has had a similar issue and has found a solution.
Here's an example of the code which is giving me the slight pause in movement:
int main(){
sf::RenderWindow window (sf::VideoMode(640, 480), "Window");
//window.setVerticalSyncEnabled(true);
sf::Texture tex;
tex.loadFromFile("Assets/Textures/player.png");
sf::Sprite s;
s.setTexture(tex);
while (window.isOpen()){
sf::Event event;
while (window.pollEvent(event)){
if (event.type == sf::Event::Closed)
window.close();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
s.move(0.01f, 0.0f);
}
window.clear();
window.draw(s);
window.display();
}
}
The delay/pause/whatever I'm experience is very slight but I can notice it and it's really bugging me. Just seeing the slight break in movement when none of the values alter makes my programming mind extremely sad.
The keyboard input will have a delay just like if you hold a key in Microsoft Word. To get around this, you could create a variable and set it to true when a key is pressed.
int main(){
sf::RenderWindow window (sf::VideoMode(640, 480), "Window");
//window.setVerticalSyncEnabled(true);
sf::Texture tex;
tex.loadFromFile("Assets/Textures/player.png");
sf::Sprite s;
s.setTexture(tex);
bool moving = false;
while (window.isOpen()){
sf::Event event;
while (window.pollEvent(event)){
if (event.type == sf::Event::Closed)
window.close();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
moving = true;
}
if (moving) {
s.move(0.01f, 0.0f);
}
window.clear();
window.draw(s);
window.display();
}
}
This sounds like a framerate/timing issue. One frame in a 60hz game is 16.666.. milliseconds, but on Windows at least, the system clock only has a resolution of 1ms, so your delays are going to be either 16ms or 17ms. This inaccuracy results in occasional jitter as some frames are skipped (or rendered twice, in your case, giving the appearance of a short pause) even if vsync is enabled.
If you can get manual control of frame timing, e.g. by disabling sf::RenderWindow's framerate limit and calling sf::sleep directly, one solution is to delay each frame in the sequence: 17, 17, 16, 17, 17, 16, so that the long-term average is closer to 60hz, minimizing jitter.
I have never used SFML so I can't provide any code but I hope this points you in the right direction.
You should also ensure that your monitor's refresh rate is the same as your game's framerate. SFML might already be doing this automatically.