1

I am attempting to implement a Bayer ordered dithering matrix algorithm to convert a 24bit color image to a 3bit image. I have read the Wikipedia page, and several textbook sections on the topic and am a bit confused. This is what I have so far:

for (int y = 0; x < image.Height; y++)
{  
    for (int x = 0; x < image.Width; x++)
    {
        Color color = image.GetPixel(x,y);  
        color.R = color.R + bayer4x4[x % 4, y % 4];  
        color.G = color.G + bayer4x4[x % 4, y % 4];  
        color.B = color.B + bayer4x4[x % 4, y % 4];  
        image[x][y] = SetPixel(x, y, GetClosestColor(color, bitdepth);  
    }  
}

However, I do not have a way of implementing GetClosestColor... how can I do this?

Also, I do not have the bayer4x4 matrix defined, I believe it should look like the following:

1,  9,  3, 11
13, 5, 15, 7
4, 12,  2, 10
16, 8, 14, 6
weston
  • 54,145
  • 21
  • 145
  • 203
Nick
  • 315
  • 2
  • 9
  • 2
    `GetClosestColor` would look at the target pallet, so what pallet do you have? – weston Mar 18 '16 at 14:45
  • also, you need different threshold map as you're scaling from 256 colors to 8 – Iłya Bursov Mar 18 '16 at 14:46
  • @Lashane yes but they say source is 24bit, so I think they need at least 8x8 matrix so size matches reduction ratio of 256:1, but if this is greyscale I don't know if different math applies. – weston Mar 18 '16 at 14:51
  • This is indeed greyscale. I am looking to have 1 bit red, 1 bit green, and 1 bit blue. So, there are 16+1 different levels of greyscale. – Nick Mar 18 '16 at 16:27
  • 1
    `1 bit red, 1 bit green, and 1 bit blue.` is 8 levels – Iłya Bursov Mar 18 '16 at 16:34
  • Right, but I am using a 4x4 matrix, so doesn't that buy me 17 levels of greyscale? – Nick Mar 18 '16 at 17:32
  • Your logic is wrong - you must multiply with the matrix value, not add it. Also, for binary dithering (per color channel) as you have here, I believe the dither matrix should be ones and zeroes, only. And for the same reason you don't need GetClosestColor - you don't have a palette, just the 8 colors made up of either 0 or 1 (times 255) for each of the three components. – 500 - Internal Server Error Mar 18 '16 at 20:17
  • 1 bit for each channel is not grey scale, it is 24 bit equivalent of `(255,0,0),(0,255,0),(0,0,255),(255,255,0),(255,0,255),(0,255,255),(255,255,255),(0,0,0)` – weston Mar 19 '16 at 13:05

1 Answers1

1

Here is my implementation of Bayer 4x4.
The both input and output are in 24 bit BGR format (for visualisation purposes).
In the output each pixel plane has value 0 or 255.

const   int BAYER_PATTERN_4X4[4][4]     =   {   //  4x4 Bayer Dithering Matrix. Color levels: 17
                                                {    15, 195,  60, 240  },
                                                {   135,  75, 180, 120  },
                                                {    45, 225,  30, 210  },
                                                {   165, 105, 150,  90  }

                                            };

void    makeColorDitherBayer4x4( BYTE* pixels, int width, int height )  noexcept
{
    int col = 0;
    int row = 0;

    for( int y = 0; y < height; y++ )
    {
        row = y & 3;    //  % 4
        
        for( int x = 0; x < width; x++ )
        {
            col = x & 3;    //  % 4

            const pixel blue    = pixels[x * 3 + 0];
            const pixel green   = pixels[x * 3 + 1];
            const pixel red     = pixels[x * 3 + 2];

            pixels[x * 3 + 0]   = (blue  < BAYER_PATTERN_4X4[col][row] ? 0 : 255);
            pixels[x * 3 + 1]   = (green < BAYER_PATTERN_4X4[col][row] ? 0 : 255);
            pixels[x * 3 + 2]   = (red   < BAYER_PATTERN_4X4[col][row] ? 0 : 255);

        }

        pixels  += width * 3;
    }
}

If you want to get the output as "compressed" data, you should replace this part of code:

pixels[x * 3 + 0]   = (blue  < BAYER_PATTERN_4X4[col][row] ? 0 : 255);
pixels[x * 3 + 1]   = (green < BAYER_PATTERN_4X4[col][row] ? 0 : 255);
pixels[x * 3 + 2]   = (red   < BAYER_PATTERN_4X4[col][row] ? 0 : 255);

with something like this:

output.writeBit( (blue  < BAYER_PATTERN_4X4[col][row] ? 0 : 1) );
output.writeBit( (green < BAYER_PATTERN_4X4[col][row] ? 0 : 1) );
output.writeBit( (red   < BAYER_PATTERN_4X4[col][row] ? 0 : 1) );
greybeard
  • 2,249
  • 8
  • 30
  • 66
Svetlyo
  • 87
  • 4
  • Dear Svetlyo, when answering it is good habit to introduce the solution with come sentence and leave comments that would be helpful for others to solve similar problems by analogy – storaged Jun 30 '21 at 11:53