public static partial class MyConverter
public static Complex[,] BitmapToComplex2D(Bitmap image)
if (image.PixelFormat != PixelFormat.Format8bppIndexed)
throw new Exception("Source image must be grayscale (8bpp indexed) only.");
BitmapData imageData = image.LockBits(
new Rectangle(0, 0, image.Width, image.Height),
ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
complexImage = FromBitmapData(imageData);
image.UnlockBits(imageData);
private static Complex[,] FromBitmapData(BitmapData bitmapData)
if (bitmapData.PixelFormat != PixelFormat.Format8bppIndexed)
throw new Exception("Source image can be graysclae (8bpp indexed) image only.");
int width = bitmapData.Width;
int height = bitmapData.Height;
int offset = bitmapData.Stride - width;
if ((!Utils.IsPowerOf2(width)) || (!Utils.IsPowerOf2(height)))
throw new Exception("Image width and height should be power of 2.");
Complex[,] data = new Complex[width, height];
byte* src = (byte*)bitmapData.Scan0.ToPointer();
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++, src++)
data[y, x] = new Complex((float)*src / 255,
public static Bitmap Complex2DToBitmap(Complex[,] twoDimComplexArray, bool fourierTransformed)
int width = twoDimComplexArray.GetLength(0);
int height = twoDimComplexArray.GetLength(1);
Bitmap dstImage = Utils.CreateGrayscaleImage(width, height);
BitmapData dstData = dstImage.LockBits(
new Rectangle(0, 0, width, height),
ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
int offset = dstData.Stride - width;
double scale = (fourierTransformed) ? Math.Sqrt(width * height) : 1;
byte* dst = (byte*)dstData.Scan0.ToPointer();
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++, dst++)
*dst = (byte)System.Math.Max(0, System.Math.Min(255,
twoDimComplexArray[y, x].Magnitude * scale * 255));
dstImage.UnlockBits(dstData);