top | item 43325777

(no title)

obrhubr | 11 months ago

Thanks for your comment! I'm glad you're seeing the same thing :) I re-implemented the linearised dithering in python and got similar results. I checked and rechecked the colour profiles in GIMP, nothing... At this point I can only hope for an expert to appear and tell me what exactly I am doing wrong.

discuss

order

bazzargh|11 months ago

I got better results just dithering the rgb channels separately (so effectively an 8 colour palette, black, white, rgb, yellow, cyan, magenta). In p5js:

    var img
    var pixel
    var threshold
    var error = [0, 0, 0]
    var a0

    function preload() {
      img = loadImage("https://upload.wikimedia.org/wikipedia/commons/thumb/4/44/Albrecht_D%C3%BCrer_-_Hare%2C_1502_-_Google_Art_Project.jpg/1920px-Albrecht_D%C3%BCrer_-_Hare%2C_1502_-_Google_Art_Project.jpg")
    }

    function setup() {
      // I'm just using a low discrepancy sequence for a quasirandom
      // dither and diffusing the error to the right, because it's
      // trivial to implement
      a0 = 1/sqrt(5)
      pixelDensity(2)
      createCanvas(400, 400);
      image(img, 0, 0, 400, 400)
      loadPixels()
      pixel = 0
      threshold = 0
    }

    function draw() {
      if (pixel > 400*400*16) {
        return
      }
      for (var i = 0; i < 2000; i++) {
        threshold = (threshold + a0)%1
        for(var j=0; j< 3; j++) {
          var c = pixels[pixel + j]
          pixels[pixel + j] = c + error[j] > threshold * 255 ? 255 : 0
          error[j] += c - pixels[pixel + j]
        }
        pixel += 4
      }
      updatePixels()
    }
Of course this isn't trying to pick the closest colour in the palette as you're doing - it's just trying to end up with the same intensity of rgb as the original image. It does make me wonder if you should be using the manhattan distance instead of euclidean, to get the errors to add correctly.

mkesper|11 months ago

Did you try any of the OKlab color space implementations for calculating? https://bottosson.github.io/posts/oklab/

obrhubr|11 months ago

I’ll try them as soon as I get the chance, I have perceptual luminance implemented already. I’ll compare :)

ack_complete|11 months ago

It looks like the images on your blog might have gone through a non-gamma-corrected scaler. The linear images produced the program look correct, they do overall match the original image in Krita when scaled in scRGB linear 32-bit float.