EDIT: This bit of code does the copying.
using UnityEngine;
using System.Collections;
using System.IO;
public class CameraBlitBehaviour : MonoBehaviour {
WebCamTexture cam_texture;
int requestedTextureWidth, requestedTextureHeight;
bool appPaused = false;
//GameObject camFeedPlane2;
// Use this for initialization
void Start () {
requestedTextureWidth = 400;
requestedTextureHeight = 400;
WebCamDevice[] cam_devices = WebCamTexture.devices;
if(Application.platform == RuntimePlatform.IPhonePlayer)
{
gameObject.transform.localScale = new Vector3(1f*gameObject.transform.localScale.x, 1f, -1f*gameObject.transform.localScale.z);
cam_texture = new WebCamTexture(cam_devices[0].name, 640, 480, 30);
}
else
{
cam_texture = new WebCamTexture(cam_devices[0].name, 480, 640, 30);
}
//if(Application.HasUserAuthorization(UserAuthorization.WebCam))
{
if(cam_texture != null)
cam_texture.Play();
}
}
void OnGUI()
{
if(GUI.Button(new Rect(110,10, 100, 60), new GUIContent("capture")))
{
cam_texture.Pause();
BlitImage();
}
int wOffset = cam_texture.width - requestedTextureWidth;
int hOffset = cam_texture.height - requestedTextureHeight;
GUI.Label(new Rect(10,500,600,50), Application.persistentDataPath);
GUI.Label(new Rect(10,550,600,50), "sourceTex"+ cam_texture.width+" "+ cam_texture.height);
GUI.Label(new Rect(10,600,600,50), ""+wOffset/2+" "+hOffset/2);
}
/// <summary>
/// Blits the image. Well it's not exactly blitting as Unity doesnt provide a blitting interface. The Graphics.Blit blits the texture
/// to a render texture which is of not much help. We copy the image to a temporary buffer and then copy it to a Texture2D.
/// </summary>
void BlitImage()
{
int width = cam_texture.width;
int height = cam_texture.height;
//assuming the source texture is always greater than the destination texture
int wOffset = width - requestedTextureWidth;
int hOffset = height - requestedTextureHeight;
Debug.Log(width+" : "+height);
Debug.Log(cam_texture.requestedWidth+" : "+cam_texture.requestedHeight);
BlitImageAndroid(wOffset/2, hOffset/2);
BlitImageIOS(wOffset/2,hOffset/2);
}
/// <summary>
/// In this function we blit the texture using the calculated texture dimensions.
/// </summary>
/// <param name='widthOffset'>
/// Width offset.
/// </param>
/// <param name='heightOffset'>
/// Height offset.
/// </param>
void BlitImageAndroid(int widthOffset, int heightOffset)
{
Debug.Log("starting blitting from"+widthOffset+" :"+(requestedTextureHeight + heightOffset));
Texture2D bufferTexture = new Texture2D(requestedTextureWidth, requestedTextureHeight, TextureFormat.ARGB32, false);
//This is the android version of blitting
for(int x = (requestedTextureWidth + widthOffset), destY = 0; x > widthOffset; x--, destY++)
{
for(int y = heightOffset, destX=0; y < (requestedTextureHeight+ heightOffset); y++, destX++)
{
bufferTexture.SetPixel(destX,destY, cam_texture.GetPixel(x,y));
}
}
bufferTexture.Apply();
byte[] pngData = bufferTexture.EncodeToPNG();
if(File.Exists(Application.persistentDataPath+"/capturedPic.png"))
{
File.Delete(Application.persistentDataPath+"/capturedPic.png");
}
File.WriteAllBytes(Application.persistentDataPath+"/capturedPic.png",pngData);
Debug.Log("pic saved to"+Application.persistentDataPath);
}
/// <summary>
/// In this function we flip the pixels around and copy them as we are flipping the texture using localscale,
/// hence the destX start from requestedTextureHeight and copies until 0
/// </summary>
/// <param name='widthOffset'>
/// Width offset.
/// </param>
/// <param name='heightOffset'>
/// Height offset.
/// </param>
void BlitImageIOS(int widthOffset, int heightOffset)
{
Texture2D destTexture = new Texture2D(requestedTextureWidth, requestedTextureHeight, TextureFormat.ARGB32, false);
for(int x = (requestedTextureWidth + widthOffset), destY = 0; x > widthOffset; x--, destY++)
{
for(int y = heightOffset, destX=requestedTextureHeight; y < (requestedTextureHeight+ heightOffset); y++, destX--)
{
destTexture.SetPixel(destX,destY, cam_texture.GetPixel(x,y));
}
}
destTexture.Apply();
byte[] pngData = destTexture.EncodeToPNG();
if(File.Exists(Application.persistentDataPath+"/capturedPic2.png"))
{
File.Delete(Application.persistentDataPath+"/capturedPic2.png");
}
File.WriteAllBytes(Application.persistentDataPath+"/capturedPic2.png",pngData);
Debug.Log("pic saved to"+Application.persistentDataPath);
}
/// <summary>
/// Blits the image using the GetPixels function.
/// </summary>
/// <param name='widthOffset'>
/// Width offset.
/// </param>
/// <param name='heightOffset'>
/// Height offset.
/// </param>
void BlitImageNormal(int widthOffset, int heightOffset)
{
Texture2D destTexture = new Texture2D(requestedTextureWidth, requestedTextureHeight, TextureFormat.ARGB32, false);
Color[] textureData = cam_texture.GetPixels(widthOffset, heightOffset,requestedTextureWidth,requestedTextureHeight);
destTexture.SetPixels(textureData);
destTexture.Apply();
byte[] pngData = destTexture.EncodeToPNG();
if(File.Exists(Application.persistentDataPath+"/capturedPic3.png"))
{
File.Delete(Application.persistentDataPath+"/capturedPic3.png");
}
File.WriteAllBytes(Application.persistentDataPath+"/capturedPic3.png",pngData);
Debug.Log("pic saved to"+Application.persistentDataPath);
}
// Update is called once per frame
void Update () {
if(!appPaused)
{
if (cam_texture != null && cam_texture.didUpdateThisFrame)
{
gameObject.renderer.material.mainTexture = cam_texture;
}
}
}
public void StopCamera()
{
cam_texture.Stop();
}
void OnApplicationPause(bool pause)
{
if(pause)
{
appPaused = true;
cam_texture.Stop();
}
else
{
appPaused = false;
if(cam_texture != null)
cam_texture.Play();
}
}
}