screenshotHandler.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. var debug = require('debug')('ylt:screenshotHandler');
  2. var Jimp = require('jimp');
  3. var Q = require('q');
  4. var fs = require('fs');
  5. var path = require('path');
  6. var screenshotHandler = function() {
  7. var tmpFolderPath = 'tmp';
  8. var tmpFolderFullPath = path.join(__dirname, '..', tmpFolderPath);
  9. var tmpFileName = 'temp-screenshot.png';
  10. var tmpFileFullPath = path.join(tmpFolderFullPath, tmpFileName);
  11. this.findAndOptimizeScreenshot = function(width) {
  12. var that = this;
  13. debug('Starting screenshot transformation');
  14. return this.openImage(tmpFileFullPath)
  15. .then(function(image) {
  16. that.deleteTmpFile(tmpFileFullPath);
  17. return that.resizeImage(image, width);
  18. })
  19. .then(this.addWhiteBackground)
  20. .then(this.toBuffer);
  21. };
  22. this.openImage = function(imagePath) {
  23. var deferred = Q.defer();
  24. Jimp.read(imagePath, function(err, image){
  25. if (err) {
  26. debug('Could not open imagePath %s', imagePath);
  27. debug(err);
  28. deferred.reject(err);
  29. } else {
  30. debug('Image correctly open');
  31. deferred.resolve(image);
  32. }
  33. });
  34. return deferred.promise;
  35. };
  36. this.resizeImage = function(image, newWidth) {
  37. var deferred = Q.defer();
  38. var currentWidth = image.bitmap.width;
  39. var ratio = newWidth / currentWidth;
  40. image.scale(ratio, function(err, image){
  41. if (err) {
  42. debug('Could not resize image');
  43. debug(err);
  44. deferred.reject(err);
  45. } else {
  46. debug('Image correctly resized');
  47. deferred.resolve(image);
  48. }
  49. });
  50. return deferred.promise;
  51. };
  52. // If the page doesn't set a bg color, the default PhantomJS one is transparent
  53. // When transforming PNG to JPG, transparent pixels become black.
  54. // This is why we need to add a transparent background.
  55. this.addWhiteBackground = function(image) {
  56. var deferred = Q.defer();
  57. // Create a canvas with the same dimensions as your image:
  58. new Jimp(image.bitmap.width, image.bitmap.height, 0xFFFFFF, function(err, canvas){
  59. if (err) {
  60. debug('Could not create a white canvas');
  61. debug(err);
  62. deferred.reject(err);
  63. } else {
  64. // Paste original image on top of the canvas
  65. canvas.composite(image, 0, 0, function(err, image){
  66. if (err) {
  67. debug('Could not paste image on the white canvas');
  68. debug(err);
  69. deferred.reject(err);
  70. } else {
  71. // Now image has a white background...
  72. debug('White background correctly added');
  73. deferred.resolve(image);
  74. }
  75. });
  76. }
  77. });
  78. return deferred.promise;
  79. };
  80. this.toBuffer = function(image) {
  81. var deferred = Q.defer();
  82. image.quality(90).getBuffer(Jimp.MIME_JPEG, function(err, buffer){
  83. if (err) {
  84. debug('Could not save image to buffer');
  85. debug(err);
  86. deferred.reject(err);
  87. } else {
  88. debug('Image correctly transformed to buffer');
  89. deferred.resolve(buffer);
  90. }
  91. });
  92. return deferred.promise;
  93. };
  94. this.deleteTmpFile = function(tmpFilePath) {
  95. var deferred = Q.defer();
  96. fs.unlink(tmpFilePath, function (err) {
  97. if (err) {
  98. debug('Screenshot temporary file not found, could not be deleted. But it is not a problem.');
  99. } else {
  100. debug('Screenshot temporary file deleted.');
  101. }
  102. deferred.resolve();
  103. });
  104. return deferred.promise;
  105. };
  106. // Create a /tmp folder on the project's root directory
  107. this.createTmpScreenshotFolder = function() {
  108. var deferred = Q.defer();
  109. // Create the folder if it doesn't exist
  110. fs.exists(tmpFolderFullPath, function(exists) {
  111. if (exists) {
  112. deferred.resolve();
  113. } else {
  114. debug('Creating the tmp image folder', tmpFolderFullPath);
  115. fs.mkdir(tmpFolderFullPath, function(err) {
  116. if (err) {
  117. deferred.reject(err);
  118. } else {
  119. deferred.resolve();
  120. }
  121. });
  122. }
  123. });
  124. return deferred.promise;
  125. };
  126. this.getTmpFileRelativePath = function() {
  127. return tmpFolderPath + '/' + tmpFileName;
  128. };
  129. };
  130. module.exports = new screenshotHandler();