diff --git a/extensions/fablabchemnitz_imagetracerjs.inx b/extensions/fablabchemnitz_imagetracerjs.inx new file mode 100644 index 00000000..4fcb1526 --- /dev/null +++ b/extensions/fablabchemnitz_imagetracerjs.inx @@ -0,0 +1,65 @@ + + + Imagetracer.js + fablabchemnitz.de.imagetracerjs + + + + + false + 1.0 + 1.0 + 8 + true + + + + + + + + + 16 + 0 + 3 + + + + + + + + + + + + 1.0 + false + + 1 + false + false + + + + 0 + 20.0 + + + + + + + + + + + image + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz_imagetracerjs/fablabchemnitz_imagetracerjs.py b/extensions/fablabchemnitz_imagetracerjs/fablabchemnitz_imagetracerjs.py new file mode 100644 index 00000000..6f42ac83 --- /dev/null +++ b/extensions/fablabchemnitz_imagetracerjs/fablabchemnitz_imagetracerjs.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python3 + +import sys +import inkex +import os +import base64 +import urllib.request as urllib +from PIL import Image +from io import BytesIO +from lxml import etree + +""" +Extension for InkScape 1.X +Features + - will vectorize your beautiful image into a more beautiful SVG trace with separated infills(break apart into single surfaces like a puzzle) + +Author: Mario Voigt / FabLab Chemnitz +Mail: mario.voigt@stadtfabrikanten.org +Date: 18.08.2020 +Last patch: 18.08.2020 +License: GNU GPL v3 + +Used version of imagetracerjs: https://github.com/jankovicsandras/imagetracerjs/commit/4d0f429efbb936db1a43db80815007a2cb113b34 +""" + +class Imagetracerjs (inkex.Effect): + + def checkImagePath(self, node): + xlink = node.get('xlink:href') + if xlink and xlink[:5] == 'data:': + # No need, data alread embedded + return + + url = urllib.urlparse(xlink) + href = urllib.url2pathname(url.path) + + # Primary location always the filename itself. + path = self.absolute_href(href or '') + + # Backup directory where we can find the image + if not os.path.isfile(path): + path = node.get('sodipodi:absref', path) + + if not os.path.isfile(path): + inkex.errormsg('File not found "{}". Unable to embed image.').format(path) + return + + if (os.path.isfile(path)): + return path + + def __init__(self): + inkex.Effect.__init__(self) + self.arg_parser.add_argument("--tabs") + self.arg_parser.add_argument("--keeporiginal", type=inkex.Boolean, default=False, help="Keep original image on canvas") + self.arg_parser.add_argument("--ltres", type=float, default=1.0, help="Error treshold straight lines") + self.arg_parser.add_argument("--qtres", type=float, default=1.0, help="Error treshold quadratic splines") + self.arg_parser.add_argument("--pathomit", type=int, default=8, help="Noise reduction - discard edge node paths shorter than") + self.arg_parser.add_argument("--rightangleenhance", type=inkex.Boolean, default=True, help="Enhance right angle corners") + self.arg_parser.add_argument("--colorsampling", default="2",help="Color sampling") + self.arg_parser.add_argument("--numberofcolors", type=int, default=16, help="Number of colors to use on palette") + self.arg_parser.add_argument("--mincolorratio", type=int, default=0, help="Color randomization ratio") + self.arg_parser.add_argument("--colorquantcycles", type=int, default=3, help="Color quantization will be repeated this many times") + self.arg_parser.add_argument("--layering", default="0",help="Layering") + self.arg_parser.add_argument("--strokewidth", type=float, default=1.0, help="SVG stroke-width") + self.arg_parser.add_argument("--linefilter", type=inkex.Boolean, default=False, help="Noise reduction line filter") + #self.arg_parser.add_argument("--scale", type=float, default=1.0, help="Coordinate scale factor") + self.arg_parser.add_argument("--roundcoords", type=int, default=1, help="Decimal places for rounding") + self.arg_parser.add_argument("--viewbox", type=inkex.Boolean, default=False, help="Enable or disable SVG viewBox") + self.arg_parser.add_argument("--desc", type=inkex.Boolean, default=False, help="SVG descriptions") + self.arg_parser.add_argument("--blurradius", type=int, default=0, help="Selective Gaussian blur preprocessing") + self.arg_parser.add_argument("--blurdelta", type=float, default=20.0, help="RGBA delta treshold for selective Gaussian blur preprocessing") + + def effect(self): + + # internal overwrite for scale: + self.options.scale = 1.0 + + if (self.options.ids): + for node in self.svg.selected.values(): + if node.tag == inkex.addNS('image', 'svg'): + self.path = self.checkImagePath(node) # This also ensures the file exists + if self.path is None: # check if image is embedded or linked + image_string = node.get('{http://www.w3.org/1999/xlink}href') + # find comma position + i = 0 + while i < 40: + if image_string[i] == ',': + break + i = i + 1 + image = Image.open(BytesIO(base64.b64decode(image_string[i + 1:len(image_string)]))) + else: + image = Image.open(self.path) + + # Write the embedded or linked image to temporary directory + exportfile = "imagetracerjs.png" + image.save(exportfile, "png") + + nodeclipath = os.path.join("imagetracerjs-master", "nodecli", "nodecli.js") + + ## Build up imagetracerjs command according to your settings from extension GUI + command = "node " # "node.exe" or "node" on Windows or just "node" on Linux + if os.name=="nt": # your OS is Windows. We handle path separator as "\\" instead of unix-like "/" + command += str(nodeclipath).replace("\\", "\\\\") + else: + command += str(nodeclipath) + command += " " + exportfile + command += " ltres " + str(self.options.ltres) + command += " qtres " + str(self.options.qtres) + command += " pathomit " + str(self.options.pathomit) + command += " rightangleenhance " + str(self.options.rightangleenhance).lower() + command += " colorsampling " + str(self.options.colorsampling) + command += " numberofcolors " + str(self.options.numberofcolors) + command += " mincolorratio " + str(self.options.mincolorratio) + command += " numberofcolors " + str(self.options.numberofcolors) + command += " colorquantcycles " + str(self.options.colorquantcycles) + command += " layering " + str(self.options.layering) + command += " strokewidth " + str(self.options.strokewidth) + command += " linefilter " + str(self.options.linefilter).lower() + command += " scale " + str(self.options.scale) + command += " roundcoords " + str(self.options.roundcoords) + command += " viewbox " + str(self.options.viewbox).lower() + command += " desc " + str(self.options.desc).lower() + command += " blurradius " + str(self.options.blurradius) + command += " blurdelta " + str(self.options.blurdelta) + + #inkex.utils.debug(command) + + # Create the vector traced SVG file + with os.popen(command, "r") as tracerprocess: + result = tracerprocess.read() + #inkex.utils.debug(result) + + # proceed if traced SVG file was successfully created + if os.path.exists(exportfile + ".svg"): + # Delete the temporary png file again because we do not need it anymore + if os.path.exists(exportfile): + os.remove(exportfile) + + # new parse the SVG file and insert it as new group into the current document tree + doc = etree.parse(exportfile + ".svg").getroot() + newGroup = self.document.getroot().add(inkex.Group()) + newGroup.attrib['transform'] = "matrix(" + \ + str(float(node.get('width')) / float(doc.get('width'))) + \ + ", 0, 0 , " + \ + str(float(node.get('height')) / float(doc.get('height'))) + \ + "," + node.get('x') + \ + "," + node.get('y') + ")" + newGroup.append(doc) + + # Delet the temporary svg file + if os.path.exists(exportfile + ".svg"): + os.remove(exportfile + ".svg") + + #remove the old image or not + if self.options.keeporiginal is not True: + node.getparent().remove(node) + else: + inkex.utils.debug("No image found for tracing. Please select an image first.") + +Imagetracerjs().run() \ No newline at end of file diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/.eslintrc.json b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/.eslintrc.json new file mode 100644 index 00000000..87f6bce6 --- /dev/null +++ b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/.eslintrc.json @@ -0,0 +1,24 @@ +{ + "env": { + "browser": true + }, + "extends": "eslint:recommended", + "rules": { + "indent": [ + 2, + "tab" + ], + "linebreak-style": [ + 2, + "windows" + ], + "quotes": [ + 2, + "single" + ], + "semi": [ + 2, + "always" + ] + } +} \ No newline at end of file diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/.project b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/.project new file mode 100644 index 00000000..4a32755f --- /dev/null +++ b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/.project @@ -0,0 +1,17 @@ + + + imagetracerjs + + + + + + org.eclipse.wst.jsdt.core.javascriptValidator + + + + + + org.eclipse.wst.jsdt.core.jsNature + + diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/.settings/.jsdtscope b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/.settings/.jsdtscope new file mode 100644 index 00000000..c19fafc7 --- /dev/null +++ b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/.settings/.jsdtscope @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/.settings/org.eclipse.wst.jsdt.ui.superType.container b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/.settings/org.eclipse.wst.jsdt.ui.superType.container new file mode 100644 index 00000000..49c8cd4f --- /dev/null +++ b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/.settings/org.eclipse.wst.jsdt.ui.superType.container @@ -0,0 +1 @@ +org.eclipse.wst.jsdt.launching.JRE_CONTAINER \ No newline at end of file diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/.settings/org.eclipse.wst.jsdt.ui.superType.name b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/.settings/org.eclipse.wst.jsdt.ui.superType.name new file mode 100644 index 00000000..11006e2a --- /dev/null +++ b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/.settings/org.eclipse.wst.jsdt.ui.superType.name @@ -0,0 +1 @@ +Global \ No newline at end of file diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/LICENSE b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/LICENSE new file mode 100644 index 00000000..a84c3956 --- /dev/null +++ b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/LICENSE @@ -0,0 +1,25 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to + diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/README.md b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/README.md new file mode 100644 index 00000000..6e9d6c9d --- /dev/null +++ b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/README.md @@ -0,0 +1,306 @@ +# imagetracerjs +![alt Bitmap to Svg](docimages/s1.png) + +Simple raster image tracer and vectorizer written in JavaScript. + +--- + +## Table of contents +- [Getting started](#getting-started) +- [News](#news) +- [API](#api) +- [Options](#options) +- [Examples](#examples) +- [Process overview](#process-overview) +- [License](#license) + +--- + +## Getting started + +### Using in the Browser +Include the script: +```javascript + +``` +Then: +```javascript +// Loading an image, tracing with the 'posterized2' option preset, and appending the SVG to an element with id="svgcontainer" +ImageTracer.imageToSVG( + + 'panda.png', /* input filename / URL */ + + function(svgstr){ ImageTracer.appendSVGString( svgstr, 'svgcontainer' ); }, /* callback function to run on SVG string result */ + + 'posterized2' /* Option preset */ + +); +``` + +### Using with Node.js + +Node.js Command line interface example: + +``` +imagetracerjs/nodecli>node nodecli ../panda.png outfilename panda.svg scale 10 +``` + +Expected result: + +``` +imagetracerjs/nodecli/panda.svg was saved! +``` + +--- + +## News + +### 1.2.6 + - FIXED: hole shape parent search (Issues #31 #39) + - FIXED: Handle (absolute) paths in CLI correctly Issue #42 + +### 1.2.5 + - RGBA ImageData check in colorquantization(), solving Issue #24 and #18 + +### 1.2.4 + - ```options.layering``` : default 0 = sequential, new method ; 1 = parallel, old method. (Enhancement Issue #17) + - case insensitive option preset names + - README.md reorganizing + +[Version history](https://github.com/jankovicsandras/imagetracerjs/blob/master/version_history.md) + +--- + +## API +|Function name|Arguments|Returns|Run type| +|-------------|---------|-------|--------| +|```imageToSVG```|```image_url /*string*/ , callback /*function*/ , options /*optional object or preset name*/```|Nothing, ```callback(svgstring)``` will be executed|Asynchronous, Browser only| +|```imagedataToSVG```|```imagedata /*object*/ , options /*optional object or preset name*/```|```svgstring /*string*/```|Synchronous, Browser & Node.js| +|```imageToTracedata```|```image_url /*string*/ , callback /*function*/ , options /*optional object or preset name*/```|Nothing, ```callback(tracedata)``` will be executed|Asynchronous, Browser only| +|```imagedataToTracedata```|```imagedata /*object*/ , options /*optional object or preset name*/```|```tracedata /*object*/```|Synchronous, Browser & Node.js| + +```imagedata``` is standard [ImageData](https://developer.mozilla.org/en-US/docs/Web/API/ImageData) here, ```canvas``` is [canvas](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas) . + +### Helper Functions (Browser only) +|Function name|Arguments|Returns|Run type| +|-------------|---------|-------|--------| +|```appendSVGString```|```svgstring /*string*/, parentid /*string*/```|Nothing, an SVG will be appended to the container DOM element with id=parentid.|Synchronous, Browser only| +|```loadImage```|```url /*string*/, callback /*function*/```|Nothing, loading an image from a URL, then executing ```callback(canvas)```|Asynchronous, Browser only| +|```getImgdata```|```canvas /*object*/```|```imagedata /*object*/```|Synchronous, Browser only| + +```imagedata``` is standard [ImageData](https://developer.mozilla.org/en-US/docs/Web/API/ImageData) here, ```canvas``` is [canvas](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas) . +There are more functions for advanced users, read the source if you are interested. :) + +"Browser only" means that Node.js doesn't have built-in canvas and DOM support as of 2018, so loading an image to an ImageData object needs an external library. + +--- + +## Options +You can use an option preset name (string) or an [options object](https://github.com/jankovicsandras/imagetracerjs/blob/master/options.md) to control the tracing and rendering process. + +![Option presets gallery](docimages/option_presets_small.png) + +These strings can be passed instead of the options object: +```'default'``` +```'posterized1'``` +```'posterized2'``` +```'posterized3'``` +```'curvy'``` +```'sharp'``` +```'detailed'``` +```'smoothed'``` +```'grayscale'``` +```'fixedpalette'``` +```'randomsampling1'``` +```'randomsampling2'``` +```'artistic1'``` +```'artistic2'``` +```'artistic3'``` +```'artistic4'``` + +[Read more about options.](https://github.com/jankovicsandras/imagetracerjs/blob/master/options.md) + +--- + +## Examples + +### Using in the Browser +Include the script: +```javascript + +``` +Then +```javascript +// Loading smiley.png, tracing and calling alert callback on the SVG string result +ImageTracer.imageToSVG( 'smiley.png', alert ); + + +// Almost the same with options, and the ImageTracer.appendSVGString callback will append the SVG +ImageTracer.imageToSVG( 'smiley.png', ImageTracer.appendSVGString, { ltres:0.1, qtres:1, scale:10, strokewidth:5 } ); + + +// This uses the 'posterized2' option preset and appends the SVG to an element with id="svgcontainer" +ImageTracer.imageToSVG( + 'panda.png', + function(svgstr){ ImageTracer.appendSVGString( svgstr, 'svgcontainer' ); }, + 'posterized2' +); + + +// The helper function loadImage() loads an image to a canvas, then executing callback: +// appending the canvas to a div here. +ImageTracer.loadImage( + 'panda.png', + function(canvas){ (document.getElementById('canvascontainer')).appendChild(canvas); } +); + + +// ImageData can be traced to an SVG string synchronously. +ImageTracer.loadImage( + 'smiley.png', + function(canvas){ + + // Getting ImageData from canvas with the helper function getImgdata(). + var imgd = ImageTracer.getImgdata( canvas ); + + // Synchronous tracing to SVG string + var svgstr = ImageTracer.imagedataToSVG( imgd, { scale:5 } ); + + // Appending SVG + ImageTracer.appendSVGString( svgstr, 'svgcontainer' ); + + } +); + + +// This will load an image, trace it when loaded, and execute callback on the tracedata: +// stringifying and alerting it here. +ImageTracer.imageToTracedata( + 'smiley.png', + function(tracedata){ alert( JSON.stringify( tracedata ) ); }, + { ltres:0.1, qtres:1, scale:10 } +); + + +// imagedataToTracedata() is very similar to the previous functions. This returns tracedata synchronously. +ImageTracer.loadImage( + 'smiley.png', + function(canvas){ + + // Getting ImageData from canvas with the helper function getImgdata(). + var imgd = ImageTracer.getImgdata(canvas); + + // Synchronous tracing to tracedata + var tracedata = ImageTracer.imagedataToTracedata( imgd, { ltres:1, qtres:0.01, scale:10 } ); + + alert( JSON.stringify( tracedata ) ); + } +); +``` + +### Using with Node.js CLI + +Node.js Command line interface example: + +``` +imagetracerjs/nodecli>node nodecli ../panda.png outfilename panda.svg scale 10 +``` + +Expected result: + +``` +imagetracerjs/nodecli/panda.svg was saved! +``` + +CLI parameter names are supported both with and without trailing dash: ```-scale 10``` and ```scale 10``` are both correct. +Almost all options are supported, except ```pal``` and ```layercontainerid```. + +### Simple Node.js converting example + +```javascript +"use strict"; + +var fs = require('fs'); + +var ImageTracer = require( __dirname + '/../imagetracer_v1.2.6' ); + +// This example uses https://github.com/arian/pngjs +// , but other libraries can be used to load an image file to an ImageData object. +var PNGReader = require( __dirname + '/PNGReader' ); + +// Input and output filepaths / URLs +var infilepath = __dirname + '/' + 'panda.png'; +var outfilepath = __dirname + '/' + 'panda.svg'; + + +fs.readFile( + + infilepath, + + function( err, bytes ){ // fs.readFile callback + if(err){ console.log(err); throw err; } + + var reader = new PNGReader(bytes); + + reader.parse( function( err, png ){ // PNGReader callback + if(err){ console.log(err); throw err; } + + // creating an ImageData object + var myImageData = { width:png.width, height:png.height, data:png.pixels }; + + // tracing to SVG string + var options = { scale: 5 }; // options object; option preset string can be used also + + var svgstring = ImageTracer.imagedataToSVG( myImageData, options ); + + // writing to file + fs.writeFile( + outfilepath, + svgstring, + function(err){ if(err){ console.log(err); throw err; } console.log( outfilepath + ' was saved!' ); } + ); + + });// End of reader.parse() + + }// End of readFile callback() + +);// End of fs.readFile() +``` + +### Tracedata processing / Simplify.js example +It's possible to process the traced geometry and color data before SVG rendering. This example [simplify_interop.html](https://github.com/jankovicsandras/imagetracerjs/blob/master/simplify_interop.html) shows polyline simplification. You need to download simplify.js from https://github.com/mourner/simplify-js . + +--- + +## Process overview +See [Process overview and Ideas for improvement](https://github.com/jankovicsandras/imagetracerjs/blob/master/process_overview.md) + +--- + +## License +### The Unlicense / PUBLIC DOMAIN + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to [http://unlicense.org](http://unlicense.org) diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/bower.json b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/bower.json new file mode 100644 index 00000000..5fcf697f --- /dev/null +++ b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/bower.json @@ -0,0 +1,34 @@ +{ + "name": "imagetracerjs", + "description": "raster image tracer and vectorizer, bitmap to SVG converter", + "repository": { + "type": "git", + "url": "https://github.com/jankovicsandras/imagetracerjs.git" + }, + "main": "imagetracer_v1.2.6.js", + "keywords": [ + "image", + "tracer", + "tracing", + "vector", + "raster", + "vectorize", + "vectorizing", + "convert", + "conversion", + "converting", + "bitmap", + "svg", + "bmp", + "png", + "jpg", + "jpeg", + "gif" + ], + "authors": [ "András Jankovics" ], + "license": "Unlicense", + "bugs": { + "url": "https://github.com/jankovicsandras/imagetracerjs/issues" + }, + "homepage": "https://github.com/jankovicsandras/imagetracerjs#readme" +} diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/cover_problem.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/cover_problem.png new file mode 100644 index 00000000..f457b688 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/cover_problem.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/option_presets.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/option_presets.png new file mode 100644 index 00000000..49be0a9d Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/option_presets.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/option_presets_small.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/option_presets_small.png new file mode 100644 index 00000000..dc21ab62 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/option_presets_small.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s1.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s1.png new file mode 100644 index 00000000..469e2acd Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s1.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s10.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s10.png new file mode 100644 index 00000000..358cb023 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s10.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s11.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s11.png new file mode 100644 index 00000000..3af8e7c2 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s11.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s12.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s12.png new file mode 100644 index 00000000..e0c8f699 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s12.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s13.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s13.png new file mode 100644 index 00000000..64eb1f6a Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s13.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s14.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s14.png new file mode 100644 index 00000000..4a61d942 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s14.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s15.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s15.png new file mode 100644 index 00000000..33d7506e Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s15.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s2.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s2.png new file mode 100644 index 00000000..ddde649f Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s2.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s3.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s3.png new file mode 100644 index 00000000..2045a109 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s3.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s4.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s4.png new file mode 100644 index 00000000..c517488e Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s4.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s7.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s7.png new file mode 100644 index 00000000..6aaf04d7 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s7.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s8.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s8.png new file mode 100644 index 00000000..1e024247 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s8.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s9.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s9.png new file mode 100644 index 00000000..17285597 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/s9.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/transparency_problem.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/transparency_problem.png new file mode 100644 index 00000000..754593ed Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/docimages/transparency_problem.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/imagetracer_examples.html b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/imagetracer_examples.html new file mode 100644 index 00000000..32d6ce7e --- /dev/null +++ b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/imagetracer_examples.html @@ -0,0 +1,82 @@ + + + + + + + + + +
+
+ \ No newline at end of file diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/imagetracer_options_gallery.html b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/imagetracer_options_gallery.html new file mode 100644 index 00000000..1866d658 --- /dev/null +++ b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/imagetracer_options_gallery.html @@ -0,0 +1,69 @@ + + + + + + + imagetracer.js options gallery + + + + + + + +
+ + + + + +

Original
+
+ + + \ No newline at end of file diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/imagetracer_test_automation.html b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/imagetracer_test_automation.html new file mode 100644 index 00000000..ff17b688 --- /dev/null +++ b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/imagetracer_test_automation.html @@ -0,0 +1,334 @@ + + + + + imagetracer.js test automation + + + + + + +
+

Test images

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
















+

Settings

+
+
+
+
+ Example Custom Options:
{"ltres":1,"qtres":1,"pathomit":8,"colorsampling":true,"numberofcolors":16,"mincolorratio":0.02,"colorquantcycles":3,"scale":1,"simplifytolerance":0,"roundcoords":1,"lcpr":0,"qcpr":0,"desc":true,"viewbox":false,"blurradius":0,"blurdelta":20}
+
+ + +
+ +

Result (if Draw SVG is active)

+ + + + + + + + + + + + +
Traced SVGOriginal rasterSVG rendered as rasterDifference
+ +

Measurements

+
+ + + + + + + + + + + + + + + + + + + +
RowIDFilenamewidth (pixels)height (pixels)area (pixels)SVG string length (bytes)Tracing time (ms)Rendering time (ms)Nr. of pathsRGBA difference (cummulative RGBA difference / (area*4))Different pixels (%)Options
+ +
+ \ No newline at end of file diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/imagetracer_v1.2.6.js b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/imagetracer_v1.2.6.js new file mode 100644 index 00000000..6c62432e --- /dev/null +++ b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/imagetracer_v1.2.6.js @@ -0,0 +1,1217 @@ +/* + imagetracer.js version 1.2.6 + Simple raster image tracer and vectorizer written in JavaScript. + andras@jankovics.net +*/ + +/* + +The Unlicense / PUBLIC DOMAIN + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to http://unlicense.org/ + +*/ + +(function(){ 'use strict'; + +function ImageTracer(){ + var _this = this; + + this.versionnumber = '1.2.6', + + //////////////////////////////////////////////////////////// + // + // API + // + //////////////////////////////////////////////////////////// + + // Loading an image from a URL, tracing when loaded, + // then executing callback with the scaled svg string as argument + this.imageToSVG = function( url, callback, options ){ + options = _this.checkoptions(options); + // loading image, tracing and callback + _this.loadImage( + url, + function(canvas){ + callback( + _this.imagedataToSVG( _this.getImgdata(canvas), options ) + ); + }, + options + ); + },// End of imageToSVG() + + // Tracing imagedata, then returning the scaled svg string + this.imagedataToSVG = function( imgd, options ){ + options = _this.checkoptions(options); + // tracing imagedata + var td = _this.imagedataToTracedata( imgd, options ); + // returning SVG string + return _this.getsvgstring(td, options); + },// End of imagedataToSVG() + + // Loading an image from a URL, tracing when loaded, + // then executing callback with tracedata as argument + this.imageToTracedata = function( url, callback, options ){ + options = _this.checkoptions(options); + // loading image, tracing and callback + _this.loadImage( + url, + function(canvas){ + callback( + _this.imagedataToTracedata( _this.getImgdata(canvas), options ) + ); + }, + options + ); + },// End of imageToTracedata() + + // Tracing imagedata, then returning tracedata (layers with paths, palette, image size) + this.imagedataToTracedata = function( imgd, options ){ + options = _this.checkoptions(options); + + // 1. Color quantization + var ii = _this.colorquantization( imgd, options ); + + if(options.layering === 0){// Sequential layering + + // create tracedata object + var tracedata = { + layers : [], + palette : ii.palette, + width : ii.array[0].length-2, + height : ii.array.length-2 + }; + + // Loop to trace each color layer + for(var colornum=0; colornum pathscan -> internodes -> batchtracepaths + var tracedlayer = + _this.batchtracepaths( + + _this.internodes( + + _this.pathscan( + _this.layeringstep( ii, colornum ), + options.pathomit + ), + + options + + ), + + options.ltres, + options.qtres + + ); + + // adding traced layer + tracedata.layers.push(tracedlayer); + + }// End of color loop + + }else{// Parallel layering + // 2. Layer separation and edge detection + var ls = _this.layering( ii ); + + // Optional edge node visualization + if(options.layercontainerid){ _this.drawLayers( ls, _this.specpalette, options.scale, options.layercontainerid ); } + + // 3. Batch pathscan + var bps = _this.batchpathscan( ls, options.pathomit ); + + // 4. Batch interpollation + var bis = _this.batchinternodes( bps, options ); + + // 5. Batch tracing and creating tracedata object + var tracedata = { + layers : _this.batchtracelayers( bis, options.ltres, options.qtres ), + palette : ii.palette, + width : imgd.width, + height : imgd.height + }; + + }// End of parallel layering + + // return tracedata + return tracedata; + + },// End of imagedataToTracedata() + + this.optionpresets = { + 'default': { + + // Tracing + corsenabled : false, + ltres : 1, + qtres : 1, + pathomit : 8, + rightangleenhance : true, + + // Color quantization + colorsampling : 2, + numberofcolors : 16, + mincolorratio : 0, + colorquantcycles : 3, + + // Layering method + layering : 0, + + // SVG rendering + strokewidth : 1, + linefilter : false, + scale : 1, + roundcoords : 1, + viewbox : false, + desc : false, + lcpr : 0, + qcpr : 0, + + // Blur + blurradius : 0, + blurdelta : 20 + + }, + 'posterized1': { colorsampling:0, numberofcolors:2 }, + 'posterized2': { numberofcolors:4, blurradius:5 }, + 'curvy': { ltres:0.01, linefilter:true, rightangleenhance:false }, + 'sharp': { qtres:0.01, linefilter:false }, + 'detailed': { pathomit:0, roundcoords:2, ltres:0.5, qtres:0.5, numberofcolors:64 }, + 'smoothed': { blurradius:5, blurdelta: 64 }, + 'grayscale': { colorsampling:0, colorquantcycles:1, numberofcolors:7 }, + 'fixedpalette': { colorsampling:0, colorquantcycles:1, numberofcolors:27 }, + 'randomsampling1': { colorsampling:1, numberofcolors:8 }, + 'randomsampling2': { colorsampling:1, numberofcolors:64 }, + 'artistic1': { colorsampling:0, colorquantcycles:1, pathomit:0, blurradius:5, blurdelta: 64, ltres:0.01, linefilter:true, numberofcolors:16, strokewidth:2 }, + 'artistic2': { qtres:0.01, colorsampling:0, colorquantcycles:1, numberofcolors:4, strokewidth:0 }, + 'artistic3': { qtres:10, ltres:10, numberofcolors:8 }, + 'artistic4': { qtres:10, ltres:10, numberofcolors:64, blurradius:5, blurdelta: 256, strokewidth:2 }, + 'posterized3': { ltres: 1, qtres: 1, pathomit: 20, rightangleenhance: true, colorsampling: 0, numberofcolors: 3, + mincolorratio: 0, colorquantcycles: 3, blurradius: 3, blurdelta: 20, strokewidth: 0, linefilter: false, + roundcoords: 1, pal: [ { r: 0, g: 0, b: 100, a: 255 }, { r: 255, g: 255, b: 255, a: 255 } ] } + },// End of optionpresets + + // creating options object, setting defaults for missing values + this.checkoptions = function(options){ + options = options || {}; + // Option preset + if(typeof options === 'string'){ + options = options.toLowerCase(); + if( _this.optionpresets[options] ){ options = _this.optionpresets[options]; }else{ options = {}; } + } + // Defaults + var ok = Object.keys(_this.optionpresets['default']); + for(var k=0; k + return options; + },// End of checkoptions() + + //////////////////////////////////////////////////////////// + // + // Vectorizing functions + // + //////////////////////////////////////////////////////////// + + // 1. Color quantization + // Using a form of k-means clustering repeatead options.colorquantcycles times. http://en.wikipedia.org/wiki/Color_quantization + this.colorquantization = function( imgd, options ){ + var arr = [], idx=0, cd,cdl,ci, paletteacc = [], pixelnum = imgd.width * imgd.height, i, j, k, cnt, palette; + + // imgd.data must be RGBA, not just RGB + if( imgd.data.length < pixelnum * 4 ){ + var newimgddata = new Uint8ClampedArray(pixelnum * 4); + for(var pxcnt = 0; pxcnt < pixelnum ; pxcnt++){ + newimgddata[pxcnt*4 ] = imgd.data[pxcnt*3 ]; + newimgddata[pxcnt*4+1] = imgd.data[pxcnt*3+1]; + newimgddata[pxcnt*4+2] = imgd.data[pxcnt*3+2]; + newimgddata[pxcnt*4+3] = 255; + } + imgd.data = newimgddata; + }// End of RGBA imgd.data check + + // Filling arr (color index array) with -1 + for( j=0; j 0 ){ imgd = _this.blur( imgd, options.blurradius, options.blurdelta ); } + + // Repeat clustering step options.colorquantcycles times + for( cnt=0; cnt < options.colorquantcycles; cnt++ ){ + + // Average colors from the second iteration + if(cnt>0){ + // averaging paletteacc for palette + for( k=0; k < palette.length; k++ ){ + + // averaging + if( paletteacc[k].n > 0 ){ + palette[k] = { r: Math.floor( paletteacc[k].r / paletteacc[k].n ), + g: Math.floor( paletteacc[k].g / paletteacc[k].n ), + b: Math.floor( paletteacc[k].b / paletteacc[k].n ), + a: Math.floor( paletteacc[k].a / paletteacc[k].n ) }; + } + + // Randomizing a color, if there are too few pixels and there will be a new cycle + if( ( paletteacc[k].n/pixelnum < options.mincolorratio ) && ( cnt < options.colorquantcycles-1 ) ){ + palette[k] = { r: Math.floor(Math.random()*255), + g: Math.floor(Math.random()*255), + b: Math.floor(Math.random()*255), + a: Math.floor(Math.random()*255) }; + } + + }// End of palette loop + }// End of Average colors from the second iteration + + // Reseting palette accumulator for averaging + for( i=0; i < palette.length; i++ ){ paletteacc[i] = { r:0, g:0, b:0, a:0, n:0 }; } + + // loop through all pixels + for( j=0; j < imgd.height; j++ ){ + for( i=0; i < imgd.width; i++ ){ + + // pixel index + idx = (j*imgd.width+i)*4; + + // find closest color from palette by measuring (rectilinear) color distance between this pixel and all palette colors + ci=0; cdl = 1024; // 4 * 256 is the maximum RGBA distance + for( k=0; k p.y) !== (pa[j].y > p.y)) && (p.x < (pa[j].x - pa[i].x) * (p.y - pa[i].y) / (pa[j].y - pa[i].y) + pa[i].x) ) + ? !isin : isin; + } + + return isin; + }, + + // Lookup tables for pathscan + // pathscan_combined_lookup[ arr[py][px] ][ dir ] = [nextarrpypx, nextdir, deltapx, deltapy]; + this.pathscan_combined_lookup = [ + [[-1,-1,-1,-1], [-1,-1,-1,-1], [-1,-1,-1,-1], [-1,-1,-1,-1]],// arr[py][px]===0 is invalid + [[ 0, 1, 0,-1], [-1,-1,-1,-1], [-1,-1,-1,-1], [ 0, 2,-1, 0]], + [[-1,-1,-1,-1], [-1,-1,-1,-1], [ 0, 1, 0,-1], [ 0, 0, 1, 0]], + [[ 0, 0, 1, 0], [-1,-1,-1,-1], [ 0, 2,-1, 0], [-1,-1,-1,-1]], + + [[-1,-1,-1,-1], [ 0, 0, 1, 0], [ 0, 3, 0, 1], [-1,-1,-1,-1]], + [[13, 3, 0, 1], [13, 2,-1, 0], [ 7, 1, 0,-1], [ 7, 0, 1, 0]], + [[-1,-1,-1,-1], [ 0, 1, 0,-1], [-1,-1,-1,-1], [ 0, 3, 0, 1]], + [[ 0, 3, 0, 1], [ 0, 2,-1, 0], [-1,-1,-1,-1], [-1,-1,-1,-1]], + + [[ 0, 3, 0, 1], [ 0, 2,-1, 0], [-1,-1,-1,-1], [-1,-1,-1,-1]], + [[-1,-1,-1,-1], [ 0, 1, 0,-1], [-1,-1,-1,-1], [ 0, 3, 0, 1]], + [[11, 1, 0,-1], [14, 0, 1, 0], [14, 3, 0, 1], [11, 2,-1, 0]], + [[-1,-1,-1,-1], [ 0, 0, 1, 0], [ 0, 3, 0, 1], [-1,-1,-1,-1]], + + [[ 0, 0, 1, 0], [-1,-1,-1,-1], [ 0, 2,-1, 0], [-1,-1,-1,-1]], + [[-1,-1,-1,-1], [-1,-1,-1,-1], [ 0, 1, 0,-1], [ 0, 0, 1, 0]], + [[ 0, 1, 0,-1], [-1,-1,-1,-1], [-1,-1,-1,-1], [ 0, 2,-1, 0]], + [[-1,-1,-1,-1], [-1,-1,-1,-1], [-1,-1,-1,-1], [-1,-1,-1,-1]]// arr[py][px]===15 is invalid + ], + + // 3. Walking through an edge node array, discarding edge node types 0 and 15 and creating paths from the rest. + // Walk directions (dir): 0 > ; 1 ^ ; 2 < ; 3 v + this.pathscan = function( arr, pathomit ){ + var paths=[], pacnt=0, pcnt=0, px=0, py=0, w = arr[0].length, h = arr.length, + dir=0, pathfinished=true, holepath=false, lookuprow; + + for(var j=0; j paths[pacnt].boundingbox[2] ){ paths[pacnt].boundingbox[2] = px-1; } + if( (py-1) < paths[pacnt].boundingbox[1] ){ paths[pacnt].boundingbox[1] = py-1; } + if( (py-1) > paths[pacnt].boundingbox[3] ){ paths[pacnt].boundingbox[3] = py-1; } + + // Next: look up the replacement, direction and coordinate changes = clear this cell, turn if required, walk forward + lookuprow = _this.pathscan_combined_lookup[ arr[py][px] ][ dir ]; + arr[py][px] = lookuprow[0]; dir = lookuprow[1]; px += lookuprow[2]; py += lookuprow[3]; + + // Close path + if( (px-1 === paths[pacnt].points[0].x ) && ( py-1 === paths[pacnt].points[0].y ) ){ + pathfinished = true; + + // Discarding paths shorter than pathomit + if( paths[pacnt].points.length < pathomit ){ + paths.pop(); + }else{ + + paths[pacnt].isholepath = holepath ? true : false; + + // Finding the parent shape for this hole + if(holepath){ + + var parentidx = 0, parentbbox = [-1,-1,w+1,h+1]; + for(var parentcnt=0; parentcnt < pacnt; parentcnt++){ + if( (!paths[parentcnt].isholepath) && + _this.boundingboxincludes( paths[parentcnt].boundingbox , paths[pacnt].boundingbox ) && + _this.boundingboxincludes( parentbbox , paths[parentcnt].boundingbox ) && + _this.pointinpoly( paths[pacnt].points[0], paths[parentcnt].points ) + ){ + parentidx = parentcnt; + parentbbox = paths[parentcnt].boundingbox; + } + } + + paths[parentidx].holechildren.push( pacnt ); + + }// End of holepath parent finding + + pacnt++; + + } + + }// End of Close path + + pcnt++; + + }// End of Path points loop + + }// End of Follow path + + }// End of i loop + }// End of j loop + + return paths; + },// End of pathscan() + + this.boundingboxincludes = function( parentbbox, childbbox ){ + return ( ( parentbbox[0] < childbbox[0] ) && ( parentbbox[1] < childbbox[1] ) && ( parentbbox[2] > childbbox[2] ) && ( parentbbox[3] > childbbox[3] ) ); + },// End of boundingboxincludes() + + // 3. Batch pathscan + this.batchpathscan = function( layers, pathomit ){ + var bpaths = []; + for(var k in layers){ + if(!layers.hasOwnProperty(k)){ continue; } + bpaths[k] = _this.pathscan( layers[k], pathomit ); + } + return bpaths; + }, + + // 4. interpollating between path points for nodes with 8 directions ( East, SouthEast, S, SW, W, NW, N, NE ) + this.internodes = function( paths, options ){ + var ins = [], palen=0, nextidx=0, nextidx2=0, previdx=0, previdx2=0, pacnt, pcnt; + + // paths loop + for(pacnt=0; pacnt 0){ + ins[pacnt].points[ ins[pacnt].points.length-1 ].linesegment = _this.getdirection( + ins[pacnt].points[ ins[pacnt].points.length-1 ].x, + ins[pacnt].points[ ins[pacnt].points.length-1 ].y, + paths[pacnt].points[pcnt].x, + paths[pacnt].points[pcnt].y + ); + } + + // This corner point + ins[pacnt].points.push({ + x : paths[pacnt].points[pcnt].x, + y : paths[pacnt].points[pcnt].y, + linesegment : _this.getdirection( + paths[pacnt].points[pcnt].x, + paths[pacnt].points[pcnt].y, + (( paths[pacnt].points[pcnt].x + paths[pacnt].points[nextidx].x ) /2), + (( paths[pacnt].points[pcnt].y + paths[pacnt].points[nextidx].y ) /2) + ) + }); + + }// End of right angle enhance + + // interpolate between two path points + ins[pacnt].points.push({ + x : (( paths[pacnt].points[pcnt].x + paths[pacnt].points[nextidx].x ) /2), + y : (( paths[pacnt].points[pcnt].y + paths[pacnt].points[nextidx].y ) /2), + linesegment : _this.getdirection( + (( paths[pacnt].points[pcnt].x + paths[pacnt].points[nextidx].x ) /2), + (( paths[pacnt].points[pcnt].y + paths[pacnt].points[nextidx].y ) /2), + (( paths[pacnt].points[nextidx].x + paths[pacnt].points[nextidx2].x ) /2), + (( paths[pacnt].points[nextidx].y + paths[pacnt].points[nextidx2].y ) /2) + ) + }); + + }// End of pathpoints loop + + }// End of paths loop + + return ins; + },// End of internodes() + + this.testrightangle = function( path, idx1, idx2, idx3, idx4, idx5 ){ + return ( (( path.points[idx3].x === path.points[idx1].x) && + ( path.points[idx3].x === path.points[idx2].x) && + ( path.points[idx3].y === path.points[idx4].y) && + ( path.points[idx3].y === path.points[idx5].y) + ) || + (( path.points[idx3].y === path.points[idx1].y) && + ( path.points[idx3].y === path.points[idx2].y) && + ( path.points[idx3].x === path.points[idx4].x) && + ( path.points[idx3].x === path.points[idx5].x) + ) + ); + },// End of testrightangle() + + this.getdirection = function( x1, y1, x2, y2 ){ + var val = 8; + if(x1 < x2){ + if (y1 < y2){ val = 1; }// SouthEast + else if(y1 > y2){ val = 7; }// NE + else { val = 0; }// E + }else if(x1 > x2){ + if (y1 < y2){ val = 3; }// SW + else if(y1 > y2){ val = 5; }// NW + else { val = 4; }// W + }else{ + if (y1 < y2){ val = 2; }// S + else if(y1 > y2){ val = 6; }// N + else { val = 8; }// center, this should not happen + } + return val; + },// End of getdirection() + + // 4. Batch interpollation + this.batchinternodes = function( bpaths, options ){ + var binternodes = []; + for (var k in bpaths) { + if(!bpaths.hasOwnProperty(k)){ continue; } + binternodes[k] = _this.internodes(bpaths[k], options); + } + return binternodes; + }, + + // 5. tracepath() : recursively trying to fit straight and quadratic spline segments on the 8 direction internode path + + // 5.1. Find sequences of points with only 2 segment types + // 5.2. Fit a straight line on the sequence + // 5.3. If the straight line fails (distance error > ltres), find the point with the biggest error + // 5.4. Fit a quadratic spline through errorpoint (project this to get controlpoint), then measure errors on every point in the sequence + // 5.5. If the spline fails (distance error > qtres), find the point with the biggest error, set splitpoint = fitting point + // 5.6. Split sequence and recursively apply 5.2. - 5.6. to startpoint-splitpoint and splitpoint-endpoint sequences + + this.tracepath = function( path, ltres, qtres ){ + var pcnt=0, segtype1, segtype2, seqend, smp = {}; + smp.segments = []; + smp.boundingbox = path.boundingbox; + smp.holechildren = path.holechildren; + smp.isholepath = path.isholepath; + + while(pcnt < path.points.length){ + // 5.1. Find sequences of points with only 2 segment types + segtype1 = path.points[pcnt].linesegment; segtype2 = -1; seqend=pcnt+1; + while( + ((path.points[seqend].linesegment === segtype1) || (path.points[seqend].linesegment === segtype2) || (segtype2 === -1)) + && (seqend < path.points.length-1) ){ + + if((path.points[seqend].linesegment!==segtype1) && (segtype2===-1)){ segtype2 = path.points[seqend].linesegment; } + seqend++; + + } + if(seqend === path.points.length-1){ seqend = 0; } + + // 5.2. - 5.6. Split sequence and recursively apply 5.2. - 5.6. to startpoint-splitpoint and splitpoint-endpoint sequences + smp.segments = smp.segments.concat( _this.fitseq(path, ltres, qtres, pcnt, seqend) ); + + // forward pcnt; + if(seqend>0){ pcnt = seqend; }else{ pcnt = path.points.length; } + + }// End of pcnt loop + + return smp; + },// End of tracepath() + + // 5.2. - 5.6. recursively fitting a straight or quadratic line segment on this sequence of path nodes, + // called from tracepath() + this.fitseq = function( path, ltres, qtres, seqstart, seqend ){ + // return if invalid seqend + if( (seqend>path.points.length) || (seqend<0) ){ return []; } + // variables + var errorpoint=seqstart, errorval=0, curvepass=true, px, py, dist2; + var tl = (seqend-seqstart); if(tl<0){ tl += path.points.length; } + var vx = (path.points[seqend].x-path.points[seqstart].x) / tl, + vy = (path.points[seqend].y-path.points[seqstart].y) / tl; + + // 5.2. Fit a straight line on the sequence + var pcnt = (seqstart+1) % path.points.length, pl; + while(pcnt != seqend){ + pl = pcnt-seqstart; if(pl<0){ pl += path.points.length; } + px = path.points[seqstart].x + vx * pl; py = path.points[seqstart].y + vy * pl; + dist2 = (path.points[pcnt].x-px)*(path.points[pcnt].x-px) + (path.points[pcnt].y-py)*(path.points[pcnt].y-py); + if(dist2>ltres){curvepass=false;} + if(dist2>errorval){ errorpoint=pcnt; errorval=dist2; } + pcnt = (pcnt+1)%path.points.length; + } + // return straight line if fits + if(curvepass){ return [{ type:'L', x1:path.points[seqstart].x, y1:path.points[seqstart].y, x2:path.points[seqend].x, y2:path.points[seqend].y }]; } + + // 5.3. If the straight line fails (distance error>ltres), find the point with the biggest error + var fitpoint = errorpoint; curvepass = true; errorval = 0; + + // 5.4. Fit a quadratic spline through this point, measure errors on every point in the sequence + // helpers and projecting to get control point + var t=(fitpoint-seqstart)/tl, t1=(1-t)*(1-t), t2=2*(1-t)*t, t3=t*t; + var cpx = (t1*path.points[seqstart].x + t3*path.points[seqend].x - path.points[fitpoint].x)/-t2 , + cpy = (t1*path.points[seqstart].y + t3*path.points[seqend].y - path.points[fitpoint].y)/-t2 ; + + // Check every point + pcnt = seqstart+1; + while(pcnt != seqend){ + t=(pcnt-seqstart)/tl; t1=(1-t)*(1-t); t2=2*(1-t)*t; t3=t*t; + px = t1 * path.points[seqstart].x + t2 * cpx + t3 * path.points[seqend].x; + py = t1 * path.points[seqstart].y + t2 * cpy + t3 * path.points[seqend].y; + + dist2 = (path.points[pcnt].x-px)*(path.points[pcnt].x-px) + (path.points[pcnt].y-py)*(path.points[pcnt].y-py); + + if(dist2>qtres){curvepass=false;} + if(dist2>errorval){ errorpoint=pcnt; errorval=dist2; } + pcnt = (pcnt+1)%path.points.length; + } + // return spline if fits + if(curvepass){ return [{ type:'Q', x1:path.points[seqstart].x, y1:path.points[seqstart].y, x2:cpx, y2:cpy, x3:path.points[seqend].x, y3:path.points[seqend].y }]; } + // 5.5. If the spline fails (distance error>qtres), find the point with the biggest error + var splitpoint = fitpoint; // Earlier: Math.floor((fitpoint + errorpoint)/2); + + // 5.6. Split sequence and recursively apply 5.2. - 5.6. to startpoint-splitpoint and splitpoint-endpoint sequences + return _this.fitseq( path, ltres, qtres, seqstart, splitpoint ).concat( + _this.fitseq( path, ltres, qtres, splitpoint, seqend ) ); + + },// End of fitseq() + + // 5. Batch tracing paths + this.batchtracepaths = function(internodepaths,ltres,qtres){ + var btracedpaths = []; + for(var k in internodepaths){ + if(!internodepaths.hasOwnProperty(k)){ continue; } + btracedpaths.push( _this.tracepath(internodepaths[k],ltres,qtres) ); + } + return btracedpaths; + }, + + // 5. Batch tracing layers + this.batchtracelayers = function(binternodes, ltres, qtres){ + var btbis = []; + for(var k in binternodes){ + if(!binternodes.hasOwnProperty(k)){ continue; } + btbis[k] = _this.batchtracepaths(binternodes[k], ltres, qtres); + } + return btbis; + }, + + //////////////////////////////////////////////////////////// + // + // SVG Drawing functions + // + //////////////////////////////////////////////////////////// + + // Rounding to given decimals https://stackoverflow.com/questions/11832914/round-to-at-most-2-decimal-places-in-javascript + this.roundtodec = function(val,places){ return +val.toFixed(places); }, + + // Getting SVG path element string from a traced path + this.svgpathstring = function( tracedata, lnum, pathnum, options ){ + + var layer = tracedata.layers[lnum], smp = layer[pathnum], str='', pcnt; + + // Line filter + if(options.linefilter && (smp.segments.length < 3)){ return str; } + + // Starting path element, desc contains layer and path number + str = ''; + + // Rendering control points + if(options.lcpr || options.qcpr){ + for(pcnt=0; pcnt'; + str += ''; + str += ''; + str += ''; + } + if( (!smp.segments[pcnt].hasOwnProperty('x3')) && options.lcpr){ + str += ''; + } + } + + // Hole children control points + for( var hcnt=0; hcnt < smp.holechildren.length; hcnt++){ + var hsmp = layer[ smp.holechildren[hcnt] ]; + for(pcnt=0; pcnt'; + str += ''; + str += ''; + str += ''; + } + if( (!hsmp.segments[pcnt].hasOwnProperty('x3')) && options.lcpr){ + str += ''; + } + } + } + }// End of Rendering control points + + return str; + + },// End of svgpathstring() + + // Converting tracedata to an SVG string + this.getsvgstring = function( tracedata, options ){ + + options = _this.checkoptions(options); + + var w = tracedata.width * options.scale, h = tracedata.height * options.scale; + + // SVG start + var svgstr = ''; + + // Drawing: Layers and Paths loops + for(var lcnt=0; lcnt < tracedata.layers.length; lcnt++){ + for(var pcnt=0; pcnt < tracedata.layers[lcnt].length; pcnt++){ + + // Adding SVG string + if( !tracedata.layers[lcnt][pcnt].isholepath ){ + svgstr += _this.svgpathstring( tracedata, lcnt, pcnt, options ); + } + + }// End of paths loop + }// End of layers loop + + // SVG End + svgstr+=''; + + return svgstr; + + },// End of getsvgstring() + + // Comparator for numeric Array.sort + this.compareNumbers = function(a,b){ return a - b; }, + + // Convert color object to rgba string + this.torgbastr = function(c){ return 'rgba('+c.r+','+c.g+','+c.b+','+c.a+')'; }, + + // Convert color object to SVG color string + this.tosvgcolorstr = function(c, options){ + return 'fill="rgb('+c.r+','+c.g+','+c.b+')" stroke="rgb('+c.r+','+c.g+','+c.b+')" stroke-width="'+options.strokewidth+'" opacity="'+c.a/255.0+'" '; + }, + + // Helper function: Appending an element to a container from an svgstring + this.appendSVGString = function(svgstr,parentid){ + var div; + if(parentid){ + div = document.getElementById(parentid); + if(!div){ + div = document.createElement('div'); + div.id = parentid; + document.body.appendChild(div); + } + }else{ + div = document.createElement('div'); + document.body.appendChild(div); + } + div.innerHTML += svgstr; + }, + + //////////////////////////////////////////////////////////// + // + // Canvas functions + // + //////////////////////////////////////////////////////////// + + // Gaussian kernels for blur + this.gks = [ [0.27901,0.44198,0.27901], [0.135336,0.228569,0.272192,0.228569,0.135336], [0.086776,0.136394,0.178908,0.195843,0.178908,0.136394,0.086776], + [0.063327,0.093095,0.122589,0.144599,0.152781,0.144599,0.122589,0.093095,0.063327], [0.049692,0.069304,0.089767,0.107988,0.120651,0.125194,0.120651,0.107988,0.089767,0.069304,0.049692] ], + + // Selective Gaussian blur for preprocessing + this.blur = function(imgd,radius,delta){ + var i,j,k,d,idx,racc,gacc,bacc,aacc,wacc; + + // new ImageData + var imgd2 = { width:imgd.width, height:imgd.height, data:[] }; + + // radius and delta limits, this kernel + radius = Math.floor(radius); if(radius<1){ return imgd; } if(radius>5){ radius = 5; } delta = Math.abs( delta ); if(delta>1024){ delta = 1024; } + var thisgk = _this.gks[radius-1]; + + // loop through all pixels, horizontal blur + for( j=0; j < imgd.height; j++ ){ + for( i=0; i < imgd.width; i++ ){ + + racc = 0; gacc = 0; bacc = 0; aacc = 0; wacc = 0; + // gauss kernel loop + for( k = -radius; k < radius+1; k++){ + // add weighted color values + if( (i+k > 0) && (i+k < imgd.width) ){ + idx = (j*imgd.width+i+k)*4; + racc += imgd.data[idx ] * thisgk[k+radius]; + gacc += imgd.data[idx+1] * thisgk[k+radius]; + bacc += imgd.data[idx+2] * thisgk[k+radius]; + aacc += imgd.data[idx+3] * thisgk[k+radius]; + wacc += thisgk[k+radius]; + } + } + // The new pixel + idx = (j*imgd.width+i)*4; + imgd2.data[idx ] = Math.floor(racc / wacc); + imgd2.data[idx+1] = Math.floor(gacc / wacc); + imgd2.data[idx+2] = Math.floor(bacc / wacc); + imgd2.data[idx+3] = Math.floor(aacc / wacc); + + }// End of width loop + }// End of horizontal blur + + // copying the half blurred imgd2 + var himgd = new Uint8ClampedArray(imgd2.data); + + // loop through all pixels, vertical blur + for( j=0; j < imgd.height; j++ ){ + for( i=0; i < imgd.width; i++ ){ + + racc = 0; gacc = 0; bacc = 0; aacc = 0; wacc = 0; + // gauss kernel loop + for( k = -radius; k < radius+1; k++){ + // add weighted color values + if( (j+k > 0) && (j+k < imgd.height) ){ + idx = ((j+k)*imgd.width+i)*4; + racc += himgd[idx ] * thisgk[k+radius]; + gacc += himgd[idx+1] * thisgk[k+radius]; + bacc += himgd[idx+2] * thisgk[k+radius]; + aacc += himgd[idx+3] * thisgk[k+radius]; + wacc += thisgk[k+radius]; + } + } + // The new pixel + idx = (j*imgd.width+i)*4; + imgd2.data[idx ] = Math.floor(racc / wacc); + imgd2.data[idx+1] = Math.floor(gacc / wacc); + imgd2.data[idx+2] = Math.floor(bacc / wacc); + imgd2.data[idx+3] = Math.floor(aacc / wacc); + + }// End of width loop + }// End of vertical blur + + // Selective blur: loop through all pixels + for( j=0; j < imgd.height; j++ ){ + for( i=0; i < imgd.width; i++ ){ + + idx = (j*imgd.width+i)*4; + // d is the difference between the blurred and the original pixel + d = Math.abs(imgd2.data[idx ] - imgd.data[idx ]) + Math.abs(imgd2.data[idx+1] - imgd.data[idx+1]) + + Math.abs(imgd2.data[idx+2] - imgd.data[idx+2]) + Math.abs(imgd2.data[idx+3] - imgd.data[idx+3]); + // selective blur: if d>delta, put the original pixel back + if(d>delta){ + imgd2.data[idx ] = imgd.data[idx ]; + imgd2.data[idx+1] = imgd.data[idx+1]; + imgd2.data[idx+2] = imgd.data[idx+2]; + imgd2.data[idx+3] = imgd.data[idx+3]; + } + } + }// End of Selective blur + + return imgd2; + + },// End of blur() + + // Helper function: loading an image from a URL, then executing callback with canvas as argument + this.loadImage = function(url,callback,options){ + var img = new Image(); + if(options && options.corsenabled){ img.crossOrigin = 'Anonymous'; } + img.onload = function(){ + var canvas = document.createElement('canvas'); + canvas.width = img.width; + canvas.height = img.height; + var context = canvas.getContext('2d'); + context.drawImage(img,0,0); + callback(canvas); + }; + img.src = url; + }, + + // Helper function: getting ImageData from a canvas + this.getImgdata = function(canvas){ + var context = canvas.getContext('2d'); + return context.getImageData(0,0,canvas.width,canvas.height); + }, + + // Special palette to use with drawlayers() + this.specpalette = [ + {r:0,g:0,b:0,a:255}, {r:128,g:128,b:128,a:255}, {r:0,g:0,b:128,a:255}, {r:64,g:64,b:128,a:255}, + {r:192,g:192,b:192,a:255}, {r:255,g:255,b:255,a:255}, {r:128,g:128,b:192,a:255}, {r:0,g:0,b:192,a:255}, + {r:128,g:0,b:0,a:255}, {r:128,g:64,b:64,a:255}, {r:128,g:0,b:128,a:255}, {r:168,g:168,b:168,a:255}, + {r:192,g:128,b:128,a:255}, {r:192,g:0,b:0,a:255}, {r:255,g:255,b:255,a:255}, {r:0,g:128,b:0,a:255} + ], + + // Helper function: Drawing all edge node layers into a container + this.drawLayers = function(layers,palette,scale,parentid){ + scale = scale||1; + var w,h,i,j,k; + + // Preparing container + var div; + if(parentid){ + div = document.getElementById(parentid); + if(!div){ + div = document.createElement('div'); + div.id = parentid; + document.body.appendChild(div); + } + }else{ + div = document.createElement('div'); + document.body.appendChild(div); + } + + // Layers loop + for (k in layers) { + if(!layers.hasOwnProperty(k)){ continue; } + + // width, height + w=layers[k][0].length; h=layers[k].length; + + // Creating new canvas for every layer + var canvas = document.createElement('canvas'); canvas.width=w*scale; canvas.height=h*scale; + var context = canvas.getContext('2d'); + + // Drawing + for(j=0; j + + + + + + + +
+ + diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/smiley.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/smiley.png new file mode 100644 index 00000000..f926601f Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/smiley.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/smileyRGB.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/smileyRGB.png new file mode 100644 index 00000000..a7c9eeea Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/smileyRGB.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/1.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/1.png new file mode 100644 index 00000000..225ee402 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/1.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/10.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/10.png new file mode 100644 index 00000000..425774b7 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/10.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/11.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/11.png new file mode 100644 index 00000000..1cc54288 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/11.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/12.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/12.png new file mode 100644 index 00000000..89259220 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/12.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/13.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/13.png new file mode 100644 index 00000000..9dcc9097 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/13.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/14.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/14.png new file mode 100644 index 00000000..433a73b7 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/14.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/15.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/15.png new file mode 100644 index 00000000..394b8006 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/15.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/16.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/16.png new file mode 100644 index 00000000..832f93dc Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/16.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/2.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/2.png new file mode 100644 index 00000000..d598a470 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/2.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/3.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/3.png new file mode 100644 index 00000000..dda0fa36 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/3.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/4.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/4.png new file mode 100644 index 00000000..62b75c1d Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/4.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/5.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/5.png new file mode 100644 index 00000000..5b5f5509 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/5.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/6.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/6.png new file mode 100644 index 00000000..21925083 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/6.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/7.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/7.png new file mode 100644 index 00000000..1514eee5 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/7.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/8.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/8.png new file mode 100644 index 00000000..7c8a32c1 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/8.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/9.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/9.png new file mode 100644 index 00000000..caff72c5 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/9.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/combined.png b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/combined.png new file mode 100644 index 00000000..a5741ea1 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/testimages/combined.png differ diff --git a/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/version_history.md b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/version_history.md new file mode 100644 index 00000000..ca1dd00a --- /dev/null +++ b/extensions/fablabchemnitz_imagetracerjs/imagetracerjs-master/version_history.md @@ -0,0 +1,75 @@ +## Version history + +### 1.2.6 + - FIXED: hole shape parent search (Issues #31 #39) + - FIXED: Handle (absolute) paths in CLI correctly Issue #42 + +### 1.2.5 + - RGBA ImageData check in colorquantization(), solving Issue #24 and #18 + +### 1.2.4 + - ```options.layering``` : default 0 = sequential, new method ; 1 = parallel, old method. (Enhancement Issue #17) + - case insensitive option preset names + - README.md reorganizing + +### 1.2.3 + + - Node.js Command line interface (Enhancement Issue #13) + - FIXED: Pathomit problem thanks to EusthEnoptEron (Issue #14) + - options.corsenabled for [CORS Image loading](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image) thanks to neel-radica (Issue #12) + +### 1.2.2 + + - FIXED: missing hole in path because of incorrect bounding box (Issue #11) + - Posterized3 option preset + - Changed svgpathstring() arguments to simplify getsvgstring() + +### 1.2.1 + + - FIXED: Gaussian blur preprocessing is now independent of DOM and canvas, thus working directly with Node.js (Issue #9) + +### 1.2.0 + +This is a major update, changing some internal logic and option default values. The API is compatible, so it should work out of the box. + + - FIXED: transparent holes are now possible. ( Issue #7 and #8 ) + - Deterministic output by default: ```options.colorsampling = 2``` ; ```options.mincolorratio = 0``` are deterministic and the defaults now. + - Right angle enhancing: ```options.rightangleenhance``` ( default : true ) + - Option presets (see below) + - Custom strokewidth with ```options.strokewidth``` ( default : 1 ) + - Line filter with ```options.linefilter``` ( default : false ) + - Simplified ```getsvgstring()```; ```options.desc = false``` by default; splitpoint = fitpoint in fitseq(); small bugfixes and optimizations + +Version history and README for the old 1.1.2 version is [here.](https://github.com/jankovicsandras/imagetracerjs/blob/master/README_v1.1.2.md) + +### 1.1.2 + +- minor bugfixes +- lookup based ```pathscan()``` + +### 1.1.1 + +- Bugfix: CSS3 RGBA output in SVG was technically incorrect (however supported by major browsers), so this is changed. [More info](https://stackoverflow.com/questions/6042550/svg-fill-color-transparency-alpha) + +### 1.1.0 + +- it works with Node.js (external library required to load image into an ImageData object) +- export as AMD module / Node module / browser or worker variable +- new syntax: ```ImageTracer112.imageToTracedata()```, no need to initialize +- fixed ```options``` with hasOwnProperty: 0 values are not replaced with defaults, fixed polygons with coordinates x=0 or y=0 +- transparency support: alpha is not discarded now, it is given more weight in color quantization +- new ```options.roundcoords``` : rounding coordinates to a given decimal place. This can reduce SVG length significantly (>20%) with minor loss of precision. +- new ```options.desc``` : setting this to false will turn off path descriptions, reducing SVG length. +- new ```options.viewbox``` : setting this to true will use viewBox instead of exact width and height +- new ```options.colorsampling``` : color quantization will sample the colors now by default, can be turned off. +- new ```options.blurradius``` : setting this to 1..5 will preprocess the image with a selective Gaussian blur with ```options.blurdelta``` treshold. This can filter noise and improve quality. +- ```imagedataToTracedata()``` returns image width and height in tracedata +- ```getsvgstring()``` needs now only ```tracedata``` and ```options``` as parameters +- ```colorquantization()``` needs now only ```imgd``` and ```options``` as parameters +- background field is removed from the results of color quantization +- ESLint passed +- test automation and simple statistics in imagetracer_test_automation.html + +### 1.0.0 - 1.0.4 + +- first published version + bugfixes \ No newline at end of file diff --git a/extensions/fablabchemnitz_imagetracerjs/node.exe b/extensions/fablabchemnitz_imagetracerjs/node.exe new file mode 100644 index 00000000..a57ccd90 Binary files /dev/null and b/extensions/fablabchemnitz_imagetracerjs/node.exe differ