Faster bitmap comparison algorithm

I have a tool with caterpillar slider controls that are used to adjust brightness, contrast, gamma, etc.

I am trying to get real-time updates for my image while the user drags the slider. Brightness and gamma algorithms are an acceptable speed (about 170 ms). But the contrast algorithm is about 380 ms.

Basically my form is a window with sliders. Each time the image is updated, it dispatches an event to the parent object, which redraws the new image. The tool window stores the original unmodified image in memory, so I always have access to its bytes. So basically, I do this every time the ValueChanged event for the slider (for example, the Contrast slider) changes.

  • LockBits of the working (target) bitmap in Format24bppRgb format (the original bitmap is in 32bppPArgb format)
  • Marshal. Copy bits to byte [] array
  • Check which operation I perform (which slider was selected)
  • Use the following code for Contrast:

the code:

double newValue = 0; double c = (100.0 + contrast) / 100.0; c *= c; for (int i = 0; i < sourcePixels.Length; i++) { newValue = sourcePixels[i]; newValue /= 255.0; newValue -= 0.5; newValue *= c; newValue += 0.5; newValue *= 255; if (newValue < 0) newValue = 0; if (newValue > 255) newValue = 255; destPixels[i] = (byte)newValue; } 

I read once about using an integer instead of floating point values ​​to increase the speed of contrast, but I could not find this article again.

I tried using unsafe code (pointers), but actually noticed a decrease in speed. I guess this was because the code used nested for loops to iterate x and y instead of a single loop.

+5
performance c # bitmap contrast
source share
2 answers

Depending on the machine you are working on, your technique may be quite slow. If you use an ARM system without FPU, each of these operations will take quite a while. Since you apply the same operation to each byte, a faster technique would be to create a lookup table with 256 inputs for the contrast level, and then translate each byte of the image through the table. Then your loop will look like this:

 byte contrast_lookup[256]; double newValue = 0; double c = (100.0 + contrast) / 100.0; c *= c; for (int i = 0; i < 256; i++) { newValue = (double)i; newValue /= 255.0; newValue -= 0.5; newValue *= c; newValue += 0.5; newValue *= 255; if (newValue < 0) newValue = 0; if (newValue > 255) newValue = 255; contrast_lookup[i] = (byte)newValue; } for (int i = 0; i < sourcePixels.Length; i++) { destPixels[i] = contrast_lookup[sourcePixels[i]]; } 
+10
source share

@BitBank answers your question, as I asked, I would like to add that if you are after execution, you should consider your code, which receives pixel data and installs it after that.

Full working code using pointers (props on @BitBank to the for loop code):

 private unsafe void ApplyContrast(double contrast, Bitmap bmp) { byte[] contrast_lookup = new byte[256]; double newValue = 0; double c = (100.0 + contrast) / 100.0; c *= c; for (int i = 0; i < 256; i++) { newValue = (double)i; newValue /= 255.0; newValue -= 0.5; newValue *= c; newValue += 0.5; newValue *= 255; if (newValue < 0) newValue = 0; if (newValue > 255) newValue = 255; contrast_lookup[i] = (byte)newValue; } var bitmapdata = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb); int PixelSize = 4; for (int y = 0; y < bitmapdata.Height; y++) { byte* destPixels = (byte*)bitmapdata.Scan0 + (y * bitmapdata.Stride); for (int x = 0; x < bitmapdata.Width; x++) { destPixels[x * PixelSize] = contrast_lookup[destPixels[x * PixelSize]]; // B destPixels[x * PixelSize + 1] = contrast_lookup[destPixels[x * PixelSize + 1]]; // G destPixels[x * PixelSize + 2] = contrast_lookup[destPixels[x * PixelSize + 2]]; // R //destPixels[x * PixelSize + 3] = contrast_lookup[destPixels[x * PixelSize + 3]]; //A } } bmp.UnlockBits(bitmapdata); } 

If you customize your pixel image data with Marshal.Copy , you will find that it works better.

This should work faster than your current code, and also reduces the amount of memory that is good when working with very large images.

+3
source share

All Articles