- Home /
EncodeToPng and WebCamTexture PROBLEM
Hello everyone I have a problem. My code saves or encodes Png photo very badly. It saves photo but it's messed up for some reason. Tested on Android and on PC but its the same all time. Here is what I get:
Can Someone Help Me? THANKS IN ADVANCE.
Here is my Code:
using UnityEngine;
using System.Collections;
using System.IO;
public class AndroidCamera : MonoBehaviour
{
public Vector2 photoSize;
public int photoFrames;
public GUIStyle guiStyle;
private WebCamTexture webCamTexture;
private string camName;
void Start ()
{
WebCamDevice[] devices = WebCamTexture.devices;
webCamTexture = new WebCamTexture(GetCamera(), (int)photoSize.x, (int)photoSize.y, photoFrames);
renderer.material.mainTexture = webCamTexture;
webCamTexture.Play();
Screen.orientation = ScreenOrientation.Portrait;
}
void TakePhoto()
{
Texture2D takenPhoto = new Texture2D((int)photoSize.x, (int)photoSize.y, TextureFormat.ARGB32, false);
Color[] texData = webCamTexture.GetPixels();
takenPhoto.SetPixels(texData);
takenPhoto.Apply();
byte[] photoData = takenPhoto.EncodeToPNG();
Destroy(takenPhoto);
//if(File.Exists(Application.persistentDataPath + "/AvatarPhoto.png"))
//{
// File.Delete(Application.persistentDataPath + "/AvatarPhoto.png");
//}
File.WriteAllBytes(Application.dataPath + "/AvatarPhoto.png", photoData);
}
void OnGUI()
{
if(GUI.Button(new Rect(0, 10, Screen.width, Screen.height / 5), "TAKE PHOTO!", guiStyle))
{
TakePhoto();
}
}
}
Answer by ImranZahid · Sep 28, 2014 at 08:02 AM
Make sure you put the right image size, try this
Texture2D takenPhoto = new Texture2D((int)renderer.material.mainTexture.width, (int)renderer.material.mainTexture.height);
It worked for me!
+1
Exactly. The result you see is clearly a wrong image size. Read the docs carefully:
The requested width, height and framerate specified by the parameters may not be supported by the chosen camera. In such cases, the closest available values will be used
So you can't rely on the size you've setup. So the image data you actually get from your webcam might be smaller / larger than your target image. That's why you have interleaved lines because either the line is too long an propergates onto the next one, shifting eferything towards the end, or the source line is too short and the target is filled partially from the next line.
Since we can kind of "see" you about 4 times i would say your actual width might be at 4 times larger. It could also be an interference size which produces this 4-images view. To be on the safe side you should use the width and height of the original webcam texture like ImranZahid did.
edit
I've shifted your image(s) back by simply enlarging the width pixel by pixel. The image is correctly shown at a width of 640, so that was the actual image width. Since you "packed" the image into a 512x512 image we can't say much about the original height since the data has been truncated. It's most likely 640x480 so there are about 45k pixels missing (`640*480 - 512*512`)
Answer by Catlard · Sep 08, 2013 at 04:14 AM
I'm positive this is problem with not yielding -- it has to do with the computer attempting to perform large operations like WriteAllBytes, on line 39, all in one frame. What I would suggest is that you make TakePhoto an IEnumerator, and try yielding after that line and some of the other large operations in that vicinity. Remember that you can Yield return StartCoroutine("Somefunction") to yield until the end of a function, and yield return 0 to skip a frame. But I would just try yield return new WaitForSeconds(1) after a few of the lines, and see if that fixes it -- then start removing them. Let us know if that fixes it!
Answer by wonker21 · Sep 08, 2013 at 09:35 AM
Hello thanks for answer but it doesnt work for me (or i'm doing it wrong). Here is code the code:
IEnumerator TakePhoto()
{
webCamTexture.Pause();
yield return new WaitForSeconds(1.0f);
Texture2D takenPhoto = new Texture2D((int)photoSize.x, (int)photoSize.y, TextureFormat.ARGB32, false);
yield return new WaitForSeconds(1.0f);
Color[] texData = webCamTexture.GetPixels();
yield return new WaitForSeconds(1.0f);
takenPhoto.SetPixels(texData);
yield return new WaitForSeconds(1.0f);
takenPhoto.Apply();
yield return new WaitForSeconds(1.0f);
byte[] photoData = takenPhoto.EncodeToPNG();
yield return new WaitForSeconds(1.0f);
Destroy(takenPhoto);
yield return new WaitForSeconds(2.0f);
File.WriteAllBytes(Application.dataPath + "/AvatarPhoto.png", photoData);
yield return new WaitForSeconds(2.0f);
Debug.Log("Done");
yield return 0;
}
And Here is the Photo:
Btw i'm making 512x512 photos. $$anonymous$$aybe dimensions are bad.. :( I'm lost
Answer by dhurstdev · Jan 17, 2017 at 09:12 AM
Thx @ImranZahid!, I had a similar issue, but wasn't using the correct size, totally missed it here: http://answers.unity3d.com/questions/337530/how-to-save-a-snapshot-of-the-webcamtexture.html , though you both helped me finish this up... @wonker21 I would suggest removing the TextureFormat from your Texture2D declaration, and/or us TextureFormat.RGBA32, but I'm feeling like ImranZahid is right for your case too, where does photoSize come from? Try Grabbing the meshRenderer, material, mainTexture x & y:
MeshRenderer m = gameObject.GetComponent(); m.material.mainTexture.width & .height. GL