protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData )
{
// get source image dimension
int width = sourceData.Width;
int height = sourceData.Height;
// if generator was specified, then generate a texture
// otherwise use provided texture
if ( textureGenerator != null )
{
texture = textureGenerator.Generate( width, height );
}
else
{
// check existing texture
if ( ( texture.GetLength( 0 ) != height ) || ( texture.GetLength( 1 ) != width ) )
{
// sorry, but source image must have the same dimension as texture
throw new InvalidImagePropertiesException( "Texture size does not match image size." );
}
}
// apply first filter
UnmanagedImage filteredImage1 = filter1.Apply( sourceData );
// check size of the result image
if ( ( width != filteredImage1.Width ) || ( height != filteredImage1.Height ) )
{
filteredImage1.Dispose( );
throw new ApplicationException( "Filters should not change image dimension." );
}
// convert 1st image to RGB if required
if ( filteredImage1.PixelFormat == PixelFormat.Format8bppIndexed )
{
GrayscaleToRGB coloringFilter = new GrayscaleToRGB( );
UnmanagedImage temp = coloringFilter.Apply( filteredImage1 );
filteredImage1.Dispose( );
filteredImage1 = temp;
}
UnmanagedImage filteredImage2 = null;
// apply second filter, if it was specified
if ( filter2 != null )
{
filteredImage2 = filter2.Apply( sourceData );
// check size of the result image
if ( ( width != filteredImage2.Width ) || ( height != filteredImage2.Height ) )
{
filteredImage1.Dispose( );
filteredImage2.Dispose( );
// we are not handling such situations yet
throw new ApplicationException( "Filters should not change image dimension." );
}
// convert 2nd image to RGB if required
if ( filteredImage2.PixelFormat == PixelFormat.Format8bppIndexed )
{
GrayscaleToRGB coloringFilter = new GrayscaleToRGB( );
UnmanagedImage temp = coloringFilter.Apply( filteredImage2 );
filteredImage2.Dispose( );
filteredImage2 = temp;
}
}
// use source image as a second image, if second filter is not set
if ( filteredImage2 == null )
{
filteredImage2 = sourceData;
}
// do the job
unsafe
{
byte* dst = (byte*) destinationData.ImageData.ToPointer( );
byte* src1 = (byte*) filteredImage1.ImageData.ToPointer( );
byte* src2 = (byte*) filteredImage2.ImageData.ToPointer( );
int dstOffset = destinationData.Stride - 3 * width;
int src1Offset = filteredImage1.Stride - 3 * width;
int src2Offset = filteredImage2.Stride - 3 * width;
if ( preserveLevel != 0.0 )
{
// for each line
for ( int y = 0; y < height; y++ )
{
// for each pixel
for ( int x = 0; x < width; x++ )
{
double t1 = texture[y, x];
double t2 = 1 - t1;
for ( int i = 0; i < 3; i++, src1++, src2++, dst++ )
{
*dst = (byte) Math.Min( 255.0f,
filterLevel * ( t1 * ( *src1 ) + t2 * ( *src2 ) ) +
preserveLevel * ( *src2 ) );
}
}
src1 += src1Offset;
src2 += src2Offset;
dst += dstOffset;
}
}
else
{
// for each line
for ( int y = 0; y < height; y++ )
{
// for each pixel
for ( int x = 0; x < width; x++ )
{
double t1 = texture[y, x];
double t2 = 1 - t1;
for ( int i = 0; i < 3; i++, src1++, src2++, dst++ )
{
*dst = (byte) Math.Min( 255.0f, t1 * *src1 + t2 * *src2 );
}
}
src1 += src1Offset;
src2 += src2Offset;
dst += dstOffset;
}
}
}
// dispose temp images
filteredImage1.Dispose( );
if ( filteredImage2 != sourceData )
{
filteredImage2.Dispose( );
}
}
}