2

Is one of these decidedly faster?

var scan0 = (uint*)bitmapData.Scan0;
int length = pixels.Length;
for (int i = 0; i < length; i++)
{
    uint j = scan0[i];
    float a = (j >> 24) / 255f;
    pixels[i] = new Vector(
        (j >> 16 & 0xff) * a / 255,
        (j >> 8 & 0xff) * a / 255,
        (j & 0xff) * a / 255);
}

versus

var scan0 = (byte*)bitmapData.Scan0;
int length = pixels.Length * 4;
for (int i = 0; i < length; i += 4)
{
    float a = scan0[i + 3] / 255f;
    pixels[i / 4] = new Vector(
        scan0[i + 2] * a / 255,
        scan0[i + 1] * a / 255,
        scan0[i] * a / 255);
}
5
  • 2
    It seems like this would be quite easy for you to measure yourself - however, I would guess that the performance would be somewhat identical on modern processors. Commented Jul 28, 2011 at 9:19
  • 2
    Maybe. Why not find out? Commented Jul 28, 2011 at 9:19
  • Also, remember that being fast isn't the be-all and end-all. The second one is an awful lot more readable, and that's valuable. Commented Jul 28, 2011 at 9:21
  • In the first example, you don't need to AND-ize the shifted "j" with 0xFF. Simply cast the shift to a byte before dividing by 255. Commented Jul 28, 2011 at 10:12
  • As a side-note: I'd calculate a2 = a*(1/255f) and multiply the pixel values with that. That might be even faster. But do benchmarks to know which is fastest. Commented Jul 28, 2011 at 10:15

2 Answers 2

5

In a 32 bit application, the second is about 2.5 times faster than the first. In a 64 bit application, the second is about 25% faster than the first.

Note that there is a bug in your second code. As you are adding four in each iteration, you will place the objects in every fourth item in the pixels array, and cause an IndexOutOfRangeException exception when it runs out of array.

Slightly faster (about 5%) than the second is to move the pointer for each pixel:

byte* scan0 = (byte*)bitmapData.Scan0;
for (int i = 0; i < pixels.Length; i++) {
  float a = scan0[3] / 255f;
  pixels[i] = new Vector(
    scan0[2] * a / 255,
    scan0[1] * a / 255,
    scan0[0] * a / 255
  );
  scan0 += 4;
}

Note also that if you are reading data from a Bitmap image, it is not stored as a continuous array of pixel data. There may be padding between the scan lines, so the code can only read pixels from a single scan line, it can not safely read data from an entire image.

Edit:

Also, I just realised that you put the length of the array in a variable and used that in the loop. That will just make the code slower instead of faster, as the compiler can't optimise away the range check on the array accesses.

Sign up to request clarification or add additional context in comments.

Comments

0

I think the bit shift "Your first solution" is faster. however you can test it by using Stopwatch. Start the stopwatch before the call the method, run the method multiple time, and then stop the watch and check its ElapcedMilliseconds. Like:

System.Diagnostics.Stopwatch watch = Stopwatch.StartNew();
//run your method that want to test its executable time multi time
for (int testIndex = 0; testIndex < 100; testIndex++)    
{ 
    TestWithShift(); 
}

watch.Stop();
Console.WriteLine("Test with shift time: {0}", watch.ElapcedMilliseconds);

And repeat the test for the other method. Hope that helps.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.