Browse Source

Added colour channel splitting support

Matt C 6 years ago
parent
commit
0046f7e3d7
3 changed files with 600 additions and 54 deletions
  1. 475 52
      package-lock.json
  2. 13 2
      src/core/Utils.mjs
  3. 112 0
      src/core/operations/SplitColourChannels.mjs

File diff suppressed because it is too large
+ 475 - 52
package-lock.json


+ 13 - 2
src/core/Utils.mjs

@@ -6,7 +6,7 @@
 
 import utf8 from "utf8";
 import moment from "moment-timezone";
-import {fromBase64} from "./lib/Base64";
+import {fromBase64, toBase64} from "./lib/Base64";
 import {fromHex} from "./lib/Hex";
 import {fromDecimal} from "./lib/Decimal";
 import {fromBinary} from "./lib/Binary";
@@ -850,6 +850,17 @@ class Utils {
             return html;
         };
 
+        const formatContent = function (buff, type) {
+            if (type.startsWith("image")) {
+                let dataURI = "data:";
+                dataURI += type + ";";
+                dataURI += "base64," + toBase64(buff);
+                return "<img src='" + dataURI + "'>";
+            } else {
+                return `<pre>${Utils.escapeHtml(Utils.arrayBufferToStr(buff.buffer))}</pre>`;
+            }
+        };
+
         const formatFile = async function(file, i) {
             const buff = await Utils.readFile(file);
             const blob = new Blob(
@@ -879,7 +890,7 @@ class Utils {
                     </div>
                     <div id='collapse${i}' class='collapse' aria-labelledby='heading${i}' data-parent="#files">
                         <div class='card-body'>
-                            <pre>${Utils.escapeHtml(Utils.arrayBufferToStr(buff.buffer))}</pre>
+                            ${formatContent(buff, file.type)}
                         </div>
                     </div>
                 </div>`;

+ 112 - 0
src/core/operations/SplitColourChannels.mjs

@@ -0,0 +1,112 @@
+/**
+ * @author Matt C [matt@artemisbot.uk]
+ * @copyright Crown Copyright 2018
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import OperationError from "../errors/OperationError";
+import Utils from "../Utils";
+import Magic from "../lib/Magic";
+
+import jimp from "jimp";
+
+/**
+ * Split Colour Channels operation
+ */
+class SplitColourChannels extends Operation {
+
+    /**
+     * SplitColourChannels constructor
+     */
+    constructor() {
+        super();
+
+        this.name = "Split Colour Channels";
+        this.module = "Image";
+        this.description = "Splits given image into its red, green and blue colour channels.";
+        this.infoURL = "https://en.wikipedia.org/wiki/Channel_(digital_image)";
+        this.inputType = "byteArray";
+        this.outputType = "List<File>";
+        this.presentType = "html";
+        this.args = [
+            /* Example arguments. See the project wiki for full details.
+            {
+                name: "First arg",
+                type: "string",
+                value: "Don't Panic"
+            },
+            {
+                name: "Second arg",
+                type: "number",
+                value: 42
+            }
+            */
+        ];
+    }
+
+    /**
+     * @param {byteArray} input
+     * @param {Object[]} args
+     * @returns {List<File>}
+     */
+    async run(input, args) {
+        const type = Magic.magicFileType(input);
+        // Make sure that the input is an image
+        if (type && type.mime.indexOf("image") === 0) {
+            const parsedImage = await jimp.read(Buffer.from(input));
+            const red = new Promise(async (resolve, reject) => {
+                try {
+                    const split = parsedImage.clone()
+                        .color([
+                            {apply: "blue", params: [-255]},
+                            {apply: "green", params: [-255]}
+                        ]).getBufferAsync(jimp.MIME_PNG);
+                    resolve(new File([new Uint8Array((await split).values())], "red.png", {type: "image/png"}));
+                } catch (err) {
+                    reject(new OperationError("Could not split red channel."));
+                }
+            });
+            const green = new Promise(async (resolve, reject) => {
+                try {
+                    const split = parsedImage.clone()
+                        .color([
+                            {apply: "red", params: [-255]},
+                            {apply: "blue", params: [-255]},
+                        ]).getBufferAsync(jimp.MIME_PNG);
+                    resolve(new File([new Uint8Array((await split).values())], "green.png", {type: "image/png"}));
+                } catch (err) {
+                    reject(new OperationError("Could not split green channel."));
+                }
+            });
+            const blue = new Promise(async (resolve, reject) => {
+                try {
+                    const split = parsedImage
+                        .color([
+                            {apply: "red", params: [-255]},
+                            {apply: "green", params: [-255]},
+                        ]).getBufferAsync(jimp.MIME_PNG);
+                    resolve(new File([new Uint8Array((await split).values())], "blue.png", {type: "image/png"}));
+                } catch (err) {
+                    reject(new OperationError("Could not split blue channel."));
+                }
+            });
+            return await Promise.all([red, green, blue]);
+        } else {
+            throw new OperationError("Invalid file type.");
+        }
+    }
+
+    /**
+     * Displays the files in HTML for web apps.
+     *
+     * @param {File[]} files
+     * @returns {html}
+     */
+    async present(files) {
+        return await Utils.displayFilesAsHTML(files);
+    }
+
+}
+
+export default SplitColourChannels;

Some files were not shown because too many files changed in this diff