erwinwolff/aforge

Grayscaling turns white pixel (255) into gray pixel (254)

Closed this issue · 7 comments

The attached image "white_255.bmp" is a 24 bit BMP. All pixels are white (255).

What steps will reproduce the problem?
1. Open the image in IP Lab
2. From the main menu select: Filters -> Color (RGB) -> Grayscale
3. Check the histogram

What is the expected output? What do you see instead?
All pixels should remain white, but instead they actually turn gray (254).

What version of the product are you using?
IP Lab v.2.8.0.0
AForge.NET v.2.2.5.0

Original issue reported on code.google.com by m.instn...@gmail.com on 11 Nov 2013 at 10:54

Attachments:

I checked the source code and I think the simplest solution (i.e. the one that 
requires the least changes) is to check whether the colors of a pixel are R=G=B.
If yes, use R as destination color. If no, use your current calculation to 
determine the destination color.

Original comment by m.instn...@gmail.com on 10 Dec 2013 at 11:43

The suggested fix sounds simplest, but not the best performance wise. Extra 
if-statement is not good in a loop.

Original comment by andrew.k...@gmail.com on 6 Jan 2014 at 2:58

  • Changed state: Accepted
Fixed Grayscale filter so it calculates integer coefficients which have a sum 
of 0x10000. This makes sure that white color (255, 255, 255) is correctly 
converted to gray value of 255.

Fixed in revision 1725.

Original comment by andrew.k...@gmail.com on 6 Jan 2014 at 2:59

  • Changed state: Fixed
  • Added labels: Milestone-Coming, Project-Imaging
The fix looks good. Thank you for this great project!
Just an idea: Performance-wise you could consider calculating lookup tables for 
grayscaling instead of do the calculation for each pixel. That should improve 
the performance for all pictures with more than 3*256=768 pixel.

Original comment by m.instn...@gmail.com on 8 Jan 2014 at 7:18

Please elaborate on your idea ...

If I don't miss anything, then look up table's size will be 256*256*256 ... 
Which is quite big to keep it in memory and for sure will take more time to 
calculate than to do a grayscaling.

Original comment by andrew.k...@gmail.com on 8 Jan 2014 at 7:58

At the moment you calculate for each pixel of the source image:
dst = rc*RGB.R + gc*RGB.G + bc*RGB.B
That makes 3 multiplications and 3 additions per pixel.

The idea of using lookup tables is t pre-calculate the results of the 
multiplications and store them in an array:
for (i=0; i <= 255; i++)
{
  LUT_R[i] = rc*i;
  LUT_G[i] = gc*i;
  LUT_B[i] = bc*i;
}
Note that the lookup table size is 3*256.

Then, for each pixel simply calculate the destination color as follows:
dst = LUT_R[RGB.R] + LUT_G[RGB.G] + LUT_B[RGB.B]

This approach has a fixed number of 768 multiplications while the number of 
additions is the same as in your approach. Hence, it should perform better on 
pictures with more than 256 pixel (not 768 as i did post before).

Original comment by m.instn...@gmail.com on 8 Jan 2014 at 9:17

Ah, OK. Just misunderstood a bit. You want 3 LUTs. OK, maybe someday.

Original comment by andrew.k...@gmail.com on 8 Jan 2014 at 9:24