diff --git a/lib/widgets/png.js b/lib/widgets/png.js index 804d088..1e6af9a 100644 --- a/lib/widgets/png.js +++ b/lib/widgets/png.js @@ -76,10 +76,10 @@ PNG.curl = function(url) { PNG.prototype.setImage = function(file) { var self = this; + this.file = typeof file === 'string' ? file : null; if (/^https?:/.test(file)) { file = PNG.curl(file); } - this.file = file; var width = this.position.width; var height = this.position.height; if (width != null) { @@ -90,12 +90,14 @@ PNG.prototype.setImage = function(file) { } try { this.setContent(''); - this.img = tng(this.file, { + this.img = tng(file, { colors: colors, - cellmapWidth: width, - cellmapHeight: height, - cellmapScale: this.scale, - ascii: this.options.ascii + width: width, + height: height, + scale: this.scale, + ascii: this.options.ascii, + speed: this.options.speed, + filename: this.file }); if (width == null || height == null) { this.width = this.img.cellmap[0].length; diff --git a/test/widget-png.js b/test/widget-png.js index 5023f1c..3dfabe2 100644 --- a/test/widget-png.js +++ b/test/widget-png.js @@ -1,13 +1,30 @@ var blessed = require('../'); var fs = require('fs'); +var argv = {}; + +process.argv = process.argv.map(function(arg, i) { + if (~arg.indexOf('=')) { + arg = arg.split('='); + if (/^[0-9.]+$/.test(arg[1])) arg[1] = +arg[1]; + argv[arg[0].replace(/^-+/, '')] = arg[1]; + return; + } + if (arg.indexOf('--') === 0) { + arg = arg.slice(2); + argv[arg] = true; + return; + } + return arg; +}).filter(Boolean); + var screen = blessed.screen({ tput: true, smartCSR: true, dump: __dirname + '/logs/png.log' }); -var box = blessed.box({ +var box1 = blessed.box({ parent: screen, left: 4, top: 3, @@ -17,8 +34,20 @@ var box = blessed.box({ style: { bg: 'green' }, - content: 'Lorem ipsum doler', - align: 'center' + content: fs.readFileSync(__dirname + '/lorem.txt', 'utf8') +}); + +var box2 = blessed.box({ + parent: screen, + left: 20, + top: 8, + width: 40, + height: 15, + border: 'line', + style: { + bg: 'green' + }, + content: fs.readFileSync(__dirname + '/lorem.txt', 'utf8') }); var file = process.argv[2]; @@ -41,16 +70,23 @@ if (!file) { } } +if (!argv.width && !argv.height && !argv.scale) { + argv.width = 20; +} + var png = blessed.png({ parent: screen, // border: 'line', - width: 20, - height: 19, + width: argv.width, + height: argv.height, top: 2, left: 0, file: file, - ascii: false, - draggable: true + draggable: true, + scale: argv.scale, + ascii: argv.ascii, + optimization: argv.optimization, + speed: argv.speed }); screen.render(); diff --git a/vendor/tng.js b/vendor/tng.js index 708d533..713047c 100644 --- a/vendor/tng.js +++ b/vendor/tng.js @@ -30,22 +30,22 @@ function PNG(file, options) { this.options = options || {}; this.colors = options.colors || require('blessed/lib/colors'); - this.options.optimization = this.options.optimization || 'mem'; + this.optimization = this.options.optimization || 'mem'; + this.speed = this.options.speed || 1; if (Buffer.isBuffer(file)) { - this.file = null; - this.ext = 'png'; + this.file = this.options.filename || null; buf = file; } else { + this.options.filename = file; this.file = path.resolve(process.cwd(), file); - this.ext = path.extname(this.file).slice(1).toLowerCase(); buf = fs.readFileSync(this.file); } this.format = buf.readUInt32BE(0) === 0x89504e47 ? 'png' : buf.slice(0, 3).toString('ascii') === 'GIF' ? 'gif' : buf.readUInt16BE(0) === 0xffd8 ? 'jpg' - : this.ext; + : path.extname(this.file).slice(1).toLowerCase() || 'png'; if (this.format !== 'png') { try { @@ -65,8 +65,6 @@ function PNG(file, options) { this.frames = this.compileFrames(this.frames); } -PNG.prototype.defaultScale = 0.20; - PNG.prototype.parseRaw = function(buf) { var chunks = [] , index = 0 @@ -595,14 +593,16 @@ PNG.prototype.createCellmap = function(bmp, options) { var bmp = bmp || this.bmp , options = options || this.options , cellmap = [] - , scale = options.cellmapScale || this.defaultScale + , scale = options.scale || 0.20 , height = bmp.length , width = bmp[0].length - , cmwidth = options.cellmapWidth - , cmheight = options.cellmapHeight + , cmwidth = options.width + , cmheight = options.height , line , x , y + , xx + , yy , scale , xs , ys; @@ -613,21 +613,27 @@ PNG.prototype.createCellmap = function(bmp, options) { scale = cmheight / height; } - ys = Math.ceil(height / (height * scale)); - xs = Math.ceil(width / (width * scale)); + if (!cmheight) { + cmheight = Math.round(height * scale); + } - // ys++; - // xs++; + if (!cmwidth) { + cmwidth = Math.round(width * scale); + } + + ys = height / cmheight; + xs = width / cmwidth; - // add a reducePixels() method here for (y = 0; y < bmp.length; y += ys) { line = []; - if (cmheight && cellmap.length === cmheight) break; - cellmap.push(line); - for (x = 0; x < bmp[y].length; x += xs) { - if (cmwidth && line.length === cmwidth) break; - line.push(bmp[y][x]); + yy = Math.round(y); + if (!bmp[yy]) break; + for (x = 0; x < bmp[yy].length; x += xs) { + xx = Math.round(x); + if (!bmp[yy][xx]) break; + line.push(bmp[yy][xx]); } + cellmap.push(line); } return cellmap; @@ -830,7 +836,7 @@ PNG.prototype.getOutch = (function() { })(); PNG.prototype.compileFrames = function(frames) { - return this.options.optimization === 'mem' + return this.optimization === 'mem' ? this.compileFrames_lomem(frames) : this.compileFrames_locpu(frames); }; @@ -978,7 +984,7 @@ PNG.prototype._animate = function(callback) { , cellmap = self.createCellmap(renderBmp); callback(renderBmp, cellmap); - return setTimeout(next, frame.delay); + return setTimeout(next, frame.delay / self.speed | 0); }; var next_locpu = function() { @@ -990,10 +996,10 @@ PNG.prototype._animate = function(callback) { return setImmediate(next); } callback(frame.bmp, frame.cellmap); - return setTimeout(next, frame.delay); + return setTimeout(next, frame.delay / self.speed | 0); }; - var next = this.options.optimization === 'mem' + var next = this.optimization === 'mem' ? next_lomem : next_locpu; @@ -1044,15 +1050,14 @@ PNG.prototype.toPNG = function(input) { , disposeOp; if (format !== 'gif') { - buf = exec('convert', - [format + ':' + file, 'png:-'], - { stdio: ['ignore', 'pipe', 'ignore']}); + buf = exec('convert', [format + ':-', 'png:-'], + { stdio: ['pipe', 'pipe', 'ignore'], input: input }); img = PNG(buf, options); img.file = file; return img; } - gif = GIF(input || file, options); + gif = GIF(input, options); this.width = gif.width; this.height = gif.height; @@ -1098,7 +1103,7 @@ PNG.prototype.toPNG = function(input) { // Convert a gif to an apng using imagemagick. Unfortunately imagemagick // doesn't support apngs, so we coalesce the gif frames into one image and then // slice them into frames. -PNG.prototype.gifMagick = function() { +PNG.prototype.gifMagick = function(input) { var options = this.options , file = this.file , format = this.format @@ -1118,11 +1123,12 @@ PNG.prototype.gifMagick = function() { , y; buf = exec('convert', - [format + ':' + file, '-coalesce', '+append', 'png:-']); + [format + ':-', '-coalesce', '+append', 'png:-'], + { stdio: ['pipe', 'pipe', 'ignore'], input: input }); fmt = '{"W":%W,"H":%H,"w":%w,"h":%h,"d":%T,"x":"%X","y":"%Y"},' - frames = exec('identify', ['-format', fmt, format + ':' + file], - { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }); + frames = exec('identify', ['-format', fmt, format + ':-'], + { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'], input: input }); frames = JSON.parse('[' + frames.trim().slice(0, -1) + ']'); img = PNG(buf, options);