public static void Scale( PixelBox src, PixelBox scaled, ImageFilter filter )
{
Contract.Requires( PixelUtil.IsAccessible( src.Format ) );
Contract.Requires( PixelUtil.IsAccessible( scaled.Format ) );
byte[] buf; // For auto-delete
PixelBox temp;
switch ( filter )
{
default:
case ImageFilter.Nearest:
if ( src.Format == scaled.Format )
{
// No intermediate buffer needed
temp = scaled;
}
else
{
// Allocate temporary buffer of destination size in source format
temp = new PixelBox( scaled.Width, scaled.Height, scaled.Depth, src.Format );
buf = new byte[ temp.ConsecutiveSize ];
temp.Data = GCHandle.Alloc( buf, GCHandleType.Pinned ).AddrOfPinnedObject();
}
// super-optimized: no conversion
NearestResampler.Scale( src, temp );
if ( temp.Data != scaled.Data )
{
// Blit temp buffer
PixelConverter.BulkPixelConversion( temp, scaled );
}
break;
case ImageFilter.Linear:
case ImageFilter.Bilinear:
switch ( src.Format )
{
case PixelFormat.L8:
case PixelFormat.A8:
case PixelFormat.BYTE_LA:
case PixelFormat.R8G8B8:
case PixelFormat.B8G8R8:
case PixelFormat.R8G8B8A8:
case PixelFormat.B8G8R8A8:
case PixelFormat.A8B8G8R8:
case PixelFormat.A8R8G8B8:
case PixelFormat.X8B8G8R8:
case PixelFormat.X8R8G8B8:
if ( src.Format == scaled.Format )
{
// No intermediate buffer needed
temp = scaled;
}
else
{
// Allocate temp buffer of destination size in source format
temp = new PixelBox( scaled.Width, scaled.Height, scaled.Depth, src.Format );
buf = new byte[ temp.ConsecutiveSize ];
temp.Data = GCHandle.Alloc( buf, GCHandleType.Pinned ).AddrOfPinnedObject();
}
// super-optimized: byte-oriented math, no conversion
switch ( PixelUtil.GetNumElemBytes( src.Format ) )
{
case 1:
( new LinearResampler.Byte( 1 ) ).Scale( src, temp );
break;
case 2:
( new LinearResampler.Byte( 2 ) ).Scale( src, temp );
break;
case 3:
( new LinearResampler.Byte( 3 ) ).Scale( src, temp );
break;
case 4:
( new LinearResampler.Byte( 4 ) ).Scale( src, temp );
break;
default:
throw new NotSupportedException( String.Format( "Scaling of images using {0} byte format is not supported.", PixelUtil.GetNumElemBytes( src.Format ) ) );
}
if ( temp.Data != scaled.Data )
{
// Blit temp buffer
PixelConverter.BulkPixelConversion( temp, scaled );
}
break;
case PixelFormat.FLOAT32_RGB:
case PixelFormat.FLOAT32_RGBA:
if ( scaled.Format == PixelFormat.FLOAT32_RGB || scaled.Format == PixelFormat.FLOAT32_RGBA )
{
// float32 to float32, avoid unpack/repack overhead
( new LinearResampler.Float32( 32 ) ).Scale( src, scaled );
}
else
{
( new LinearResampler.Float32() ).Scale( src, scaled );
}
break;
default:
// non-optimized: floating-point math, performs conversion but always works
( new LinearResampler.Float32() ).Scale( src, scaled );
break;
}
break;
}
}