Add support for draw and allow font selection EditImage-Node

This commit is contained in:
Jan Oberhauser 2020-11-18 18:19:41 +01:00
parent b81d175145
commit 02669c04f1
2 changed files with 221 additions and 2 deletions

View file

@ -4,17 +4,23 @@ import {
} from 'n8n-core';
import {
IDataObject,
ILoadOptionsFunctions,
INodeExecutionData,
INodePropertyOptions,
INodeType,
INodeTypeDescription,
} from 'n8n-workflow';
import * as gm from 'gm';
import { file } from 'tmp-promise';
import {
parse as pathParse,
} from 'path';
import {
writeFile as fsWriteFile,
} from 'fs';
import { promisify } from 'util';
const fsWriteFileAsync = promisify(fsWriteFile);
import * as getSystemFonts from 'get-system-fonts';
export class EditImage implements INodeType {
@ -57,6 +63,11 @@ export class EditImage implements INodeType {
value: 'composite',
description: 'Composite image on top of another one',
},
{
name: 'Draw',
value: 'draw',
description: 'Draw on image',
},
{
name: 'Get Information',
value: 'information',
@ -96,6 +107,140 @@ export class EditImage implements INodeType {
},
// ----------------------------------
// draw
// ----------------------------------
{
displayName: 'Primitive',
name: 'primitive',
type: 'options',
displayOptions: {
show: {
operation: [
'draw',
],
},
},
options: [
{
name: 'Line',
value: 'line',
},
{
name: 'Rectangle',
value: 'rectangle',
},
],
default: 'rectangle',
description: 'The primitive to draw.',
},
{
displayName: 'Color',
name: 'color',
type: 'color',
default: '#ff000000',
typeOptions: {
showAlpha: true,
},
displayOptions: {
show: {
operation: [
'draw',
],
},
},
description: 'The color of the primitive to draw',
},
{
displayName: 'Start Position X',
name: 'startPositionX',
type: 'number',
default: 50,
displayOptions: {
show: {
operation: [
'draw',
],
primitive: [
'line',
'rectangle',
],
},
},
description: 'X (horizontal) start position of the primitive.',
},
{
displayName: 'Start Position Y',
name: 'startPositionY',
type: 'number',
default: 50,
displayOptions: {
show: {
operation: [
'draw',
],
primitive: [
'line',
'rectangle',
],
},
},
description: 'Y (horizontal) start position of the primitive.',
},
{
displayName: 'End Position X',
name: 'endPositionX',
type: 'number',
default: 250,
displayOptions: {
show: {
operation: [
'draw',
],
primitive: [
'line',
'rectangle',
],
},
},
description: 'X (horizontal) end position of the primitive.',
},
{
displayName: 'End Position Y',
name: 'endPositionY',
type: 'number',
default: 250,
displayOptions: {
show: {
operation: [
'draw',
],
primitive: [
'line',
'rectangle',
],
},
},
description: 'Y (horizontal) end position of the primitive.',
},
{
displayName: 'Corner Radius',
name: 'cornerRadius',
type: 'number',
default: 0,
displayOptions: {
show: {
operation: [
'draw',
],
primitive: [
'rectangle',
],
},
},
description: 'The radius of the corner to create round corners.',
},
// ----------------------------------
// text
// ----------------------------------
@ -501,7 +646,7 @@ export class EditImage implements INodeType {
],
},
},
description: 'The color to use for the background when image gets rotated by anything which is not a multiple of 90..',
description: 'The color to use for the background when image gets rotated by anything which is not a multiple of 90.',
},
@ -558,6 +703,23 @@ export class EditImage implements INodeType {
default: '',
description: 'File name to set in binary data.',
},
{
displayName: 'Font',
name: 'font',
type: 'options',
displayOptions: {
show: {
'/operation': [
'text',
],
},
},
typeOptions: {
loadOptionsMethod: 'getFonts',
},
default: 'default',
description: 'The font to use.',
},
{
displayName: 'Format',
name: 'format',
@ -613,6 +775,40 @@ export class EditImage implements INodeType {
};
methods = {
loadOptions: {
async getFonts(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
// @ts-ignore
const files = await getSystemFonts();
const returnData: INodePropertyOptions[] = [];
files.forEach((file: string) => {
const pathParts = pathParse(file);
returnData.push({
name: pathParts.name,
value: file,
});
});
returnData.sort((a, b) => {
if (a.name < b.name) { return -1; }
if (a.name > b.name) { return 1; }
return 0;
});
returnData.unshift({
name: 'default',
value: 'default',
});
return returnData;
},
},
};
async executeSingle(this: IExecuteSingleFunctions): Promise<INodeExecutionData> {
const item = this.getInputData();
@ -670,7 +866,24 @@ export class EditImage implements INodeType {
const positionY = this.getNodeParameter('positionY') as number;
gmInstance = gmInstance.crop(width, height, positionX, positionY);
} else if (operation === 'information') {
} else if (operation === 'draw') {
const startPositionX = this.getNodeParameter('startPositionX') as number;
const startPositionY = this.getNodeParameter('startPositionY') as number;
const endPositionX = this.getNodeParameter('endPositionX') as number;
const endPositionY = this.getNodeParameter('endPositionY') as number;
const primitive = this.getNodeParameter('primitive') as string;
const color = this.getNodeParameter('color') as string;
gmInstance = gmInstance.fill(color);
if (primitive === 'line') {
gmInstance = gmInstance.drawLine(startPositionX, startPositionY, endPositionX, endPositionY);
} else if (primitive === 'rectangle') {
const cornerRadius = this.getNodeParameter('cornerRadius') as number;
gmInstance = gmInstance.drawRectangle(startPositionX, startPositionY, endPositionX, endPositionY, cornerRadius || undefined);
}
} else if (operation === 'information') {
const imageData = await new Promise<IDataObject>((resolve, reject) => {
gmInstance = gmInstance.identify((error, imageData) => {
if (error) {
@ -738,6 +951,10 @@ export class EditImage implements INodeType {
// Combine the lines to a single string
const renderText = lines.join('\n');
if (options.font && options.font !== 'default') {
gmInstance = gmInstance.font(options.font as string);
}
gmInstance = gmInstance
.fill(fontColor)
.fontSize(fontSize)

View file

@ -453,6 +453,7 @@
"@types/redis": "^2.8.11",
"@types/request-promise-native": "~1.0.15",
"@types/ssh2-sftp-client": "^5.1.0",
"@types/tmp": "^0.2.0",
"@types/uuid": "^3.4.6",
"@types/xml2js": "^0.4.3",
"gulp": "^4.0.0",
@ -471,6 +472,7 @@
"cron": "^1.7.2",
"eventsource": "^1.0.7",
"formidable": "^1.2.1",
"get-system-fonts": "^2.0.2",
"glob-promise": "^3.4.0",
"gm": "^1.23.1",
"imap-simple": "^4.3.0",