diff --git a/docs/src/content/docs/api-constructor.md b/docs/src/content/docs/api-constructor.md
index 62e6ddca1..b0c2e6982 100644
--- a/docs/src/content/docs/api-constructor.md
+++ b/docs/src/content/docs/api-constructor.md
@@ -76,7 +76,7 @@ where the overall height is the `pageHeight` multiplied by the number of `pages`
| [options.text.wrap] | string | "'word'" | word wrapping style when width is provided, one of: 'word', 'char', 'word-char' (prefer word, fallback to char) or 'none'. |
| [options.join] | Object | | describes how an array of input images should be joined. |
| [options.join.across] | number | 1 | number of images to join horizontally. |
-| [options.join.animated] | boolean | false | set this to `true` to join the images as an animated image. |
+| [options.join.animated] | boolean | false | set this to `true` to join the images as an animated image, cannot be used with `across` or `shim`. |
| [options.join.shim] | number | 0 | number of pixels to insert between joined images. |
| [options.join.background] | string \| Object | | parsed by the [color](https://www.npmjs.org/package/color) module to extract values for red, green, blue and alpha. |
| [options.join.halign] | string | "'left'" | horizontal alignment style for images joined horizontally (`'left'`, `'centre'`, `'center'`, `'right'`). |
diff --git a/lib/constructor.mjs b/lib/constructor.mjs
index 6d3356827..5c386e440 100644
--- a/lib/constructor.mjs
+++ b/lib/constructor.mjs
@@ -202,7 +202,7 @@ const queueListener = (queueLength) => {
* @param {string} [options.text.wrap='word'] - word wrapping style when width is provided, one of: 'word', 'char', 'word-char' (prefer word, fallback to char) or 'none'.
* @param {Object} [options.join] - describes how an array of input images should be joined.
* @param {number} [options.join.across=1] - number of images to join horizontally.
- * @param {boolean} [options.join.animated=false] - set this to `true` to join the images as an animated image.
+ * @param {boolean} [options.join.animated=false] - set this to `true` to join the images as an animated image, cannot be used with `across` or `shim`.
* @param {number} [options.join.shim=0] - number of pixels to insert between joined images.
* @param {string|Object} [options.join.background] - parsed by the [color](https://www.npmjs.org/package/color) module to extract values for red, green, blue and alpha.
* @param {string} [options.join.halign='left'] - horizontal alignment style for images joined horizontally (`'left'`, `'centre'`, `'center'`, `'right'`).
diff --git a/lib/input.mjs b/lib/input.mjs
index 062181f35..baf39eb17 100644
--- a/lib/input.mjs
+++ b/lib/input.mjs
@@ -511,6 +511,9 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
throw is.invalidParameterError('join.valign', 'valid alignment', inputOptions.join.valign);
}
}
+ if (inputDescriptor.joinAnimated && (inputDescriptor.joinAcross > 1 || inputDescriptor.joinShim > 0)) {
+ throw new Error('Expected neither join.across nor join.shim when join.animated is set');
+ }
} else {
throw new Error('Expected input to be an array of images to join');
}
diff --git a/test/unit/join.js b/test/unit/join.js
index 4dcfbf5a6..f3eee5575 100644
--- a/test/unit/join.js
+++ b/test/unit/join.js
@@ -124,6 +124,26 @@ suite('Join input images together', () => {
/Expected integer between 0 and 100000 for join.shim but received -1 of type number/
);
});
+ test('Animated with across throws', (t) => {
+ t.plan(2);
+ t.assert.throws(
+ () => sharp([fixtures.inputJpg, fixtures.inputJpg], { join: { animated: true, across: 2 } }),
+ /Expected neither join.across nor join.shim when join.animated is set/
+ );
+ t.assert.doesNotThrow(
+ () => sharp([fixtures.inputJpg, fixtures.inputJpg], { join: { animated: true, across: 1 } })
+ );
+ });
+ test('Animated with shim throws', (t) => {
+ t.plan(2);
+ t.assert.throws(
+ () => sharp([fixtures.inputJpg, fixtures.inputJpg], { join: { animated: true, shim: 4 } }),
+ /Expected neither join.across nor join.shim when join.animated is set/
+ );
+ t.assert.doesNotThrow(
+ () => sharp([fixtures.inputJpg, fixtures.inputJpg], { join: { animated: true, shim: 0 } })
+ );
+ });
test('Invalid halign', (t) => {
t.plan(1);
t.assert.throws(