Skip to content

Instantly share code, notes, and snippets.

@ratozumbi
Created March 24, 2021 06:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ratozumbi/5b835dee430a5ba9456ac93587190169 to your computer and use it in GitHub Desktop.
Save ratozumbi/5b835dee430a5ba9456ac93587190169 to your computer and use it in GitHub Desktop.
Save webcam with grayscale filter and alpha blend
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