about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2021-07-07 08:25:42 -0700
committerKartik K. Agaram <vc@akkartik.com>2021-07-07 08:35:17 -0700
commita9353ea327a7b6915cf2c4784744b8e4b7b77169 (patch)
treef6cb91b971a430e4c8bc6959b68d6dc37f5729d3
parentef73cb78f15839cf0254ead273e0d1eca1d4826c (diff)
downloadmu-a9353ea327a7b6915cf2c4784744b8e4b7b77169.tar.gz
load ppm/pgm/ppm on demand
-rw-r--r--img.mu121
1 files changed, 113 insertions, 8 deletions
diff --git a/img.mu b/img.mu
index cae31b1f..7aecbabf 100644
--- a/img.mu
+++ b/img.mu
@@ -1,6 +1,11 @@
 # load an image from disk and display it on screen
 
 type image {
+  type: int  # supported types:
+             #  1: portable bitmap (P1) - pixels 0 or 1
+             #  2: portable greymap (P2) - pixels 1-byte greyscale values
+             #  3: portable pixmap (P3) - pixels 3-byte rgb values
+  max: int
   width: int
   height: int
   data: (handle array byte)
@@ -24,7 +29,42 @@ fn load-image self: (addr image), data-disk: (addr disk) {
   # stream -> gap-buffer (HACK: we temporarily cannibalize the sandbox's gap-buffer)
   draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "parsing", 3/fg, 0/bg
   move-cursor-to-left-margin-of-next-line 0/screen
-  initialize-image-from-pgm self, s
+  initialize-image self, s
+}
+
+fn initialize-image _self: (addr image), in: (addr stream byte) {
+  var self/esi: (addr image) <- copy _self
+  var mode-storage: slice
+  var mode/ecx: (addr slice) <- address mode-storage
+  next-word in, mode
+  {
+    var P1?/eax: boolean <- slice-equal? mode, "P1"
+    compare P1?, 0/false
+    break-if-=
+    var type-a/eax: (addr int) <- get self, type
+    copy-to *type-a, 1
+    initialize-image-from-pbm self, in
+    return
+  }
+  {
+    var P2?/eax: boolean <- slice-equal? mode, "P2"
+    compare P2?, 0/false
+    break-if-=
+    var type-a/eax: (addr int) <- get self, type
+    copy-to *type-a, 2
+    initialize-image-from-pgm self, in
+    return
+  }
+  {
+    var P3?/eax: boolean <- slice-equal? mode, "P3"
+    compare P3?, 0/false
+    break-if-=
+    var type-a/eax: (addr int) <- get self, type
+    copy-to *type-a, 3
+    initialize-image-from-ppm self, in
+    return
+  }
+  abort "unrecognized image type"
 }
 
 # import a black-and-white ascii bitmap
@@ -32,17 +72,19 @@ fn initialize-image-from-pbm _self: (addr image), in: (addr stream byte) {
   var self/esi: (addr image) <- copy _self
   var curr-word-storage: slice
   var curr-word/ecx: (addr slice) <- address curr-word-storage
-  next-word in, curr-word   # skip 'P1'
+  # load width, height
   next-word in, curr-word
   var tmp/eax: int <- parse-decimal-int-from-slice curr-word
   var width/edx: int <- copy tmp
   next-word in, curr-word
   tmp <- parse-decimal-int-from-slice curr-word
   var height/ebx: int <- copy tmp
+  # save width, height
   var dest/eax: (addr int) <- get self, width
   copy-to *dest, width
   dest <- get self, height
   copy-to *dest, height
+  # initialize data
   var capacity/edx: int <- copy width
   capacity <- multiply height
   var data-ah/edi: (addr handle array byte) <- get self, data
@@ -64,27 +106,90 @@ fn initialize-image-from-pbm _self: (addr image), in: (addr stream byte) {
   }
 }
 
-# import a greyscale ascii bitmap
+# import a greyscale ascii "greymap"
 fn initialize-image-from-pgm _self: (addr image), in: (addr stream byte) {
   var self/esi: (addr image) <- copy _self
   var curr-word-storage: slice
   var curr-word/ecx: (addr slice) <- address curr-word-storage
-  next-word in, curr-word   # skip 'P2'
+  # load width, height
   next-word in, curr-word
   var tmp/eax: int <- parse-decimal-int-from-slice curr-word
   var width/edx: int <- copy tmp
-#?   draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, width, 3/fg 0/bg
   next-word in, curr-word
   tmp <- parse-decimal-int-from-slice curr-word
   var height/ebx: int <- copy tmp
-#?   draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, height, 4/fg 0/bg
-  next-word in, curr-word   # skip levels of grey
-  var dest/eax: (addr int) <- get self, width
+  # check and save color levels
+  next-word in, curr-word
+  {
+    tmp <- parse-decimal-int-from-slice curr-word
+    compare tmp, 0xff
+    break-if-<=
+    abort "initialize-image-from-pgm: no more than 255 levels of grey"
+  }
+  var dest/edi: (addr int) <- get self, max
+  copy-to *dest, tmp
+  # save width, height
+  dest <- get self, width
+  copy-to *dest, width
+  dest <- get self, height
+  copy-to *dest, height
+  # initialize data
+  var capacity/edx: int <- copy width
+  capacity <- multiply height
+  var data-ah/edi: (addr handle array byte) <- get self, data
+  populate data-ah, capacity
+  var _data/eax: (addr array byte) <- lookup *data-ah
+  var data/edi: (addr array byte) <- copy _data
+  var i/ebx: int <- copy 0
+  {
+    compare i, capacity
+    break-if->=
+    next-word in, curr-word
+    var src/eax: int <- parse-decimal-int-from-slice curr-word
+    {
+      var dest/ecx: (addr byte) <- index data, i
+      copy-byte-to *dest, src
+    }
+    i <- increment
+    loop
+  }
+}
+
+# import a color ascii "pixmap"
+fn initialize-image-from-ppm _self: (addr image), in: (addr stream byte) {
+  var self/esi: (addr image) <- copy _self
+  var curr-word-storage: slice
+  var curr-word/ecx: (addr slice) <- address curr-word-storage
+  # load width, height
+  next-word in, curr-word
+  var tmp/eax: int <- parse-decimal-int-from-slice curr-word
+  var width/edx: int <- copy tmp
+  next-word in, curr-word
+  tmp <- parse-decimal-int-from-slice curr-word
+  var height/ebx: int <- copy tmp
+  next-word in, curr-word
+  # check color levels
+  {
+    tmp <- parse-decimal-int-from-slice curr-word
+    compare tmp, 0xff
+    break-if-=
+    abort "initialize-image-from-ppm: supports exactly 255 levels per rgb channel"
+  }
+  var dest/edi: (addr int) <- get self, max
+  copy-to *dest, tmp
+  # save width, height
+  dest <- get self, width
   copy-to *dest, width
   dest <- get self, height
   copy-to *dest, height
+  # initialize data
   var capacity/edx: int <- copy width
   capacity <- multiply height
+  # . multiply by 3 for the r/g/b channels
+  var tmp/eax: int <- copy capacity
+  tmp <- shift-left 1
+  capacity <- add tmp
+  #
   var data-ah/edi: (addr handle array byte) <- get self, data
   populate data-ah, capacity
   var _data/eax: (addr array byte) <- lookup *data-ah