5
\$\begingroup\$

I have written the following routines to work with digital images in various representations.

Can I optimize them for better accuracy and performance?

public static partial class ImageDataConverter
{
 #region Bitmap ToBitmap32(int[,] image)
 //Tested
 ///Working fine. 
 public static Bitmap ToBitmap32(int[,] image)
 {
 int Width = image.GetLength(0);
 int Height = image.GetLength(1);
 int i, j;
 Bitmap bitmap = new Bitmap(Width, Height);
 BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, Width, Height),
 ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
 int bytesPerPixel = sizeof(int);
 unsafe
 {
 byte* address = (byte*)bitmapData.Scan0;
 for (i = 0; i < bitmapData.Height; i++)
 {
 for (j = 0; j < bitmapData.Width; j++)
 {
 byte[] bytes = BitConverter.GetBytes(image[j, i]);
 for (int k = 0; k < bytesPerPixel; k++)
 {
 address[k] = bytes[k];
 }
 //4 bytes per pixel
 address += bytesPerPixel;
 }//end for j
 //4 bytes per pixel
 address += (bitmapData.Stride - (bitmapData.Width * bytesPerPixel));
 }//end for i
 }//end unsafe
 bitmap.UnlockBits(bitmapData);
 return bitmap;// col;
 } 
 #endregion
 #region int[,] ToInteger32(Bitmap bitmap)
 //Tested
 ///Working fine. 
 public static int[,] ToInteger32(Bitmap bitmap)
 {
 int[,] array2D = new int[bitmap.Width, bitmap.Height];
 BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
 ImageLockMode.ReadWrite,
 PixelFormat.Format32bppRgb);
 int bytesPerPixel = sizeof(int);
 unsafe
 {
 byte* address = (byte*)bitmapData.Scan0;
 int paddingOffset = bitmapData.Stride - (bitmap.Width * bytesPerPixel);//4 bytes per pixel
 for (int i = 0; i < bitmap.Width; i++)
 {
 for (int j = 0; j < bitmap.Height; j++)
 {
 byte[] temp = new byte[bytesPerPixel];
 for (int k = 0; k < bytesPerPixel; k++)
 {
 temp[k] = address[k];
 }
 array2D[j, i] = BitConverter.ToInt32(temp, 0);
 //4-bytes per pixel
 address += bytesPerPixel;//4-channels
 }
 address += paddingOffset;
 }
 }
 bitmap.UnlockBits(bitmapData);
 return array2D;
 } 
 #endregion
 public static int[,] ToInteger(Bitmap image)
 {
 Bitmap bitmap = (Bitmap)image.Clone();
 int[,] array2D = new int[bitmap.Width, bitmap.Height];
 BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
 ImageLockMode.ReadWrite,
 PixelFormat.Format8bppIndexed);
 int bytesPerPixel = sizeof(byte);
 unsafe
 {
 byte* address = (byte*)bitmapData.Scan0;
 int paddingOffset = bitmapData.Stride - (bitmap.Width * bytesPerPixel);
 for (int i = 0; i < bitmap.Width; i++)
 {
 for (int j = 0; j < bitmap.Height; j++)
 {
 byte[] temp = new byte[bytesPerPixel];
 for (int k = 0; k < bytesPerPixel; k++)
 {
 temp[k] = address[k];
 }
 int iii = 0;
 if (bytesPerPixel >= sizeof(int))
 {
 iii = BitConverter.ToInt32(temp, 0);
 }
 else
 {
 iii = (int)temp[0];
 }
 array2D[j, i] = iii;
 address += bytesPerPixel;
 }
 address += paddingOffset;
 }
 }
 bitmap.UnlockBits(bitmapData);
 return array2D;
 }
 public static Bitmap ToBitmap(int[,] image)
 {
 int Width = image.GetLength(0);
 int Height = image.GetLength(1);
 int i, j;
 Bitmap bitmap = new Bitmap(Width, Height, PixelFormat.Format8bppIndexed);
 BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, Width, Height),
 ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
 int bytesPerPixel = sizeof(byte);
 unsafe
 {
 byte* address = (byte*)bitmapData.Scan0;
 for (i = 0; i < bitmapData.Height; i++)
 {
 for (j = 0; j < bitmapData.Width; j++)
 {
 byte[] bytes = BitConverter.GetBytes(image[j, i]);
 for (int k = 0; k < bytesPerPixel; k++)
 {
 address[k] = bytes[k];
 }
 address += bytesPerPixel;
 }
 address += (bitmapData.Stride - (bitmapData.Width * bytesPerPixel));
 }
 }
 bitmap.UnlockBits(bitmapData);
 Grayscale.SetGrayscalePalette(bitmap);
 return bitmap;
 }
 public static int [,] ToInteger(Complex [,] image)
 {
 int Width = image.GetLength(0);
 int Height = image.GetLength(1);
 int[,] integer = new int[Width, Height];
 for (int j = 0; j <= Height - 1; j++)
 {
 for (int i = 0; i <= Width - 1; i++)
 {
 integer[i, j] = ((int)image[i, j].Magnitude);
 }
 }
 return integer;
 }
 public static Complex [,] ToComplex(int[,] image)
 {
 int Width = image.GetLength(0);
 int Height = image.GetLength(1);
 Complex[,] comp = new Complex[Width, Height];
 for (int j = 0; j <= Height - 1; j++)
 {
 for (int i = 0; i <= Width - 1; i++)
 {
 Complex tempComp = new Complex((double)image[i,j], 0.0);
 comp[i,j] = tempComp;
 }
 }
 return comp;
 }
 public static Complex[,] ToComplexFaster(Bitmap image)
 {
 Bitmap bitmap = (Bitmap)image.Clone();
 Complex[,] comp = new Complex[bitmap.Width, bitmap.Height];
 BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
 ImageLockMode.ReadWrite,
 PixelFormat.Format8bppIndexed);
 int bytesPerPixel = sizeof(byte);
 unsafe
 {
 byte* address = (byte*)bitmapData.Scan0;
 int paddingOffset = bitmapData.Stride - (bitmap.Width * bytesPerPixel);
 for (int j = 0; j < bitmap.Height; j++)
 {
 for (int i = 0; i < bitmap.Width; i++)
 {
 byte[] temp = new byte[bytesPerPixel];
 for (int k = 0; k < bytesPerPixel; k++)
 {
 temp[k] = address[k];
 }
 int iii = 0;
 if (bytesPerPixel >= sizeof(int))
 {
 iii = BitConverter.ToInt32(temp, 0);
 }
 else
 {
 iii = (int)temp[0];
 }
 Complex tempComp = new Complex((double)iii, 0.0);
 comp[i,j] = tempComp;
 address += bytesPerPixel;
 }
 address += paddingOffset;
 }
 }
 bitmap.UnlockBits(bitmapData);
 return comp;
 }
 public static Bitmap ToBitmapFaster(Complex[,] image)
 {
 int Width = image.GetLength(0);
 int Height = image.GetLength(1);
 int i, j;
 Bitmap bitmap = new Bitmap(Width, Height, PixelFormat.Format8bppIndexed);
 BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, Width, Height),
 ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
 int bytesPerPixel = sizeof(byte);
 unsafe
 {
 byte* address = (byte*)bitmapData.Scan0;
 for (i = 0; i < bitmapData.Height; i++)
 {
 for (j = 0; j < bitmapData.Width; j++)
 {
 int integer = ((int)image[j, i].Magnitude);
 byte[] bytes = BitConverter.GetBytes(integer);
 for (int k = 0; k < bytesPerPixel; k++)
 {
 address[k] = bytes[k];
 }
 address += bytesPerPixel;
 }
 address += (bitmapData.Stride - (bitmapData.Width * bytesPerPixel));
 }
 }
 bitmap.UnlockBits(bitmapData);
 Grayscale.SetGrayscalePalette(bitmap);
 return bitmap;
 }
}
asked Aug 28, 2016 at 16:03
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Loops

I do not really like this kind of loops :

for (int j = 0; j <= Height - 1; j++)

I would prefer :

for (int j = 0; j < Height; j++)

but according to this stack overflow thread performance should not be harmed.

Operations within the loops

I notice that this operation : bitmapData.Width * bytesPerPixel is repeated in some of your loops. You can expect a (small) gain if you evaluate them outside the loop.

Towards better accessors ?

Actually the accessor a[i,j] can be improved, especially in loops like :

 for (int j = 0; j <= Height - 1; j++)
 {
 for (int i = 0; i <= Width - 1; i++)
 {
 integer[i, j] = ((int)image[i, j].Magnitude);
 }
}

If integer was a 1-dimensional array, of size Height * Width, you could just have a single loop over all the elements, that would be faster. But this needs you to change all your code.

Parallel processing ?

We do not have information regarding the size of the images you are working with, and parallel processing can make you waste a lot of time, especially if the number of instructions per loop are small.

But these loops :

 for (int j = 0; j <= Height - 1; j++)
 {
 for (int i = 0; i <= Width - 1; i++)
 {
 integer[i, j] = ((int)image[i, j].Magnitude);
 }
}

and:

for (int j = 0; j <= Height - 1; j++)
{
for (int i = 0; i <= Width - 1; i++)
{
 Complex tempComp = new Complex((double)image[i,j], 0.0);
 comp[i,j] = tempComp;
 }
}

could easily be parallelized over the rows or the columns.

answered Oct 20, 2016 at 11:19
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.