From 31edb6b1c5ed1330db93d7765e4d8ede60f859b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Ro=CC=88s?= Date: Thu, 3 May 2018 14:42:53 +0200 Subject: [PATCH] add feature to convert a whole file; add feature to combine generated images in order to get one single image from one PDF --- README.md | 40 +++++++++++++++++++++------- index.js | 66 ++++++++++++++++++++++++++++++++++++++++++++++ tests/test-main.js | 39 +++++++++++++++++++++++++++ 3 files changed, 135 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index c702b72..61b0b88 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ Ensure you have `convert`, `gs`, and `pdfinfo` (part of poppler) commands. ## Usage +#### Convert single page: ```javascript var PDFImage = require("pdf-image").PDFImage; @@ -29,6 +30,29 @@ pdfImage.convertPage(0).then(function (imagePath) { }); ``` +#### Convert full file +```javascript +var PDFImage = require("pdf-image").PDFImage; + +var pdfImage = new PDFImage("/tmp/slide.pdf"); +pdfImage.convertFile().then(function (imagePaths) { + // [ /tmp/slide-0.png, /tmp/slide-1.png ] +}); + + +``` +#### Convert full file and merge result into single image +```javascript +var PDFImage = require("pdf-image").PDFImage; +var pdfImage = new PDFImage("/tmp/slide.pdf", { + combinedImage: true +}); + +pdfImage.convertFile().then(function (imagePaths) { + // /tmp/slide.png +}); +``` + ## Express Following example shows an example of pdf-image in Express, which gives @@ -56,14 +80,10 @@ URLs for each pages of a PDF like Following example shows an example of how to add imagemagick command-line options (you can find the complete list here -> http://www.imagemagick.org/script/convert.php): ```javascript -var theOptions = {}; -theOptions.convertOptions = {}; -theOptions.convertOptions["-resize"] = "2000x2000"; -theOptions.convertOptions["-quality"] = "75"; -``` - -And then just change the instantiation of a new PDFImage by: - -```javascript -var pdfImage = new PDFImage(pdfPath, theOptions); +var pdfImage = new PDFImage(pdfPath, { + convertOptions: { + "-resize": "2000x2000", + "-quality": "75" + } +}); ``` diff --git a/index.js b/index.js index 203e2c0..4fa6231 100644 --- a/index.js +++ b/index.js @@ -16,6 +16,7 @@ function PDFImage(pdfFilePath, options) { this.setConvertOptions(options.convertOptions); this.setConvertExtension(options.convertExtension); this.useGM = options.graphicsMagick || false; + this.combinedImage = options.combinedImage || false; this.outputDirectory = options.outputDirectory || path.dirname(pdfFilePath); } @@ -65,6 +66,12 @@ PDFImage.prototype = { this.pdfFileBaseName + "-" + pageNumber + "." + this.convertExtension ); }, + getOutputImagePathForFile: function () { + return path.join( + this.outputDirectory, + this.pdfFileBaseName + "." + this.convertExtension + ); + }, setConvertOptions: function (convertOptions) { this.convertOptions = convertOptions || {}; }, @@ -85,6 +92,14 @@ PDFImage.prototype = { pdfFilePath, pageNumber, outputImagePath ); }, + constructCombineCommandForFile: function (imagePaths) { + return util.format( + "%s -append %s \"%s\"", + this.useGM ? "gm convert" : "convert", + imagePaths.join(' '), + this.getOutputImagePathForFile() + ); + }, constructConvertOptions: function () { return Object.keys(this.convertOptions).sort().map(function (optionName) { if (this.convertOptions[optionName] !== null) { @@ -94,6 +109,57 @@ PDFImage.prototype = { } }, this).join(" "); }, + combineImages: function(imagePaths) { + var pdfImage = this; + var combineCommand = pdfImage.constructCombineCommandForFile(imagePaths); + return new Promise(function (resolve, reject) { + exec(combineCommand, function (err, stdout, stderr) { + if (err) { + return reject({ + message: "Failed to combine images", + error: err, + stdout: stdout, + stderr: stderr + }); + } + exec("rm "+imagePaths.join(' ')); //cleanUp + return resolve(pdfImage.getOutputImagePathForFile()); + }); + }); + }, + convertFile: function () { + var pdfImage = this; + return new Promise(function (resolve, reject) { + pdfImage.numberOfPages().then(function (totalPages) { + var convertPromise = new Promise(function (resolve, reject){ + var imagePaths = []; + for (var i = 0; i < totalPages; i++) { + pdfImage.convertPage(i).then(function(imagePath){ + imagePaths.push(imagePath); + if (imagePaths.length === parseInt(totalPages)){ + imagePaths.sort(); //because of asyc pages we have to reSort pages + resolve(imagePaths); + } + }).catch(function(error){ + reject(error); + }); + } + }); + + convertPromise.then(function(imagePaths){ + if (pdfImage.combinedImage){ + pdfImage.combineImages(imagePaths).then(function(imagePath){ + resolve(imagePath); + }); + } else { + resolve(imagePaths); + } + }).catch(function(error){ + reject(error); + }); + }); + }); + }, convertPage: function (pageNumber) { var pdfFilePath = this.pdfFilePath; var outputImagePath = this.getOutputImagePathForPage(pageNumber); diff --git a/tests/test-main.js b/tests/test-main.js index 4f1673c..d022d56 100644 --- a/tests/test-main.js +++ b/tests/test-main.js @@ -7,6 +7,7 @@ describe("PDFImage", function () { let pdfPath = "/tmp/test.pdf"; let pdfImage; let generatedFiles = []; + this.timeout(7000); before(function(done){ fs.createReadStream('tests/test.pdf').pipe(fs.createWriteStream(pdfPath)); @@ -39,6 +40,8 @@ describe("PDFImage", function () { .equal("/tmp/test-2.png"); expect(pdfImage.getOutputImagePathForPage(1000)) .equal("/tmp/test-1000.png"); + expect(pdfImage.getOutputImagePathForFile()) + .equal("/tmp/test.png"); }); it("should return correct convert command", function () { @@ -46,6 +49,11 @@ describe("PDFImage", function () { .equal('convert "/tmp/test.pdf[1]" "/tmp/test-1.png"'); }); + it("should return correct convert command to combine images", function () { + expect(pdfImage.constructCombineCommandForFile(['/tmp/test-0.png', '/tmp/test-1.png'])) + .equal('convert -append /tmp/test-0.png /tmp/test-1.png "/tmp/test.png"'); + }); + it("should use gm when you ask it to", function () { pdfImage = new PDFImage(pdfPath, {graphicsMagick: true}); expect(pdfImage.constructConvertCommandForPage(1)) @@ -93,6 +101,37 @@ describe("PDFImage", function () { }); }); + it("should convert all PDF's pages to files", function () { + return new Promise(function(resolve, reject) { + pdfImage.convertFile().then(function (imagePaths) { + imagePaths.forEach(function(imagePath){ + expect(fs.existsSync(imagePath)).to.be.true; + generatedFiles.push(imagePath); + }); + resolve(); + }).catch(function(err){ + reject(err); + }); + }); + }); + + it("should convert all PDF's pages to single image", function () { + return new Promise(function(resolve, reject){ + let pdfImageCombined = new PDFImage(pdfPath, { + combinedImage: true, + }); + + pdfImageCombined.convertFile().then(function (imagePath) { + expect(imagePath).to.equal("/tmp/test.png"); + expect(fs.existsSync(imagePath)).to.be.true; + generatedFiles.push(imagePath); + resolve(); + }).catch(function (error) { + reject(error); + }); + }) + }); + it("should return # of pages", function () { return new Promise(function(resolve, reject) { pdfImage.numberOfPages().then(function (numberOfPages) {