From 7ec9357ab9f0db994b4b5513f85a3007cf825f57 Mon Sep 17 00:00:00 2001 From: Vladyslav Hrytsenko Date: Tue, 25 Jun 2024 10:22:27 +0300 Subject: [PATCH] added image action --- packages/nexrender-action-image/index.js | 36 ++++++++ packages/nexrender-action-image/package.json | 13 +++ packages/nexrender-action-image/test.js | 91 ++++++++++++++++++++ packages/nexrender-core/package.json | 1 + packages/nexrender-core/src/index.js | 1 + 5 files changed, 142 insertions(+) create mode 100644 packages/nexrender-action-image/index.js create mode 100644 packages/nexrender-action-image/package.json create mode 100644 packages/nexrender-action-image/test.js diff --git a/packages/nexrender-action-image/index.js b/packages/nexrender-action-image/index.js new file mode 100644 index 00000000..3a814df1 --- /dev/null +++ b/packages/nexrender-action-image/index.js @@ -0,0 +1,36 @@ +const jimp = require('jimp'); + +module.exports = async (job, settings, { create, input, output, filters }) => { + if (!filters || !filters.length) { + throw new Error('No filters provided'); + } + + let image; + + if (!input && !create) { + throw new Error('No input or create provided'); + } + + if (!output) { + throw new Error('No output provided'); + } + + if (!input && create) { + const [width, height] = create; + image = new jimp(width, height); + } else { + image = await jimp.read(input); + } + + for (const filter of filters) { + const { name, args } = filter; + + if (!image[name]) { + throw new Error(`Filter "${name}" does not exist`); + } + + image[name](...args); + } + + await image.writeAsync(output); +} diff --git a/packages/nexrender-action-image/package.json b/packages/nexrender-action-image/package.json new file mode 100644 index 00000000..51a6f7dc --- /dev/null +++ b/packages/nexrender-action-image/package.json @@ -0,0 +1,13 @@ +{ + "name": "@nexrender/action-image", + "homepage": "https://www.nexrender.com", + "author": "inlife", + "version": "1.49.4", + "main": "index.js", + "publishConfig": { + "access": "public" + }, + "dependencies": { + "jimp": "^0.22.12" + } +} diff --git a/packages/nexrender-action-image/test.js b/packages/nexrender-action-image/test.js new file mode 100644 index 00000000..69c21b35 --- /dev/null +++ b/packages/nexrender-action-image/test.js @@ -0,0 +1,91 @@ +const action = require("./index.js"); +const assert = require("assert"); +const fs = require("fs"); +const path = require("path"); + +describe("action/image", () => { + it("should throw an error if no filters are provided", async () => { + const job = {}; + const settings = {}; + const params = { + input: 'foobar', + output: 'foobar', + }; + + try { + await action(job, settings, params); + } catch (err) { + assert.equal(err.message, "No filters provided"); + } + }); + + it("should throw an error if no input or create is provided", async () => { + const job = {}; + const settings = {}; + const { create, input, output, filters } = {filters: [{}]}; + + try { + await action(job, settings, { create, input, output, filters }); + } catch (err) { + assert.equal(err.message, "No input or create provided"); + } + }); + + it("should throw an error if no output is provided", async () => { + const job = {}; + const settings = {}; + const { create, input, output, filters } = {input: 'foobar', filters: [{}]}; + + try { + await action(job, settings, { create, input, output, filters }); + } catch (err) { + assert.equal(err.message, "No output provided"); + } + }); + + const imagePath = path.join(__dirname, "test.png"); + + it("should create a new image with the provided dimensions", async () => { + const job = {}; + const settings = {}; + const create = [21, 21]; + const output = imagePath; + const filters = [ + { name: "background", args: [0xFFFFFF] }, + { name: "setPixelColor", args: [0xFF0000FF, 10, 10] }, + { name: "setPixelColor", args: [0xFF0000FF, 9, 10] }, + { name: "setPixelColor", args: [0xFF0000FF, 11, 10] }, + { name: "setPixelColor", args: [0xFF0000FF, 10, 9] }, + { name: "setPixelColor", args: [0xFF0000FF, 10, 10] }, + { name: "setPixelColor", args: [0xFF0000FF, 10, 11] }, + ]; + + await action(job, settings, { create, output, filters }); + + // assert that the image was created + assert.ok(fs.existsSync(output)); + }); + + it("should apply filters to the input image", async () => { + const job = {}; + const settings = {}; + + const input = imagePath; + const output = imagePath + ".jpg"; + + const filters = [ + { name: "greyscale", args: [] }, + { name: "invert", args: [] }, + ]; + + await action(job, settings, { input, output, filters }); + + // assert that the image was created + assert.ok(fs.existsSync(output)); + }); + + after(() => { + fs.unlinkSync(imagePath); + fs.unlinkSync(imagePath + ".jpg"); + }); +}) diff --git a/packages/nexrender-core/package.json b/packages/nexrender-core/package.json index d7d31364..c9a476f9 100644 --- a/packages/nexrender-core/package.json +++ b/packages/nexrender-core/package.json @@ -28,6 +28,7 @@ "@nexrender/action-decompress": "^1.48.2", "@nexrender/action-encode": "^1.1.4", "@nexrender/action-upload": "^1.0.0", + "@nexrender/action-image": "^1.49.4", "@nexrender/provider-ftp": "^1.17.2", "@nexrender/provider-gs": "^1.21.3", "@nexrender/provider-nx": "^1.47.0", diff --git a/packages/nexrender-core/src/index.js b/packages/nexrender-core/src/index.js index c44766ed..addbe130 100644 --- a/packages/nexrender-core/src/index.js +++ b/packages/nexrender-core/src/index.js @@ -31,6 +31,7 @@ if (process.env.NEXRENDER_REQUIRE_PLUGINS) { require('@nexrender/action-encode'); require('@nexrender/action-upload'); require('@nexrender/action-decompress'); + require('@nexrender/action-image'); require('@nexrender/provider-s3'); require('@nexrender/provider-ftp');