it is possible for a camera to take a picture and save it as jpg? I could not find on google or unity.
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.
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
{0} {1}
255
", 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;
}
}
}
}
- 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);
}
}
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
May be this will help someone. Here it is, follow this steps;
1.) Go to Edit → Project setting → Player → Other Setting → Bundle Identifier. In that you can type the name company name and the product name like this “com.your_company_name.your_product_name”.
2.) Go to Edit → Project setting → Player → Other Setting → Write Access → External(SD Card). That will create a new folder in your android device.
3.) Now the path in your device is Android → Data → com.your_company_name.your_product_name → files.
4.) Create a class for take a screenshot and drag that into your maincamera.
using UnityEngine;
using System.Collections;
public class Capture : MonoBehaviour
{
// Store more screenshots...
private int Screen_Shot_Count = 0;
// Screenshot taking by touch the button.
public GUITexture Capture_Model;
void Update()
{
if (Input.touches.Length > 0)
// Finger hit the button position.
if(Capture_Model.HitTest (Input.GetTouch(0).position))
{
if (Input.GetTouch(0).phase == TouchPhase.Began)
{
// Screenshot name.
string Screen_Shot_File_Name;
do
{
// Increament the screenshot count.
Screen_Shot_Count++;
// Save the screenshot name as Screenshot_1.png, Screenshot_2.png, ...
Screen_Shot_File_Name = "Screenshot_" + Screen_Shot_Count + ".png";
}
while (System.IO.File.Exists(Screen_Shot_File_Name));
// Taking Screenshot.
Application.CaptureScreenshot(Screen_Shot_File_Name);
}
}
}
}
This script will help you to take a screenshot by using button.
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
Inside the editor only
This answer is for the Game view, and GUI specifically. If you want to take a screenshot from a specific camera you’ll need to disable other cameras first.
I made that small script that takes a screenshot of the Game view, which includes uGUI with a Canvas in Screen Space - Overlay mode. Since my game was a 2D game almost entirely composed of UI, it was necessary for me to use this, or I had to switch my camera to Screen Space - Camera just for the RenderTexture-based screenshot (could be automated though, if anyone interested in an alternative method).
using UnityEngine;
using UnityEditor;
using System;
using System.Collections;
using System.Reflection;
public static class EditorScreenshot
{
const string screenshotFolderPath = "Screenshots";
static int nextScreenshotIndex = 0;
[MenuItem("Tools/Screenshot/Take Screenshot _F11")]
static void TakeScreenshot()
{
// get name of current focused window, which should be " (UnityEditor.GameView)" if it is a Game view
string focusedWindowName = EditorWindow.focusedWindow.ToString();
if (!focusedWindowName.Contains("UnityEditor.GameView")) {
// since no Game view is focused right now, focus on any Game view, or create one if needed
Type gameViewType = Type.GetType("UnityEditor.GameView,UnityEditor");
EditorWindow.GetWindow(gameViewType);
}
string path = string.Format("{0}/screen_{1:00}.png", screenshotFolderPath, nextScreenshotIndex);
Application.CaptureScreenshot(path);
Debug.LogFormat("Screenshot recorded in {0}", path);
++nextScreenshotIndex;
}
[MenuItem("Tools/Screenshot/Reset screenshot count")]
static void ResetCount()
{
nextScreenshotIndex = 0;
}
}
For now, it’s just a clumsy editor menu item but I will probably turn it into a full editor window later. When I take care of that, I’ll put it on my blog and post a link to the updated version here (and show the main changes in the answer too).
Explanations
The trick here is that you need to have your Game view focused to take the screenshot (even if it is a visible pane, you would need to click on it). Else all screenshots are ignored but the last, which will be taken next time to click on the Game view. So instead, I check if any Game view is focused, and if not I seek any existing Game view or create a new one if needed using EditorWindow.GetWindow
(or its variant GetWindowWithRect
). GetWindow()
will also automatically focus on the found / created window, so I can take the screenshot. Next time the existing game view will be taken. Note that in practice, you probably want to open the Game view yourself since you want to see what you are actually going to capture, but the script is still useful just for the focus part.
In order to retrieve the internal class GameView
I had to use Reflection, hence the GetType
.
Finally, I used a rough count increment to name screenshots and added a method to reset the counter. You may consider using System.DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss")
instead or just allow custom naming in your editor window.
Note that all screenshots are taken into a Screenshots folder at the root project. This can be changed but will still result in a path inside the project, which should be ignored by your version control system. To write a file somewhere else on your system, consider Write methods as showed in other answers. However, since CaptureScreenshot
does output a file by itself, you’ll need to read it back first (or Copy it directly somewhere else).
I also tried to use GameView’s private field s_LastFocusedGameView
to get the last focused game view if you are using several ones, but it didn’t work well. But at least with the focusedWindow check you will be sure that the focused game view will be used for the screenshot even if there are other game views.
If you are still interested in using s_LastFocusedGameView
, here is the (non-working) code:
// Tried getting the last focused window, but does not always work (even for focused window!)
EditorWindow lastFocusedGameView = (EditorWindow) gameViewType.GetField("s_LastFocusedGameView", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);
if (lastFocusedGameView != null) {
lastFocusedGameView.Focus();
} else {
// no Game view created since editor launch, create one
Type gameViewType = Type.GetType("UnityEditor.GameView,UnityEditor");
EditorWindow.GetWindow(gameViewType);
}
im very new to unity and i Had trouble saving images to a path… so after a few hours of playing around i come up with this.
using UnityEngine.UI;
public InputField NameA;
public void TakeScreenShot()
{
Application.CaptureScreenshot("screenshot" + NameA + ".png")
}
works perfect for me to save multiple screenshots without overwriting old ones(if you save screenshot with the same name it will be over written).
now i just need to make a function that pulls the image to the app when requested or saves the image to the photo gallery.
hope this helps someone out a little.
We made a plugin which is compatible on iOS and Android , easy to use unified API and battle tested!
Hi. Is it possible to make a screenshot with a transparent background?
Thank you. Wewerak
Use this if you want to capture screen shots of game to upload to Google Play or Store.
Add an empty object in scene and add this script as a component.
Generate a prefab if you want to use in multiple scenes.
Open the scene and run it. Pause the game when you want to capture the screen.
Add the prefab into the hierarchy and tick the " clicked " in the script;
Resume the game ( Un - pause ) - Now the frames will be captured and will be in your Games Main project folder.
Caution : Don’t Accidentally delete project files while removing unwanted screen shots.
Adjust the number of frames to capture as you need in the prefab.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TakeScreenshot : MonoBehaviour
{
public bool clicked = false;
int counter = 0;
private void Update()
{
if (clicked && counter < 2)
{
TakeAShot();
}
}
public void TakeAShot()
{
StartCoroutine("CaptureIt");
counter++;
}
IEnumerator CaptureIt()
{
string timeStamp = System.DateTime.Now.ToString("dd-MM-yyyy-HH-mm-ss" + counter);
string fileName = "Screenshot" + timeStamp + ".png";
string pathToSave = fileName;
ScreenCapture.CaptureScreenshot(pathToSave);
Debug.Log("Screen Captured");
yield return new WaitForEndOfFrame();
}
}
Hey folks.
I’ve tried to get this to work, I got the screenshots alright but they are solid black.
I don’t know how to show the stuff in my scene?
I want to save a few specific GameObjects on the scene if possible but I don’t know how?