- Home /
How to save a picture (take screenshot) from a camera in game?
it is possible for a camera to take a picture and save it as jpg? I could not find on google or unity.
interesting article about 3 ways of doing it: http://ralphbarbagallo.com/2012/04/09/3-ways-to-capture-a-screenshot-in-unity3d/
By the way, asset store has now a script to do it and store it in iOS and Android gallery. Great responsive developer behind it, I've used it and approved: http://u3d.as/content/ryansoft/gallery-screenshot/4pz
Hi. Is it possible to make a screenshot with a transparent background? Thank you. Wewerak
Yes, you can use the way as answered by $$anonymous$$ate-O, which is a good and easy solution to implement. But if you want to see your photo in device native gallery then you have to transfer that screenshot into native gallery, for that you can write native code (java for android & objective-c/swift for ios) to do that, which is little complicated.
If you don't have time to explore too much then you can choose use any plugin, Capture and Save - its good plugin that will also fulfil your need, it may help you.
Answer by jashan · Jul 21, 2010 at 11:12 AM
Yes, it is possible. And there's even a couple of different approaches you could use:
There's a script for taking screenshots on the Unifycommunity Wiki: TakeScreenshot
The method used to do this is: Application.CaptureScreenshot, [EDIT: Which also has a parameter superSize for high resolution screenshots using an integer multiple of the current screen resolution]
There's also an approach to do [-high resolution-] screenshots [EDIT: with any arbitrary resolution]. I have a script which is based on the script posted in Submitting featured content. This will take a screenshot and store it to disk when you press the key "k" (you could change the key by changing the code). You have to attach the script to a camera for it to work:
using UnityEngine;
using System.Collections;
public class HiResScreenShots : MonoBehaviour {
public int resWidth = 2550;
public int resHeight = 3300;
private bool takeHiResShot = false;
public static string ScreenShotName(int width, int height) {
return string.Format("{0}/screenshots/screen_{1}x{2}_{3}.png",
Application.dataPath,
width, height,
System.DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"));
}
public void TakeHiResShot() {
takeHiResShot = true;
}
void LateUpdate() {
takeHiResShot |= Input.GetKeyDown("k");
if (takeHiResShot) {
RenderTexture rt = new RenderTexture(resWidth, resHeight, 24);
camera.targetTexture = rt;
Texture2D screenShot = new Texture2D(resWidth, resHeight, TextureFormat.RGB24, false);
camera.Render();
RenderTexture.active = rt;
screenShot.ReadPixels(new Rect(0, 0, resWidth, resHeight), 0, 0);
camera.targetTexture = null;
RenderTexture.active = null; // JC: added to avoid errors
Destroy(rt);
byte[] bytes = screenShot.EncodeToPNG();
string filename = ScreenShotName(resWidth, resHeight);
System.IO.File.WriteAllBytes(filename, bytes);
Debug.Log(string.Format("Took screenshot to: {0}", filename));
takeHiResShot = false;
}
}
}
It also shouldn't be too hard to post those screenshots to combine this with the example code in the WWWForm-documentation to post those screenshots to a server.
I dont now if this is a common issue, but i had to use the function in the LateUpdate call, some of my objects, which i create with Graphics.Draw$$anonymous$$esh() were not on the screenshot.
Good point - I've changed the code to use LateUpdate() ins$$anonymous$$d of Update() to be on the safe side.
@Cawas: Not sure if the parameter "superSize : int = 0" was added later to Application.CaptureScreenshot, or whether I missed it when I wrote the original answer. In most cases, using CaptureScreenshot is probably the best way to do it. An advantage of the other script may be that you can use any resolution, not just multiples of the current screen resolution. I'll edit the wording to reflect that change.
the supersize parameter in Application.CaptureScreenshot is not really useful because it only enlarges the pixels - it does not provide higher quality. So this provided script ist excellent for taking screenshots for resolutions that don't fit on my own monitor. Thanks you! One disadvantage: The UI Layer is not on the screenshot. Any idea how to also add the UI Layer this way?
Put the UI on the same layer as the camera (search for something called "Layer" in the top of the Inspector of your UI, set it to 0, it should work. Sorry for the late answer
Answer by toddmoore · Jan 09, 2017 at 05:05 PM
Thanks for all the great code samples! I made an implementation that has pretty good performance, supports multiple image formats (jpeg, png, raw, and ppm), and you can configure almost everything from within the editor such as capture size, image format, output folder, etc. It also supports continuous capture by pressing 'v' or single image capture with 's'. If you want to create a video I suggest using the ppm format as it's just as fast as raw and ffmpeg can be used to generate the video from all the images saved. Cheers, Todd
using UnityEngine;
using System.Collections;
using System.IO;
// Screen Recorder will save individual images of active scene in any resolution and of a specific image format
// including raw, jpg, png, and ppm. Raw and PPM are the fastest image formats for saving.
//
// You can compile these images into a video using ffmpeg:
// ffmpeg -i screen_3840x2160_%d.ppm -y test.avi
public class ScreenRecorder : MonoBehaviour
{
// 4k = 3840 x 2160 1080p = 1920 x 1080
public int captureWidth = 1920;
public int captureHeight = 1080;
// optional game object to hide during screenshots (usually your scene canvas hud)
public GameObject hideGameObject;
// optimize for many screenshots will not destroy any objects so future screenshots will be fast
public bool optimizeForManyScreenshots = true;
// configure with raw, jpg, png, or ppm (simple raw format)
public enum Format { RAW, JPG, PNG, PPM };
public Format format = Format.PPM;
// folder to write output (defaults to data path)
public string folder;
// private vars for screenshot
private Rect rect;
private RenderTexture renderTexture;
private Texture2D screenShot;
private int counter = 0; // image #
// commands
private bool captureScreenshot = false;
private bool captureVideo = false;
// create a unique filename using a one-up variable
private string uniqueFilename(int width, int height)
{
// if folder not specified by now use a good default
if (folder == null || folder.Length == 0)
{
folder = Application.dataPath;
if (Application.isEditor)
{
// put screenshots in folder above asset path so unity doesn't index the files
var stringPath = folder + "/..";
folder = Path.GetFullPath(stringPath);
}
folder += "/screenshots";
// make sure directoroy exists
System.IO.Directory.CreateDirectory(folder);
// count number of files of specified format in folder
string mask = string.Format("screen_{0}x{1}*.{2}", width, height, format.ToString().ToLower());
counter = Directory.GetFiles(folder, mask, SearchOption.TopDirectoryOnly).Length;
}
// use width, height, and counter for unique file name
var filename = string.Format("{0}/screen_{1}x{2}_{3}.{4}", folder, width, height, counter, format.ToString().ToLower());
// up counter for next call
++counter;
// return unique filename
return filename;
}
public void CaptureScreenshot()
{
captureScreenshot = true;
}
void Update()
{
// check keyboard 'k' for one time screenshot capture and holding down 'v' for continious screenshots
captureScreenshot |= Input.GetKeyDown("k");
captureVideo = Input.GetKey("v");
if (captureScreenshot || captureVideo)
{
captureScreenshot = false;
// hide optional game object if set
if (hideGameObject != null) hideGameObject.SetActive(false);
// create screenshot objects if needed
if (renderTexture == null)
{
// creates off-screen render texture that can rendered into
rect = new Rect(0, 0, captureWidth, captureHeight);
renderTexture = new RenderTexture(captureWidth, captureHeight, 24);
screenShot = new Texture2D(captureWidth, captureHeight, TextureFormat.RGB24, false);
}
// get main camera and manually render scene into rt
Camera camera = this.GetComponent<Camera>(); // NOTE: added because there was no reference to camera in original script; must add this script to Camera
camera.targetTexture = renderTexture;
camera.Render();
// read pixels will read from the currently active render texture so make our offscreen
// render texture active and then read the pixels
RenderTexture.active = renderTexture;
screenShot.ReadPixels(rect, 0, 0);
// reset active camera texture and render texture
camera.targetTexture = null;
RenderTexture.active = null;
// get our unique filename
string filename = uniqueFilename((int) rect.width, (int) rect.height);
// pull in our file header/data bytes for the specified image format (has to be done from main thread)
byte[] fileHeader = null;
byte[] fileData = null;
if (format == Format.RAW)
{
fileData = screenShot.GetRawTextureData();
}
else if (format == Format.PNG)
{
fileData = screenShot.EncodeToPNG();
}
else if (format == Format.JPG)
{
fileData = screenShot.EncodeToJPG();
}
else // ppm
{
// create a file header for ppm formatted file
string headerStr = string.Format("P6\n{0} {1}\n255\n", rect.width, rect.height);
fileHeader = System.Text.Encoding.ASCII.GetBytes(headerStr);
fileData = screenShot.GetRawTextureData();
}
// create new thread to save the image to file (only operation that can be done in background)
new System.Threading.Thread(() =>
{
// create file and write optional header with image bytes
var f = System.IO.File.Create(filename);
if (fileHeader != null) f.Write(fileHeader, 0, fileHeader.Length);
f.Write(fileData, 0, fileData.Length);
f.Close();
Debug.Log(string.Format("Wrote screenshot {0} of size {1}", filename, fileData.Length));
}).Start();
// unhide optional game object if set
if (hideGameObject != null) hideGameObject.SetActive(true);
// cleanup if needed
if (optimizeForManyScreenshots == false)
{
Destroy(renderTexture);
renderTexture = null;
screenShot = null;
}
}
}
}
Thanks Todd, this is perfect! The only thing that I should add there to use it in my program is property "screenshotPath" (because I would like to save screenshot with another filename). string filename = screenshotPath.Length == 0 ? uniqueFilename((int)rect.width, (int)rect.height) : screenshotPath; ... and comment out keyboard shortcuts. Great component.
The script works great when using it in the editor, but it doesn't save the screen shot anywhere when I test it on the device.
Problem was line 46, its was defaulting to the .dataPath, replaced it with .persistentDataPath.
Hello Joorst, Can you help me with the line of code because i changed to persistentdataPath but still the screenshot is not showing when i m running on the standalone application.
thanks for the bit of code! reusing it for something else but the head start is useful !
@toddmoore Hi there, how can I when pressing for example „h“ take a screenshot, and continuously keep taking screenshots until I hit „h“ again! I would very much appreciate it if you could help me on this one. Cheers
In case, someone needs the answer to my question, here you go:
if( Input.Get$$anonymous$$eyDown("k") )
captureVideo = !captureVideo ;
if (captureScreenshot || captureVideo)
{
// ....
}
This doesn't capture every frame. Can you please help me this?
how can i save screenshot in android phone and see in native android galelry
Answer by Mate-O · May 20, 2013 at 08:49 AM
Create a render texture.
Apply it on the camera.
Reference the camera in the script
Set the render texture as active RenderTexture.active
Create a Texture2D to which you dump the current RenderTexture
Put back the original RenderTexture.active back. Things to worry about: PNG files store alpha channels as well as any other color information. Sometimes some object might not appear because they simply have that information on it. Most of the time the Texture2D that you need has to be simply of type RGB24, not ARGB32.
Here is a code snippet that should help you:
using UnityEngine;
using System.Collections;
using System;
public class ScreenCapture : MonoBehaviour
{
public RenderTexture overviewTexture;
GameObject OVcamera;
public string path = "";
void Start()
{
OVcamera = GameObject.FindGameObjectWithTag("OverviewCamera");
}
void LateUpdate()
{
if (Input.GetKeyDown("f9"))
{
StartCoroutine(TakeScreenShot());
}
}
// return file name
string fileName(int width, int height)
{
return string.Format("screen_{0}x{1}_{2}.png",
width, height,
System.DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"));
}
public IEnumerator TakeScreenShot()
{
yield return new WaitForEndOfFrame();
Camera camOV = OVcamera.camera;
RenderTexture currentRT = RenderTexture.active;
RenderTexture.active = camOV.targetTexture;
camOV.Render();
Texture2D imageOverview = new Texture2D(camOV.targetTexture.width, camOV.targetTexture.height, TextureFormat.RGB24, false);
imageOverview.ReadPixels(new Rect(0, 0, camOV.targetTexture.width, camOV.targetTexture.height), 0, 0);
imageOverview.Apply();
RenderTexture.active = currentRT;
// Encode texture into PNG
byte[] bytes = imageOverview.EncodeToPNG();
// save in memory
string filename = fileName(Convert.ToInt32(imageOverview.width), Convert.ToInt32(imageOverview.height));
path = Application.persistentDataPath + "/Snapshots/" + filename;
System.IO.File.WriteAllBytes(path, bytes);
}
}
Answer by Julian-Glenn · Jul 21, 2010 at 08:58 AM
You could try this:
http://unity3d.com/support/documentation/ScriptReference/WWWForm.html
Which from the link in this Answer: http://answers.unity3d.com/questions/292/is-is-possible-to-output-screenshots-from-unity
Answer by OmerEizenberg · May 07, 2015 at 09:42 AM
if you want to save to a android device try this :
public static void SaveTextureToFile( Texture2D texture, string fileName)
{
byte[] bytes=texture.EncodeToPNG();
if (Application.platform != RuntimePlatform.Android)
File.WriteAllBytes (fileName + ".png", bytes);
else {
Debug.Log ("Android save file. path = " + Application.persistentDataPath + "/" + fileName + ".png");
File.WriteAllBytes (Application.persistentDataPath + "/" + fileName + ".png", bytes);
}
}
a little present which i have worked on for about a day :P
Your answer
Follow this Question
Related Questions
I need to take (save) a screenshot from a camera other than the main one. How would I do this? 0 Answers
Take screenshot of pixels OUTSIDE the game window? 0 Answers
Create a break screen effect 0 Answers
capture a screen shot and show in the album folder 1 Answer
Taking a screenshot of the current screen and displaying that as a texture? 1 Answer