Add pageHeight and pages to anim output response #3411

This commit is contained in:
Lovell Fuller 2024-06-17 16:32:49 +01:00
parent 472aaf3311
commit 9c05ea8dd2
6 changed files with 26 additions and 3 deletions

View File

@ -24,7 +24,7 @@ A `Promise` is returned when `callback` is not provided.
| Param | Type | Description |
| --- | --- | --- |
| fileOut | <code>string</code> | the path to write the image data to. |
| [callback] | <code>function</code> | called on completion with two arguments `(err, info)`. `info` contains the output image `format`, `size` (bytes), `width`, `height`, `channels` and `premultiplied` (indicating if premultiplication was used). When using a crop strategy also contains `cropOffsetLeft` and `cropOffsetTop`. When using the attention crop strategy also contains `attentionX` and `attentionY`, the focal point of the cropped region. May also contain `textAutofitDpi` (dpi the font was rendered at) if image was created from text. |
| [callback] | <code>function</code> | called on completion with two arguments `(err, info)`. `info` contains the output image `format`, `size` (bytes), `width`, `height`, `channels` and `premultiplied` (indicating if premultiplication was used). When using a crop strategy also contains `cropOffsetLeft` and `cropOffsetTop`. When using the attention crop strategy also contains `attentionX` and `attentionY`, the focal point of the cropped region. Animated output will also contain `pageHeight` and `pages`. May also contain `textAutofitDpi` (dpi the font was rendered at) if image was created from text. |
**Example**
```js
@ -59,6 +59,7 @@ See [withMetadata](#withmetadata) for control over this.
- `info` contains the output image `format`, `size` (bytes), `width`, `height`,
`channels` and `premultiplied` (indicating if premultiplication was used).
When using a crop strategy also contains `cropOffsetLeft` and `cropOffsetTop`.
Animated output will also contain `pageHeight` and `pages`.
May also contain `textAutofitDpi` (dpi the font was rendered at) if image was created from text.
A `Promise` is returned when `callback` is not provided.

View File

@ -6,6 +6,9 @@ Requires libvips v8.15.2
### v0.33.5 - TBD
* Add `pageHeight` and `pages` to response of multi-page output.
[#3411](https://github.com/lovell/sharp/issues/3411)
* Ensure option to force use of a globally-installed libvips works correctly.
[#4111](https://github.com/lovell/sharp/pull/4111)
[@project0](https://github.com/project0)

View File

@ -65,6 +65,7 @@ const bitdepthFromColourCount = (colours) => 1 << 31 - Math.clz32(Math.ceil(Math
* `channels` and `premultiplied` (indicating if premultiplication was used).
* When using a crop strategy also contains `cropOffsetLeft` and `cropOffsetTop`.
* When using the attention crop strategy also contains `attentionX` and `attentionY`, the focal point of the cropped region.
* Animated output will also contain `pageHeight` and `pages`.
* May also contain `textAutofitDpi` (dpi the font was rendered at) if image was created from text.
* @returns {Promise<Object>} - when no callback is provided
* @throws {Error} Invalid parameters
@ -109,6 +110,7 @@ function toFile (fileOut, callback) {
* - `info` contains the output image `format`, `size` (bytes), `width`, `height`,
* `channels` and `premultiplied` (indicating if premultiplication was used).
* When using a crop strategy also contains `cropOffsetLeft` and `cropOffsetTop`.
* Animated output will also contain `pageHeight` and `pages`.
* May also contain `textAutofitDpi` (dpi the font was rendered at) if image was created from text.
*
* A `Promise` is returned when `callback` is not provided.

View File

@ -849,6 +849,11 @@ class PipelineWorker : public Napi::AsyncWorker {
image = sharp::SetAnimationProperties(
image, nPages, targetPageHeight, baton->delay, baton->loop);
if (image.get_typeof(VIPS_META_PAGE_HEIGHT) == G_TYPE_INT) {
baton->pageHeightOut = image.get_int(VIPS_META_PAGE_HEIGHT);
baton->pagesOut = image.get_int(VIPS_META_N_PAGES);
}
// Output
sharp::SetTimeout(image, baton->timeoutSeconds);
if (baton->fileOut.empty()) {
@ -1284,6 +1289,10 @@ class PipelineWorker : public Napi::AsyncWorker {
if (baton->input->textAutofitDpi) {
info.Set("textAutofitDpi", static_cast<uint32_t>(baton->input->textAutofitDpi));
}
if (baton->pageHeightOut) {
info.Set("pageHeight", static_cast<int32_t>(baton->pageHeightOut));
info.Set("pages", static_cast<int32_t>(baton->pagesOut));
}
if (baton->bufferOutLength > 0) {
// Add buffer size to info

View File

@ -43,6 +43,8 @@ struct PipelineBaton {
std::string fileOut;
void *bufferOut;
size_t bufferOutLength;
int pageHeightOut;
int pagesOut;
std::vector<Composite *> composite;
std::vector<sharp::InputDescriptor *> joinChannelIn;
int topOffsetPre;
@ -226,6 +228,8 @@ struct PipelineBaton {
PipelineBaton():
input(nullptr),
bufferOutLength(0),
pageHeightOut(0),
pagesOut(0),
topOffsetPre(-1),
topOffsetPost(-1),
channels(0),

View File

@ -39,7 +39,7 @@ describe('GIF input', () => {
})
);
it('Animated GIF first page to PNG', () =>
it('Animated GIF first page to non-animated GIF', () =>
sharp(fixtures.inputGifAnimated)
.toBuffer({ resolveWithObject: true })
.then(({ data, info }) => {
@ -49,10 +49,12 @@ describe('GIF input', () => {
assert.strictEqual(80, info.width);
assert.strictEqual(80, info.height);
assert.strictEqual(4, info.channels);
assert.strictEqual(undefined, info.pages);
assert.strictEqual(undefined, info.pageHeight);
})
);
it('Animated GIF all pages to PNG "toilet roll"', () =>
it('Animated GIF round trip', () =>
sharp(fixtures.inputGifAnimated, { pages: -1 })
.toBuffer({ resolveWithObject: true })
.then(({ data, info }) => {
@ -62,6 +64,8 @@ describe('GIF input', () => {
assert.strictEqual(80, info.width);
assert.strictEqual(2400, info.height);
assert.strictEqual(4, info.channels);
assert.strictEqual(30, info.pages);
assert.strictEqual(80, info.pageHeight);
})
);