Browse Source

Added 'isImage' and 'isType' functions

n1474335 6 years ago
parent
commit
f4f9b5c91c

+ 33 - 0
src/core/lib/FileType.mjs

@@ -703,6 +703,39 @@ export function detectFileType(buf) {
 }
 
 
+/**
+ * Detects whether the given buffer is a file of the type specified.
+ *
+ * @param {string|RegExp} type
+ * @param {Uint8Array} buf
+ * @returns {string|false} The mime type or false if the type does not match
+ */
+export function isType(type, buf) {
+    const types = detectFileType(buf);
+
+    if (!(types && types.length)) return false;
+
+    if (typeof type === "string") {
+        return types[0].mime.startsWith(type) ? types[0].mime : false;
+    } else if (type instanceof RegExp) {
+        return type.test(types[0].mime) ? types[0].mime : false;
+    } else {
+        throw new Error("Invalid type input.");
+    }
+}
+
+
+/**
+ * Detects whether the given buffer contains an image file.
+ *
+ * @param {Uint8Array} buf
+ * @returns {string|false} The mime type or false if the type does not match
+ */
+export function isImage(buf) {
+    return isType("image", buf);
+}
+
+
 /**
  * Attempts to extract a file from a data stream given its offset and extractor function.
  *

+ 4 - 4
src/core/operations/GenerateQRCode.mjs

@@ -8,7 +8,7 @@ import Operation from "../Operation";
 import OperationError from "../errors/OperationError";
 import qr from "qr-image";
 import { toBase64 } from "../lib/Base64";
-import Magic from "../lib/Magic";
+import { isImage } from "../lib/FileType";
 import Utils from "../Utils";
 
 /**
@@ -100,9 +100,9 @@ class GenerateQRCode extends Operation {
 
         if (format === "PNG") {
             let dataURI = "data:";
-            const type = Magic.magicFileType(data);
-            if (type && type.mime.indexOf("image") === 0){
-                dataURI += type.mime + ";";
+            const mime = isImage(data);
+            if (mime){
+                dataURI += mime + ";";
             } else {
                 throw new OperationError("Invalid PNG file generated by QR image");
             }

+ 43 - 46
src/core/operations/ParseQRCode.mjs

@@ -6,7 +6,7 @@
 
 import Operation from "../Operation";
 import OperationError from "../errors/OperationError";
-import Magic from "../lib/Magic";
+import { isImage } from "../lib/FileType";
 import jsqr from "jsqr";
 import jimp from "jimp";
 
@@ -42,64 +42,61 @@ class ParseQRCode extends Operation {
      * @returns {string}
      */
     async run(input, args) {
-        const type = Magic.magicFileType(input);
         const [normalise] = args;
 
         // Make sure that the input is an image
-        if (type && type.mime.indexOf("image") === 0) {
-            let image = input;
+        if (!isImage(input)) throw new OperationError("Invalid file type.");
 
-            if (normalise) {
-                // Process the image to be easier to read by jsqr
-                // Disables the alpha channel
-                // Sets the image default background to white
-                // Normalises the image colours
-                // Makes the image greyscale
-                // Converts image to a JPEG
-                image = await new Promise((resolve, reject) => {
-                    jimp.read(Buffer.from(input))
-                        .then(image => {
-                            image
-                                .rgba(false)
-                                .background(0xFFFFFFFF)
-                                .normalize()
-                                .greyscale()
-                                .getBuffer(jimp.MIME_JPEG, (error, result) => {
-                                    resolve(result);
-                                });
-                        })
-                        .catch(err => {
-                            reject(new OperationError("Error reading the image file."));
-                        });
-                });
-            }
-
-            if (image instanceof OperationError) {
-                throw image;
-            }
+        let image = input;
 
-            return new Promise((resolve, reject) => {
-                jimp.read(Buffer.from(image))
+        if (normalise) {
+            // Process the image to be easier to read by jsqr
+            // Disables the alpha channel
+            // Sets the image default background to white
+            // Normalises the image colours
+            // Makes the image greyscale
+            // Converts image to a JPEG
+            image = await new Promise((resolve, reject) => {
+                jimp.read(Buffer.from(input))
                     .then(image => {
-                        if (image.bitmap != null) {
-                            const qrData = jsqr(image.bitmap.data, image.getWidth(), image.getHeight());
-                            if (qrData != null) {
-                                resolve(qrData.data);
-                            } else {
-                                reject(new OperationError("Couldn't read a QR code from the image."));
-                            }
-                        } else {
-                            reject(new OperationError("Error reading the image file."));
-                        }
+                        image
+                            .rgba(false)
+                            .background(0xFFFFFFFF)
+                            .normalize()
+                            .greyscale()
+                            .getBuffer(jimp.MIME_JPEG, (error, result) => {
+                                resolve(result);
+                            });
                     })
                     .catch(err => {
                         reject(new OperationError("Error reading the image file."));
                     });
             });
-        } else {
-            throw new OperationError("Invalid file type.");
         }
 
+        if (image instanceof OperationError) {
+            throw image;
+        }
+
+        return new Promise((resolve, reject) => {
+            jimp.read(Buffer.from(image))
+                .then(image => {
+                    if (image.bitmap != null) {
+                        const qrData = jsqr(image.bitmap.data, image.getWidth(), image.getHeight());
+                        if (qrData != null) {
+                            resolve(qrData.data);
+                        } else {
+                            reject(new OperationError("Couldn't read a QR code from the image."));
+                        }
+                    } else {
+                        reject(new OperationError("Error reading the image file."));
+                    }
+                })
+                .catch(err => {
+                    reject(new OperationError("Error reading the image file."));
+                });
+        });
+
     }
 
 }

+ 2 - 3
src/core/operations/PlayMedia.mjs

@@ -9,7 +9,7 @@ import { fromHex } from "../lib/Hex";
 import Operation from "../Operation";
 import OperationError from "../errors/OperationError";
 import Utils from "../Utils";
-import { detectFileType } from "../lib/FileType";
+import { isType, detectFileType } from "../lib/FileType";
 
 /**
  * PlayMedia operation
@@ -66,8 +66,7 @@ class PlayMedia extends Operation {
 
 
         // Determine file type
-        const types = detectFileType(input);
-        if (!(types && types.length && /^audio|video/.test(types[0].mime))) {
+        if (!isType(/^(audio|video)/, input)) {
             throw new OperationError("Invalid or unrecognised file type");
         }
 

+ 5 - 6
src/core/operations/RenderImage.mjs

@@ -9,7 +9,7 @@ import { fromHex } from "../lib/Hex";
 import Operation from "../Operation";
 import OperationError from "../errors/OperationError";
 import Utils from "../Utils";
-import {detectFileType} from "../lib/FileType";
+import {isImage} from "../lib/FileType";
 
 /**
  * Render Image operation
@@ -72,8 +72,7 @@ class RenderImage extends Operation {
         }
 
         // Determine file type
-        const types = detectFileType(input);
-        if (!(types.length && types[0].mime.indexOf("image") === 0)) {
+        if (!isImage(input)) {
             throw new OperationError("Invalid file type");
         }
 
@@ -92,9 +91,9 @@ class RenderImage extends Operation {
         let dataURI = "data:";
 
         // Determine file type
-        const types = detectFileType(data);
-        if (types.length && types[0].mime.indexOf("image") === 0) {
-            dataURI += types[0].mime + ";";
+        const mime = isImage(data);
+        if (mime) {
+            dataURI += mime + ";";
         } else {
             throw new OperationError("Invalid file type");
         }

+ 43 - 46
src/core/operations/SplitColourChannels.mjs

@@ -7,7 +7,7 @@
 import Operation from "../Operation";
 import OperationError from "../errors/OperationError";
 import Utils from "../Utils";
-import Magic from "../lib/Magic";
+import {isImage} from "../lib/FileType";
 
 import jimp from "jimp";
 
@@ -38,56 +38,53 @@ class SplitColourChannels extends Operation {
      * @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));
+        if (!isImage(input)) throw new OperationError("Invalid file type.");
 
-            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: ${err}`));
-                }
-            });
+        const parsedImage = await jimp.read(Buffer.from(input));
 
-            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: ${err}`));
-                }
-            });
+        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: ${err}`));
+            }
+        });
 
-            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: ${err}`));
-                }
-            });
+        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: ${err}`));
+            }
+        });
 
-            return await Promise.all([red, green, blue]);
-        } else {
-            throw new OperationError("Invalid file type.");
-        }
+        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: ${err}`));
+            }
+        });
+
+        return await Promise.all([red, green, blue]);
     }
 
     /**