public static void BulkPixelConversion( PixelBox src, PixelBox dst )
{
Debug.Assert( src.Width == dst.Width && src.Height == dst.Height && src.Depth == dst.Depth );
LogManager.Instance.Write( "Converting image from {0} to {1}", PixelUtil.GetFormatName( src.Format ), PixelUtil.GetFormatName( dst.Format ) );
// Check for compressed formats, we don't support decompression, compression or recoding
if ( PixelBox.Compressed( src.Format ) || PixelBox.Compressed( dst.Format ) )
{
if ( src.Format == dst.Format )
{
Memory.Copy( src.Data, dst.Data, src.Offset, dst.Offset, src.ConsecutiveSize );
return;
}
else
throw new Exception( "This method can not be used to compress or decompress images, in PixelBox.BulkPixelConversion" );
}
// The easy case
if ( src.Format == dst.Format )
{
// Everything consecutive?
if ( src.IsConsecutive && dst.IsConsecutive )
{
Memory.Copy( src.Data, dst.Data, src.Offset, dst.Offset, src.ConsecutiveSize );
return;
}
// TODO : Use OptimizedPixelConversion to elminate this duplicate code.
unsafe
{
byte* srcBytes = (byte*)src.Data.ToPointer();
byte* dstBytes = (byte*)dst.Data.ToPointer();
byte* srcptr = srcBytes + src.Offset;
byte* dstptr = dstBytes + dst.Offset;
int srcPixelSize = PixelUtil.GetNumElemBytes( src.Format );
int dstPixelSize = PixelUtil.GetNumElemBytes( dst.Format );
// Calculate pitches+skips in bytes
int srcRowPitchBytes = src.RowPitch * srcPixelSize;
//int srcRowSkipBytes = src.RowSkip * srcPixelSize;
int srcSliceSkipBytes = src.SliceSkip * srcPixelSize;
int dstRowPitchBytes = dst.RowPitch * dstPixelSize;
//int dstRowSkipBytes = dst.RowSkip * dstPixelSize;
int dstSliceSkipBytes = dst.SliceSkip * dstPixelSize;
// Otherwise, copy per row
int rowSize = src.Width * srcPixelSize;
for ( int z = src.Front; z < src.Back; z++ )
{
for ( int y = src.Top; y < src.Bottom; y++ )
{
byte* s = srcptr;
byte* d = dstptr;
for ( int i = 0; i < rowSize; i++ )
*d++ = *s++;
srcptr += srcRowPitchBytes;
dstptr += dstRowPitchBytes;
}
srcptr += srcSliceSkipBytes;
dstptr += dstSliceSkipBytes;
}
}
return;
}
// Converting to X8R8G8B8 is exactly the same as converting to
// A8R8G8B8. (same with X8B8G8R8 and A8B8G8R8)
if ( dst.Format == PixelFormat.X8R8G8B8 || dst.Format == PixelFormat.X8B8G8R8 )
{
// Do the same conversion, with A8R8G8B8, which has a lot of
// optimized conversions
PixelFormat dstFormat = dst.Format == PixelFormat.X8R8G8B8 ? PixelFormat.A8R8G8B8 : PixelFormat.A8B8G8R8;
PixelBox tempdst = new PixelBox( dst, dstFormat, dst.Data );
BulkPixelConversion( src, tempdst );
return;
}
// Converting from X8R8G8B8 is exactly the same as converting from
// A8R8G8B8, given that the destination format does not have alpha.
if ( ( src.Format == PixelFormat.X8R8G8B8 || src.Format == PixelFormat.X8B8G8R8 ) && !PixelUtil.HasAlpha( dst.Format ) )
{
// Do the same conversion, with A8R8G8B8, which has a lot of
// optimized conversions
PixelFormat srcFormat = src.Format == PixelFormat.X8R8G8B8 ? PixelFormat.A8R8G8B8 : PixelFormat.A8B8G8R8;
PixelBox tempsrc = new PixelBox( src, srcFormat, src.Data );
BulkPixelConversion( tempsrc, dst );
return;
}
if ( OptimizedPixelConversion.DoOptimizedConversion( src, dst ) )
// If so, good
return;
// TODO : Use OptimizedPixelConversion to elminate this duplicate code.
unsafe
{
byte* srcBytes = (byte*)src.Data.ToPointer();
byte* dstBytes = (byte*)dst.Data.ToPointer();
byte* srcptr = srcBytes + src.Offset;
byte* dstptr = dstBytes + dst.Offset;
int srcPixelSize = PixelUtil.GetNumElemBytes( src.Format );
int dstPixelSize = PixelUtil.GetNumElemBytes( dst.Format );
// Calculate pitches+skips in bytes
int srcRowSkipBytes = src.RowSkip * srcPixelSize;
int srcSliceSkipBytes = src.SliceSkip * srcPixelSize;
int dstRowSkipBytes = dst.RowSkip * dstPixelSize;
int dstSliceSkipBytes = dst.SliceSkip * dstPixelSize;
// The brute force fallback
float r, g, b, a;
for ( int z = src.Front; z < src.Back; z++ )
{
for ( int y = src.Top; y < src.Bottom; y++ )
{
for ( int x = src.Left; x < src.Right; x++ )
{
UnpackColor( out r, out g, out b, out a, src.Format, (IntPtr)srcptr );
PackColor( r, g, b, a, dst.Format, (IntPtr)dstptr );
srcptr += srcPixelSize;
dstptr += dstPixelSize;
}
srcptr += srcRowSkipBytes;
dstptr += dstRowSkipBytes;
}
srcptr += srcSliceSkipBytes;
dstptr += dstSliceSkipBytes;
}
}
}