private static unsafe void ApplyGRBG(UnmanagedImage sourceData, UnmanagedImage destinationData)
{
int width = sourceData.Width;
int height = sourceData.Height;
int widthM1 = width - 1;
int heightM1 = height - 1;
int srcStride = sourceData.Stride;
int dstStride = destinationData.Stride;
int srcStrideP1 = srcStride + 1;
int srcStrideM1 = srcStride - 1;
int srcMStride = -srcStride;
int srcMStrideP1 = srcMStride + 1;
int srcMStrideM1 = srcMStride - 1;
int srcOffset = srcStride - width;
int dstOffset = dstStride - width * 3;
// do the job
byte* src = (byte*)sourceData.ImageData.ToPointer();
byte* dst = (byte*)destinationData.ImageData.ToPointer();
// --- process the first line
// . . .
// . G R
// . B G
dst[RGB.R] = src[1];
dst[RGB.G] = (byte)((*src + src[srcStrideP1]) >> 1);
dst[RGB.B] = src[srcStride];
src++;
dst += 3;
for (int x = 1; x < widthM1; x += 2)
{
// . . .
// G R G
// B G B
dst[RGB.R] = *src;
dst[RGB.G] = (byte)((src[srcStride] + src[-1] + src[1]) / 3);
dst[RGB.B] = (byte)((src[srcStrideM1] + src[srcStrideP1]) >> 1);
src++;
dst += 3;
// . . .
// R G R
// G B G
dst[RGB.R] = (byte)((src[-1] + src[1]) >> 1);
dst[RGB.G] = (byte)((*src + src[srcStrideM1] + src[srcStrideP1]) / 3);
dst[RGB.B] = src[srcStride];
src++;
dst += 3;
}
// . . .
// G R .
// B G .
dst[RGB.R] = *src;
dst[RGB.G] = (byte)((src[-1] + src[srcStride]) >> 1);
dst[RGB.B] = src[srcStrideM1];
// allign to the next line
src += srcOffset + 1;
dst += dstOffset + 3;
// --- process all lines except the first one and the last one
for (int y = 1; y < heightM1; y += 2)
{
// . G R
// . B G
// . G R
dst[RGB.R] = (byte)((src[srcMStrideP1] + src[srcStrideP1]) >> 1);
dst[RGB.G] = (byte)((src[srcMStride] + src[srcStride] + src[1]) / 3);
dst[RGB.B] = *src;
dst += dstStride;
src += srcStride;
// ( y+1 pixel )
// . B G
// . G R
// . B G
dst[RGB.R] = src[1];
dst[RGB.G] = (byte)((*src + src[srcMStrideP1] + src[srcStrideP1]) / 3);
dst[RGB.B] = (byte)((src[srcMStride] + src[srcStride]) >> 1);
dst -= dstStride;
src -= srcStride;
src++;
dst += 3;
for (int x = 1; x < widthM1; x += 2)
{
// G R G
// B G B
// G R G
dst[RGB.R] = (byte)((src[srcMStride] + src[srcStride]) >> 1);
dst[RGB.G] = (byte)((*src + src[srcMStrideM1] + src[srcMStrideP1] +
src[srcStrideM1] + src[srcStrideP1]) / 5);
dst[RGB.B] = (byte)((src[-1] + src[1]) >> 1);
// ( y+1 pixel )
// B G B
// G R G
// B G B
dst += dstStride;
src += srcStride;
dst[RGB.R] = *src;
dst[RGB.G] = (byte)((src[srcMStride] + src[srcStride] +
src[-1] + src[1]) >> 2);
dst[RGB.B] = (byte)((src[srcMStrideM1] + src[srcMStrideP1] +
src[srcStrideM1] + src[srcStrideP1]) >> 2);
// ( y+1 x+1 pixel )
// G B G
// R G R
// G B G
dst += 3;
src++;
dst[RGB.R] = (byte)((src[-1] + src[1]) >> 1);
dst[RGB.G] = (byte)((*src + src[srcMStrideM1] + src[srcMStrideP1] +
src[srcStrideM1] + src[srcStrideP1]) / 5);
dst[RGB.B] = (byte)((src[srcMStride] + src[srcStride]) >> 1);
// ( x+1 pixel )
// R G R
// G B G
// R G R
dst -= dstStride;
src -= srcStride;
dst[RGB.R] = (byte)((src[srcMStrideM1] + src[srcMStrideP1] +
src[srcStrideM1] + src[srcStrideP1]) >> 2);
dst[RGB.G] = (byte)((src[srcMStride] + src[srcStride] +
src[-1] + src[1]) >> 2);
dst[RGB.B] = *src;
dst += 3;
src++;
}
// G R .
// B G .
// G R .
dst[RGB.R] = (byte)((src[srcMStride] + src[srcStride]) >> 1);
dst[RGB.G] = (byte)((*src + src[srcMStrideM1] + src[srcStrideM1]) / 3);
dst[RGB.B] = (byte)src[-1];
src += srcStride;
dst += dstStride;
// ( y+1 pixel )
// B G .
// G R .
// B G .
dst[RGB.R] = *src;
dst[RGB.G] = (byte)((src[srcMStride] + src[srcStride] + src[-1]) / 3);
dst[RGB.B] = (byte)((src[srcMStrideM1] + src[srcStrideM1]) >> 1);
// allign to the next line
src += srcOffset + 1;
dst += dstOffset + 3;
}
// --- process the first line
// . G R
// . B G
// . . .
dst[RGB.R] = src[srcMStrideP1];
dst[RGB.G] = (byte)((src[srcMStride] + src[1]) >> 1);
dst[RGB.B] = *src;
src++;
dst += 3;
for (int x = 1; x < widthM1; x += 2)
{
// G R G
// B G B
// . . .
dst[RGB.R] = src[srcMStride];
dst[RGB.G] = (byte)((src[srcMStrideM1] + src[srcMStrideP1] + *src) / 3);
dst[RGB.B] = (byte)((src[-1] + src[1]) >> 1);
src++;
dst += 3;
// R G R
// G B G
// . . .
dst[RGB.R] = (byte)((src[srcMStrideM1] + src[srcMStrideP1]) >> 1);
dst[RGB.G] = (byte)((src[srcMStride] + src[-1] + src[1]) / 3);
dst[RGB.B] = *src;
src++;
dst += 3;
}
// G R .
// B G .
// . . .
dst[RGB.R] = src[srcMStride];
dst[RGB.G] = (byte)((*src + src[srcMStrideM1]) >> 1);
dst[RGB.B] = src[-1];
}
#endregion