Skip to content

Instantly share code, notes, and snippets.

@smakhtin
Created July 10, 2013 08:58
Show Gist options
  • Save smakhtin/08c8eaae8e5db470685e to your computer and use it in GitHub Desktop.
Save smakhtin/08c8eaae8e5db470685e to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Emgu.CV;
using System.Drawing;
using SlimDX.Direct3D9;
using SlimDX;
using VVVV.Utils.SlimDX;
using FeralTic.DX11.Resources;
using FeralTic.DX11;
namespace VVVV.Nodes.OpenCV
{
class AsDX11TextureInstance : IDestinationInstance
{
// [DllImport("msvcrt.dll", EntryPoint = "memcpy")]
// public unsafe static extern void CopyMemory(IntPtr pDest, IntPtr pSrc, int length);
public int Width { get; private set; }
public int Height { get; private set; }
CVImageDoubleBuffer FBufferConverted;
TColorFormat FConvertedFormat;
bool FNeedsConversion = false;
Object FLockTexture = new Object();
private Dictionary<DX11DynamicTexture2D, bool> FNeedsRefresh = new Dictionary<DX11DynamicTexture2D, bool>();
private bool FNeedsTexture = false;
public bool NeedsTexture
{
get
{
if (FNeedsTexture)
{
FNeedsTexture = false;
return true;
}
return false;
}
}
public override void Allocate()
{
FNeedsConversion = ImageUtils.NeedsConversion(FInput.ImageAttributes.ColourFormat, out FConvertedFormat);
if (FNeedsConversion)
{
FBufferConverted = new CVImageDoubleBuffer();
FBufferConverted.Initialise(new CVImageAttributes(FInput.ImageAttributes.Size, FConvertedFormat));
}
FNeedsTexture = true;
}
public override void Process()
{
lock (FLockTexture)
{
//ImageChanged so mark needs refresh on created textures
foreach (var key in FNeedsRefresh.Keys.ToList())
{
FNeedsRefresh[key] = true;
}
}
if (FNeedsConversion)
{
FInput.GetImage(FBufferConverted);
FBufferConverted.Swap();
}
}
private bool InputOK
{
get
{
if (FNeedsConversion)
{
if (FBufferConverted == null)
return false;
if (!FBufferConverted.Allocated)
return false;
}
else
{
if (FInput == null)
return false;
if (!FInput.Allocated)
return false;
}
return true;
}
}
private SlimDX.DXGI.Format GetFormat(TColorFormat format)
{
switch (format)
{
case TColorFormat.L16 :
return SlimDX.DXGI.Format.R16_UNorm;
case TColorFormat.L32F:
return SlimDX.DXGI.Format.R32_Float;
case TColorFormat.RGB8:
return SlimDX.DXGI.Format.R8G8B8A8_UNorm;
case TColorFormat.RGBA8:
return SlimDX.DXGI.Format.R8G8B8A8_UNorm;
case TColorFormat.RGB32F:
return SlimDX.DXGI.Format.R32G32B32A32_Float;
case TColorFormat.RGBA32F:
return SlimDX.DXGI.Format.R32G32B32A32_Float;
}
return SlimDX.DXGI.Format.Unknown;
}
public DX11DynamicTexture2D CreateTexture(DX11RenderContext context)
{
lock (FLockTexture)
{
if (InputOK)
{
DX11DynamicTexture2D output;
if (FNeedsConversion)
{
CVImageAttributes attr = FBufferConverted.ImageAttributes.Clone() as CVImageAttributes;
SlimDX.DXGI.Format format = this.GetFormat(attr.ColourFormat);
output = new DX11DynamicTexture2D(context, attr.Width, attr.Height, format);
}
else
{
CVImageAttributes attr = FBufferConverted.ImageAttributes as CVImageAttributes;
SlimDX.DXGI.Format format = this.GetFormat(attr.ColourFormat);
output = new DX11DynamicTexture2D(context, attr.Width, attr.Height, format);
}
FNeedsRefresh.Add(output, true);
return output;
}
else
{
return context.DefaultTextures.WhiteTexture;
}
}
}
public void UpdateTexture(DX11DynamicTexture2D texture)
{
lock (FLockTexture)
{
if (!InputOK)
return;
if (!FNeedsRefresh.ContainsKey(texture))
{
FNeedsTexture = true;
return;
}
if (!FNeedsRefresh[texture])
return;
if (FInput.ImageAttributesChanged)
{
//reset flag we just dropped
FInput.ImageAttributesChanged = true;
return;
}
/*Surface srf = texture.GetSurfaceLevel(0);
DataRectangle rect = srf.LockRectangle(LockFlags.None);*/
try
{
Size imageSize = FNeedsConversion ? FBufferConverted.ImageAttributes.Size : FInput.ImageAttributes.Size;
if (texture.Width != imageSize.Width || texture.Height != imageSize.Height)
{
throw (new Exception("AsTextureInstance : srf dimensions don't match image dimensions"));
}
if (FNeedsConversion)
{
FInput.GetImage(FBufferConverted);
FBufferConverted.Swap();
FBufferConverted.LockForReading();
try
{
if (!FBufferConverted.FrontImage.Allocated)
throw (new Exception());
texture.WriteData(FInput.Data, FInput.BytesPerFrame);
//rect.Data.WriteRange(FBufferConverted.FrontImage.Data, FBufferConverted.ImageAttributes.BytesPerFrame);
FNeedsRefresh[texture] = false;
}
catch (Exception e)
{
ImageUtils.Log(e);
}
finally
{
FBufferConverted.ReleaseForReading();
}
}
else
{
FInput.LockForReading();
try
{
texture.WriteData(FInput.Data, FInput.BytesPerFrame);
//rect.Data.WriteRange(FInput.Data, FInput.ImageAttributes.BytesPerFrame);
FNeedsRefresh[texture] = false;
}
catch (Exception e)
{
ImageUtils.Log(e);
}
finally
{
FInput.ReleaseForReading();
}
}
}
catch (Exception e)
{
throw (e);
}
finally
{
//srf.UnlockRectangle();
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VVVV.PluginInterfaces.V2;
using FeralTic.DX11.Resources;
using VVVV.Nodes.OpenCV;
using System.ComponentModel.Composition;
using VVVV.PluginInterfaces.V1;
using System.Drawing;
namespace VVVV.DX11.CVLink
{
public class TestNoiseInstance : IStaticGeneratorInstance
{
string FLoadedImage = "";
Size FSize = new Size(32, 32);
float FRadius = 1;
Random FRandom = new Random();
public override bool NeedsThread()
{
return false;
}
public void Refresh()
{
FOutput.Image.Initialise(FSize, TColorFormat.RGBA32F);
FillRandomValues();
FOutput.Send();
}
public int Dimension
{
set
{
if (value < 1)
value = 1;
if (value > 4096)
value = 4096;
double valueLog2 = Math.Log((double)value) / Math.Log(2.0d);
value = 1 << (int)valueLog2;
FSize.Width = value;
FSize.Height = value;
Refresh();
}
}
private unsafe void FillRandomValues()
{
float* xyzt = (float*)FOutput.Data.ToPointer();
int width = FSize.Width;
int height = FSize.Height;
for (int i = 0; i < width * height; i++)
{
*xyzt++ = ((float)FRandom.NextDouble() - 0.5f) * 2.0f * FRadius;
*xyzt++ = ((float)FRandom.NextDouble() - 0.5f) * 2.0f * FRadius;
*xyzt++ = ((float)FRandom.NextDouble() - 0.5f) * 2.0f * FRadius;
*xyzt++ = 1;
}
}
}
[PluginInfo(Name = "FromTexture",
Category = "EmguCV",
Version = "DX11",
Help = "Converts Texture to IPLImage",
Tags = "", Author = "vux")]
public unsafe class FromDX11TextureInstance : IGeneratorNode<TestNoiseInstance>, IPluginEvaluate, IDX11ResourceDataRetriever
{
[Input("Texture In")]
Pin<DX11Resource<DX11Texture2D>> FTexIn;
[Input("Refresh", IsBang = true)]
ISpread<bool> FRefresh;
[Input("Dimension", DefaultValue = 32, MinValue = 1, MaxValue = 4096)]
IDiffSpread<int> FDimension;
/*[Output("Image",IsSingle=true)]
ISpread<CVImageLink> FPinOutImage;*/
[Import()]
protected IPluginHost FHost;
bool FInitialised = false;
CVImageOutputSpread FOutputs;
public void Evaluate(int SpreadMax)
{
if (this.FTexIn.PluginIO.IsConnected)
{
if (this.RenderRequest != null) { this.RenderRequest(this, this.FHost); }
if (this.AssignedContext == null) { return; }
DX11Texture2D t = this.FTexIn[0][this.AssignedContext];
}
}
public FeralTic.DX11.DX11RenderContext AssignedContext
{
get;
set;
}
public event DX11RenderRequestDelegate RenderRequest;
protected override void Update(int InstanceCount, bool SpreadChanged)
{
for (int i = 0; i < InstanceCount; i++)
if (FRefresh[i])
FProcessor[i].Refresh();
if (FDimension.IsChanged)
for (int i = 0; i < InstanceCount; i++)
FProcessor[i].Dimension = FDimension[i];
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VideoInputSharp;
using VVVV.PluginInterfaces.V2;
using VVVV.PluginInterfaces.V1;
using FeralTic.DX11;
using FeralTic.DX11.Resources;
using System.Runtime.InteropServices;
namespace VVVV.DX11.Nodes
{
[PluginInfo(Name="VideoIn",Category="DX11.Texture", Version="DShow")]
public unsafe class VideoInNode : IPluginEvaluate, IDX11ResourceProvider, IDisposable
{
[Input("Width", DefaultValue =640)]
IDiffSpread<int> FInW;
[Input("Height", DefaultValue = 480)]
IDiffSpread<int> FInH;
[Input("Fps", DefaultValue = 30)]
IDiffSpread<int> FInFPS;
[Input("Device Id", Order = 500, MinValue = 0)]
IDiffSpread<int> FInDeviceId;
[Input("Reset", Order = 505, IsBang=true)]
IDiffSpread<bool> FInReset;
[Input("Enabled", Order = 501, MinValue = 0)]
IDiffSpread<bool> FInEnabled;
[Output("Texture Out", IsSingle = true)]
protected Pin<DX11Resource<DX11DynamicTexture2D>> FTextureOutput;
[Output("Width Out", DefaultValue = 640)]
ISpread<int> FOutW;
[Output("Height Out", DefaultValue = 480)]
ISpread<int> FOutH;
VideoInputSharp.Capture c;
bool invalidate = true;
bool copyframe = false;
private IntPtr data = IntPtr.Zero;
private IntPtr rgbadata = IntPtr.Zero;
private long size;
private int pixcount;
public void Evaluate(int SpreadMax)
{
this.copyframe = false;
if (c == null || this.FInReset[0])
{
if (c != null)
{
c.Close();
}
if (this.data != IntPtr.Zero)
{
Marshal.FreeCoTaskMem(this.data);
}
c = new Capture();
c.Open(this.FInDeviceId[0], this.FInFPS[0], this.FInW[0], this.FInH[0]);
this.size = this.FInW[0] * this.FInH[0] * 4;
this.pixcount = this.FInW[0] * this.FInH[0];
this.data = Marshal.AllocCoTaskMem(this.FInW[0] * this.FInH[0] * 3);
this.rgbadata = Marshal.AllocCoTaskMem((int)size);
this.invalidate = true;
}
if (this.FTextureOutput[0] == null)
{
this.FTextureOutput[0] = new DX11Resource<DX11DynamicTexture2D>();
}
if (c != null && this.FInEnabled[0])
{
this.c.GetPixels(this.data);
byte* brgb = (byte*) this.data.ToPointer();
byte* brgba = (byte*)this.rgbadata.ToPointer();
/*int cnt = 0;
int cnta = 0;
for (int i = 0; i < this.FInH[0]; i++)
{
for (int j = 0; j < this.FInW[0]; j++)
{
brgba[cnta] = brgb[cnt];
brgba[cnta + 1] = brgb[cnt + 1];
brgba[cnta + 2] = brgb[cnt + 2];
cnta += 4;
cnt += 3;
}
}*/
for (int i = 0; i < this.pixcount; i++)
{
brgba[i * 4] = brgb[i * 3];
brgba[i * 4 + 1] = brgb[i * 3 + 1];
brgba[i * 4 + 2] = brgb[i * 3 + 2];
}
this.copyframe = true;
try
{
this.FOutW[0] = c.GetWidth();
this.FOutH[0] = c.GetHeight();
}
catch
{
}
}
}
public void Update(IPluginIO pin, DX11RenderContext context)
{
if (c != null)
{
if (this.invalidate || !this.FTextureOutput[0].Contains(context))
{
try
{
if (this.FTextureOutput[0].Contains(context))
{
this.FTextureOutput[0].Dispose(context);
}
DX11DynamicTexture2D t = new DX11DynamicTexture2D(context, this.FInW[0], this.FInH[0], SlimDX.DXGI.Format.B8G8R8A8_UNorm);
this.FTextureOutput[0][context] = t;
}
catch
{
}
}
if (this.copyframe && this.FTextureOutput[0].Contains(context))
{
this.FTextureOutput[0][context].WriteData(this.rgbadata, this.size);
}
}
}
public void Destroy(IPluginIO pin, DX11RenderContext context, bool force)
{
this.FTextureOutput[0].Dispose(context);
}
public void Dispose()
{
this.FTextureOutput[0].Dispose();
if (c != null)
{
c.Close();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment