Xbox LIVE Indie Games
Sort Discussions: Previous Discussion Next Discussion
Page 1 of 1 (11 posts)

Here's code to capture screen on PC in XNA 4.0

Last post 3/29/2013 3:09 PM by Jakob Krarup. 10 replies.
  • 11/27/2010 11:42 PM

    Here's code to capture screen on PC in XNA 4.0

    I couldn't find this code for 4.0 anywhere, so here's what I came up with. I don't like making the texture, but it was the simplest way to go.This won't work on the phone (because of GetBackBufferData), but it works on PC.

    You should call this before the end of your Draw function, otherwise you may get a screen grab of the helpfully cleared screen after the swap.


    public static void Screenshot(GraphicsDevice device) 
        byte[] screenData; 
     
        screenData = new byte[device.PresentationParameters.BackBufferWidth * device.PresentationParameters.BackBufferHeight * 4]; 
     
        device.GetBackBufferData<byte>(screenData); 
     
        Texture2D t2d = new Texture2D(device, device.PresentationParameters.BackBufferWidth, device.PresentationParameters.BackBufferHeight, false, device.PresentationParameters.BackBufferFormat); 
     
        t2d.SetData<byte>(screenData); 
     
        int i = 0; 
        string name = "ScreenShot" + i.ToString() + ".png"
        while (File.Exists(name)) 
        { 
            i += 1; 
            name = "ScreenShot" + i.ToString() + ".png"
     
        } 
     
        Stream st = new FileStream(name, FileMode.Create); 
     
        t2d.SaveAsPng(st, t2d.Width, t2d.Height); 
     
        st.Close(); 
     
        t2d.Dispose(); 
     

    some search terms: screengrab screenshot screen capture screen shot screen grab

  • 11/30/2010 8:01 PM In reply to

    Re: Here's code to capture screen on PC in XNA 4.0

    Thank you this is really useful :)
  • 2/10/2012 3:16 AM In reply to

    Re: Here's code to capture screen on PC in XNA 4.0

    I get an error while using this code.

    XNA Framework Reach profile does not support GetBackBufferData.

    I took out
    device.GetBackBufferData<byte>(screenData)

    and tried to take a screen shot and it came up with nothing something was saved.

    Anyone have any ideas?

    Thanks a lot,

    Pete

    ::EDIT::
    I just figured it out. I had to change the game profile to use the HiDef to access the complete API.

    Right now I am not loading in any models, but when I take a screenshot I get a purple background instead of the blue that I have it set up as.

    Will this be fixed once I have a 3D model loaded in or is this another issue?

    Thanks again,

    Pete
  • 7/18/2012 4:15 PM In reply to

    Re: Here's code to capture screen on PC in XNA 4.0

    With the newest version of the XNA framework (4.0 Refresh) I'm getting a purple screen with the code posted above.  Here is an updated method that seems to be working for me

    public static void TakeScreenShot(GraphicsDevice device) 
            { 
                Color[] screenData = new Color[device.PresentationParameters.BackBufferWidth * 
                                               device.PresentationParameters.BackBufferHeight]; 
     
                RenderTarget2D screenShot = new RenderTarget2D(device, 
                    device.PresentationParameters.BackBufferWidth, 
                    device.PresentationParameters.BackBufferHeight); 
     
                device.SetRenderTarget(screenShot); 
     
                //Put your drawing method here.  Just copy and paste if from your game class/wherever  
                //you are performing drawing.  Alternatively, you can just pass in to this method whatever object is performing the drawing
     
                //In My case, I am using the GameStateManagement Sample,  
                //where all screens draw themselves.  So in my case this  
                //method is contained in the Screen Manager Class 
                Draw(); 
     
                device.SetRenderTarget(null); 
     
                int index = 0; 
                string name = "Screenshot" + index + ".png"
                while (File.Exists(name)) 
                { 
                    index++; 
                    name = "Screenshot" + index + ".jpg"
                } 
     
                using (FileStream stream = new FileStream(name, FileMode.Create)) 
                { 
                    screenShot.SaveAsJpeg(stream, screenShot.Width, screenShot.Height); 
                    screenShot.Dispose(); 
                } 
            } 

  • 1/4/2013 9:35 AM In reply to

    Re: Here's code to capture screen on PC in XNA 4.0

    Hey thankyou so much for giving a code sample since XNA 4.0 has updated, however I'm having trouble following what you are saying in regards to the Draw() method.

    Spoiler: I am new to XNA.  

    In my main Game1.cs class my Draw method has inside of it lines that use each of my various classes' individual draw 
    methods to populate the screen.  (i.e.  level.Draw(spriteBatch)   player.Draw(spriteBatch)  etc etc).

    I don't understand in my case what I should put where you have the large commented portion of your code, I have tried a few different things but unfortunately can't get it to compile.

     I know this post is old but it is the most recent one regarding a ScreenShot method for XNA.

     Thanks for your help, Bryan


  • 1/4/2013 12:14 PM In reply to

    Re: Here's code to capture screen on PC in XNA 4.0

    Bryan Curran:
    I don't understand in my case what I should put where you have the large commented portion of your code, I have tried a few different things but unfortunately can't get it to compile.
    What part of "put your drawing code here" don't you understand? Saying you can't get it to compile doesn't help us help you.
  • 1/4/2013 1:00 PM In reply to

    Re: Here's code to capture screen on PC in XNA 4.0

    I'm guessing Bryan is having trouble figuring out how the Game class' Draw() method, the  TakeScreenShot() method and his own objects' Draw() method fit together.
    Since the logical place (for me) to call TakeScreenShot() would be in the Game class' Draw() method, it would be necessary to pass the gameTime variable along as well so it can be used for Bryan's own objects' Draw().
    So I can understand why it would be difficult to merge the code for a beginning XNA coder :)

    Bryan, I've merged the Reach and HiDef screenshot code in a little GraphicsDevice extension method. I hope this makes it easier to make screenshots :)

    If you aren't familiar with extension methods, basically they add new functionality to existing classes - in this case adds two new methods to Microsoft's GraphicsDevice class.

    class diagram


    The class is here C# (right click > "save as..."), or ZIP

    To use it :
    1. add the GraphicsDeviceExtensions class to your project
    2. call the GraphicsDevice.PrepareScreenshot() before the spriteBatch.Begin()
    3. call the GraphicsDevice.SaveScreenshot() after spriteBatch.End()

      In the code sample below, the screenshot is prepared on line 9 and the screenshot is taken on line 33.

      1 bool doScreenshot = false;  //set this to true to perform screenshot 
      2  
      3 protected override void Draw(GameTime gameTime) 
      4
      5  
      6     //if necessary, we prepare for a screenshot  
      7     if (doScreenshot)  
      8     {  
      9         GraphicsDevice.PrepareScreenShot(); 
      10     } 
      11  
      12     //Clear graphicsdevice with blue background 
      13     GraphicsDevice.Clear(Color.Blue); 
      14  
      15     //begin drawing 
      16     spriteBatch.Begin(); 
      17  
      18     //write test string 
      19     spriteBatch.DrawString(_defaultFont, "Screenshot test! :)"new Vector2(100, 100), Color.Yellow); 
      20  
      21     //write whether we are running in HiDef or Reach graphics profile 
      22     spriteBatch.DrawString(_defaultFont, "Profile: " + graphics.GraphicsProfile, new Vector2(100, 200), Color.Yellow); 
      23  
      24     //call superclass' Draw() 
      25     base.Draw(gameTime); 
      26  
      27     //end drawing  
      28     spriteBatch.End(); 
      29  
      30     //if necessary, we save the image to a screenshot 
      31     if (doScreenshot) 
      32     { 
      33         GraphicsDevice.SaveScreenshot(); 
      34         doScreenshot = false
      35     } 
      36


      Let me know if this helps you or you need more help :)

      Kind regards - Jakob

    • 3/23/2013 7:07 PM In reply to

      Re: Here's code to capture screen on PC in XNA 4.0

      This code works great to take screenshots for me in both Reach and HiDef mode in XNA 4.0. Thank you for developing and posting it.
    • 3/23/2013 8:15 PM In reply to

      Re: Here's code to capture screen on PC in XNA 4.0

      Great to know it proved useful :-)
    • 3/29/2013 1:58 PM In reply to

      Re: Here's code to capture screen on PC in XNA 4.0

      Very cool.  Thanks for the code.

      -Chris
      Flattened Pixel
    • 3/29/2013 3:09 PM In reply to

      Re: Here's code to capture screen on PC in XNA 4.0

      you're welcome :)
      ...and cool games you've made - I like the look of Denizen's Den!

      Kind regards - Jakob
    Page 1 of 1 (11 posts) Previous Discussion Next Discussion