private unsafe void ProcessFilter16bpc( UnmanagedImage sourceData, UnmanagedImage destinationData )
{
// get source image size
int width = sourceData.Width;
int height = sourceData.Height;
double halfWidth = (double) width / 2;
double halfHeight = (double) height / 2;
// get destination image size
int newWidth = destinationData.Width;
int newHeight = destinationData.Height;
double halfNewWidth = (double) newWidth / 2;
double halfNewHeight = (double) newHeight / 2;
// angle's sine and cosine
double angleRad = -angle * Math.PI / 180;
double angleCos = Math.Cos( angleRad );
double angleSin = Math.Sin( angleRad );
int srcStride = sourceData.Stride;
int dstStride = destinationData.Stride;
// fill values
ushort fillR = (ushort) ( fillColor.R << 8 );
ushort fillG = (ushort) ( fillColor.G << 8 );
ushort fillB = (ushort) ( fillColor.B << 8 );
// do the job
byte* src = (byte*) sourceData.ImageData.ToPointer( );
byte* dstBase = (byte*) destinationData.ImageData.ToPointer( );
// destination pixel's coordinate relative to image center
double cx, cy;
// source pixel's coordinates
int ox, oy;
// temporary pointer
ushort* p;
// check pixel format
if ( destinationData.PixelFormat == PixelFormat.Format16bppGrayScale )
{
// grayscale
cy = -halfNewHeight;
for ( int y = 0; y < newHeight; y++ )
{
ushort* dst = (ushort*) ( dstBase + y * dstStride );
cx = -halfNewWidth;
for ( int x = 0; x < newWidth; x++, dst++ )
{
// coordinate of the nearest point
ox = (int) ( angleCos * cx + angleSin * cy + halfWidth );
oy = (int) ( -angleSin * cx + angleCos * cy + halfHeight );
// validate source pixel's coordinates
if ( ( ox < 0 ) || ( oy < 0 ) || ( ox >= width ) || ( oy >= height ) )
{
// fill destination image with filler
*dst = fillG;
}
else
{
// fill destination image with pixel from source image
p = (ushort*) ( src + oy * srcStride + ox * 2 );
*dst = *p;
}
cx++;
}
cy++;
}
}
else
{
// RGB
cy = -halfNewHeight;
for ( int y = 0; y < newHeight; y++ )
{
ushort* dst = (ushort*) ( dstBase + y * dstStride );
cx = -halfNewWidth;
for ( int x = 0; x < newWidth; x++, dst += 3 )
{
// coordinate of the nearest point
ox = (int) ( angleCos * cx + angleSin * cy + halfWidth );
oy = (int) ( -angleSin * cx + angleCos * cy + halfHeight );
// validate source pixel's coordinates
if ( ( ox < 0 ) || ( oy < 0 ) || ( ox >= width ) || ( oy >= height ) )
{
// fill destination image with filler
dst[RGB.R] = fillR;
dst[RGB.G] = fillG;
dst[RGB.B] = fillB;
}
else
{
// fill destination image with pixel from source image
p = (ushort*) ( src + oy * srcStride + ox * 6 );
dst[RGB.R] = p[RGB.R];
dst[RGB.G] = p[RGB.G];
dst[RGB.B] = p[RGB.B];
}
cx++;
}
cy++;
}
}
}
}