diff --git a/bkcore.coffee/ImageData.coffee b/bkcore.coffee/ImageData.coffee new file mode 100644 index 0000000..aedf606 --- /dev/null +++ b/bkcore.coffee/ImageData.coffee @@ -0,0 +1,141 @@ +### + Loads an image and gives access to pixel data. + + @class bkcore.ImageData + @author Thibaut 'BKcore' Despoulain +### +class ImageData + + ### + Creates a new ImageData object + + @param path string The path of the image + @param callback function A callback function to be called + once th eimage is loaded + ### + constructor: (path, callback)-> + + @image = new Image + @pixels = null + @canvas = null + @loaded = false + + @image.onload = ()=> + + @canvas = document.createElement('canvas') + @canvas.width = @image.width + @canvas.height = @image.height + + context = @canvas.getContext('2d') + context.drawImage(@image, 0, 0) + + @pixels = context.getImageData(0,0, @canvas.width, @canvas.height) + @loaded = true + + context = null + @canvas = null + @image = null + + callback?.call(@) + + @image.crossOrigin = "anonymous" + @image.src = path + + ### + Gets pixel RGBA data at given index + + @param x int In pixels + @param y int In pixels + @return Object{r,g,b,a} + ### + getPixel: (x, y)-> + + if !@pixels? or x < 0 or y < 0 or x >= @pixels.width or y >= @pixels.height + return {r: 0, g: 0, b:0, a:0} + + i = (y*@pixels.width + x) * 4 + + return { + r: @pixels.data[i] + g: @pixels.data[i+1] + b: @pixels.data[i+2] + a: @pixels.data[i+3] + } + + ### + Gets pixel RGBA data at given float index using bilinear interpolation + + @param x float In subpixels + @param y float In subpixels + @return Object{r,g,b,a} + ### + getPixelBilinear: (fx, fy)-> + + x = Math.floor(fx) + y = Math.floor(fy) + rx = fx - x - .5 + ry = fy - y - .5 + ax = Math.abs(rx) + ay = Math.abs(ry) + dx = if rx < 0 then -1 else 1 + dy = if ry < 0 then -1 else 1 + + c = @getPixel(x, y) + cx = @getPixel(x+dx, y) + cy = @getPixel(x, y+dy) + cxy = @getPixel(x+dx, y+dy) + + cf1 = [ + (1-ax) * c.r + ax * cx.r + (1-ax) * c.g + ax * cx.g + (1-ax) * c.b + ax * cx.b + (1-ax) * c.a + ax * cx.a + ] + + cf2 = [ + (1-ax) * cy.r + ax * cxy.r + (1-ax) * cy.g + ax * cxy.g + (1-ax) * cy.b + ax * cxy.b + (1-ax) * cy.a + ax * cxy.a + ] + + return { + r: (1-ay) * cf1[0] + ay * cf2[0] + g: (1-ay) * cf1[1] + ay * cf2[1] + b: (1-ay) * cf1[2] + ay * cf2[2] + a: (1-ay) * cf1[3] + ay * cf2[3] + } + + ### + Gets pixel data at given index + as 3-bytes integer (for floating-point textures erzats, from RGB values) + + @param x int In pixels + @param y int In pixels + @return int (R + G*255 + B*255*255) + ### + getPixelF: (x, y)-> + + c = @getPixel(x, y) + return c.r + c.g * 255 + c.b * 255 * 255 + + ### + Gets pixel data at given float index using bilinear interpolationas + as 3-bytes integer (for floating-point textures erzats, from RGB values) + + @param x float In subpixels + @param y float In subpixels + @return Object{r,g,b,a} + ### + getPixelFBilinear: (fx, fy)-> + + c = @getPixelBilinear(fx, fy) + return c.r + c.g * 255 + c.b * 255 * 255 + +### + Exports + @package bkcore +### +exports = exports ? @ +exports.bkcore ||= {} +exports.bkcore.ImageData = ImageData \ No newline at end of file diff --git a/bkcore.coffee/ImageData.js b/bkcore.coffee/ImageData.js new file mode 100644 index 0000000..a24ee84 --- /dev/null +++ b/bkcore.coffee/ImageData.js @@ -0,0 +1,156 @@ +// Generated by CoffeeScript 1.4.0 + +/* + Loads an image and gives access to pixel data. + + @class bkcore.ImageData + @author Thibaut 'BKcore' Despoulain +*/ + + +(function() { + var ImageData, exports; + + ImageData = (function() { + /* + Creates a new ImageData object + + @param path string The path of the image + @param callback function A callback function to be called + once th eimage is loaded + */ + + function ImageData(path, callback) { + var _this = this; + this.image = new Image; + this.pixels = null; + this.canvas = null; + this.loaded = false; + this.image.onload = function() { + var context; + _this.canvas = document.createElement('canvas'); + _this.canvas.width = _this.image.width; + _this.canvas.height = _this.image.height; + context = _this.canvas.getContext('2d'); + context.drawImage(_this.image, 0, 0); + _this.pixels = context.getImageData(0, 0, _this.canvas.width, _this.canvas.height); + _this.loaded = true; + context = null; + _this.canvas = null; + _this.image = null; + return callback != null ? callback.call(_this) : void 0; + }; + this.image.crossOrigin = "anonymous"; + this.image.src = path; + } + + /* + Gets pixel RGBA data at given index + + @param x int In pixels + @param y int In pixels + @return Object{r,g,b,a} + */ + + + ImageData.prototype.getPixel = function(x, y) { + var i; + if (!(this.pixels != null) || x < 0 || y < 0 || x >= this.pixels.width || y >= this.pixels.height) { + return { + r: 0, + g: 0, + b: 0, + a: 0 + }; + } + i = (y * this.pixels.width + x) * 4; + return { + r: this.pixels.data[i], + g: this.pixels.data[i + 1], + b: this.pixels.data[i + 2], + a: this.pixels.data[i + 3] + }; + }; + + /* + Gets pixel RGBA data at given float index using bilinear interpolation + + @param x float In subpixels + @param y float In subpixels + @return Object{r,g,b,a} + */ + + + ImageData.prototype.getPixelBilinear = function(fx, fy) { + var ax, ay, c, cf1, cf2, cx, cxy, cy, dx, dy, rx, ry, x, y; + x = Math.floor(fx); + y = Math.floor(fy); + rx = fx - x - .5; + ry = fy - y - .5; + ax = Math.abs(rx); + ay = Math.abs(ry); + dx = rx < 0 ? -1 : 1; + dy = ry < 0 ? -1 : 1; + c = this.getPixel(x, y); + cx = this.getPixel(x + dx, y); + cy = this.getPixel(x, y + dy); + cxy = this.getPixel(x + dx, y + dy); + cf1 = [(1 - ax) * c.r + ax * cx.r, (1 - ax) * c.g + ax * cx.g, (1 - ax) * c.b + ax * cx.b, (1 - ax) * c.a + ax * cx.a]; + cf2 = [(1 - ax) * cy.r + ax * cxy.r, (1 - ax) * cy.g + ax * cxy.g, (1 - ax) * cy.b + ax * cxy.b, (1 - ax) * cy.a + ax * cxy.a]; + return { + r: (1 - ay) * cf1[0] + ay * cf2[0], + g: (1 - ay) * cf1[1] + ay * cf2[1], + b: (1 - ay) * cf1[2] + ay * cf2[2], + a: (1 - ay) * cf1[3] + ay * cf2[3] + }; + }; + + /* + Gets pixel data at given index + as 3-bytes integer (for floating-point textures erzats, from RGB values) + + @param x int In pixels + @param y int In pixels + @return int (R + G*255 + B*255*255) + */ + + + ImageData.prototype.getPixelF = function(x, y) { + var c; + c = this.getPixel(x, y); + return c.r + c.g * 255 + c.b * 255 * 255; + }; + + /* + Gets pixel data at given float index using bilinear interpolationas + as 3-bytes integer (for floating-point textures erzats, from RGB values) + + @param x float In subpixels + @param y float In subpixels + @return Object{r,g,b,a} + */ + + + ImageData.prototype.getPixelFBilinear = function(fx, fy) { + var c; + c = this.getPixelBilinear(fx, fy); + return c.r + c.g * 255 + c.b * 255 * 255; + }; + + return ImageData; + + })(); + + /* + Exports + @package bkcore + */ + + + exports = exports != null ? exports : this; + + exports.bkcore || (exports.bkcore = {}); + + exports.bkcore.ImageData = ImageData; + +}).call(this); diff --git a/bkcore.coffee/Timer.coffee b/bkcore.coffee/Timer.coffee index 7d5da39..d978bae 100644 --- a/bkcore.coffee/Timer.coffee +++ b/bkcore.coffee/Timer.coffee @@ -1,5 +1,15 @@ +### + new Date().getTime() wrapper to use as timer. + + @class bkcore.Timer + @author Thibaut 'BKcore' Despoulain +### class Timer + ### + Creates a new timer, inactive by default. + Call Timer.start() to activate. + ### constructor: ()-> @time = @@ -11,6 +21,9 @@ class Timer @active = false + ### + Starts/restarts the timer. + ### start: ()-> now = (new Date).getTime() @@ -23,13 +36,21 @@ class Timer @active = true + ### + Pauses(true)/Unpauses(false) the timer. + + @param bool Do pause + ### pause: (doPause)-> @active = not doPause + ### + Update method to be called inside a RAF loop + ### update: ()-> - if not active then return + if not @active then return now = (new Date).getTime() @@ -38,10 +59,19 @@ class Timer @time.delta = now - @time.previous @time.previous = now + ### + Returns a formatted version of the current elapsed time using msToTime(). + ### getElapsedTime: ()-> return @constructor.msToTime(@time.elapsed) + ### + Formats a millisecond integer into a h/m/s/ms object + + @param x int In milliseconds + @return Object{h,m,s,ms} + ### @msToTime: (t)-> ms = t%1000 @@ -51,6 +81,12 @@ class Timer return {h:h, m:m, s:s, ms,ms} + ### + Formats a millisecond integer into a h/m/s/ms object with prefix zeros + + @param x int In milliseconds + @return Object{h,m,s,ms} + ### @msToTimeString: (t)-> time = @msToTime(t) @@ -62,10 +98,21 @@ class Timer return time + ### + Convert given integer to string and fill with heading zeros + + @param num int Number to convert/fill + @param size int Desired string size + ### @zfill: (num, size)-> len = size - num.toString().length return if len > 0 then new Array(len+1).join('0') + num else num.toString() +### + Exports + @package bkcore +### exports = exports ? @ +exports.bkcore ||= {} exports.bkcore.Timer = Timer \ No newline at end of file diff --git a/bkcore.coffee/Timer.js b/bkcore.coffee/Timer.js index b2b4b63..1de825b 100644 --- a/bkcore.coffee/Timer.js +++ b/bkcore.coffee/Timer.js @@ -1,8 +1,21 @@ // Generated by CoffeeScript 1.4.0 + +/* + new Date().getTime() wrapper to use as timer. + + @class bkcore.Timer + @author Thibaut 'BKcore' Despoulain +*/ + + (function() { var Timer, exports; Timer = (function() { + /* + Creates a new timer, inactive by default. + Call Timer.start() to activate. + */ function Timer() { this.time = { @@ -15,6 +28,11 @@ this.active = false; } + /* + Starts/restarts the timer. + */ + + Timer.prototype.start = function() { var now; now = (new Date).getTime(); @@ -26,13 +44,25 @@ return this.active = true; }; + /* + Pauses(true)/Unpauses(false) the timer. + + @param bool Do pause + */ + + Timer.prototype.pause = function(doPause) { return this.active = !doPause; }; + /* + Update method to be called inside a RAF loop + */ + + Timer.prototype.update = function() { var now; - if (!active) { + if (!this.active) { return; } now = (new Date).getTime(); @@ -42,10 +72,23 @@ return this.time.previous = now; }; + /* + Returns a formatted version of the current elapsed time using msToTime(). + */ + + Timer.prototype.getElapsedTime = function() { return this.constructor.msToTime(this.time.elapsed); }; + /* + Formats a millisecond integer into a h/m/s/ms object + + @param x int In milliseconds + @return Object{h,m,s,ms} + */ + + Timer.msToTime = function(t) { var h, m, ms, s; ms = t % 1000; @@ -61,6 +104,14 @@ }; }; + /* + Formats a millisecond integer into a h/m/s/ms object with prefix zeros + + @param x int In milliseconds + @return Object{h,m,s,ms} + */ + + Timer.msToTimeString = function(t) { var time; time = this.msToTime(t); @@ -71,6 +122,14 @@ return time; }; + /* + Convert given integer to string and fill with heading zeros + + @param num int Number to convert/fill + @param size int Desired string size + */ + + Timer.zfill = function(num, size) { var len; len = size - num.toString().length; @@ -85,8 +144,16 @@ })(); + /* + Exports + @package bkcore + */ + + exports = exports != null ? exports : this; + exports.bkcore || (exports.bkcore = {}); + exports.bkcore.Timer = Timer; }).call(this); diff --git a/bkcore.coffee/tests.html b/bkcore.coffee/tests.html new file mode 100644 index 0000000..43f8204 --- /dev/null +++ b/bkcore.coffee/tests.html @@ -0,0 +1,10 @@ + + + CoffeeScript Tests + + + + + + + \ No newline at end of file