diff --git a/ui (gen4)/experiments/ig-image-graph-obj.js b/ui (gen4)/experiments/ig-image-graph-obj.js new file mode 100644 index 00000000..4c02f583 --- /dev/null +++ b/ui (gen4)/experiments/ig-image-graph-obj.js @@ -0,0 +1,473 @@ +//--------------------------------------------------------------------- +// +// +// XXX still thinking on how to package this correctly... +// +//--------------------------------------------------------------------- +// image manipulation basics... + +var Filters = { + makeCanvas: function(w, h){ + var c = document.createElement('canvas') + c.width = w + c.height = h + return c + }, + + // as input takes an HTML Image object... + getPixels: function(img, w, h){ + var w = w || img.width + var h = h || img.height + var c = this.makeCanvas(w, h) + var context = c.getContext('2d') + if(img == null){ + context.rect(0, 0, w, h) + context.fillStyle = "black" + context.fill() + } else { + context.drawImage(img, 0, 0, w, h) + } + return context.getImageData(0,0,c.width,c.height) + }, + setPixels: function(c, data, w, h){ + c.width = data.width + c.height = data.height + var context = c.getContext('2d') + context.putImageData(data, 0, 0) + }, + + filterImage: function(filter, image, var_args){ + var args = [this.getPixels(image)] + for(var i=2; i + :host { + position: relative; + display: inline-block; + + background: black; + + width: attr(image-width); + height: attr(graph-height); + } + :host canvas { + box-sizing: border-box; + width: 100%; + height: 100%; + + border: 2px solid gray; + } + :host .controls { + display: inline-block; + position: absolute; + top: 2px; + right: 2px; + left: 2px; + } + :host .controls button { + background: transparent; + border: none; + color: white; + opacity: 0.7; + float: right; + } + :host .controls button.current { + text-decoration: underline; + opacity: 0.9; + } + :host .controls button:hover { + opacity: 1; + } + + +
+` + +var igImageGraph = +object.Constructor('igImageGraph', HTMLElement, { + template: 'ig-image-graph', + graphs: { + waveform, + histogram, + }, + modes: ['luminance', 'color', 'R', 'G', 'B'], + color_modes: ['normalized', 'white', 'point'], + + __init__: function(src){ + // shadow DOM + var shadow = this.__shadow = + this.attachShadow({mode: 'open'}) + // get/create template... + var tpl = document.getElementById(this.template) + if(!tpl){ + var tpl = document.createElement('template') + tpl.setAttribute('id', this.template) + tpl.innerHTML = igImageGraph_template + document.head.appendChild(tpl) } + shadow.appendChild(tpl.content.cloneNode(true)) }, + connectedCallback: function(){ + this.update_controls() + this.update() }, + + // attributes... + get observedAttributes(){ + return [ + 'src', + 'mode', + 'color', + 'nocontrols', + 'graph', + ]}, + attributeChangedCallback: function(name, from, to){ + name == 'nocontrols' + && this.update_controls() + this.update() }, + + get graph(){ + return this.getAttribute('graph') || 'waveform' }, + set graph(value){ + value in this.graphs + && this.setAttribute('graph', value) + value == '' + && this.removeAttribute('graph') + this.update() }, + get src(){ + return this.getAttribute('src') }, + set src(value){ + var that = this + this.__update_handler = this.__update_handler + || this.update.bind(this) + var url = typeof(value) == typeof('str') + // get/create image... + var img = this.image = + url ? + (this.image || document.createElement('img')) + : value + img.removeEventListener('load', this.__update_handler) + img.addEventListener('load', this.__update_handler) + // set .src and img.src... + this.setAttribute('src', + url ? + (img.src = value) + : img.src) }, + get mode(){ + return this.getAttribute('mode') || 'color' }, + set mode(value){ + this.modes.includes(value) + && this.setAttribute('mode', value) + value === undefined + && this.removeAttribute('color') + this.update_controls() + this.update() }, + get color(){ + return this.getAttribute('color') || 'normalized' }, + set color(value){ + this.color_modes.includes(value) + && this.setAttribute('color', value) + value === undefined + && this.removeAttribute('color') + this.update() }, + get nocontrols(){ + return this.getAttribute('nocontrols') != null }, + set nocontrols(value){ + value ? + this.setAttribute('nocontrols', '') + : this.removeAttribute('nocontrols') + this.update_controls() + this.update() }, + + // API... + update_controls: function(){ + var that = this + var mode = this.mode + + var controls = this.__shadow.querySelector('.controls') + controls.innerHTML = '' + // modes... + var buttons = [ + // graph... + function(){ + var button = document.createElement('button') + button.classList.add('update') + //button.innerHTML = '◑' + button.innerHTML = '◪' + button.onclick = function(){ + that.graph = that.graph == 'waveform' ? + 'histogram' + : 'waveform' + that.update() } + return button }(), + // modes... + (this.nocontrols ? + [] + : this.modes) + // mode buttons... + .map(function(m){ + var button = document.createElement('button') + button.innerText = m + button.classList.add(m, ...(m == mode ? ['current'] : [])) + button.onclick = function(){ + that.mode = m } + return button }), + /* + // color mode switch... + function(){ + var button = document.createElement('button') + button.innerText = '('+ that.color[0] +')' + button.onclick = function(){ + that.color = that.color_modes[ + (that.color_modes.indexOf(that.color) + 1) + % that.color_modes.length] + this.innerText = '('+ that.color[0] +')' } + return button }(), + //*/ + // reload... + function(){ + var button = document.createElement('button') + button.classList.add('update') + button.innerHTML = '⟳' + button.onclick = function(){ that.update() } + return button }(), + ] + .flat() + .reverse() + .forEach(function(button){ + controls.appendChild(button) }) + return this }, + update: function(){ + var that = this + var mode = this.mode + + // controls... + // remove... + if(!this.nocontrols){ + var controls = this.__shadow.querySelector('.controls') + // current button state... + var button = controls.querySelector('button.'+this.mode) + button + && button.classList.add('current') + } + + // XXX configurable... + var type = this.graph + var graph = this.graphs[type] + + var canvas = this.__shadow.querySelector('canvas') + + if(this.image){ + graph(this.image, canvas, this.mode, this.color) + + } else if(this.src){ + this.src = this.src + } + + return this }, +}) +window.customElements.define('ig-image-graph', igImageGraph) + + + +var makeImageGraph = +function(img, options){ + var g = document.createElement('ig-image-graph') + Object.assign(g, + options || {}) + g.src = img + return g } + + + + +//--------------------------------------------------------------------- +// vim:set ts=4 sw=4 :