Axiom.Media.PixelConverter.BulkPixelConversion C# (CSharp) Method

BulkPixelConversion() public static method

Convert pixels from one format to another. No dithering or filtering is being done. Converting from RGB to luminance takes the R channel.
The source and destination boxes must have the same dimensions. In case the source and destination format match, a plain copy is done.
public static BulkPixelConversion ( PixelBox src, PixelBox dst ) : void
src PixelBox PixelBox containing the source pixels, pitches and format
dst PixelBox PixelBox containing the destination pixels, pitches and format
return void
		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;
				}
			}
		}

Same methods

PixelConverter::BulkPixelConversion ( IntPtr srcBytes, int srcOffset, PixelFormat srcFormat, IntPtr dstBytes, int dstOffset, PixelFormat dstFormat, int count ) : void