Did a few things
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
using System;
|
||||
|
||||
namespace Unity.Screenshots
|
||||
{
|
||||
public static class Downsampler
|
||||
{
|
||||
#region Static Methods
|
||||
|
||||
public static byte[] Downsample(byte[] dataRgba, int stride, int maximumWidth, int maximumHeight, out int downsampledStride)
|
||||
{
|
||||
// Preconditions
|
||||
if (stride == 0)
|
||||
{
|
||||
throw new ArgumentException("The stride must be greater than 0.");
|
||||
}
|
||||
if (stride % 4 != 0)
|
||||
{
|
||||
throw new ArgumentException("The stride must be evenly divisible by 4.");
|
||||
}
|
||||
if (dataRgba == null)
|
||||
{
|
||||
throw new ArgumentNullException("dataRgba");
|
||||
}
|
||||
if (dataRgba.Length == 0)
|
||||
{
|
||||
throw new ArgumentException("The data length must be greater than 0.");
|
||||
}
|
||||
if (dataRgba.Length % 4 != 0)
|
||||
{
|
||||
throw new ArgumentException("The data must be evenly divisible by 4.");
|
||||
}
|
||||
if (dataRgba.Length % stride != 0)
|
||||
{
|
||||
throw new ArgumentException("The data must be evenly divisible by the stride.");
|
||||
}
|
||||
|
||||
// Implementation
|
||||
int width = stride / 4;
|
||||
int height = dataRgba.Length / stride;
|
||||
float ratioX = maximumWidth / (float) width;
|
||||
float ratioY = maximumHeight / (float) height;
|
||||
float ratio = Math.Min(ratioX, ratioY);
|
||||
if (ratio < 1)
|
||||
{
|
||||
int downsampledWidth = (int) Math.Round(width * ratio);
|
||||
int downsampledHeight = (int) Math.Round(height * ratio);
|
||||
float[] downsampledData = new float[downsampledWidth * downsampledHeight * 4];
|
||||
float sampleWidth = width / (float) downsampledWidth;
|
||||
float sampleHeight = height / (float) downsampledHeight;
|
||||
int kernelWidth = (int) Math.Floor(sampleWidth);
|
||||
int kernelHeight = (int) Math.Floor(sampleHeight);
|
||||
int kernelSize = kernelWidth * kernelHeight;
|
||||
for (int y = 0; y < downsampledHeight; y++)
|
||||
{
|
||||
for (int x = 0; x < downsampledWidth; x++)
|
||||
{
|
||||
int destinationIndex = y * downsampledWidth * 4 + x * 4;
|
||||
int sampleLowerX = (int) Math.Floor(x * sampleWidth);
|
||||
int sampleLowerY = (int) Math.Floor(y * sampleHeight);
|
||||
int sampleUpperX = sampleLowerX + kernelWidth;
|
||||
int sampleUpperY = sampleLowerY + kernelHeight;
|
||||
for (int sampleY = sampleLowerY; sampleY < sampleUpperY; sampleY++)
|
||||
{
|
||||
if (sampleY >= height)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (int sampleX = sampleLowerX; sampleX < sampleUpperX; sampleX++)
|
||||
{
|
||||
if (sampleX >= width)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int sourceIndex = sampleY * width * 4 + sampleX * 4;
|
||||
downsampledData[destinationIndex] += dataRgba[sourceIndex];
|
||||
downsampledData[destinationIndex + 1] += dataRgba[sourceIndex + 1];
|
||||
downsampledData[destinationIndex + 2] += dataRgba[sourceIndex + 2];
|
||||
downsampledData[destinationIndex + 3] += dataRgba[sourceIndex + 3];
|
||||
}
|
||||
}
|
||||
downsampledData[destinationIndex] /= kernelSize;
|
||||
downsampledData[destinationIndex + 1] /= kernelSize;
|
||||
downsampledData[destinationIndex + 2] /= kernelSize;
|
||||
downsampledData[destinationIndex + 3] /= kernelSize;
|
||||
}
|
||||
}
|
||||
byte[] flippedData = new byte[downsampledWidth * downsampledHeight * 4];
|
||||
for (int y = 0; y < downsampledHeight; y++)
|
||||
{
|
||||
for (int x = 0; x < downsampledWidth; x++)
|
||||
{
|
||||
int sourceIndex = (downsampledHeight - 1 - y) * downsampledWidth * 4 + x * 4;
|
||||
int destinationIndex = y * downsampledWidth * 4 + x * 4;
|
||||
flippedData[destinationIndex] += (byte) downsampledData[sourceIndex];
|
||||
flippedData[destinationIndex + 1] += (byte) downsampledData[sourceIndex + 1];
|
||||
flippedData[destinationIndex + 2] += (byte) downsampledData[sourceIndex + 2];
|
||||
flippedData[destinationIndex + 3] += (byte) downsampledData[sourceIndex + 3];
|
||||
}
|
||||
}
|
||||
downsampledStride = downsampledWidth * 4;
|
||||
return flippedData;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] flippedData = new byte[dataRgba.Length];
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
int sourceIndex = (height - 1 - y) * width * 4 + x * 4;
|
||||
int destinationIndex = y * width * 4 + x * 4;
|
||||
flippedData[destinationIndex] += (byte) dataRgba[sourceIndex];
|
||||
flippedData[destinationIndex + 1] += (byte) dataRgba[sourceIndex + 1];
|
||||
flippedData[destinationIndex + 2] += (byte) dataRgba[sourceIndex + 2];
|
||||
flippedData[destinationIndex + 3] += (byte) dataRgba[sourceIndex + 3];
|
||||
}
|
||||
}
|
||||
downsampledStride = width * 4;
|
||||
return flippedData;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user