From 23330d06c74e8f4bcbcbb36bca107f567411eb92 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Mon, 12 Jul 2021 22:52:08 -0700 Subject: . Undo commit 70a03be0d0 and reinline the helper extracted there. I have a better sense now of the primitives to reuse between greyscale and color dithering. https://merveilles.town/@akkartik/106571585137582228 --- img.mu | 80 ++-- rgb-dither.png | Bin 0 -> 46657 bytes rgb-dither.svg | 1294 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1331 insertions(+), 43 deletions(-) create mode 100644 rgb-dither.png create mode 100644 rgb-dither.svg diff --git a/img.mu b/img.mu index db9cff4e..6b37a3d9 100644 --- a/img.mu +++ b/img.mu @@ -477,10 +477,43 @@ fn dither-pgm-unordered _src: (addr image), _dest: (addr image) { { compare x, src-width break-if->= - var color/eax: byte <- _read-pgm-buffer src-data, x, y, src-width - var error/esi: int <- copy 0 - color, error <- compute-greyscale-color-and-error errors, color, x, y, src-width - _write-raw-buffer dest-data, x, y, src-width, color + var initial-color/eax: byte <- _read-pgm-buffer src-data, x, y, src-width + var error/esi: int <- _read-dithering-error errors, x, y, src-width + # error += (initial-color << 16) + { + var tmp/eax: int <- copy initial-color + tmp <- shift-left 0x10 # we have 32 bits; we'll use 16 bits for the fraction and leave 8 for unanticipated overflow + error <- add tmp + } + # nearest-color = nearest(error >> 16) + var nearest-color/eax: int <- copy error + nearest-color <- shift-right-signed 0x10 + { + compare nearest-color, 0 + break-if->= + nearest-color <- copy 0 + } + # . round to nearest multiple of 0x10 + { + var tmp/ecx: int <- copy nearest-color + tmp <- and 0xf + compare tmp, 8 + break-if-< + nearest-color <- add 8 + } + nearest-color <- and 0xf0 + # error -= (nearest-color << 16) + { + var tmp/eax: int <- copy nearest-color + tmp <- shift-left 0x10 + error <- subtract tmp + } + # color-index = (nearest-color >> 4 + 16) + var color-index/eax: int <- copy nearest-color + color-index <- shift-right 4 + color-index <- add 0x10 + var color-index-byte/eax: byte <- copy-byte color-index + _write-raw-buffer dest-data, x, y, src-width, color-index-byte _diffuse-dithering-error-floyd-steinberg errors, x, y, src-width, src-height, error x <- increment loop @@ -491,45 +524,6 @@ fn dither-pgm-unordered _src: (addr image), _dest: (addr image) { } } -fn compute-greyscale-color-and-error errors: (addr array int), initial-color: byte, x: int, y: int, width: int -> _/eax: byte, _/esi: int { - # pseudocode: - # error += (initial-color << 16) - # nearest-color = nearest(error >> 16) - # error -= (nearest-color << 16) - # return nearest-color >> 4 + 16, error - var error/esi: int <- _read-dithering-error errors, x, y, width - # error += (initial-color << 16) - var tmp/eax: int <- copy initial-color - tmp <- shift-left 0x10 # we have 32 bits; we'll use 16 bits for the fraction and leave 8 for unanticipated overflow - error <- add tmp - # nearest-color = nearest(error >> 16) - var nearest-color/ecx: int <- copy error - nearest-color <- shift-right-signed 0x10 - { - compare nearest-color, 0 - break-if->= - nearest-color <- copy 0 - } - # . round to nearest multiple of 0x10 - { - var tmp/eax: int <- copy nearest-color - tmp <- and 0xf - compare tmp, 8 - break-if-< - nearest-color <- add 8 - } - nearest-color <- and 0xf0 - # error -= (nearest-color << 16) - var tmp/eax: int <- copy nearest-color - tmp <- shift-left 0x10 - error <- subtract tmp - # return (nearest-color >> 4 + 16), error - nearest-color <- shift-right 4 - nearest-color <- add 0x10 - var color-byte/eax: byte <- copy-byte nearest-color - return color-byte, error -} - # Use Floyd-Steinberg algorithm for diffusing error at x, y in a 2D grid of # dimensions (width, height) # diff --git a/rgb-dither.png b/rgb-dither.png new file mode 100644 index 00000000..957e1a17 Binary files /dev/null and b/rgb-dither.png differ diff --git a/rgb-dither.svg b/rgb-dither.svg new file mode 100644 index 00000000..0cfa60bb --- /dev/null +++ b/rgb-dither.svg @@ -0,0 +1,1294 @@ + + + + + + + + + + + + + + + + + + + + + + + + red-error(x, y) + + red + + + + green + blue + + + red + + + + green + blue + + + 0 + + + + red + 0 (16) + + + 0 + + + + red + 0 (16) + + + + + red + + + + + + + + - + + - + + - + + + round + + + + blue-error(x, y) + + 0 + + + + blue + 0 (16) + + + 0 + + + + blue + 0 (16) + + blue + + + + + + + + + round + + + + green-error(x, y) + + 0 + + + + green + 0 (16) + + + 0 + + + + green + 0 (16) + + green + + + + red + + + + green + blue + + + 0 + + + + red + 0 (16) + + + + + red + + + 0 + + + + blue + 0 (16) + + blue + + + 0 + + + + green + 0 (16) + + green + + + + + + + + round + + + + + + + + nearest + + + + + + + + + + + + + + img(x, y) + diffuse(red-errors) + diffuse(green-errors) + diffuse(blue-errors) + + -- cgit 1.4.1-2-gfad0