ansiimage.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /**
  2. * ansiimage.js - render PNGS/GIFS as ANSI
  3. * Copyright (c) 2013-2015, Christopher Jeffrey and contributors (MIT License).
  4. * https://github.com/chjj/blessed
  5. */
  6. /**
  7. * Modules
  8. */
  9. var cp = require('child_process');
  10. var colors = require('../colors');
  11. var Node = require('./node');
  12. var Box = require('./box');
  13. var tng = require('../../vendor/tng');
  14. /**
  15. * ANSIImage
  16. */
  17. function ANSIImage(options) {
  18. var self = this;
  19. if (!(this instanceof Node)) {
  20. return new ANSIImage(options);
  21. }
  22. options = options || {};
  23. options.shrink = true;
  24. Box.call(this, options);
  25. this.scale = this.options.scale || 1.0;
  26. this.options.animate = this.options.animate !== false;
  27. this._noFill = true;
  28. if (this.options.file) {
  29. this.setImage(this.options.file);
  30. }
  31. this.screen.on('prerender', function() {
  32. var lpos = self.lpos;
  33. if (!lpos) return;
  34. // prevent image from blending with itself if there are alpha channels
  35. self.screen.clearRegion(lpos.xi, lpos.xl, lpos.yi, lpos.yl);
  36. });
  37. this.on('destroy', function() {
  38. self.stop();
  39. });
  40. }
  41. ANSIImage.prototype.__proto__ = Box.prototype;
  42. ANSIImage.prototype.type = 'ansiimage';
  43. ANSIImage.curl = function(url) {
  44. try {
  45. return cp.execFileSync('curl',
  46. ['-s', '-A', '', url],
  47. { stdio: ['ignore', 'pipe', 'ignore'] });
  48. } catch (e) {
  49. ;
  50. }
  51. try {
  52. return cp.execFileSync('wget',
  53. ['-U', '', '-O', '-', url],
  54. { stdio: ['ignore', 'pipe', 'ignore'] });
  55. } catch (e) {
  56. ;
  57. }
  58. throw new Error('curl or wget failed.');
  59. };
  60. ANSIImage.prototype.setImage = function(file) {
  61. this.file = typeof file === 'string' ? file : null;
  62. if (/^https?:/.test(file)) {
  63. file = ANSIImage.curl(file);
  64. }
  65. var width = this.position.width;
  66. var height = this.position.height;
  67. if (width != null) {
  68. width = this.width;
  69. }
  70. if (height != null) {
  71. height = this.height;
  72. }
  73. try {
  74. this.setContent('');
  75. this.img = tng(file, {
  76. colors: colors,
  77. width: width,
  78. height: height,
  79. scale: this.scale,
  80. ascii: this.options.ascii,
  81. speed: this.options.speed,
  82. filename: this.file
  83. });
  84. if (width == null || height == null) {
  85. this.width = this.img.cellmap[0].length;
  86. this.height = this.img.cellmap.length;
  87. }
  88. if (this.img.frames && this.options.animate) {
  89. this.play();
  90. } else {
  91. this.cellmap = this.img.cellmap;
  92. }
  93. } catch (e) {
  94. this.setContent('Image Error: ' + e.message);
  95. this.img = null;
  96. this.cellmap = null;
  97. }
  98. };
  99. ANSIImage.prototype.play = function() {
  100. var self = this;
  101. if (!this.img) return;
  102. return this.img.play(function(bmp, cellmap) {
  103. self.cellmap = cellmap;
  104. self.screen.render();
  105. });
  106. };
  107. ANSIImage.prototype.pause = function() {
  108. if (!this.img) return;
  109. return this.img.pause();
  110. };
  111. ANSIImage.prototype.stop = function() {
  112. if (!this.img) return;
  113. return this.img.stop();
  114. };
  115. ANSIImage.prototype.clearImage = function() {
  116. this.stop();
  117. this.setContent('');
  118. this.img = null;
  119. this.cellmap = null;
  120. };
  121. ANSIImage.prototype.render = function() {
  122. var coords = this._render();
  123. if (!coords) return;
  124. if (this.img && this.cellmap) {
  125. this.img.renderElement(this.cellmap, this);
  126. }
  127. return coords;
  128. };
  129. /**
  130. * Expose
  131. */
  132. module.exports = ANSIImage;