private unsafe void ApplyBGGR( 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
// . . .
// . B G
// . G R
dst[RGB.R] = src[srcStrideP1];
dst[RGB.G] = (byte) ( ( src[1] + src[srcStride] ) >> 1 );
dst[RGB.B] = *src;
src++;
dst += 3;
for ( int x = 1; x < widthM1; x += 2 )
{
// . . .
// B G B
// G R G
dst[RGB.R] = src[srcStride];
dst[RGB.G] = (byte) ( ( *src + src[srcStrideM1] + src[srcStrideP1] ) / 3 );
dst[RGB.B] = (byte) ( ( src[-1] + src[1] ) >> 1 );
src++;
dst += 3;
// . . .
// G B G
// R G R
dst[RGB.R] = (byte) ( ( src[srcStrideM1] + src[srcStrideP1] ) >> 1 );
dst[RGB.G] = (byte) ( ( src[-1] + src[srcStride] + src[1] ) / 3 );
dst[RGB.B] = *src;
src++;
dst += 3;
}
// . . .
// B G .
// G R .
dst[RGB.R] = src[srcStride];
dst[RGB.G] = (byte) ( ( *src + src[srcStrideM1] ) >> 1 );
dst[RGB.B] = src[-1];
// 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 )
{
// . B G
// . G R
// . B G
dst[RGB.R] = src[1];
dst[RGB.G] = (byte) ( ( src[srcMStrideP1] + src[srcStrideP1] + *src ) / 3 );
dst[RGB.B] = (byte) ( ( src[srcMStride] + src[srcStride] ) >> 1 );
dst += dstStride;
src += srcStride;
// ( y+1 pixel )
// . G R
// . B G
// . G R
dst[RGB.R] = (byte) ( ( src[srcMStrideP1] + src[srcStrideP1] ) >> 1 );
dst[RGB.G] = (byte) ( ( src[1] + src[srcMStride] + src[srcStride] ) / 3 );
dst[RGB.B] = *src;
dst -= dstStride;
src -= srcStride;
src++;
dst += 3;
for ( int x = 1; x < widthM1; x += 2 )
{
// B G B
// G R G
// B G B
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 pixel )
// G R G
// B G B
// G R G
dst += dstStride;
src += srcStride;
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 x+1 pixel )
// R G R
// G B G
// R G R
dst += 3;
src++;
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;
// ( x+1 pixel )
// G B G
// R G R
// G B G
dst -= dstStride;
src -= srcStride;
dst[RGB.R] = (byte) ( ( src[-1] + src[1] ) >> 1 );
dst[RGB.G] = (byte) ( ( src[srcMStrideM1] + src[srcMStrideP1] + src[srcStrideM1] + src[srcStrideP1] + *src ) / 5 );
dst[RGB.B] = (byte) ( ( src[srcMStride] + src[srcStride] ) >> 1 );
dst += 3;
src++;
}
// 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 );
src += srcStride;
dst += dstStride;
// ( y+1 pixel )
// G R .
// B G .
// G R .
dst[RGB.R] = (byte) ( ( src[srcMStride] + src[srcStride] ) >> 1 );
dst[RGB.G] = (byte) ( ( src[srcMStrideM1] + src[srcStrideM1] + *src ) / 3 );
dst[RGB.B] = src[-1];
// align to the next line
src += srcOffset + 1;
dst += dstOffset + 3;
}
// --- process the first line
// . B G
// . G R
// . . .
dst[RGB.R] = src[1];
dst[RGB.G] = (byte) ( ( src[srcMStrideP1] + *src ) >> 1 );
dst[RGB.B] = src[srcMStride];
src++;
dst += 3;
for ( int x = 1; x < widthM1; x += 2 )
{
// B G B
// G R G
// . . .
dst[RGB.R] = *src;
dst[RGB.G] = (byte) ( ( src[-1] + src[1] + src[srcMStride] ) / 3 );
dst[RGB.B] = (byte) ( ( src[srcMStrideM1] + src[srcMStrideP1] ) >> 1 );
src++;
dst += 3;
// G B G
// R G R
// . . .
dst[RGB.R] = (byte) ( ( src[-1] + src[1] ) >> 1 );
dst[RGB.G] = (byte) ( ( *src + src[srcMStrideM1] + src[srcMStrideP1] ) / 3 );
dst[RGB.B] = src[srcMStride];
src++;
dst += 3;
}
// B G .
// G R .
// . . .
dst[RGB.R] = *src;
dst[RGB.G] = (byte) ( ( src[srcMStride] + src[-1] ) >> 1 );
dst[RGB.B] = src[srcMStrideM1];
}
#endregion