QRCode.mjs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /**
  2. * QR code resources
  3. *
  4. * @author j433866 [j433866@gmail.com]
  5. * @copyright Crown Copyright 2019
  6. * @license Apache-2.0
  7. */
  8. import OperationError from "../errors/OperationError.mjs";
  9. import jsQR from "jsqr";
  10. import qr from "qr-image";
  11. import jimp from "jimp";
  12. import Utils from "../Utils.mjs";
  13. /**
  14. * Parses a QR code image from an image
  15. *
  16. * @param {ArrayBuffer} input
  17. * @param {boolean} normalise
  18. * @returns {string}
  19. */
  20. export async function parseQrCode(input, normalise) {
  21. let image;
  22. try {
  23. image = await jimp.read(input);
  24. } catch (err) {
  25. throw new OperationError(`Error opening image. (${err})`);
  26. }
  27. try {
  28. if (normalise) {
  29. image.rgba(false);
  30. image.background(0xFFFFFFFF);
  31. image.normalize();
  32. image.greyscale();
  33. image = await image.getBufferAsync(jimp.MIME_JPEG);
  34. image = await jimp.read(image);
  35. }
  36. } catch (err) {
  37. throw new OperationError(`Error normalising image. (${err})`);
  38. }
  39. const qrData = jsQR(image.bitmap.data, image.getWidth(), image.getHeight());
  40. if (qrData) {
  41. return qrData.data;
  42. } else {
  43. throw new OperationError("Could not read a QR code from the image.");
  44. }
  45. }
  46. /**
  47. * Generates a QR code from the input string
  48. *
  49. * @param {string} input
  50. * @param {string} format
  51. * @param {number} moduleSize
  52. * @param {number} margin
  53. * @param {string} errorCorrection
  54. * @returns {ArrayBuffer}
  55. */
  56. export function generateQrCode(input, format, moduleSize, margin, errorCorrection) {
  57. const formats = ["SVG", "EPS", "PDF", "PNG"];
  58. if (!formats.includes(format.toUpperCase())) {
  59. throw new OperationError("Unsupported QR code format.");
  60. }
  61. let qrImage;
  62. try {
  63. qrImage = qr.imageSync(input, {
  64. type: format,
  65. size: moduleSize,
  66. margin: margin,
  67. "ec_level": errorCorrection.charAt(0).toUpperCase()
  68. });
  69. } catch (err) {
  70. throw new OperationError(`Error generating QR code. (${err})`);
  71. }
  72. if (!qrImage) {
  73. throw new OperationError("Error generating QR code.");
  74. }
  75. switch (format) {
  76. case "SVG":
  77. case "EPS":
  78. case "PDF":
  79. return Utils.strToArrayBuffer(qrImage);
  80. case "PNG":
  81. return qrImage.buffer;
  82. default:
  83. throw new OperationError("Unsupported QR code format.");
  84. }
  85. }