From 2946774e60ed0cff9afefc89707fd916bb7c117d Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Thu, 30 Nov 2017 01:56:23 -0500 Subject: [PATCH] WIP: Add unsharp-mask filter layer to sharpen background imagery --- modules/renderer/background.js | 118 ++++++++++++++++++++++++++------- modules/ui/background.js | 12 ++-- 2 files changed, 101 insertions(+), 29 deletions(-) diff --git a/modules/renderer/background.js b/modules/renderer/background.js index d1d59042e..8fd9720be 100644 --- a/modules/renderer/background.js +++ b/modules/renderer/background.js @@ -12,24 +12,79 @@ import { utilRebind } from '../util/rebind'; export function rendererBackground(context) { - var dispatch = d3_dispatch('change'), - baseLayer = rendererTileLayer(context).projection(context.projection), - overlayLayers = [], - backgroundSources; + var dispatch = d3_dispatch('change'); + var baseLayer = rendererTileLayer(context).projection(context.projection); + var _overlayLayers = []; + var _backgroundSources = []; + var _brightness = 1; + var _sharpness = 1; function background(selection) { + var baseFilter = ''; + if (_brightness !== 1) { + baseFilter += 'brightness(' + _brightness + ')'; + } + if (_sharpness !== 1) { + baseFilter += 'contrast(1.25)';// + _sharpness + ')'; + } + var base = selection.selectAll('.layer-background') .data([0]); - base.enter() + base = base.enter() .insert('div', '.layer-data') .attr('class', 'layer layer-background') .merge(base) + .style('-webkit-filter', baseFilter || null) + .style('filter', baseFilter || null); + + + var imagery = base.selectAll('.layer-imagery') + .data([0]); + + imagery.enter() + .append('div') + .attr('class', 'layer layer-imagery') + .merge(imagery) .call(baseLayer); + + var maskFilter = ''; + var mixBlendMode = ''; + if (_sharpness !== 1) { + var blur = Math.abs(_sharpness - 1) * 10; + maskFilter += 'blur(' + blur + 'px)'; + + if (_sharpness > 1) { + maskFilter += 'invert(1)'; + mixBlendMode = 'overlay'; + } else { + mixBlendMode = 'normal'; + } + + // var contrast = 1 / (_sharpness || 0.1); + maskFilter += 'contrast(0.75)';// + contrast + ')'; + } + + var mask = base.selectAll('.layer-unsharp-mask') + .data(_sharpness !== 1 ? [0] : []); + + mask.exit() + .remove(); + + mask.enter() + .append('div') + .attr('class', 'layer layer-unsharp-mask') + .merge(mask) + .call(baseLayer) + .style('-webkit-filter', maskFilter || null) + .style('filter', maskFilter || null) + .style('mix-blend-mode', mixBlendMode || null); + + var overlays = selection.selectAll('.layer-overlay') - .data(overlayLayers, function(d) { return d.source().name(); }); + .data(_overlayLayers, function(d) { return d.source().name(); }); overlays.exit() .remove(); @@ -46,7 +101,7 @@ export function rendererBackground(context) { if (context.inIntro()) return; var b = background.baseLayerSource(), - o = overlayLayers + o = _overlayLayers .filter(function (d) { return !d.source().isLocatorOverlay() && !d.source().isHidden(); }) .map(function (d) { return d.source().id; }) .join(','), @@ -85,7 +140,7 @@ export function rendererBackground(context) { var imageryUsed = [b.imageryUsed()]; - overlayLayers + _overlayLayers .filter(function (d) { return !d.source().isLocatorOverlay() && !d.source().isHidden(); }) .forEach(function (d) { imageryUsed.push(d.source().imageryUsed()); }); @@ -117,7 +172,7 @@ export function rendererBackground(context) { background.sources = function(extent) { - return backgroundSources.filter(function(source) { + return _backgroundSources.filter(function(source) { return source.intersects(extent); }); }; @@ -127,7 +182,7 @@ export function rendererBackground(context) { if (!_) return; baseLayer.dimensions(_); - overlayLayers.forEach(function(layer) { + _overlayLayers.forEach(function(layer) { layer.dimensions(_); }); }; @@ -172,7 +227,7 @@ export function rendererBackground(context) { background.findSource = function(id) { - return _find(backgroundSources, function(d) { + return _find(_backgroundSources, function(d) { return d.id && d.id === id; }); }; @@ -185,22 +240,22 @@ export function rendererBackground(context) { background.showsLayer = function(d) { return d.id === baseLayer.source().id || - overlayLayers.some(function(layer) { return d.id === layer.source().id; }); + _overlayLayers.some(function(layer) { return d.id === layer.source().id; }); }; background.overlayLayerSources = function() { - return overlayLayers.map(function (l) { return l.source(); }); + return _overlayLayers.map(function (l) { return l.source(); }); }; background.toggleOverlayLayer = function(d) { var layer; - for (var i = 0; i < overlayLayers.length; i++) { - layer = overlayLayers[i]; + for (var i = 0; i < _overlayLayers.length; i++) { + layer = _overlayLayers[i]; if (layer.source() === d) { - overlayLayers.splice(i, 1); + _overlayLayers.splice(i, 1); dispatch.call('change'); background.updateImagery(); return; @@ -210,9 +265,10 @@ export function rendererBackground(context) { layer = rendererTileLayer(context) .source(d) .projection(context.projection) - .dimensions(baseLayer.dimensions()); + .dimensions(baseLayer.dimensions() + ); - overlayLayers.push(layer); + _overlayLayers.push(layer); dispatch.call('change'); background.updateImagery(); }; @@ -235,6 +291,22 @@ export function rendererBackground(context) { }; + background.brightness = function(d) { + if (!arguments.length) return _brightness; + _brightness = d; + if (context.mode()) dispatch.call('change'); + return background; + }; + + + background.sharpness = function(d) { + if (!arguments.length) return _sharpness; + _sharpness = d; + if (context.mode()) dispatch.call('change'); + return background; + }; + + background.init = function() { function parseMap(qmap) { if (!qmap) return false; @@ -251,7 +323,7 @@ export function rendererBackground(context) { best; // Add all the available imagery sources - backgroundSources = dataImagery.map(function(source) { + _backgroundSources = dataImagery.map(function(source) { if (source.type === 'bing') { return rendererBackgroundSource.Bing(source, dispatch); } else if (source.id === 'EsriWorldImagery') { @@ -261,15 +333,15 @@ export function rendererBackground(context) { } }); - first = backgroundSources.length && backgroundSources[0]; + first = _backgroundSources.length && _backgroundSources[0]; // Add 'None' - backgroundSources.unshift(rendererBackgroundSource.None()); + _backgroundSources.unshift(rendererBackgroundSource.None()); // Add 'Custom' var template = context.storage('background-custom-template') || ''; var custom = rendererBackgroundSource.Custom(template); - backgroundSources.unshift(custom); + _backgroundSources.unshift(custom); // Decide which background layer to display @@ -290,7 +362,7 @@ export function rendererBackground(context) { ); } - var locator = _find(backgroundSources, function(d) { + var locator = _find(_backgroundSources, function(d) { return d.overlay && d.default; }); diff --git a/modules/ui/background.js b/modules/ui/background.js index e2ecfe678..3777975d6 100644 --- a/modules/ui/background.js +++ b/modules/ui/background.js @@ -51,12 +51,12 @@ export function uiBackground(context) { // Can be 0 from <1.3.0 use or due to issue #1923. if (!d) d = 1.0; - var bg = context.container().selectAll('.layer-background') - .style('opacity', d); - - if (!detected.opera) { - utilSetTransform(bg, 0, 0); - } + // var bg = context.container().selectAll('.layer-background') + // .style('opacity', d); + // if (!detected.opera) { + // utilSetTransform(bg, 0, 0); + // } + context.background().brightness(d); _displayOptions.selectAll('.opacity-input') .property('value', d);