From 6084654601960b9d4bf2e852fa42a403f9b12bfd Mon Sep 17 00:00:00 2001 From: Maksim Date: Tue, 29 Jan 2019 00:00:49 -0800 Subject: [PATCH] added CSS back into SVG output, added credits --- src/App.vue | 492 +++++++++++++++++--------------- src/components/svgChart.vue | 20 +- src/components/svgChartLine.vue | 5 +- src/styles/index.scss | 49 +++- 4 files changed, 323 insertions(+), 243 deletions(-) diff --git a/src/App.vue b/src/App.vue index 8ed69fd..5770128 100644 --- a/src/App.vue +++ b/src/App.vue @@ -9,6 +9,43 @@
+
+ + + +
+
+
+ + + +
+
+ +
+ + {{widthInCM}}cm + + + Width + + +
{{ settings.width }}
+
+ +
+ + {{widthInCM}}cm + + + Height + + +
{{ settings.height }}
+
+
+
+
-
- - -
-
- - Width - - -
{{ settings.width }}
-
- -
- - Height - - -
{{ settings.height }}
-
-
-
@@ -172,7 +188,6 @@
-
@@ -184,10 +199,17 @@
+
+

+ Project by @msurguy +
Source on Github +

+
+
-
- +
+
@@ -201,234 +223,248 @@ import svgChart from './components/svgChart'; export default { - name: 'App', - components: { - imageChooser: ImageChooser, - webcam: WebCam, - svgChart: svgChart - }, - data() { - return { - cropper: {}, - dataUrl: '', - lines: [], - inputType: "upload", - settings: { - frequency: 150, - amplitude: 1, - lineCount: 50, - brightness: 0, - contrast: 0, - minBrightness: 0, - maxBrightness: 255, - spacing: 1, - width: 500, - height: 500 - }, - canvasData: null, - webcam: { - img: null, - camera: null, - deviceId: null, - device: null, - devices: [], - streaming: false - }, - }; - }, - - watch: { - 'webcam.camera': function(id) { - this.webcam.deviceId = id; + name: 'App', + components: { + imageChooser: ImageChooser, + webcam: WebCam, + svgChart: svgChart }, - 'webcam.devices': function() { - // Once we have a list select the first one - let first = this.webcam.devices[0]; - if (first) { - this.webcam.camera = first.deviceId; - this.webcam.deviceId = first.deviceId; + data() { + return { + cropper: {}, + dataUrl: '', + lines: [], + inputType: "upload", + settings: { + black: false, + frequency: 150, + amplitude: 1, + lineCount: 50, + brightness: 0, + contrast: 0, + minBrightness: 0, + maxBrightness: 255, + spacing: 1, + width: 500, + height: 500 + }, + canvasData: null, + webcam: { + img: null, + camera: null, + deviceId: null, + device: null, + devices: [], + streaming: false + }, + }; + }, + + watch: { + 'webcam.camera': function(id) { + this.webcam.deviceId = id; + }, + 'webcam.devices': function() { + // Once we have a list select the first one + let first = this.webcam.devices[0]; + if (first) { + this.webcam.camera = first.deviceId; + this.webcam.deviceId = first.deviceId; + } + }, + 'settings.frequency': function(){ + this.processImage(); + }, + 'settings.spacing': function(){ + this.processImage(); + }, + 'settings.lineCount': function(){ + this.processImage(); + }, + 'settings.amplitude': function(){ + this.processImage(); + }, + 'settings.minBrightness': function(){ + this.processImage(); + }, + 'settings.maxBrightness': function(){ + this.processImage(); + }, + 'settings.brightness': function(){ + this.processImage(); + }, + 'settings.contrast': function(){ + this.processImage(); + }, + 'settings.black': function(){ + this.processImage(); + }, + 'canvasData': function(){ + this.processImage(); } }, - 'settings.frequency': function(){ - this.processImage(); + computed: { + widthInCM(){ + return Math.round(10*this.settings.width / 38)/10; + }, + heightInCM(){ + return Math.round(10*this.settings.height / 38)/10; + } }, - 'settings.spacing': function(){ - this.processImage(); - }, - 'settings.lineCount': function(){ - this.processImage(); - }, - 'settings.amplitude': function(){ - this.processImage(); - }, - 'settings.minBrightess': function(){ - this.processImage(); - }, - 'settings.maxBrightness': function(){ - this.processImage(); - }, - 'settings.brightness': function(){ - this.processImage(); - }, - 'settings.contrast': function(){ - this.processImage(); - }, - 'canvasData': function(){ - this.processImage(); - } - }, + methods: { + downloadSVG(){ + const svgDoctype = '' + + ''; - methods: { - downloadSVG(){ - const svgDoctype = '' - + ''; + // serialize our SVG XML to a string. + const svgString = (new XMLSerializer()).serializeToString(this.$refs.svgResult.$el); + const blob = new Blob([svgDoctype + svgString], {type: 'image/svg+xml;charset=utf-8'}); - // serialize our SVG XML to a string. - const svgString = (new XMLSerializer()).serializeToString(this.$refs.svgResult.$el); - const blob = new Blob([svgDoctype + svgString], {type: 'image/svg+xml;charset=utf-8'}); + /* This portion of script saves the file to local filesystem as a download */ + const svgUrl = URL.createObjectURL(blob); + const downloadLink = document.createElement("a"); + downloadLink.href = svgUrl; + downloadLink.download = "squiggleCam_" + Date.now() + ".svg"; + document.body.appendChild(downloadLink); + downloadLink.click(); + document.body.removeChild(downloadLink); + }, + uploadCroppedImage() { + this.cropper.generateBlob((blob) => { + let canvas = document.createElement("canvas"); + canvas.width = this.settings.width; + canvas.height = this.settings.height; - /* This portion of script saves the file to local filesystem as a download */ - const svgUrl = URL.createObjectURL(blob); - const downloadLink = document.createElement("a"); - downloadLink.href = svgUrl; - downloadLink.download = "squiggleCam_" + Date.now() + ".svg"; - document.body.appendChild(downloadLink); - downloadLink.click(); - document.body.removeChild(downloadLink); - }, - uploadCroppedImage() { - this.cropper.generateBlob((blob) => { - let canvas = document.createElement("canvas"); - canvas.width = this.settings.width; - canvas.height = this.settings.height; + const ctx = canvas.getContext('2d'); + let img = new Image(); - const ctx = canvas.getContext('2d'); - let img = new Image(); + img.onload = () => { + ctx.drawImage(img, 0, 0) + this.canvasData = ctx.getImageData(0, 0, this.settings.width, this.settings.height); + }; - img.onload = () => { - ctx.drawImage(img, 0, 0) - this.canvasData = ctx.getImageData(0, 0, this.settings.width, this.settings.height); - }; - - img.src = URL.createObjectURL(blob); - }, 'image/jpeg', 1) - }, - processImage() { - this.$worker.run((data) => { - // Gather all necessary data from the main thread - let config = data.config; + img.src = URL.createObjectURL(blob); + }, 'image/jpeg', 1) + }, + processImage() { + this.$worker.run((data) => { + // Gather all necessary data from the main thread + let config = data.config; // context.getImageData(0, 0, config.WIDTH, config.HEIGHT); - const imagePixels = data.image; - const width = parseInt(config.width); - const height = parseInt(config.height); - const contrast = parseInt(config.contrast); - const brightness = parseInt(config.brightness); - const lineCount = parseInt(config.lineCount); - const minBrightness = parseInt(config.minBrightness); - const maxBrightness = parseInt(config.maxBrightness); - const spacing = parseFloat(config.spacing); + const imagePixels = data.image; + const width = parseInt(config.width); + const height = parseInt(config.height); + const contrast = parseInt(config.contrast); + const brightness = parseInt(config.brightness); + const lineCount = parseInt(config.lineCount); + const minBrightness = parseInt(config.minBrightness); + const maxBrightness = parseInt(config.maxBrightness); + const spacing = parseFloat(config.spacing); + const black = config.black; // Create some defaults for squiggle-point array - let squiggleData = []; - let r = 5; - let a = 0; - let b; - let z; - let currentLine = []; // create empty array for storing x,y coordinate pairs - let currentVerticalPixelIndex = 0; - let currentHorizontalPixelIndex = 0; - let contrastFactor = (259 * (contrast + 255)) / (255 * (259 - contrast)); // This was established through experiments - let horizontalLineSpacing = Math.floor(height / lineCount); // Number of pixels to advance in vertical direction - //console.log(horizontalLineSpacing); + let squiggleData = []; + let r = 5; + let a = 0; + let b; + let z; + let currentLine = []; // create empty array for storing x,y coordinate pairs + let currentVerticalPixelIndex = 0; + let currentHorizontalPixelIndex = 0; + let contrastFactor = (259 * (contrast + 255)) / (255 * (259 - contrast)); // This was established through experiments + let horizontalLineSpacing = Math.floor(height / lineCount); // Number of pixels to advance in vertical direction // Iterate line by line (top line to bottom line) in increments of horizontalLineSpacing - //let tmpCounter = 0; - for (let y = 0; y < height; y+= horizontalLineSpacing) { - a = 0; - currentLine = []; - currentLine.push([0, y]); // Start the line + //let tmpCounter = 0; + for (let y = 0; y < height; y+= horizontalLineSpacing) { + a = 0; + currentLine = []; + currentLine.push([0, y]); // Start the line - currentVerticalPixelIndex = y*width; // Because Image Pixel array is of length width * height, - // starting pixel for each line will be this + currentVerticalPixelIndex = y*width; // Because Image Pixel array is of length width * height, + // starting pixel for each line will be this - // Loop through pixels from left to right within the current line, advancing by increments of config.SPACING - //console.log(config.spacing, width); - for (let x = spacing; x < width; x += spacing ) { + // Loop through pixels from left to right within the current line, advancing by increments of config.SPACING + //console.log(config.spacing, width); + for (let x = spacing; x < width; x += spacing ) { - currentHorizontalPixelIndex = Math.floor(x + currentVerticalPixelIndex); // Get array position of current pixel + currentHorizontalPixelIndex = Math.floor(x + currentVerticalPixelIndex); // Get array position of current pixel - // When there is contrast adjustment, the calculations of brightness values are a bit different - if (contrast !== 0) { - // Determine how bright a pixel is, from 0 to 255 by summing three channels (R,G,B) multiplied by some coefficients - b = (0.2125 * ((contrastFactor * (imagePixels.data[4 * currentHorizontalPixelIndex] - 128) + 128 ) - + brightness)) + (0.7154 * ((contrastFactor * (imagePixels.data[4 * (currentHorizontalPixelIndex + 1)] - 128) + 128) - + brightness)) + (0.0721 * ((contrastFactor*(imagePixels.data[4*(currentHorizontalPixelIndex+2)]-128)+128) + brightness)); - } else { - b = (0.2125 * (imagePixels.data[4*currentHorizontalPixelIndex] + brightness)) + (0.7154 * (imagePixels.data[4*(currentHorizontalPixelIndex + 1)]+ brightness)) + (0.0721 * (imagePixels.data[4*(currentHorizontalPixelIndex + 2)] + brightness)); + // When there is contrast adjustment, the calculations of brightness values are a bit different + if (contrast !== 0) { + // Determine how bright a pixel is, from 0 to 255 by summing three channels (R,G,B) multiplied by some coefficients + b = (0.2125 * ((contrastFactor * (imagePixels.data[4 * currentHorizontalPixelIndex] - 128) + 128 ) + + brightness)) + (0.7154 * ((contrastFactor * (imagePixels.data[4 * (currentHorizontalPixelIndex + 1)] - 128) + 128) + + brightness)) + (0.0721 * ((contrastFactor*(imagePixels.data[4*(currentHorizontalPixelIndex+2)]-128)+128) + brightness)); + } else { + b = (0.2125 * (imagePixels.data[4*currentHorizontalPixelIndex] + brightness)) + (0.7154 * (imagePixels.data[4*(currentHorizontalPixelIndex + 1)]+ brightness)) + (0.0721 * (imagePixels.data[4*(currentHorizontalPixelIndex + 2)] + brightness)); + } + + if (black) { + b = Math.min(255-minBrightness,255-b); // Set minimum line curvature to value set by the user + z = Math.max(maxBrightness-b,0); // Set maximum line curvature to value set by the user + } else { + b = Math.max(minBrightness,b); // Set minimum line curvature to value set by the user + z = Math.max(maxBrightness-b,0); // Set maximum line curvature to value set by the user + } + + // The magic of the script, determines how high / low the squiggle goes + r = config.amplitude * z / lineCount; + + a += z / config.frequency; + currentLine.push([x,y + Math.sin(a)*r]); } - - b = Math.max(minBrightness,b); // Set minimum line curvature to value set by the user - z = Math.max(maxBrightness-b,0); // Set maximum line curvature to value set by the user - - // The magic of the script, determines how high / low the squiggle goes - r = config.amplitude * z / lineCount; - - a += z / config.frequency; - currentLine.push([x,y + Math.sin(a)*r]); + //currentLine.push([config.width, y]); + squiggleData.push(currentLine); } - //currentLine.push([config.width, y]); - squiggleData.push(currentLine); - } - return squiggleData; - }, [{ - config: Object.assign({}, this.settings), - image: this.canvasData - }]) - .then(result => { - this.lines = []; - - result.forEach( line => { - this.lines.push({values: line}); + return squiggleData; + }, [{ + config: Object.assign({}, this.settings), + image: this.canvasData + }]) + .then(result => { + this.lines = []; + result.forEach( line => { + this.lines.push({values: line}); + }) }) - }) - .catch(e => { - console.error(e) - }) - }, - onCapture() { - this.webcam.img = this.$refs.webcam.capture(); - this.canvasData = this.$refs.webcam.getCanvasRaw(); - }, - onStarted(stream) { - this.webcam.streaming = true; - }, - onStopped(stream) { - this.webcam.streaming = false; - }, - onStop() { - this.$refs.webcam.stop(); - }, - onStart() { - this.$refs.webcam.start(); - }, - onError(error) { - //console.log("On Error Event", error); - }, - onCameras(cameras) { - this.webcam.devices = cameras; - //console.log("On Cameras Event", cameras); - }, - onCameraChange(deviceId) { - this.webcam.deviceId = deviceId; - this.webcam.camera = deviceId; - //console.log("On Camera Change Event", deviceId); - }, - onInputSelected(type) { - this.inputType = type; + .catch(e => { + console.error(e) + }) + }, + onCapture() { + this.webcam.img = this.$refs.webcam.capture(); + this.canvasData = this.$refs.webcam.getCanvasRaw(); + }, + onStarted(stream) { + this.webcam.streaming = true; + }, + onStopped(stream) { + this.webcam.streaming = false; + }, + onStop() { + this.$refs.webcam.stop(); + }, + onStart() { + this.$refs.webcam.start(); + }, + onError(error) { + console.log("On Error Event", error); + }, + onCameras(cameras) { + this.webcam.devices = cameras; + console.log("On Cameras Event", cameras); + }, + onCameraChange(deviceId) { + this.webcam.deviceId = deviceId; + this.webcam.camera = deviceId; + }, + onInputSelected(type) { + this.inputType = type; + } } } -} diff --git a/src/components/svgChartLine.vue b/src/components/svgChartLine.vue index a0d23fc..6f8d3e5 100644 --- a/src/components/svgChartLine.vue +++ b/src/components/svgChartLine.vue @@ -1,15 +1,14 @@