From 4150d83b3ee622abb6a2a7b3346a364c44dacfa9 Mon Sep 17 00:00:00 2001 From: Bala Clark Date: Thu, 15 Jul 2010 09:40:02 +0000 Subject: [PATCH] basic enhancements api implemented --- lib/ComicBook.js | 59 ++- lib/pixastic/actions/brightness.js | 79 ++++ .../actions}/desaturate.js | 2 +- lib/pixastic/actions/sharpen.js | 110 +++++ lib/pixastic/pixastic.core.js | 435 ++++++++++++++++++ reader.html | 5 +- 6 files changed, 684 insertions(+), 6 deletions(-) create mode 100644 lib/pixastic/actions/brightness.js rename lib/{Effects => pixastic/actions}/desaturate.js (98%) create mode 100644 lib/pixastic/actions/sharpen.js create mode 100644 lib/pixastic/pixastic.core.js diff --git a/lib/ComicBook.js b/lib/ComicBook.js index 077992a..5f5efe2 100644 --- a/lib/ComicBook.js +++ b/lib/ComicBook.js @@ -60,6 +60,7 @@ function ComicBook(id, srcs, opts) { var loaded = 0; // the amount of images that have been loaded so far var scale = 1; // page zoom scale, 1 = 100% + var enhancements = {}; /** * Figure out the cursor position relative to the canvas. @@ -174,7 +175,7 @@ function ComicBook(id, srcs, opts) { var page = pages[pointer]; var page2 = pages[pointer + 1]; - + if (typeof page !== "object") { throw "invalid page type '"+ typeof page +"'"; } var width = page.width; @@ -243,12 +244,15 @@ function ComicBook(id, srcs, opts) { page = tmpPage2; page2 = tmpPage; } - + // draw the page(s) context.drawImage(page, offsetW, offsetH, page_width, page_height); if (options.displayMode === "double" && typeof page2 === "object") { context.drawImage(page2, page_width + offsetW, offsetH, page_width, page_height); } - Pixastic.process(canvas, "desaturate", {average : false}); + // apply any image enhancements previously defined + $.each(enhancements, function(action, options) { + ComicBook.prototype.enhance[action](options); + }); }; /** @@ -275,8 +279,54 @@ function ComicBook(id, srcs, opts) { } }; + /** + * Apply image enhancements to the canvas. + * + * Powered by the awesome Pixastic: http://www.pixastic.com/ + * + * FIXME: page navigation breaks after enhancements are applied + * TODO: reset() + * TODO: allow multiple effects at once + * + * TODO: abstract this into an "Enhance" object, separate from ComicBook? + */ + ComicBook.prototype.enhance = { + + reset: function () {}, + + brightness: function (options) { + + // merge user options with defaults + var options = merge({ brightness: 0, contrast: 0 }, options); + + // remember options for later + enhancements.brightness = options; + + // run the enhancement + Pixastic.process(canvas, "brightness", { + brightness: options.brightness, + contrast: options.contrast, + legacy: true + }); + }, + + desaturate: function () { + enhancements.desaturate = {}; + Pixastic.process(canvas, "desaturate", { average : false }); + }, + + sharpen: function (options) { + + var options = merge({ amount: 0 }, options); + + Pixastic.process(canvas, "sharpen", { + amount: options.amount + }); + } + }; + ComicBook.prototype.navigation = function (e) { - + if (e.type === "click") { var side = getCursorPosition(e); @@ -338,6 +388,7 @@ $(document).ready(function() { book = new ComicBook("comic", pages, options); book.draw(); + //book.enhance.brightness({ brightness: 100 }) }); $(window).resize(function() { diff --git a/lib/pixastic/actions/brightness.js b/lib/pixastic/actions/brightness.js new file mode 100644 index 0000000..cb3693f --- /dev/null +++ b/lib/pixastic/actions/brightness.js @@ -0,0 +1,79 @@ +/* + * Pixastic Lib - Brightness/Contrast filter - v0.1.1 + * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/ + * License: [http://www.pixastic.com/lib/license.txt] + */ + +Pixastic.Actions.brightness = { + + process : function(params) { + + var brightness = parseInt(params.options.brightness,10) || 0; + var contrast = parseFloat(params.options.contrast)||0; + var legacy = !!(params.options.legacy && params.options.legacy != "false"); + + if (legacy) { + brightness = Math.min(150,Math.max(-150,brightness)); + } else { + var brightMul = 1 + Math.min(150,Math.max(-150,brightness)) / 150; + } + contrast = Math.max(0,contrast+1); + + if (Pixastic.Client.hasCanvasImageData()) { + var data = Pixastic.prepareData(params); + var rect = params.options.rect; + var w = rect.width; + var h = rect.height; + + var p = w*h; + var pix = p*4, pix1, pix2; + + var mul, add; + if (contrast != 1) { + if (legacy) { + mul = contrast; + add = (brightness - 128) * contrast + 128; + } else { + mul = brightMul * contrast; + add = - contrast * 128 + 128; + } + } else { // this if-then is not necessary anymore, is it? + if (legacy) { + mul = 1; + add = brightness; + } else { + mul = brightMul; + add = 0; + } + } + var r, g, b; + while (p--) { + if ((r = data[pix-=4] * mul + add) > 255 ) + data[pix] = 255; + else if (r < 0) + data[pix] = 0; + else + data[pix] = r; + + if ((g = data[pix1=pix+1] * mul + add) > 255 ) + data[pix1] = 255; + else if (g < 0) + data[pix1] = 0; + else + data[pix1] = g; + + if ((b = data[pix2=pix+2] * mul + add) > 255 ) + data[pix2] = 255; + else if (b < 0) + data[pix2] = 0; + else + data[pix2] = b; + } + return true; + } + }, + checkSupport : function() { + return Pixastic.Client.hasCanvasImageData(); + } +} + diff --git a/lib/Effects/desaturate.js b/lib/pixastic/actions/desaturate.js similarity index 98% rename from lib/Effects/desaturate.js rename to lib/pixastic/actions/desaturate.js index 0fe1c24..0c346c1 100644 --- a/lib/Effects/desaturate.js +++ b/lib/pixastic/actions/desaturate.js @@ -19,7 +19,7 @@ Pixastic.Actions.desaturate = { var pix = p*4, pix1, pix2; if (useAverage) { - while (p--) + while (p--) data[pix-=4] = data[pix1=pix+1] = data[pix2=pix+2] = (data[pix]+data[pix1]+data[pix2])/3 } else { while (p--) diff --git a/lib/pixastic/actions/sharpen.js b/lib/pixastic/actions/sharpen.js new file mode 100644 index 0000000..cbf7ba9 --- /dev/null +++ b/lib/pixastic/actions/sharpen.js @@ -0,0 +1,110 @@ +/* + * Pixastic Lib - Sharpen filter - v0.1.0 + * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/ + * License: [http://www.pixastic.com/lib/license.txt] + */ + +Pixastic.Actions.sharpen = { + process : function(params) { + + var strength = 0; + if (typeof params.options.amount != "undefined") + strength = parseFloat(params.options.amount)||0; + + if (strength < 0) strength = 0; + if (strength > 1) strength = 1; + + if (Pixastic.Client.hasCanvasImageData()) { + var data = Pixastic.prepareData(params); + var dataCopy = Pixastic.prepareData(params, true) + + var mul = 15; + var mulOther = 1 + 3*strength; + + var kernel = [ + [0, -mulOther, 0], + [-mulOther, mul, -mulOther], + [0, -mulOther, 0] + ]; + + var weight = 0; + for (var i=0;i<3;i++) { + for (var j=0;j<3;j++) { + weight += kernel[i][j]; + } + } + + weight = 1 / weight; + + var rect = params.options.rect; + var w = rect.width; + var h = rect.height; + + mul *= weight; + mulOther *= weight; + + var w4 = w*4; + var y = h; + do { + var offsetY = (y-1)*w4; + + var nextY = (y == h) ? y - 1 : y; + var prevY = (y == 1) ? 0 : y-2; + + var offsetYPrev = prevY*w4; + var offsetYNext = nextY*w4; + + var x = w; + do { + var offset = offsetY + (x*4-4); + + var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4; + var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4; + + var r = (( + - dataCopy[offsetPrev] + - dataCopy[offset-4] + - dataCopy[offset+4] + - dataCopy[offsetNext]) * mulOther + + dataCopy[offset] * mul + ); + + var g = (( + - dataCopy[offsetPrev+1] + - dataCopy[offset-3] + - dataCopy[offset+5] + - dataCopy[offsetNext+1]) * mulOther + + dataCopy[offset+1] * mul + ); + + var b = (( + - dataCopy[offsetPrev+2] + - dataCopy[offset-2] + - dataCopy[offset+6] + - dataCopy[offsetNext+2]) * mulOther + + dataCopy[offset+2] * mul + ); + + + if (r < 0 ) r = 0; + if (g < 0 ) g = 0; + if (b < 0 ) b = 0; + if (r > 255 ) r = 255; + if (g > 255 ) g = 255; + if (b > 255 ) b = 255; + + data[offset] = r; + data[offset+1] = g; + data[offset+2] = b; + + } while (--x); + } while (--y); + + return true; + + } + }, + checkSupport : function() { + return Pixastic.Client.hasCanvasImageData(); + } +} diff --git a/lib/pixastic/pixastic.core.js b/lib/pixastic/pixastic.core.js new file mode 100644 index 0000000..f616e07 --- /dev/null +++ b/lib/pixastic/pixastic.core.js @@ -0,0 +1,435 @@ +/* + * Pixastic Lib - Core Functions - v0.1.3 + * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/ + * License: [http://www.pixastic.com/lib/license.txt] + */ + +var Pixastic = (function() { + + + function addEvent(el, event, handler) { + if (el.addEventListener) + el.addEventListener(event, handler, false); + else if (el.attachEvent) + el.attachEvent("on" + event, handler); + } + + function onready(handler) { + var handlerDone = false; + var execHandler = function() { + if (!handlerDone) { + handlerDone = true; + handler(); + } + } + document.write("<"+"script defer src=\"//:\" id=\"__onload_ie_pixastic__\">"); + var script = document.getElementById("__onload_ie_pixastic__"); + script.onreadystatechange = function() { + if (script.readyState == "complete") { + script.parentNode.removeChild(script); + execHandler(); + } + } + if (document.addEventListener) + document.addEventListener("DOMContentLoaded", execHandler, false); + addEvent(window, "load", execHandler); + } + + function init() { + var imgEls = getElementsByClass("pixastic", null, "img"); + var canvasEls = getElementsByClass("pixastic", null, "canvas"); + var elements = imgEls.concat(canvasEls); + for (var i=0;i -1) { + var tmp = actionName; + actionName = tmp.substr(0, tmp.indexOf("(")); + var arg = tmp.match(/\((.*?)\)/); + if (arg[1]) { + arg = arg[1].split(";"); + for (var a=0;a - + + + +