title: Is this a correct implementation of ordered dithering?
body: <p>I am interested in dithering, ordered dithering to be more precise.
  I spent many hours on researching and experimenting. And hope that after all the effort my code works as it should.</p>
  
  <p>I am going to provide my code that does the dithering, and some examples.</p>
  
  <p><strong>My questions</strong></p>
  
  <ul>
  <li>How does it work?</li>
  <li>Is my code correct? </li>
  <li>Could there be any simplifications?</li>
  </ul>
  
  <hr>
  
  <p>Here is the pseudo code for the dithering algorithm from <a href="https://en.wikipedia.org/wiki/Ordered_dithering" rel="nofollow noreferrer">this</a> Wikipedia article, on which my code is based on. </p>
  
  <p><img src="https://i.stack.imgur.com/i25GI.png" alt="Pseudo code"></p>
  
  <p>And here are the variable explanations:</p>
  
  <blockquote>
    <p><em>M(i, j)</em> is the threshold map on the <em>i</em>-th row and <em>j</em>-th column, <em>c′</em> is the transformed color, and <em>r</em> is the amount of spread in color space. Assuming an RGB palette with <em>N³</em> evenly chosen colors where each color coordinate is represented by an octet, one would typically choose: <a href="https://i.stack.imgur.com/PRDLG.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/PRDLG.png" alt="enter image description here"></a></p>
  </blockquote>
  
  <hr>
  
  <p><strong>Now, here is my implementation (in pseudo code):</strong></p>
  
  <pre><code>ditherMatrix = 4x4; // By 4x4 I mean the normal 4x4 dither matrix from the wikipedia article
  ditherMatrixSize = 4;
  offset = (ditherMatrixSize * (ditherMatrixSize / 2) - 0.5); 
  /* In the wiki article it uses 0.5 as an offset, 
     but I have to do this instead. 
     Is this correct? Atleast it works. */
  
  allowedChanelValues = 1; // example: 2 = (0 or 128 or 255 red, 0 or 128 or 255 green, 0 or 128 or 255 blue)
  r = 255 / allowedChanelValues / (ditherMatrixSize * ditherMatrixSize);
  
  // Applying the dither
  transfromedColor.r = 
      currentPixel.r + r * ((ditherMatrix[x % ditherMatrixSize, y % ditherMatrixSize]) - offset);
  transfromedColor.g = 
      currentPixel.g + r * ((ditherMatrix[x % ditherMatrixSize, y % ditherMatrixSize]) - offset);
  transfromedColor.g = 
      currentPixel.g + r * ((ditherMatrix[x % ditherMatrixSize, y % ditherMatrixSize]) - offset);
  
  // Quantizing, see https://youtu.be/0L2n8Tg2FwI 6:40 and 9:58 for explanation
  transfromedColor.r = Round(allowedChanelValues * oldR / 255) * (255 / allowedChanelValues);
  transfromedColor.g = Round(allowedChanelValues * oldG / 255) * (255 / allowedChanelValues);
  transfromedColor.b = Round(allowedChanelValues * oldB / 255) * (255 / allowedChanelValues);
  </code></pre>
  
  <p><strong>IMPORTANT:</strong> Now, this code could be optimized in many ways, but that's not my intention (for now) I just want it to work correctly, and then I'll look at what could be optimized.</p>
  
  <p><strong>SIDE NOTE:</strong> When I was just starting out I was hardcoding the values, for example, instead of  ditherMatrixSize * (ditherMatrixSize / 2) - 0.5, I was hardcoding 
  7.5. But after trying other dither matrices I just used this code to get the value instead of hardcoding it.</p>
  
  <hr>
  
  <p><strong>Here are some examples</strong></p>
  
  <p><a href="https://i.stack.imgur.com/XSUVQ.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/XSUVQ.png" alt="enter image description here"></a></p>
  
  <p>(Top - Dithered, Bottom - Original. The matrix is <strong>4x4</strong> and allowedChanelValues is <strong>1</strong>)</p>
  
  <hr>
  
  <p><a href="https://i.stack.imgur.com/uNNWJ.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/uNNWJ.png" alt="enter image description here"></a></p>
  
  <p>(Left - Dithered, Right- Original. The matrix is <strong>4x4</strong> and allowedChanelValues is <strong>1</strong>)</p>
  
  <hr>
  
  <p>I talked earlier about if it was possible to simplify the code.</p>
  
  <p>I found this pseudo code <a href="https://bisqwit.iki.fi/story/howto/dither/jy/" rel="nofollow noreferrer">here</a></p>
  
  <pre><code>  Threshold = COLOR(256/4, 256/4, 256/4); /* Estimated precision of the palette */
    For each pixel, Input, in the original picture:
      Factor  = ThresholdMatrix[xcoordinate % X][ycoordinate % Y];
      Attempt = Input + Factor * Threshold
      Color = FindClosestColorFrom(Palette, Attempt)
      Draw pixel using Color
  </code></pre>
  
  <p>In order to implement this, I have to normalize the matrix so it ranges from 0 to 1.
  And this is how I implement it:</p>
  
  <pre><code>factor = 1;
  offset = (ditherMatrixSize * (ditherMatrixSize / 2) - 0.5d) / (ditherMatrixSize * ditherMatrixSize); 
  // This time the offset is a bit different because I normalized the matrix
  r = 256 / factor; // r is the same as the Threshold
  
  transformedPixelColor.R = 
     currentPixel.R + r * (ditherMatrix[(x) % ditherMatrixSize, (y) % ditherMatrixSize] - offset)
  transformedPixelColor.G = 
     currentPixel.G + r * (ditherMatrix[(x) % ditherMatrixSize, (y) % ditherMatrixSize] - offset)
  transformedPixelColor.B = 
     currentPixel.B + r * (ditherMatrix[(x) % ditherMatrixSize, (y) % ditherMatrixSize] - offset)
  </code></pre>
  
  <p>This works the same as the other one.
  I even found a third way to dither, but it's more complicated and dithers the same way as these two, so I won't cover it.</p>
  
  <p>So what do you think? 
  Is the algorithm working corectly?</p>
  
  <p><strong>Thank you in advance!</strong></p>