diff --git a/readme.md b/readme.md index 6eb05e3..8968ae9 100644 --- a/readme.md +++ b/readme.md @@ -174,16 +174,17 @@ Functions same as `fromPath(filePath, options).setGMClass(subClass)` only input ### options Following are the options that can be passed on the pdf2pic api: -| option | default value | description | -|--------------|--------------- |------------------------------| -| quality | `0` | Image compression level. Value depends on `format`, usually from `0` to `100` ([more info](http://www.graphicsmagick.org/GraphicsMagick.html#details-quality)) | -| format | `'png'` | Formatted image characteristics / image format ([image characteristics](http://www.graphicsmagick.org/GraphicsMagick.html#details-format), [image format](http://www.graphicsmagick.org/formats.html)) | -| width | `768` | Output width | -| height | `512` | Output height | -| density | `72` | Output DPI (dots per inch) ([more info](http://www.graphicsmagick.org/GraphicsMagick.html#details-density)) | -| savePath | `'./'` | Path where to save the output | -| saveFilename | `'untitled'` | Output filename | -| compression | `'jpeg'` | Compression method ([more info](http://www.graphicsmagick.org/GraphicsMagick.html#details-compress)) | +| option | default value | description | +|---------------------|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| quality | `0` | Image compression level. Value depends on `format`, usually from `0` to `100` ([more info](http://www.graphicsmagick.org/GraphicsMagick.html#details-quality)) | +| format | `'png'` | Formatted image characteristics / image format ([image characteristics](http://www.graphicsmagick.org/GraphicsMagick.html#details-format), [image format](http://www.graphicsmagick.org/formats.html)) | +| width | `768` | Output width | +| height | `512` | Output height | +| preserveAspectRatio | `false` | Maintains the aspect ratio of the image. When set to `true` and both `width` and `height` are specified, they are interpreted as the minimum width and minimum height, respectively. If set to `true` with only the `width` specified, the `height` will be automatically determined while preserving the aspect ratio, and vice versa. | +| density | `72` | Output DPI (dots per inch) ([more info](http://www.graphicsmagick.org/GraphicsMagick.html#details-density)) | +| savePath | `'./'` | Path where to save the output | +| saveFilename | `'untitled'` | Output filename | +| compression | `'jpeg'` | Compression method ([more info](http://www.graphicsmagick.org/GraphicsMagick.html#details-compress)) | ### convertOptions diff --git a/src/graphics.ts b/src/graphics.ts index d42019a..b7c7d68 100644 --- a/src/graphics.ts +++ b/src/graphics.ts @@ -13,6 +13,8 @@ export class Graphics { private height = 512; + private preserveAspectRatio = false; + private density = 72; private savePath = "./"; @@ -39,7 +41,7 @@ export class Graphics { public gmBaseCommand(stream: fs.ReadStream, filename: string): gm.State { return this.gm(stream, filename) .density(this.density, this.density) - .resize(this.width, this.height, "!") + .resize(this.width, this.height, this.preserveAspectRatio ? '^' : '!') .quality(this.quality) .compress(this.compression) } @@ -136,7 +138,13 @@ export class Graphics { public setSize(width: number, height?: number): Graphics { this.width = width; - this.height = !!height ? height : width; + this.height = this.preserveAspectRatio || !!height ? height : width; + + return this; + } + + public setPreserveAspectRatio(preserveAspectRatio: boolean): Graphics { + this.preserveAspectRatio = preserveAspectRatio; return this; } @@ -189,6 +197,7 @@ export class Graphics { format: this.format, width: this.width, height: this.height, + preserveAspectRatio: this.preserveAspectRatio, density: this.density, savePath: this.savePath, saveFilename: this.saveFilename, diff --git a/src/pdf2picCore.ts b/src/pdf2picCore.ts index eb203c3..45ce00b 100644 --- a/src/pdf2picCore.ts +++ b/src/pdf2picCore.ts @@ -73,6 +73,7 @@ export function pdf2picCore(source: string, data: string | Buffer, options = def function setGMOptions(gm: Graphics, options: Options): void { gm.setQuality(options.quality) .setFormat(options.format) + .setPreserveAspectRatio(options.preserveAspectRatio) .setSize(options.width, options.height) .setDensity(options.density) .setSavePath(options.savePath) diff --git a/src/types/options.ts b/src/types/options.ts index deb75dc..28fada4 100644 --- a/src/types/options.ts +++ b/src/types/options.ts @@ -3,6 +3,7 @@ export type Options = { format?: string; width?: number; height?: number; + preserveAspectRatio?: boolean; density?: number; savePath?: string; saveFilename?: string; diff --git a/src/utils/defaultOptions.ts b/src/utils/defaultOptions.ts index 4e3924a..e17417d 100644 --- a/src/utils/defaultOptions.ts +++ b/src/utils/defaultOptions.ts @@ -6,6 +6,7 @@ export const defaultOptions: Options = { width: 768, height: 512, density: 72, + preserveAspectRatio: false, savePath: "./", saveFilename: "untitled", compression: "jpeg" diff --git a/test/graphics.test.ts b/test/graphics.test.ts index 672bba8..e7455ed 100644 --- a/test/graphics.test.ts +++ b/test/graphics.test.ts @@ -72,6 +72,7 @@ describe("graphics", () => { gm.setQuality(100); gm.setFormat("jpg"); + gm.setPreserveAspectRatio(true); gm.setSize(100, 100); gm.setDensity(100); gm.setSavePath("./test/data"); @@ -92,6 +93,9 @@ describe("graphics", () => { expect(options).to.haveOwnProperty("height"); expect(options.height).to.be.equal(100); + expect(options).to.haveOwnProperty("preserveAspectRatio"); + expect(options.preserveAspectRatio).to.be.equal(true); + expect(options).to.haveOwnProperty("density"); expect(options.density).to.be.equal(100); @@ -119,6 +123,21 @@ describe("graphics", () => { expect(options.height).to.be.equal(200); }); + it("should by not set height if preserveAspectRatio is `true`", () => { + const gm = new Graphics(); + + gm.setPreserveAspectRatio(true); + gm.setSize(200); + + const options = gm.getOptions(); + + expect(options).to.haveOwnProperty("width"); + expect(options.width).to.be.equal(200); + + expect(options).to.haveOwnProperty("height"); + expect(options.height).to.be.equal(undefined); + }); + it("should save first page as image file", async () => { const gm = new Graphics(); diff --git a/test/index.test.ts b/test/index.test.ts index 43bd26a..f8c173d 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -364,4 +364,70 @@ describe("PDF2Pic Core", () => { } }).timeout(7000); }); + + describe('preserveAspectRatio', () => { + it('should preserve aspect ratio of pages', async () => { + const gm = new Graphics(); + const options = { + ...baseOptions, + format: "png", + width: undefined, + height: undefined, + preserveAspectRatio: true, + saveFilename: "test-aspect-ratio-1" + } + + const convert = fromPath("./test/data/pdf1.pdf", options); + const imageResponse = await convert.bulk([1, 2], { responseType: 'image' }); + + expect(imageResponse).to.be.an('array').that.has.lengthOf(2) + + + expectImageResponseToBeValid(imageResponse[0], options) + const page1Info = await gm.identify(`./dump/fromfiletest/${options.saveFilename}.1.png`) as gm.ImageInfo; + expectInfoToBeValid(page1Info, { ...options, width: 842, height: 595 }) + + expectImageResponseToBeValid(imageResponse[1], options) + const page2Info = await gm.identify(`./dump/fromfiletest/${options.saveFilename}.2.png`) as gm.ImageInfo; + expectInfoToBeValid(page2Info, { ...options, width: 1684, height: 595 }) + }); + + it('should set height automatically', async () => { + const gm = new Graphics(); + const options = { + ...baseOptions, + format: "png", + width: 600, + height: undefined, + preserveAspectRatio: true, + saveFilename: "test-aspect-ratio-2" + } + + const convert = fromPath("./test/data/pdf1.pdf", options); + const imageResponse = await convert(1, { responseType: 'image' }); + + expectImageResponseToBeValid(imageResponse, options) + const page1Info = await gm.identify(`./dump/fromfiletest/${options.saveFilename}.1.png`) as gm.ImageInfo; + expectInfoToBeValid(page1Info, { ...options, height: 424 }) + }); + + it('should set width automatically', async () => { + const gm = new Graphics(); + const options = { + ...baseOptions, + format: "png", + width: undefined, + height: 600, + preserveAspectRatio: true, + saveFilename: "test-aspect-ratio-3" + } + + const convert = fromPath("./test/data/pdf1.pdf", options); + const imageResponse = await convert(1, { responseType: 'image' }); + + expectImageResponseToBeValid(imageResponse, options) + const page1Info = await gm.identify(`./dump/fromfiletest/${options.saveFilename}.1.png`) as gm.ImageInfo; + expectInfoToBeValid(page1Info, { ...options, width: 849 }) + }); + }) });