about summary refs log tree commit diff stats
path: root/img.mu
diff options
context:
space:
mode:
Diffstat (limited to 'img.mu')
-rw-r--r--img.mu159
1 files changed, 157 insertions, 2 deletions
diff --git a/img.mu b/img.mu
index f9f2d6e9..76ecdd23 100644
--- a/img.mu
+++ b/img.mu
@@ -109,8 +109,8 @@ fn render-image screen: (addr screen), _img: (addr image), xmin: int, ymin: int,
     break-if-!=
     var img2-storage: image
     var img2/edi: (addr image) <- address img2-storage
-    dither-pgm-unordered-monochrome img, img2
-    render-pbm-image screen, img2, xmin, ymin, width, height
+    dither-pgm-unordered img, img2
+    render-raw-image screen, img2, xmin, ymin, width, height
     return
   }
   {
@@ -433,6 +433,94 @@ fn _dither-pgm-unordered-monochrome src: (addr array byte), width: int, height:
   }
 }
 
+fn dither-pgm-unordered _src: (addr image), _dest: (addr image) {
+  var src/esi: (addr image) <- copy _src
+  var dest/edi: (addr image) <- copy _dest
+  # copy 'width'
+  var src-width-a/ecx: (addr int) <- get src, width
+  var src-width/ecx: int <- copy *src-width-a
+  {
+    var dest-width-a/edx: (addr int) <- get dest, width
+    copy-to *dest-width-a, src-width
+  }
+  # copy 'height'
+  var src-height-a/edx: (addr int) <- get src, height
+  var src-height/edx: int <- copy *src-height-a
+  {
+    var dest-height-a/ecx: (addr int) <- get dest, height
+    copy-to *dest-height-a, src-height
+  }
+  # transform 'data'
+  var capacity/ebx: int <- copy src-width
+  capacity <- multiply src-height
+  var dest/edi: (addr image) <- copy _dest
+  var dest-data-ah/eax: (addr handle array byte) <- get dest, data
+  populate dest-data-ah, capacity
+  var _dest-data/eax: (addr array byte) <- lookup *dest-data-ah
+  var dest-data/edi: (addr array byte) <- copy _dest-data
+  # needs a buffer to temporarily hold more than 256 levels of precision
+  var buffer-storage: (array int 0xc0000)
+  var buffer/ebx: (addr array int) <- address buffer-storage
+  var src-data-ah/eax: (addr handle array byte) <- get src, data
+  var _src-data/eax: (addr array byte) <- lookup *src-data-ah
+  var src-data/esi: (addr array byte) <- copy _src-data
+  _dither-pgm-unordered src-data, src-width, src-height, buffer, dest-data
+}
+
+fn _dither-pgm-unordered src: (addr array byte), width: int, height: int, buf: (addr array int), dest: (addr array byte) {
+  var y/edx: int <- copy 0
+  {
+    compare y, height
+    break-if->=
+    var x/ecx: int <- copy 0
+    {
+      compare x, width
+      break-if->=
+      var error/ebx: int <- _read-pgm-buffer buf, x, y, width
+      $_dither-pgm-unordered-monochrome:update-error: {
+        # error += src_color << 16
+        var curr/eax: byte <- _read-pgm-byte-buffer src, x, y, width
+        var curr-int/eax: int <- copy curr
+#?         draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, curr-int, 2/fg 0/bg
+        curr-int <- shift-left 0x10  # we have 32 bits; we'll use 16 bits for the fraction and leave 8 for unanticipated overflow
+        error <- add curr-int
+        # tmp = max(error, 0)
+        var tmp/eax: int <- copy error
+        {
+          compare tmp, 0
+          break-if->=
+          tmp <- copy 0
+        }
+        # round tmp to nearest multiple of 0x100000
+        {
+          var tmp2/ecx: int <- copy tmp
+          tmp2 <- and   0xfffff
+          compare tmp2, 0x80000
+          break-if-<
+          tmp <- add    0x80000
+        }
+        tmp <- and 0xf00000
+        # error -= tmp
+        error <- subtract tmp
+        # color = tmp >> 20 + 16
+        var color/eax: int <- copy tmp
+        color <- shift-right-signed 0x14
+        color <- add 0x10
+#?         draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, color, 3/fg 0/bg
+#?         draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, " ", 7/fg 0/bg
+        var color-byte/eax: byte <- copy-byte color
+        _write-pgm-byte-buffer dest, x, y, width, color-byte
+      }
+      _diffuse-dithering-error-floyd-steinberg buf, x, y, width, height, error
+      x <- increment
+      loop
+    }
+    move-cursor-to-left-margin-of-next-line 0/screen
+    y <- increment
+    loop
+  }
+}
+
 # Use Floyd-Steinberg algorithm for turning an image of greyscale pixels into
 # one of pure black or white pixels.
 #
@@ -754,3 +842,70 @@ fn render-ppm-image screen: (addr screen), _img: (addr image), xmin: int, ymin:
     loop
   }
 }
+
+fn render-raw-image screen: (addr screen), _img: (addr image), xmin: int, ymin: int, width: int, height: int {
+  var img/esi: (addr image) <- copy _img
+  # yratio = height/img->height
+  var img-height-a/eax: (addr int) <- get img, height
+  var img-height/xmm0: float <- convert *img-height-a
+  var yratio/xmm1: float <- convert height
+  yratio <- divide img-height
+  # xratio = width/img->width
+  var img-width-a/eax: (addr int) <- get img, width
+  var img-width/ebx: int <- copy *img-width-a
+  var img-width-f/xmm0: float <- convert img-width
+  var xratio/xmm2: float <- convert width
+  xratio <- divide img-width-f
+  # esi = img->data
+  var img-data-ah/eax: (addr handle array byte) <- get img, data
+  var _img-data/eax: (addr array byte) <- lookup *img-data-ah
+  var img-data/esi: (addr array byte) <- copy _img-data
+  var len/edi: int <- length img-data
+  #
+  var one/eax: int <- copy 1
+  var one-f/xmm3: float <- convert one
+  var width-f/xmm4: float <- convert width
+  var height-f/xmm5: float <- convert height
+  var zero/eax: int <- copy 0
+  var zero-f/xmm0: float <- convert zero
+  var y/xmm6: float <- copy zero-f
+  {
+    compare y, height-f
+    break-if-float>=
+    var imgy-f/xmm5: float <- copy y
+    imgy-f <- divide yratio
+    var imgy/edx: int <- truncate imgy-f
+    var x/xmm7: float <- copy zero-f
+    {
+      compare x, width-f
+      break-if-float>=
+      var imgx-f/xmm5: float <- copy x
+      imgx-f <- divide xratio
+      var imgx/ecx: int <- truncate imgx-f
+      var idx/eax: int <- copy imgy
+      idx <- multiply img-width
+      idx <- add imgx
+      # error info in case we rounded wrong and 'index' will fail bounds-check
+      compare idx, len
+      {
+        break-if-<
+        set-cursor-position 0/screen, 0x20/x 0x20/y
+        draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, imgx, 3/fg 0/bg
+        draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, imgy, 4/fg 0/bg
+        draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, idx, 5/fg 0/bg
+      }
+      var color-a/eax: (addr byte) <- index img-data, idx
+      var color/eax: byte <- copy-byte *color-a
+      var color-int/eax: int <- copy color
+      var screenx/ecx: int <- convert x
+      screenx <- add xmin
+      var screeny/edx: int <- convert y
+      screeny <- add ymin
+      pixel screen, screenx, screeny, color-int
+      x <- add one-f
+      loop
+    }
+    y <- add one-f
+    loop
+  }
+}