浏览代码

Add convert image format operation

j433866 6 年之前
父节点
当前提交
e95b7075b9
共有 2 个文件被更改,包括 144 次插入1 次删除
  1. 2 1
      src/core/config/Categories.json
  2. 142 0
      src/core/operations/ConvertImageFormat.mjs

+ 2 - 1
src/core/config/Categories.json

@@ -375,7 +375,8 @@
             "Contain Image",
             "Cover Image",
             "Image Hue/Saturation/Lightness",
-            "Sharpen Image"
+            "Sharpen Image",
+            "Convert image format"
         ]
     },
     {

+ 142 - 0
src/core/operations/ConvertImageFormat.mjs

@@ -0,0 +1,142 @@
+/**
+ * @author j433866 [j433866@gmail.com]
+ * @copyright Crown Copyright 2019
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import OperationError from "../errors/OperationError";
+import { isImage } from "../lib/FileType";
+import { toBase64 } from "../lib/Base64";
+import jimp from "jimp";
+
+/**
+ * Convert Image Format operation
+ */
+class ConvertImageFormat extends Operation {
+
+    /**
+     * ConvertImageFormat constructor
+     */
+    constructor() {
+        super();
+
+        this.name = "Convert image format";
+        this.module = "Image";
+        this.description = "Converts an image between different formats. Supported formats:<br><ul><li>Joint Photographic Experts Group (JPEG)</li><li>Portable Network Graphics (PNG)</li><li>Bitmap (BMP)</li><li>Tagged Image File Format (TIFF)</li></ul><br>Note: GIF files are supported for input, but cannot be outputted.";
+        this.infoURL = "https://wikipedia.org/wiki/Image_file_formats";
+        this.inputType = "byteArray";
+        this.outputType = "byteArray";
+        this.presentType = "html";
+        this.args = [
+            {
+                name: "Output Format",
+                type: "option",
+                value: [
+                    "JPEG",
+                    "PNG",
+                    "BMP",
+                    "TIFF"
+                ]
+            },
+            {
+                name: "JPEG Quality",
+                type: "number",
+                value: 80,
+                min: 1,
+                max: 100
+            },
+            {
+                name: "PNG Filter Type",
+                type: "option",
+                value: [
+                    "Auto",
+                    "None",
+                    "Sub",
+                    "Up",
+                    "Average",
+                    "Paeth"
+                ]
+            },
+            {
+                name: "PNG Deflate Level",
+                type: "number",
+                value: 9,
+                min: 0,
+                max: 9
+            }
+        ];
+    }
+
+    /**
+     * @param {byteArray} input
+     * @param {Object[]} args
+     * @returns {byteArray}
+     */
+    async run(input, args) {
+        const [format, jpegQuality, pngFilterType, pngDeflateLevel] = args;
+        const formatMap = {
+            "JPEG": jimp.MIME_JPEG,
+            "PNG": jimp.MIME_PNG,
+            "BMP": jimp.MIME_BMP,
+            "TIFF": jimp.MIME_TIFF
+        };
+
+        const pngFilterMap = {
+            "Auto": jimp.PNG_FILTER_AUTO,
+            "None": jimp.PNG_FILTER_NONE,
+            "Sub": jimp.PNG_FILTER_SUB,
+            "Up": jimp.PNG_FILTER_UP,
+            "Average": jimp.PNG_FILTER_AVERAGE,
+            "Paeth": jimp.PNG_FILTER_PATH // Incorrect spelling in Jimp library
+        };
+
+        const mime = formatMap[format];
+
+        if (!isImage(input)) {
+            throw new OperationError("Invalid file format.");
+        }
+        let image;
+        try {
+            image = await jimp.read(Buffer.from(input));
+        } catch (err) {
+            throw new OperationError(`Error opening image file. (${err})`);
+        }
+        try {
+            switch (format) {
+                case "JPEG":
+                    image.quality(jpegQuality);
+                    break;
+                case "PNG":
+                    image.filterType(pngFilterMap[pngFilterType]);
+                    image.deflateLevel(pngDeflateLevel);
+                    break;
+            }
+
+            const imageBuffer = await image.getBufferAsync(mime);
+            return [...imageBuffer];
+        } catch (err) {
+            throw new OperationError(`Error converting image format. (${err})`);
+        }
+    }
+
+    /**
+     * Displays the converted image using HTML for web apps
+     *
+     * @param {byteArray} data
+     * @returns {html}
+     */
+    present(data) {
+        if (!data.length) return "";
+
+        const type = isImage(data);
+        if (!type) {
+            throw new OperationError("Invalid image type.");
+        }
+
+        return `<img src="data:${type};base64,${toBase64(data)}">`;
+    }
+
+}
+
+export default ConvertImageFormat;