After our session on MTS there were two questions. I think that those questions need some comment. We were not 100% sure of answers, so we said that it will be the best to make some test and check how the phone will behave. We didn’t have possibility to do this on MTS, so we have done it now. The results confirmed our answers.

# Question 1

The first question concerned whether changing only loop order will accelerate application in a similar way. The common index calculation will not be introduced in this solution. Our code has been changed from:

public void Convert1(WriteableBitmap bitmap)
{
int[] grayScale = new int[bitmap.PixelHeight * bitmap.PixelWidth];
for (int i = 0; i < bitmap.PixelWidth; i++) { for (int j = 0; j < bitmap.PixelHeight; j++) { Color currentColor = this.ConvertToColor( bitmap.Pixels[i + (bitmap.PixelHeight * j)]); Color grayColor = this.ToGrayScale(currentColor); grayScale[i + (bitmap.PixelHeight * j)] = this.ToIntFromColor(grayColor); } } }[/code]

to:

public void Convert2(WriteableBitmap bitmap)
{
int[] grayScale = new int[bitmap.PixelHeight * bitmap.PixelWidth];
for (int j = 0; j < bitmap.PixelHeight; j++) { for (int i = 0; i < bitmap.PixelWidth; i++) { Color currentColor = this.ConvertToColor( bitmap.Pixels[i + (bitmap.PixelHeight * j)]); Color grayColor = this.ToGrayScale(currentColor); grayScale[i + (bitmap.PixelHeight * j)] = this.ToIntFromColor(grayColor); } } }[/code]

As a reminder, you can find our proposal of the first step of optimisation:

public void Convert3(WriteableBitmap bitmap)
{
int[] grayScale = new int[bitmap.PixelHeight * bitmap.PixelWidth];
for (int j = 0; j < bitmap.PixelHeight; j++) { int heightIndex = bitmap.PixelHeight * j; for (int i = 0; i < bitmap.PixelWidth; i++) { int pixelIndex = i + heightIndex; Color currentColor = this.ConvertToColor(bitmap.Pixels[pixelIndex]); Color grayColor = this.ToGrayScale(currentColor); grayScale[pixelIndex] = this.ToIntFromColor(grayColor); } } }[/code]

We have made 1000 measurements on each of three devices – Nokia Lumia 800, HTC Titan and HTC 7 Pro. As you can see the execution time has shortened, but only slightly.

 Method Nokia Lumia 800 HTC Titan HTC 7 Pro Convert1 236,57 ms 263,42 ms 393,08 ms Convert2 223,17 ms 234,88 ms 350,30 ms Convert3 179,32 ms 170,63 ms 253,50 ms

Based on these results, we can see that the first modification shortened the duration of method execution only by an average 9%. After adding common index calculation to method with reordered loops we can reduce time by 32% average.

# Question 2

The second question was about final implementation:

public void Convert4(WriteableBitmap bitmap)
{
int[] pixels = bitmap.Pixels;
int length = pixels.Length;
int[] grayScale = new int[length];
for (int i = 0; i < length; i++) { int currentPixel = pixels[i]; int a = (byte)(currentPixel >> 24);
int r = (byte)(currentPixel >> 16);
int g = (byte)(currentPixel >> 8);
int b = (byte)currentPixel;
int gray = (6966 * r + 23436 * g + 2366 * b) >> 15;
int grayColor = (a << 24) | (gray << 16) | (gray << 8) | gray; grayScale[i] = grayColor; } }[/code]

There was an idea to put [mark]int[/mark] variables declaration before the loop. Let’s see what will happen. Below you can find proposed implementation:

public void Convert5(WriteableBitmap bitmap)
{
int[] pixels = bitmap.Pixels;
int length = pixels.Length;
int[] grayScale = new int[length];
int currentPixel, a, r, g, b, gray, grayColor;
for (int i = 0; i < length; i++) { currentPixel = pixels[i]; a = (byte)(currentPixel >> 24);
r = (byte)(currentPixel >> 16);
g = (byte)(currentPixel >> 8);
b = (byte)currentPixel;
gray = (6966 * r + 23436 * g + 2366 * b) >> 15;
grayColor = (a << 24) | (gray << 16) | (gray << 8) | gray; grayScale[i] = grayColor; } }[/code]

After this change nothing has changed. Both – the maximum of memory usage and the execution time – remains the same.