245 lines
7.6 KiB
C#
245 lines
7.6 KiB
C#
using System;
|
|
using Unity.Jobs;
|
|
using Unity.Collections;
|
|
using UnityEngine.XR.ARSubsystems;
|
|
|
|
namespace UnityEngine.XR.ARCore
|
|
{
|
|
internal struct FlipVerticalJob : IJobParallelFor
|
|
{
|
|
public int width;
|
|
|
|
public int height;
|
|
|
|
[ReadOnly]
|
|
[NativeDisableParallelForRestriction]
|
|
public NativeSlice<byte> grayscaleIn;
|
|
|
|
[WriteOnly]
|
|
[NativeDisableParallelForRestriction]
|
|
public NativeArray<byte> grayscaleOut;
|
|
|
|
public void Execute(int row)
|
|
{
|
|
int inputOffset = (height - 1 - row) * width;
|
|
int outputOffset = row * width;
|
|
int lastOffset = outputOffset + width;
|
|
while (outputOffset < lastOffset)
|
|
{
|
|
grayscaleOut[outputOffset++] = grayscaleIn[inputOffset++];
|
|
}
|
|
}
|
|
}
|
|
|
|
internal struct ConvertRFloatToGrayscaleJob : IJobParallelFor
|
|
{
|
|
public int width;
|
|
|
|
public int height;
|
|
|
|
[ReadOnly]
|
|
public NativeSlice<float> rfloatIn;
|
|
|
|
[WriteOnly]
|
|
public NativeArray<byte> grayscaleImageOut;
|
|
|
|
public void Execute(int row)
|
|
{
|
|
int inputOffset = (height - 1 - row) * width;
|
|
int outputOffset = row * width;
|
|
int lastOffset = outputOffset + width;
|
|
while (outputOffset < lastOffset)
|
|
{
|
|
grayscaleImageOut[outputOffset++] = (byte)(rfloatIn[inputOffset++] * 255);
|
|
}
|
|
}
|
|
}
|
|
|
|
internal struct ConvertBGRA32ToGrayscaleJob : IJobParallelFor
|
|
{
|
|
public int width;
|
|
|
|
public int height;
|
|
|
|
[ReadOnly]
|
|
[NativeDisableParallelForRestriction]
|
|
public NativeSlice<byte> colorImageIn;
|
|
|
|
[WriteOnly]
|
|
[NativeDisableParallelForRestriction]
|
|
public NativeArray<byte> grayscaleImageOut;
|
|
|
|
public void Execute(int row)
|
|
{
|
|
int colorImageOffset = (height - 1 - row) * width * 4;
|
|
int grayImageOffset = row * width;
|
|
int lastOffset = grayImageOffset + width;
|
|
while (grayImageOffset < lastOffset)
|
|
{
|
|
grayscaleImageOut[grayImageOffset++] = (byte)(
|
|
colorImageIn[colorImageOffset ] * 0.11f +
|
|
colorImageIn[colorImageOffset + 1] * 0.59f +
|
|
colorImageIn[colorImageOffset + 2] * 0.3f);
|
|
|
|
colorImageOffset += 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal struct ConvertARGB32ToGrayscaleJob : IJobParallelFor
|
|
{
|
|
public int width;
|
|
|
|
public int height;
|
|
|
|
[ReadOnly]
|
|
[NativeDisableParallelForRestriction]
|
|
public NativeSlice<byte> colorImageIn;
|
|
|
|
[WriteOnly]
|
|
[NativeDisableParallelForRestriction]
|
|
public NativeArray<byte> grayscaleImageOut;
|
|
|
|
public void Execute(int row)
|
|
{
|
|
int colorImageOffset = (height - 1 - row) * width * 4;
|
|
int grayImageOffset = row * width;
|
|
int lastOffset = grayImageOffset + width;
|
|
while (grayImageOffset < lastOffset)
|
|
{
|
|
//ARGB so need to account for ALPHA index.
|
|
grayscaleImageOut[grayImageOffset++] = (byte)(
|
|
colorImageIn[colorImageOffset + 1] * 0.3f +
|
|
colorImageIn[colorImageOffset + 2] * 0.59f +
|
|
colorImageIn[colorImageOffset + 3] * 0.11f);
|
|
|
|
colorImageOffset += 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal struct ConvertStridedToGrayscaleJob : IJobParallelFor
|
|
{
|
|
public int stride;
|
|
|
|
public int width;
|
|
|
|
public int height;
|
|
|
|
// NB: NativeDisableParallelForRestriction to allow
|
|
// us to read and write to indices other than the
|
|
// one passed into the Execute method. This is because
|
|
// we interpret the index as the row number and process
|
|
// and entire row at a time. This takes about 75% the
|
|
// time of doing it one pixel at a time.
|
|
|
|
[ReadOnly]
|
|
[NativeDisableParallelForRestriction]
|
|
public NativeSlice<byte> colorImageIn;
|
|
|
|
[WriteOnly]
|
|
[NativeDisableParallelForRestriction]
|
|
public NativeArray<byte> grayscaleImageOut;
|
|
|
|
public void Execute(int row)
|
|
{
|
|
int colorImageOffset = (height - 1 - row) * width * stride;
|
|
int grayImageOffset = row * width;
|
|
int lastOffset = grayImageOffset + width;
|
|
while (grayImageOffset < lastOffset)
|
|
{
|
|
grayscaleImageOut[grayImageOffset++] = (byte)(
|
|
colorImageIn[colorImageOffset ] * 0.3f +
|
|
colorImageIn[colorImageOffset + 1] * 0.59f +
|
|
colorImageIn[colorImageOffset + 2] * 0.11f);
|
|
|
|
colorImageOffset += stride;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal static class ConversionJob
|
|
{
|
|
public static JobHandle Schedule(
|
|
NativeSlice<byte> inputImage,
|
|
Vector2Int sizeInPixels,
|
|
TextureFormat format,
|
|
NativeArray<byte> grayscaleImage,
|
|
JobHandle inputDeps)
|
|
{
|
|
int width = sizeInPixels.x;
|
|
int height = sizeInPixels.y;
|
|
|
|
if ((format == TextureFormat.R8) ||
|
|
(format == TextureFormat.Alpha8))
|
|
{
|
|
return new FlipVerticalJob
|
|
{
|
|
width = width,
|
|
height = height,
|
|
grayscaleIn = inputImage,
|
|
grayscaleOut = grayscaleImage
|
|
}.Schedule(height, 1, inputDeps);
|
|
}
|
|
|
|
// We'll have to convert it. Create an output buffer.
|
|
if (format == TextureFormat.RGB24)
|
|
{
|
|
return new ConvertStridedToGrayscaleJob
|
|
{
|
|
stride = 3,
|
|
width = width,
|
|
height = height,
|
|
colorImageIn = inputImage,
|
|
grayscaleImageOut = grayscaleImage
|
|
}.Schedule(height, 1, inputDeps);
|
|
}
|
|
else if (format == TextureFormat.RGBA32)
|
|
{
|
|
return new ConvertStridedToGrayscaleJob
|
|
{
|
|
stride = 4,
|
|
width = width,
|
|
height = height,
|
|
colorImageIn = inputImage,
|
|
grayscaleImageOut = grayscaleImage
|
|
}.Schedule(height, 1, inputDeps);
|
|
}
|
|
else if (format == TextureFormat.ARGB32)
|
|
{
|
|
return new ConvertARGB32ToGrayscaleJob
|
|
{
|
|
width = width,
|
|
height = height,
|
|
colorImageIn = inputImage,
|
|
grayscaleImageOut = grayscaleImage
|
|
}.Schedule(height, 1, inputDeps);
|
|
}
|
|
else if (format == TextureFormat.BGRA32)
|
|
{
|
|
return new ConvertBGRA32ToGrayscaleJob
|
|
{
|
|
width = width,
|
|
height = height,
|
|
colorImageIn = inputImage,
|
|
grayscaleImageOut = grayscaleImage
|
|
}.Schedule(height, 1, inputDeps);
|
|
}
|
|
else if (format == TextureFormat.RFloat)
|
|
{
|
|
return new ConvertRFloatToGrayscaleJob
|
|
{
|
|
width = width,
|
|
height = height,
|
|
rfloatIn = inputImage.SliceConvert<float>(),
|
|
grayscaleImageOut = grayscaleImage
|
|
}.Schedule(height, 1, inputDeps);
|
|
}
|
|
else
|
|
{
|
|
throw new InvalidOperationException($"Texture format {format} is not supported.");
|
|
}
|
|
}
|
|
}
|
|
}
|