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

Author Topic: Is it possible to save the image of a rendertexture to a file? [SFML2.0]  (Read 16220 times)

0 Members and 1 Guest are viewing this topic.

xNidhogg

  • Newbie
  • *
  • Posts: 9
    • View Profile
I can't find anything in the documentation and googling brings results for 1.6 or older 2.0 builds but not from 2.0 RC. Also if it's possible is there a resolution limit?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
rtexture.getTexture().copyToImage().saveToFile("toto.png");
Laurent Gomila - SFML developer

xNidhogg

  • Newbie
  • *
  • Posts: 9
    • View Profile
rtexture.getTexture().copyToImage().saveToFile("toto.png");

how...how did I miss .getTexture()? My eyes are trolling me sometimes...thank you for such a lightning-fast reply! Really having a good time with this framework.

xNidhogg

  • Newbie
  • *
  • Posts: 9
    • View Profile
It seems I do have to follow up on this question again as I can't seem to get it working.
During runtime when I press my button to save the screenshot I get this printed to stderr:
Quote from: stderr date=1337350721
radeon: The kernel rejected CS, see dmesg for more information

Here are last few lines of dmesg:
Quote from: dmesg
[ 1493.222196] [drm:radeon_cs_parser_relocs] *ERROR* gem object lookup failed 0x13
[ 1493.222201] [drm:radeon_cs_ioctl] *ERROR* Failed to parse relocation -2!

Here is the drawing code (I hid the drawing code to the vertexarray because it doesn't even work simplified like this):
template<class TMap, class TCell, class TCodes>
void TileMap<TMap, TCell, TCodes>::SaveToFile(sf::String const& path)
{
  using namespace sf;
  RenderTexture texture;
  int mapWidth(GetMapWidth());
  int mapHeight(GetMapHeight());

  texture.create(mapWidth * _tileWidth, mapHeight * _tileHeight);
  texture.clear(Color::Black);
  VertexArray vMap(Quads, mapWidth * mapHeight * 4);
 /* actual drawing code hidden because irrelevant */
  texture.draw(vMap, &_tileSheet);
  texture.display();
  texture.getTexture().copyToImage().saveToFile(path);
}

It creates the file and it has the right dimensions, but it's transparent and not black as expected (in this simplified version).
« Last Edit: May 21, 2012, 08:30:45 am by Laurent »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Can you write a complete and minimal code that reproduces the problem, so that I can try it?
Laurent Gomila - SFML developer

xNidhogg

  • Newbie
  • *
  • Posts: 9
    • View Profile
Can you write a complete and minimal code that reproduces the problem, so that I can try it?

Actually no. When I do it like this:

int main(int argc, char** argv)
{
  using namespace sf;
  RenderTexture texture;
  texture.create(800,600);
  texture.clear(Color::Black);
  texture.display();
  texture.getTexture().copyToImage().saveToFile("test.png");
}
 

it works, but when I copy&paste this function body to my function where it should happen I get the error again.

For additional information that may help: I am calling the function in my update loop, which means the last command sent to my usual RenderWindow was renderWindow.display(). Maybe there is some internal context switching problems or something where the opengl of the normal RenderWindow and RenderTexture clashes internally? Is that possible?
« Last Edit: May 21, 2012, 08:48:32 am by Laurent »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Quote
Maybe there is some internal context switching problems or something where the opengl of the normal RenderWindow and RenderTexture clashes internally? Is that possible?
No, especially if you don't use threads.

If the complete and minimal code works, then there's something wrong in your code that we can't see here. We won't be able to help you, you have to do some debugging and find what makes your code different from the minimal one that works.
Laurent Gomila - SFML developer

xNidhogg

  • Newbie
  • *
  • Posts: 9
    • View Profile
I managed to produce a minimal example of non working code

#include <SFML/Graphics.hpp>
int main(int argc, char** argv)
{
  using namespace sf;
  RenderWindow rWindow(sf::VideoMode(640,480), "Test",
                       Style::Close | Style::Titlebar, ContextSettings());

  rWindow.clear(Color::Blue);
  rWindow.display();

  RenderTexture rTexture;
  rTexture.create(800,600);
  rTexture.clear(Color::Black);
  rTexture.display();
  rTexture.getTexture().copyToImage().saveToFile("test.png");

  rWindow.clear(Color::Blue);
  rWindow.display();
}
 

This reflects the order of stuff that goes on and produces the error.

It creates test.png but it's transparent (and now with garbage data in it) see here: http://imgur.com/uuNSs

I'm running Ubuntu 12.04 LTS 64-Bit with opensource radeon drivers on a ATI Radeon Mobility HD 5650

I'm compiling 64 bit binaries with gcc-4.7 and -std=C++11
« Last Edit: May 21, 2012, 09:06:34 am by Laurent »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Thanks, I'll test that as soon as I can :)

By the way, can you use the [code=cpp] tag so that I don't have to edit all your posts?
Laurent Gomila - SFML developer

xNidhogg

  • Newbie
  • *
  • Posts: 9
    • View Profile
Thanks, I'll test that as soon as I can :)

By the way, can you use the [code=cpp] tag so that I don't have to edit all your posts?

yes, sure I just noticed that you did that =p

I think it may be because of the two different sizes of the output? Thing is I really need two different sizes for this. Scratch that, tested and still failed.
« Last Edit: May 21, 2012, 09:20:49 am by xNidhogg »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
You can try something: replace the RenderWindow with this:
sf::Context context;
If it still produces the error, try to move it after "rtexture.create".

(this is just some debug stuff to help me figure out what happens)
Laurent Gomila - SFML developer

xNidhogg

  • Newbie
  • *
  • Posts: 9
    • View Profile
You can try something: replace the RenderWindow with this:
sf::Context context;
If it still produces the error, try to move it after "rtexture.create".

(this is just some debug stuff to help me figure out what happens)

int main(int argc, char** argv)
{
  using namespace sf;
  /*
  RenderWindow rWindow(sf::VideoMode(640,480), "Test",
                       Style::Close | Style::Titlebar, ContextSettings());

  rWindow.clear(Color::Blue);
  rWindow.display();
  */


  Context context;
  RenderTexture rTexture;  
  rTexture.create(800,600);
  rTexture.clear(Color::Black);
  rTexture.display();
  rTexture.getTexture().copyToImage().saveToFile("test.png");

  /*
  rWindow.clear(Color::Blue);
  rWindow.display();
  */

}
 

Causes screen to flicker black, locks up OS and ultimately forces me to restart (complete crash and unresponsive).

int main(int argc, char** argv)
{
  using namespace sf;
  /*
  RenderWindow rWindow(sf::VideoMode(640,480), "Test",
                       Style::Close | Style::Titlebar, ContextSettings());

  rWindow.clear(Color::Blue);
  rWindow.display();
  */


  RenderTexture rTexture;
  Context context;
  rTexture.create(800,600);
  rTexture.clear(Color::Black);
  rTexture.display();
  rTexture.getTexture().copyToImage().saveToFile("test.png");

  /*
  rWindow.clear(Color::Blue);
  rWindow.display();
  */

}
 

Works as expected.

#include <SFML/Graphics.hpp>
int main(int argc, char** argv)
{
  using namespace sf;
  RenderWindow rWindow(sf::VideoMode(640,480), "Test",
                       Style::Close | Style::Titlebar, ContextSettings());

  rWindow.clear(Color::Blue);
  rWindow.display();


  RenderTexture rTexture;
  Context context;
  rTexture.create(800,600);
  rTexture.clear(Color::Black);
  rTexture.display();
  rTexture.getTexture().copyToImage().saveToFile("test.png");


  rWindow.clear(Color::Blue);
  rWindow.display();
}
 

Testing this one now, wrote this before testing it so be back in a sec if it crashes.

Seems to work this way. No crashes, no errors. Testing it with my actual code now.

Strange, getting flash&crash in actual code again.
« Last Edit: May 21, 2012, 09:57:21 am by xNidhogg »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Are your graphics drivers up to date?
Laurent Gomila - SFML developer

xNidhogg

  • Newbie
  • *
  • Posts: 9
    • View Profile
#include <SFML/Graphics.hpp>
int main(int argc, char** argv)
{
  using namespace sf;
  RenderWindow rWindow(sf::VideoMode(640,480), "Test",
                       Style::Close | Style::Titlebar, ContextSettings());

  for(int i = 0; i < 2; ++i)
  {
    rWindow.clear(Color::Blue);
    rWindow.display();

    RenderTexture rTexture;
    Context context;
    rTexture.create(800,600);
    rTexture.clear(Color::Red);
    rTexture.display();
    rTexture.getTexture().copyToImage().saveToFile("test.png");

    rWindow.clear(Color::Blue);
    rWindow.display();
  }
}
 

Cause flicker & crash in a minimal case. Produces transparent png of the right size.

I'm using the open source ATI drivers (propietary doesn't allow 3 monitors) and according to my package manager it is up 2 date.

I have another linux + windows machine with a propietary Nvidia driver. I can test the code there but I don't have access to it for atleast 7 more hours so I would need to report back then.

I understand if you can't support the opensource ones and would probably just disable screenshot function under linux if it other wise would work.
« Last Edit: May 21, 2012, 10:12:31 am by xNidhogg »

xNidhogg

  • Newbie
  • *
  • Posts: 9
    • View Profile
Here's the promised update: It works on my Linux 64-bit with propietary Nvidia drivers and Windows with Nvidia.

So I guess it's a bug with the opensource drivers, I can live with that.

Thank you very much Laurent for the fast support. It really shows how dedicated you are and it amazes me that you find the time helping so many people in between coding.