diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json
index 2edc50ab..92f74212 100755
--- a/src/core/config/Categories.json
+++ b/src/core/config/Categories.json
@@ -375,7 +375,8 @@
"Contain Image",
"Cover Image",
"Image Hue/Saturation/Lightness",
- "Sharpen Image"
+ "Sharpen Image",
+ "Convert image format"
]
},
{
diff --git a/src/core/operations/ConvertImageFormat.mjs b/src/core/operations/ConvertImageFormat.mjs
new file mode 100644
index 00000000..c8152908
--- /dev/null
+++ b/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:
- Joint Photographic Experts Group (JPEG)
- Portable Network Graphics (PNG)
- Bitmap (BMP)
- Tagged Image File Format (TIFF)
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 ``;
+ }
+
+}
+
+export default ConvertImageFormat;