Pārlūkot izejas kodu

Move parsing and generation of QR codes to lib folder.
Also rewrote QR code parsing to be more readable and actually error out properly.

j433866 6 gadi atpakaļ
vecāks
revīzija
21a8d03201

+ 90 - 0
src/core/lib/QRCode.mjs

@@ -0,0 +1,90 @@
+/**
+ * QR code resources
+ *
+ * @author j433866 [j433866@gmail.com]
+ * @copyright Crown Copyright 2019
+ * @license Apache-2.0
+ */
+
+import OperationError from "../errors/OperationError";
+import jsQR from "jsqr";
+import qr from "qr-image";
+import jimp from "jimp";
+
+/**
+ * Parses a QR code image from an image
+ *
+ * @param {byteArray} input
+ * @param {boolean} normalise
+ * @returns {string}
+ */
+export async function parseQrCode(input, normalise) {
+    let image;
+    try {
+        image = await jimp.read(Buffer.from(input));
+    } catch (err) {
+        throw new OperationError(`Error opening image. (${err})`);
+    }
+
+    try {
+        if (normalise) {
+            image.rgba(false);
+            image.background(0xFFFFFFFF);
+            image.normalize();
+            image.greyscale();
+        }
+    } catch (err) {
+        throw new OperationError(`Error normalising iamge. (${err})`);
+    }
+
+    const qrData = jsQR(image.bitmap.data, image.getWidth(), image.getHeight());
+    if (qrData) {
+        return qrData.data;
+    } else {
+        throw new OperationError("Could not read a QR code from the image.");
+    }
+}
+
+/**
+ * Generates a QR code from the input string
+ *
+ * @param {string} input
+ * @param {string} format
+ * @param {number} moduleSize
+ * @param {number} margin
+ * @param {string} errorCorrection
+ * @returns {byteArray}
+ */
+export function generateQrCode(input, format, moduleSize, margin, errorCorrection) {
+    const formats = ["SVG", "EPS", "PDF", "PNG"];
+    if (!formats.includes(format.toUpperCase())) {
+        throw new OperationError("Unsupported QR code format.");
+    }
+
+    let qrImage;
+    try {
+        qrImage = qr.imageSync(input, {
+            type: format,
+            size: moduleSize,
+            margin: margin,
+            "ec_level": errorCorrection.charAt(0).toUpperCase()
+        });
+    } catch (err) {
+        throw new OperationError(`Error generating QR code. (${err})`);
+    }
+
+    if (!qrImage) {
+        throw new OperationError("Error generating QR code.");
+    }
+
+    switch (format) {
+        case "SVG":
+        case "EPS":
+        case "PDF":
+            return [...Buffer.from(qrImage)];
+        case "PNG":
+            return [...qrImage];
+        default:
+            throw new OperationError("Unsupported QR code format.");
+    }
+}

+ 2 - 24
src/core/operations/GenerateQRCode.mjs

@@ -6,7 +6,7 @@
 
 import Operation from "../Operation";
 import OperationError from "../errors/OperationError";
-import qr from "qr-image";
+import { generateQrCode } from "../lib/QRCode";
 import { toBase64 } from "../lib/Base64";
 import Magic from "../lib/Magic";
 import Utils from "../Utils";
@@ -62,29 +62,7 @@ class GenerateQRCode extends Operation {
     run(input, args) {
         const [format, size, margin, errorCorrection] = args;
 
-        // Create new QR image from the input data, and convert it to a buffer
-        const qrImage = qr.imageSync(input, {
-            type: format,
-            size: size,
-            margin: margin,
-            "ec_level": errorCorrection.charAt(0).toUpperCase()
-        });
-
-        if (qrImage == null) {
-            throw new OperationError("Error generating QR code.");
-        }
-
-        switch (format) {
-            case "SVG":
-            case "EPS":
-            case "PDF":
-                return [...Buffer.from(qrImage)];
-            case "PNG":
-                // Return the QR image buffer as a byte array
-                return [...qrImage];
-            default:
-                throw new OperationError("Unsupported QR code format.");
-        }
+        return generateQrCode(input, format, size, margin, errorCorrection);
     }
 
     /**

+ 4 - 56
src/core/operations/ParseQRCode.mjs

@@ -7,8 +7,7 @@
 import Operation from "../Operation";
 import OperationError from "../errors/OperationError";
 import Magic from "../lib/Magic";
-import jsqr from "jsqr";
-import jimp from "jimp";
+import { parseQrCode } from "../lib/QRCode";
 
 /**
  * Parse QR Code operation
@@ -42,64 +41,13 @@ class ParseQRCode extends Operation {
      * @returns {string}
      */
     async run(input, args) {
-        const type = Magic.magicFileType(input);
         const [normalise] = args;
+        const type = Magic.magicFileType(input);
 
-        // Make sure that the input is an image
-        if (type && type.mime.indexOf("image") === 0) {
-            let image = input;
-
-            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;
-            }
-
-            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."));
-                    });
-            });
-        } else {
+        if (!type || type.mime.indexOf("image") !== 0) {
             throw new OperationError("Invalid file type.");
         }
-
+        return await parseQrCode(input, normalise);
     }
 
 }