I am making a mobile application using Unity where I open the camera and get data from it using WebcamTexture
.
The data which I get from the camera is Color32[]
.
I stored the data in the memory and then read it from memory:
// Address the variable (data) to a memory location
data = new Color32[width * height];
gcHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
// this didn't work
data = webcamTexture.GetPixels32();
// this worked fine
webcamTexture.GetPixels32(data);
// read data from memory using this
gcHandle.AddrOfPinnedObject()
When I used webcamTexture.GetPixels32(data);
I was able to see the image of the camera, while when I used data = webcamTexture.GetPixels32();
I am getting a black screen from the camera.
My Questions:
1. Is there a difference between the two functions?
2. What I should do if I want to get Color32[]
from Texture2D
?
(Texture2D
has 2 functions to get Color32[]
: GetPixels32()
and
GetRawTextureData<Color32>().ToArray()
, both giving me a black
screen)
As to the title
Difference between GetPixels32() & GetPixels32(colors)
If you look into the API you will see that the method signature is
public Color32[] GetPixels32(Color32[] colors = null);
so colors
is an optional parameter.
So on a very high level perspective: There is no difference, both are the same method.
However, this parameter wouldn't exist, if the method wouldn't behave different with or without it.
If you read on
You can optionally pass in an array of
Color32
s to use in colors to avoid allocating new memory each frame, which is faster when you are continuously reading data from the camera. The array needs to be initialized to a length matching width * height of the texture. If you don't pass an array,GetPixels32
will allocate one for you and return it.
you see that the difference in passing in an array or not is that if you don't do it, it allocates a new array for every time you call it. This is of course a lot more expensive if you are using this every frame. But letting aside this performance impact it also means that this way you get a new array reference every time.
So this said now looking again into your code you are doing
data = new Color32[width * height];
gcHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
so if you are filling this array it is still the same array object
webcamTexture.GetPixels32(data);
var ptr = gcHandle.AddrOfPinnedObject();
so this works since you are filling the same array reference that is pinned in the gcHandle
.
On the other side this does not work
data = webcamTexture.GetPixels32();
var ptr = gcHandle.AddrOfPinnedObject();
since here you create a new array reference. On this one you didn't call
gcHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
on and thus, when you reach
gcHandle.AddrOfPinnedObject()
this gcHandle
still references to the previous Color32[]
which was referenced by data
the moment you did the Alloc
call. That is still an empty array you did never write to.
For Texture2D
it should be GetPixels32()
but you would probably want to first get that array before getting the pointer to it:
var data = texture2D.GetPixels32();
var gcHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
var ptr = gcHandle.AddrOfPinnedObject();