diff --git a/files.html b/files.html
index 9e7b86c26bbe930f10b03aaf41a93629e28ee221..52ce998063029fd01a84c48a0d8a4d4b3b737116 100644
--- a/files.html
+++ b/files.html
@@ -41,6 +41,8 @@
 <i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;control</i><br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/control/slider'>slider</a><br>
 <i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;convert</i><br>
+<i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rgba</i><br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/convert/rgba/png'>png</a><br>
 <i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;svg</i><br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/convert/svg/array'>array</a><br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='./modules/convert/svg/image'>image</a><br>
diff --git a/modules/convert/rgba/png b/modules/convert/rgba/png
new file mode 100755
index 0000000000000000000000000000000000000000..3b901ce289b1d5e6441c531fb8b1fc0f0180e255
--- /dev/null
+++ b/modules/convert/rgba/png
@@ -0,0 +1,169 @@
+//
+// convert rgba png
+//
+// Neil Gershenfeld 
+// (c) Massachusetts Institute of Technology 2017
+// 
+// This work may be reproduced, modified, distributed, performed, and 
+// displayed for any purpose, but must acknowledge the mods
+// project. Copyright is retained and must be preserved. The work is 
+// provided as is; no warranty is provided, and users accept all 
+// liability.
+//
+// closure
+//
+(function(){
+//
+// module globals
+//
+var mod = {}
+//
+// name
+//
+var name = 'convert RGBA to PNG'
+//
+// initialization
+//
+var init = function() {
+   }
+//
+// inputs
+//
+var inputs = {
+   image:{type:'RGBA',
+      event:function(evt){
+         mod.input = evt.detail
+         var ctx = mod.img.getContext("2d")
+         ctx.canvas.width = mod.input.width
+         ctx.canvas.height = mod.input.height 
+         ctx.putImageData(mod.input,0,0)
+         convert_image()
+         }},
+   imageInfo:{type:'object',
+      event:function(){
+         }}
+   }
+//
+// outputs
+//
+var outputs = {
+   PNG:{type:'file',
+      event:function(){
+         }}
+   }
+//
+// interface
+//
+var interface = function(div){
+   mod.div = div
+   //
+   // on-screen drawing canvas
+   //
+   var canvas = document.createElement('canvas')
+      canvas.width = mods.ui.canvas
+      canvas.height = mods.ui.canvas
+      canvas.style.backgroundColor = 'rgb(255,255,255)'
+      div.appendChild(canvas)
+      mod.canvas = canvas
+   div.appendChild(document.createElement('br'))
+   //
+   // off-screen image canvas
+   //
+   var canvas = document.createElement('canvas')
+      mod.img = canvas
+   //
+   // view button
+   //
+   var btn = document.createElement('button')
+      btn.style.padding = mods.ui.padding
+      btn.style.margin = 1
+      btn.appendChild(document.createTextNode('view'))
+      btn.addEventListener('click',function(){
+         var win = window.open('')
+         var btn = document.createElement('button')
+            btn.appendChild(document.createTextNode('close'))
+            btn.style.padding = mods.ui.padding
+            btn.style.margin = 1
+            btn.addEventListener('click',function(){
+               win.close()
+               })
+            win.document.body.appendChild(btn)
+         win.document.body.appendChild(document.createElement('br'))
+         var canvas = document.createElement('canvas')
+            canvas.width = mod.img.width
+            canvas.height = mod.img.height
+            win.document.body.appendChild(canvas)
+         var ctx = canvas.getContext("2d")
+            ctx.drawImage(mod.img,0,0)
+         })
+      div.appendChild(btn)
+   div.appendChild(document.createTextNode(' '))
+   //
+   // info div
+   //
+   var info = document.createElement('div')
+      info.setAttribute('id',div.id+'info')
+      info.appendChild(document.createTextNode('dpi: '))
+      var input = document.createElement('input')
+         input.type = 'text'
+         input.size = 6
+         input.addEventListener('input',function(){
+            mod.dpi = parseFloat(mod.dpitext.value)
+            mod.mmtext.nodeValue = (25.4*mod.img.width/mod.dpi).toFixed(3)
+               +' x '+(25.4*mod.img.height/mod.dpi).toFixed(3)+' mm'
+            mod.intext.nodeValue = (mod.img.width/mod.dpi).toFixed(3)
+               +' x '+(mod.img.height/mod.dpi).toFixed(3)+' in'
+            outputs.imageInfo.event()
+            })
+         info.appendChild(input)
+         mod.dpitext = input
+      info.appendChild(document.createElement('br'))
+      var text = document.createTextNode('px: ')
+         info.appendChild(text)
+         mod.pxtext = text
+      info.appendChild(document.createElement('br'))
+      var text = document.createTextNode('mm: ')
+         info.appendChild(text)
+         mod.mmtext = text
+      info.appendChild(document.createElement('br'))
+      var text = document.createTextNode('in: ')
+         info.appendChild(text)
+         mod.intext = text
+      info.appendChild(document.createElement('br'))
+      var text = document.createTextNode('')
+         info.appendChild(text)
+         mod.name = text
+      div.appendChild(info)
+   }
+//
+// local functions
+//
+function convert_image() {
+   var h = mod.img.height
+   var w = mod.img.width
+   if (w > h) {
+      var x0 = 0
+      var y0 = mod.canvas.height*.5*(1-h/w)
+      var wd = mod.canvas.width
+      var hd = mod.canvas.width*h/w
+      }
+   else {
+      var x0 = mod.canvas.width*.5*(1-w/h)
+      var y0 = 0
+      var wd = mod.canvas.height*w/h
+      var hd = mod.canvas.height
+      }
+   var ctx = mod.canvas.getContext("2d")
+   ctx.clearRect(0,0,mod.canvas.width,mod.canvas.height)
+   ctx.drawImage(mod.img,x0,y0,wd,hd)
+   }
+// return values
+//
+return ({
+   name:name,
+   init:init,
+   inputs:inputs,
+   outputs:outputs,
+   interface:interface
+   })
+}())
diff --git a/modules/index.html b/modules/index.html
index eb200c3799c3bb22375b4910580a612f95919618..16dd32881cf60ec9b18350bd6cfbd8a5878cb118 100644
--- a/modules/index.html
+++ b/modules/index.html
@@ -24,6 +24,8 @@
 <i>control</i><br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="javascript:handler('modules/control/slider')">slider</a><br>
 <i>convert</i><br>
+<i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rgba</i><br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="javascript:handler('modules/convert/rgba/png')">png</a><br>
 <i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;svg</i><br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="javascript:handler('modules/convert/svg/array')">array</a><br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="javascript:handler('modules/convert/svg/image')">image</a><br>