From 346f3a9817b1e0812565396b9811a1ce5adc97b8 Mon Sep 17 00:00:00 2001 From: jules Date: Fri, 13 Dec 2013 15:28:31 -0500 Subject: reorganize --- js/canvasquery.dither.js | 228 +++++ js/util.js | 3 + js/vendor/FileSaver/.bower.json | 15 + js/vendor/FileSaver/FileSaver.js | 232 +++++ js/vendor/FileSaver/LICENSE.md | 30 + js/vendor/FileSaver/README.md | 78 ++ js/vendor/FileSaver/bower.json | 7 + js/vendor/FileSaver/demo/demo.css | 55 ++ js/vendor/FileSaver/demo/demo.js | 213 ++++ js/vendor/FileSaver/demo/demo.min.js | 2 + js/vendor/FileSaver/demo/index.xhtml | 57 ++ js/vendor/FileSaver/package.json | 23 + js/vendor/canvasquery.js | 1767 ++++++++++++++++++++++++++++++++++ js/vendor/dataUriToBlob.js | 47 + js/vendor/gif-encode/GIFEncoder.js | 513 ++++++++++ js/vendor/gif-encode/LZWEncoder.js | 328 +++++++ js/vendor/gif-encode/NeuQuant.js | 538 +++++++++++ js/vendor/gif-encode/client.js | 260 +++++ js/vendor/gif-encode/tube.js | 323 +++++++ js/vendor/gif-encode/util.js | 15 + js/vendor/gif-encode/worker.js | 88 ++ js/vendor/gif.js | 1690 ++++++++++++++++++++++++++++++++ 22 files changed, 6512 insertions(+) create mode 100644 js/canvasquery.dither.js create mode 100644 js/util.js create mode 100644 js/vendor/FileSaver/.bower.json create mode 100644 js/vendor/FileSaver/FileSaver.js create mode 100644 js/vendor/FileSaver/LICENSE.md create mode 100644 js/vendor/FileSaver/README.md create mode 100644 js/vendor/FileSaver/bower.json create mode 100644 js/vendor/FileSaver/demo/demo.css create mode 100644 js/vendor/FileSaver/demo/demo.js create mode 100644 js/vendor/FileSaver/demo/demo.min.js create mode 100644 js/vendor/FileSaver/demo/index.xhtml create mode 100644 js/vendor/FileSaver/package.json create mode 100644 js/vendor/canvasquery.js create mode 100644 js/vendor/dataUriToBlob.js create mode 100755 js/vendor/gif-encode/GIFEncoder.js create mode 100644 js/vendor/gif-encode/LZWEncoder.js create mode 100644 js/vendor/gif-encode/NeuQuant.js create mode 100644 js/vendor/gif-encode/client.js create mode 100644 js/vendor/gif-encode/tube.js create mode 100644 js/vendor/gif-encode/util.js create mode 100644 js/vendor/gif-encode/worker.js create mode 100644 js/vendor/gif.js (limited to 'js') diff --git a/js/canvasquery.dither.js b/js/canvasquery.dither.js new file mode 100644 index 0000000..88b2588 --- /dev/null +++ b/js/canvasquery.dither.js @@ -0,0 +1,228 @@ + +// These patterns are used by the pattern dither effect +(function(){ + var patterns = {} + patterns[2] = [ 0, 2, + 3, 1 ] + + patterns[3] = [ 0, 5, 3, + 8, 1, 6, + 4, 7, 2, ] + + patterns[4] = [ 0, 8, 2, 10, + 6, 14, 4, 12, + 3, 11, 1, 9, + 5, 13, 7, 15 ] + CanvasQuery.Wrapper.prototype.pattern2Dither = function() { + this.patternDither(patterns[2]) + } + CanvasQuery.Wrapper.prototype.pattern3Dither = function() { + this.patternDither(patterns[3]) + } + CanvasQuery.Wrapper.prototype.pattern4Dither = function() { + this.patternDither(patterns[4]) + } + CanvasQuery.Wrapper.prototype.pattern2LiteDither = function() { + this.patternLiteDither(patterns[2]) + } + CanvasQuery.Wrapper.prototype.pattern3LiteDither = function() { + this.patternLiteDither(patterns[3]) + } + CanvasQuery.Wrapper.prototype.pattern4LiteDither = function() { + this.patternLiteDither(patterns[4]) + } +})() + +// Threshold dither, black if less than n, white otherwise +CanvasQuery.Wrapper.prototype.threshold = function(n) { + var bitmap = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height) + var bitmapData = bitmap.data + + var width = this.canvas.width + var height = this.canvas.height + + if (n < 1) n *= 255 + + for (var i = 0; i < height; i++) { + for (var j = 0; j < width; j++) { + var a = 4 * (i*width + j) + var val = (bitmapData[a] + bitmapData[a+1] + bitmapData[a+2]) / 3 + var lum = val > n ? 255 : 0 + bitmapData[a] = bitmapData[a+1] = bitmapData[a+2] = lum + } + } + this.context.putImageData(bitmap, 0, 0); + return this; +} + +// Random dither, black if less than a random number (chosen per pixel), white otherwise +CanvasQuery.Wrapper.prototype.randomDither = function() { + var bitmap = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height) + var bitmapData = bitmap.data + + var width = this.canvas.width + var height = this.canvas.height + + for (var i = 0; i < height; i++) { + for (var j = 0; j < width; j++) { + var a = 4 * (i*width + j) + var val = (bitmapData[a] + bitmapData[a+1] + bitmapData[a+2]) / (3*255) + var lum = val > Math.random() ? 255 : 0 + bitmapData[a] = bitmapData[a+1] = bitmapData[a+2] = lum + } + } + this.context.putImageData(bitmap, 0, 0); + return this; +} + +// Pattern dither, uses a square matrix of dither steps (see patterns above) to dither +CanvasQuery.Wrapper.prototype.patternDither = function(pattern) { + var bitmap = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height) + var bitmapData = bitmap.data + + var width = this.canvas.width + var height = this.canvas.height + + var n = Math.floor(Math.sqrt(pattern.length)) + var len = pattern.length - 1 + + for (var i = 0; i < height; i++) { + for (var j = 0; j < width; j++) { + var p = ((i % n) * n) + (j % n) + var a = 4 * (i*width + j) + var val = (bitmapData[a] + bitmapData[a+1] + bitmapData[a+2]) / (3*255) + var lum = val > pattern[p]/len ? 255 : 0 + bitmapData[a] = bitmapData[a+1] = bitmapData[a+2] = lum + } + } + this.context.putImageData(bitmap, 0, 0); + return this; +} + +// Light version of pattern dither, uses the wrong array size +CanvasQuery.Wrapper.prototype.patternLiteDither = function(pattern) { + var bitmap = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height) + var bitmapData = bitmap.data + + var width = this.canvas.width + var height = this.canvas.height + + var n = Math.floor(Math.sqrt(pattern.length)) + var len = pattern.length + + for (var i = 0; i < height; i++) { + for (var j = 0; j < width; j++) { + var p = ((i % n) * n) + (j % n) + var a = 4 * (i*width + j) + var val = (bitmapData[a] + bitmapData[a+1] + bitmapData[a+2]) / (3*255) + var lum = val > pattern[p]/len ? 255 : 0 + bitmapData[a] = bitmapData[a+1] = bitmapData[a+2] = lum + } + } + this.context.putImageData(bitmap, 0, 0); + return this; +} + +// Floyd-Steinberg error diffusion, propagates error down and to the right +CanvasQuery.Wrapper.prototype.floydSteinbergDither = function(n) { + var bitmap = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height) + var bitmapData = bitmap.data + + var mask = this.grayscaleToMask() + + var width = this.canvas.width + var height = this.canvas.height + + for (var y = 0; y < height; y++) { + for (var x = 0; x < width; x++) { + var p = (y*width + x) + var a = 4 * p + var val = mask[p] + var lum = val > 127 ? 255 : 0 + var error = val - lum + if (x < width-1) + mask[ (y*width) + x+1 ] += 7/16 * error + if (y < height-1 && x > 0) + mask[ ((y+1)*width) + x-1 ] += 5/16 * error + if (y < height-1) + mask[ ((y+1)*width) + x ] += 3/16 * error + if (y < height-1 && x < width-1) + mask[ ((y+1)*width) + x+1 ] += 1/16 * error + bitmapData[a] = bitmapData[a+1] = bitmapData[a+2] = lum + } + } + this.context.putImageData(bitmap, 0, 0); + return this; +} + +// Rightwise diffusion dither, propagates error to the right only +CanvasQuery.Wrapper.prototype.rightDither = function(n) { + var bitmap = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height) + var bitmapData = bitmap.data + + var mask = this.grayscaleToMask() + + var width = this.canvas.width + var height = this.canvas.height + + for (var y = 0; y < height; y++) { + for (var x = 0; x < width; x++) { + var p = (y*width + x) + var a = 4 * p + var val = mask[p] + var lum = val > 127 ? 255 : 0 + var error = val - lum + if (x < width-1) + mask[ (y*width) + x+1 ] += 7/16 * error + bitmapData[a] = bitmapData[a+1] = bitmapData[a+2] = lum + } + } + this.context.putImageData(bitmap, 0, 0); + return this; +} + +// Print-style halftone effect +CanvasQuery.Wrapper.prototype.halftone = function(radius, angle) { + var mask = this.grayscaleToMask() + + this.fillStyle("#fff") + this.fillRect(0, 0, this.canvas.width, this.canvas.height) + + var diameter = radius*2 + var TWO_PI = Math.PI*2 + + var angle = angle / 180 * Math.PI + + var cos = Math.cos(angle) + var sin = Math.sin(angle) + + var xstep = cos * radius + var ystep = sin * radius + + var w = this.canvas.width + var h = this.canvas.height + + this.fillStyle("#000") + + for (var i = -w; i < w; i++) { + for (var j = -h; j < h; j++) { + var x = i * ystep - j * xstep + var y = i * xstep + j * ystep + if (x > -diameter && y > -diameter && x < w+diameter && y < h+diameter) { + circle(this,x,y) + } + } + } + + function circle(cq,x,y) { + var xx = x < 0 ? 0 : x > w ? w - 1 : x; + var yy = y < 0 ? 0 : y > h ? h - 1 : y; + var r = (1 - Math.pow( mask[ ~~(~~yy*w+(xx)) ] / 255, Math.E/4 )) * radius + cq.beginPath() + .arc(x,y,r,0,TWO_PI) + .closePath() + .fill(); + } + return this; +} + diff --git a/js/util.js b/js/util.js new file mode 100644 index 0000000..9dc306c --- /dev/null +++ b/js/util.js @@ -0,0 +1,3 @@ +$.fn.int = function(){ return parseInt($(this).val(),10) } +$.fn.float = function(){ return parseFloat($(this).val()) } +function clamp(n,a,b){ return n + + + +FileSaver.js demo + + + +

FileSaver.js demo

+

+The following examples demonstrate how it is possible to generate and save any type of data right in the browser using the W3C saveAs() FileSaver interface, without contacting any servers. +

+
+

Saving an image

+ +
+ + + +
+
+
+

Saving text

+