private 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