title: Floyd Steinberg Dithering Matlab - What am I doing wrong?
body: <p>I am trying to implement Floyd Steinberg Dithering in MATLAB, using the pseudocode on the Wikipedia page <a href="https://en.wikipedia.org/wiki/Floyd%E2%80%93Steinberg_dithering" rel="nofollow noreferrer">https://en.wikipedia.org/wiki/Floyd%E2%80%93Steinberg_dithering</a></p>
  <p>My code is below</p>
  <pre class="lang-matlab prettyprint-override"><code>image = double(imread(&quot;dithering.jpg&quot;)) ./ 255;
  levels = 2;
  
  image_quantised = round(image .* (levels - 1)) ./ (levels - 1);
  error = image - image_quantised;
  
  height = size(image(:, :, 1), 1);
  width = size(image(:, :, 1), 2);
  
  image_dithered = image_quantised;
  
  for y = 1:height - 1
      for x = 2:width - 1
                  
          image_dithered(y    , x + 1, :) = image_dithered(y    , x + 1, :) + error(y, x, :) .* 7 / 16;
          image_dithered(y + 1, x - 1, :) = image_dithered(y + 1, x - 1, :) + error(y, x, :) .* 3 / 16;
          image_dithered(y + 1, x    , :) = image_dithered(y + 1, x    , :) + error(y, x, :) .* 5 / 16;
          image_dithered(y + 1, x + 1, :) = image_dithered(y + 1, x + 1, :) + error(y, x, :) .* 1 / 16;
          
      end
  end
  
  imshow(image_dithered)  % Image 1
  imshow(dither(mean(image, 3)))  % Image 2
  </code></pre>
  <p>Image 1</p>
  <p><a href="https://i.stack.imgur.com/ixMBa.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ixMBa.png" alt="Image 1, incorrectly dithered" /></a></p>
  <p>Image 2</p>
  <p><a href="https://i.stack.imgur.com/JgDAl.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/JgDAl.png" alt="Image 2, correct dithering result" /></a></p>
  <p>I am expecting the result in Image 2, but I am getting Image 1. It looks as though the algorithm isn't doing anything. Any ideas? :)</p>
  <p>Edit: I have tried initialising <code>image_dithered</code> with different values; all zeros, the quantised image, and the original image. None of them work correctly</p>
  <p>Edit 2: I'm getting closer by now calculating the error and quantisation within the loop. Still not spot on however.</p>
  <pre class="lang-matlab prettyprint-override"><code>for y = 1:height - 1
      for x = 2:width - 1
          new_pixel = round(image_dithered(y, x, :) .* (levels - 1)) ./ (levels - 1);
          image_dithered(y, x, :) = new_pixel;
  
          error = image(y, x, :) - new_pixel;
  
          image_dithered(y    , x + 1, :) = image_dithered(y    , x + 1, :) + error .* 7 / 16;
          image_dithered(y + 1, x - 1, :) = image_dithered(y + 1, x - 1, :) + error .* 3 / 16;
          image_dithered(y + 1, x    , :) = image_dithered(y + 1, x    , :) + error .* 5 / 16;
          image_dithered(y + 1, x + 1, :) = image_dithered(y + 1, x + 1, :) + error .* 1 / 16;
      end
  end
  </code></pre>
  <p>Edit 3: Thanks for the @saastn and @Cris Luengo, both of the answers helped me work out where I was going wrong and it appears to be working as expected now!</p>
  <p>The fixed code is below for completeness.</p>
  <pre class="lang-matlab prettyprint-override"><code>height = size(image(:, :, 1), 1);
  width = size(image(:, :, 1), 2);
  
  image_dithered = image;
  
  for y = 1:height - 1
      for x = 2:width - 1
          old_pixel = image_dithered(y, x, :);
          new_pixel = round(image_dithered(y, x, :) .* (levels - 1)) ./ (levels - 1);
          
          image_dithered(y, x, :) = new_pixel;
          
          error = old_pixel - new_pixel;
          
          image_dithered(y    , x + 1, :) = image_dithered(y    , x + 1, :) + error .* 7 / 16;
          image_dithered(y + 1, x - 1, :) = image_dithered(y + 1, x - 1, :) + error .* 3 / 16;
          image_dithered(y + 1, x    , :) = image_dithered(y + 1, x    , :) + error .* 5 / 16;
          image_dithered(y + 1, x + 1, :) = image_dithered(y + 1, x + 1, :) + error .* 1 / 16;
          
      end
  end
  
  imshow(image_dithered)
  imshow(dither(mean(image, 3)))
  </code></pre>
  <p><a href="https://i.stack.imgur.com/hJ2qk.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/hJ2qk.png" alt="Almost working dithering image, however not exactly the result that is expected" /></a></p>