diff --git a/packages/nodes-base/nodes/EditImage.node.ts b/packages/nodes-base/nodes/EditImage.node.ts
index 5c3b9c53aa..fba65d1144 100644
--- a/packages/nodes-base/nodes/EditImage.node.ts
+++ b/packages/nodes-base/nodes/EditImage.node.ts
@@ -52,6 +52,11 @@ export class EditImage implements INodeType {
value: 'crop',
description: 'Crops the image',
},
+ {
+ name: 'Composite',
+ value: 'composite',
+ description: 'Composite image on top of another one',
+ },
{
name: 'Get Information',
value: 'information',
@@ -275,6 +280,53 @@ export class EditImage implements INodeType {
},
+ // ----------------------------------
+ // composite
+ // ----------------------------------
+ {
+ displayName: 'Composite Image Property',
+ name: 'dataPropertyNameComposite',
+ type: 'string',
+ default: '',
+ placeholder: 'data2',
+ displayOptions: {
+ show: {
+ operation: [
+ 'composite',
+ ],
+ },
+ },
+ description: 'The name of the binary property which contains the data of the image to
composite on top of image which is found in Property Name.',
+ },
+ {
+ displayName: 'Position X',
+ name: 'positionX',
+ type: 'number',
+ default: 0,
+ displayOptions: {
+ show: {
+ operation: [
+ 'composite',
+ ],
+ },
+ },
+ description: 'X (horizontal) position of composite image.',
+ },
+ {
+ displayName: 'Position Y',
+ name: 'positionY',
+ type: 'number',
+ default: 0,
+ displayOptions: {
+ show: {
+ operation: [
+ 'composite',
+ ],
+ },
+ },
+ description: 'Y (vertical) position of composite image.',
+ },
+
// ----------------------------------
// crop
// ----------------------------------
@@ -582,6 +634,8 @@ export class EditImage implements INodeType {
gmInstance = gmInstance.background('transparent');
+ const cleanupFunctions: Array<() => void> = [];
+
if (operation === 'blur') {
const blur = this.getNodeParameter('blur') as number;
const sigma = this.getNodeParameter('sigma') as number;
@@ -592,7 +646,23 @@ export class EditImage implements INodeType {
const borderColor = this.getNodeParameter('borderColor') as string;
gmInstance = gmInstance.borderColor(borderColor).border(borderWidth, borderHeight);
- } else if (operation === 'crop') {
+ } else if (operation === 'composite') {
+ const dataPropertyNameComposite = this.getNodeParameter('dataPropertyNameComposite') as string;
+ const positionX = this.getNodeParameter('positionX') as number;
+ const positionY = this.getNodeParameter('positionY') as number;
+
+ const geometryString = (positionX >= 0 ? '+' : '') + positionX + (positionY >= 0 ? '+' : '') + positionY;
+
+ if (item.binary[dataPropertyNameComposite as string] === undefined) {
+ throw new Error('');
+ }
+
+ const { fd, path, cleanup } = await file();
+ cleanupFunctions.push(cleanup);
+ fsWriteFileAsync(fd, Buffer.from(item.binary![dataPropertyNameComposite as string].data, BINARY_ENCODING));
+
+ gmInstance = gmInstance.composite(path).geometry(geometryString);
+ } else if (operation === 'crop') {
const width = this.getNodeParameter('width') as number;
const height = this.getNodeParameter('height') as number;
@@ -708,6 +778,8 @@ export class EditImage implements INodeType {
return new Promise((resolve, reject) => {
gmInstance
.toBuffer((error: Error | null, buffer: Buffer) => {
+ cleanupFunctions.forEach(async cleanup => await cleanup());
+
if (error) {
return reject(error);
}
diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json
index 7214127df7..85b84dafd0 100644
--- a/packages/nodes-base/package.json
+++ b/packages/nodes-base/package.json
@@ -498,6 +498,7 @@
"rhea": "^1.0.11",
"rss-parser": "^3.7.0",
"ssh2-sftp-client": "^5.2.1",
+ "tmp-promise": "^3.0.2",
"uuid": "^3.4.0",
"vm2": "^3.6.10",
"xlsx": "^0.16.7",