Created
March 24, 2021 06:31
-
-
Save ratozumbi/5b835dee430a5ba9456ac93587190169 to your computer and use it in GitHub Desktop.
Save webcam with grayscale filter and alpha blend
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEngine.UI; | |
namespace Fotoprint | |
{ | |
public class PrintManager : MonoBehaviour | |
{ | |
private WebCamTexture webcam; | |
[SerializeField] | |
private RawImage cameraFrame; | |
[NonSerialized] | |
public bool useFrame = false; | |
[NonSerialized] | |
public bool grayScale = false; | |
public Sprite[] frame; | |
//todo: optimize | |
private void Update() | |
{ | |
if(webcam != null && !webcam.isPlaying) | |
{ | |
if (grayScale || useFrame) | |
{ | |
Texture2D snap = new Texture2D(webcam.width, webcam.height); | |
snap.SetPixels(webcam.GetPixels()); | |
snap.Apply(); | |
if (grayScale) | |
{ | |
snap = ToGrayScale(webcam.GetPixels()); | |
} | |
if (useFrame) | |
{ | |
foreach (Sprite image in frame) | |
{ | |
snap = AlphaBlend(snap, image.texture); | |
} | |
} | |
cameraFrame.texture = snap; | |
} | |
else | |
{ | |
cameraFrame.texture = webcam; | |
} | |
} | |
} | |
//Prints picture | |
public void Print() | |
{ | |
Texture2D snap = new Texture2D(webcam.width, webcam.height); | |
snap.SetPixels(webcam.GetPixels()); | |
snap.Apply(); | |
if (grayScale) | |
{ | |
snap = ToGrayScale(snap); | |
} | |
if (useFrame) | |
{ | |
foreach (Sprite image in frame) | |
{ | |
snap = AlphaBlend(snap, image.texture); | |
} | |
} | |
System.IO.File.WriteAllBytes(Application.persistentDataPath+"/foto.png", snap.EncodeToPNG()); | |
webcam.Stop(); | |
webcam = null; | |
} | |
public void OpenCamera() | |
{ | |
if (webcam == null) | |
{ | |
var devices = WebCamTexture.devices; | |
for( var i = 0 ; i < devices.Length ; i++ ) | |
{ | |
Debug.Log(devices[i].name); | |
} | |
webcam = new WebCamTexture(devices[0].name,1280,720); | |
cameraFrame.texture = webcam; | |
} | |
webcam.Play(); | |
} | |
public void PauseCamera() | |
{ | |
webcam.Pause(); | |
} | |
public Texture2D ToGrayScale(Texture2D texture) | |
{ | |
var bottomPixelData = texture.GetPixels(); | |
int count = bottomPixelData.Length; | |
var resultData = new Color[count]; | |
for(int i = 0; i < count; i++) | |
{ | |
Color bottomPixels = bottomPixelData[i]; | |
Color temp = new Color( | |
(1f-bottomPixels.r), | |
(1f-bottomPixels.g), | |
(1f-bottomPixels.b), | |
(1f-bottomPixels.a)); | |
resultData[i] = bottomPixels * temp.grayscale * bottomPixels.linear; | |
} | |
var res = new Texture2D(texture.width, texture.height); | |
res.SetPixels(resultData); | |
res.Apply(); | |
return res; | |
} | |
public Texture2D ToGrayScale(Color[] cArr) | |
{ | |
var bottomPixelData = cArr; | |
int count = bottomPixelData.Length; | |
var resultData = new Color[count]; | |
for(int i = 0; i < count; i++) | |
{ | |
Color bottomPixels = bottomPixelData[i]; | |
Color temp = new Color( | |
(1f-bottomPixels.r), | |
(1f-bottomPixels.g), | |
(1f-bottomPixels.b), | |
(1f-bottomPixels.a)); | |
resultData[i] = bottomPixels * temp.grayscale * bottomPixels.linear; | |
} | |
var res = new Texture2D(1280, 720); | |
res.SetPixels(resultData); | |
res.Apply(); | |
return res; | |
} | |
public Texture2D AlphaBlend(Texture2D textureBottom, Texture2D textureTop) | |
{ | |
if (textureBottom.width != textureTop.width || textureBottom.height != textureTop.height) | |
throw new System.InvalidOperationException("AlphaBlend only works with two equal sized images"); | |
var bottomPixelData = textureBottom.GetPixels(); | |
var topPixelData = textureTop.GetPixels(); | |
int count = bottomPixelData.Length; | |
var resultData = new Color[count]; | |
for(int i = 0; i < count; i++) | |
{ | |
Color bottomPixels = bottomPixelData[i]; | |
Color topPixels = topPixelData[i]; | |
float srcF = topPixels.a; | |
float destF = 1f - topPixels.a; | |
float alpha = srcF + destF * bottomPixels.a; | |
Color resultColor = (topPixels * srcF + bottomPixels * bottomPixels.a * destF)/alpha; | |
resultColor.a = alpha; | |
resultData[i] = resultColor; | |
} | |
var res = new Texture2D(textureBottom.width, textureBottom.height); | |
res.SetPixels(resultData); | |
res.Apply(); | |
return res; | |
} | |
public Texture2D AlphaBlend( Color[] cArr, Texture2D textureTop) | |
{ | |
var bottomPixelData = cArr; | |
var topPixelData = textureTop.GetPixels(); | |
int count = bottomPixelData.Length; | |
var resultData = new Color[count]; | |
for(int i = 0; i < count; i++) | |
{ | |
Color bottomPixels = bottomPixelData[i]; | |
Color topPixels = topPixelData[i]; | |
float srcF = topPixels.a; | |
float destF = 1f - topPixels.a; | |
float alpha = srcF + destF * bottomPixels.a; | |
Color resultColor = (topPixels * srcF + bottomPixels * bottomPixels.a * destF)/alpha; | |
resultColor.a = alpha; | |
resultData[i] = resultColor; | |
} | |
var res = new Texture2D(textureTop.width, textureTop.height); | |
res.SetPixels(resultData); | |
res.Apply(); | |
return res; | |
} | |
//NOT WORKING | |
// let posx and posy be the placement position of the foreground image | |
// let foreground.sizex and foreground.sizey the size of the foreground image | |
// for each row of the background image | |
// for each column of the background image | |
// // check if the position overlaps the foreground image | |
// if column - posx >= 0 and column - posx < foreground.sizex | |
// if row - posy >= 0 and row - posy < foreground.sizey | |
// alpha blend the background and the foreground | |
// else | |
// output background value | |
public Texture2D AlphaBlend(Texture2D textureBottom, Texture2D textureTop,int x, int y) | |
{ | |
var bottomPixelData = textureBottom.GetPixels(); | |
var topPixelData = textureTop.GetPixels(); | |
int count = bottomPixelData.Length; | |
var resultData = new Color[count]; | |
for (int w = 0; w < textureBottom.width; w++) | |
{ | |
for (int h = 0; h < textureBottom.height; h++) | |
{ | |
if (w - x >= 0 && w - x < textureBottom.width) | |
{ | |
if (h - y >= 0 && h - y < textureBottom.height) | |
{ | |
Color bottomPixel = textureBottom.GetPixel(w,h); | |
Color topPixel = textureTop.GetPixel(w-x,h-y); | |
float srcF = topPixel.a; | |
float destF = 1f - topPixel.a; | |
float alpha = srcF + destF * bottomPixel.a; | |
//int grayScale = (int)((oc.R * 0.3) + (oc.G * 0.59) + (oc.B * 0.11)); | |
Color resultColor = (topPixel * srcF + bottomPixel * bottomPixel.a * destF)/alpha; | |
resultColor.a = alpha; | |
resultData[(w+1)*(h+1)] = resultColor; | |
} | |
else | |
{ | |
Color resultColor = textureBottom.GetPixel(w,h); | |
resultColor.a = 1; | |
resultData[w+h] = resultColor; | |
} | |
} | |
else | |
{ | |
Color resultColor = textureBottom.GetPixel(w,h); | |
resultColor.a = 1; | |
resultData[w+h] = resultColor; | |
} | |
} | |
} | |
var res = new Texture2D(textureBottom.width, textureBottom.height); | |
res.SetPixels(resultData); | |
res.Apply(); | |
return res; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment