UNPKG

awesome-qr

Version:

An awesome but simple QR code generator written in JavaScript.

562 lines (561 loc) 34.7 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AwesomeQR = void 0; var canvas_1 = require("canvas"); var gifuct_js_1 = require("./gifuct-js"); var qrcode_1 = require("./qrcode"); var GIFEncoder_1 = __importDefault(require("./gif.js/GIFEncoder")); var defaultScale = 0.4; var AwesomeQR = /** @class */ (function () { function AwesomeQR(options) { var _options = Object.assign({}, options); Object.keys(AwesomeQR.defaultOptions).forEach(function (k) { if (!(k in _options)) { Object.defineProperty(_options, k, { value: AwesomeQR.defaultOptions[k], enumerable: true, writable: true }); } }); if (!_options.components) { _options.components = AwesomeQR.defaultComponentOptions; } else if (typeof _options.components === "object") { Object.keys(AwesomeQR.defaultComponentOptions).forEach(function (k) { if (!(k in _options.components)) { Object.defineProperty(_options.components, k, { value: AwesomeQR.defaultComponentOptions[k], enumerable: true, writable: true, }); } else { Object.defineProperty(_options.components, k, { value: __assign(__assign({}, AwesomeQR.defaultComponentOptions[k]), _options.components[k]), enumerable: true, writable: true, }); } }); } if (_options.dotScale !== null && _options.dotScale !== undefined) { if (_options.dotScale <= 0 || _options.dotScale > 1) { throw new Error("dotScale should be in range (0, 1]."); } _options.components.data.scale = _options.dotScale; _options.components.timing.scale = _options.dotScale; _options.components.alignment.scale = _options.dotScale; } this.options = _options; this.canvas = canvas_1.createCanvas(options.size, options.size); this.canvasContext = this.canvas.getContext("2d"); this.qrCode = new qrcode_1.QRCodeModel(-1, this.options.correctLevel); if (Number.isInteger(this.options.maskPattern)) { this.qrCode.maskPattern = this.options.maskPattern; } if (Number.isInteger(this.options.version)) { this.qrCode.typeNumber = this.options.version; } this.qrCode.addData(this.options.text); this.qrCode.make(); } AwesomeQR.prototype.draw = function () { var _this = this; return new Promise(function (resolve) { return _this._draw().then(resolve); }); }; AwesomeQR.prototype._clear = function () { this.canvasContext.clearRect(0, 0, this.canvas.width, this.canvas.height); }; AwesomeQR._prepareRoundedCornerClip = function (canvasContext, x, y, w, h, r) { canvasContext.beginPath(); canvasContext.moveTo(x, y); canvasContext.arcTo(x + w, y, x + w, y + h, r); canvasContext.arcTo(x + w, y + h, x, y + h, r); canvasContext.arcTo(x, y + h, x, y, r); canvasContext.arcTo(x, y, x + w, y, r); canvasContext.closePath(); }; AwesomeQR._getAverageRGB = function (image) { var blockSize = 5; var defaultRGB = { r: 0, g: 0, b: 0, }; var width, height; var i = -4; var rgb = { r: 0, g: 0, b: 0, }; var count = 0; height = image.naturalHeight || image.height; width = image.naturalWidth || image.width; var canvas = canvas_1.createCanvas(width, height); var context = canvas.getContext("2d"); if (!context) { return defaultRGB; } context.drawImage(image, 0, 0); var data; try { data = context.getImageData(0, 0, width, height); } catch (e) { return defaultRGB; } while ((i += blockSize * 4) < data.data.length) { if (data.data[i] > 200 || data.data[i + 1] > 200 || data.data[i + 2] > 200) continue; ++count; rgb.r += data.data[i]; rgb.g += data.data[i + 1]; rgb.b += data.data[i + 2]; } rgb.r = ~~(rgb.r / count); rgb.g = ~~(rgb.g / count); rgb.b = ~~(rgb.b / count); return rgb; }; AwesomeQR._drawDot = function (canvasContext, centerX, centerY, nSize, xyOffset, dotScale) { if (xyOffset === void 0) { xyOffset = 0; } if (dotScale === void 0) { dotScale = 1; } canvasContext.fillRect((centerX + xyOffset) * nSize, (centerY + xyOffset) * nSize, dotScale * nSize, dotScale * nSize); }; AwesomeQR._drawAlignProtector = function (canvasContext, centerX, centerY, nSize) { canvasContext.clearRect((centerX - 2) * nSize, (centerY - 2) * nSize, 5 * nSize, 5 * nSize); canvasContext.fillRect((centerX - 2) * nSize, (centerY - 2) * nSize, 5 * nSize, 5 * nSize); }; AwesomeQR._drawAlign = function (canvasContext, centerX, centerY, nSize, xyOffset, dotScale, colorDark, hasProtector) { if (xyOffset === void 0) { xyOffset = 0; } if (dotScale === void 0) { dotScale = 1; } var oldFillStyle = canvasContext.fillStyle; canvasContext.fillStyle = colorDark; new Array(4).fill(0).map(function (_, i) { AwesomeQR._drawDot(canvasContext, centerX - 2 + i, centerY - 2, nSize, xyOffset, dotScale); AwesomeQR._drawDot(canvasContext, centerX + 2, centerY - 2 + i, nSize, xyOffset, dotScale); AwesomeQR._drawDot(canvasContext, centerX + 2 - i, centerY + 2, nSize, xyOffset, dotScale); AwesomeQR._drawDot(canvasContext, centerX - 2, centerY + 2 - i, nSize, xyOffset, dotScale); }); AwesomeQR._drawDot(canvasContext, centerX, centerY, nSize, xyOffset, dotScale); if (!hasProtector) { canvasContext.fillStyle = "rgba(255, 255, 255, 0.6)"; new Array(2).fill(0).map(function (_, i) { AwesomeQR._drawDot(canvasContext, centerX - 1 + i, centerY - 1, nSize, xyOffset, dotScale); AwesomeQR._drawDot(canvasContext, centerX + 1, centerY - 1 + i, nSize, xyOffset, dotScale); AwesomeQR._drawDot(canvasContext, centerX + 1 - i, centerY + 1, nSize, xyOffset, dotScale); AwesomeQR._drawDot(canvasContext, centerX - 1, centerY + 1 - i, nSize, xyOffset, dotScale); }); } canvasContext.fillStyle = oldFillStyle; }; AwesomeQR.prototype._draw = function () { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u; return __awaiter(this, void 0, void 0, function () { var nCount, rawSize, rawMargin, margin, rawViewportSize, whiteMargin, backgroundDimming, nSize, viewportSize, size, mainCanvas, mainCanvasContext, backgroundCanvas, backgroundCanvasContext, parsedGIFBackground, gifFrames, gif, r, g, b, count, i, c, backgroundImage, avgRGB, alignmentPatternCenters, dataScale, dataXyOffset, row, col, bIsDark, isBlkPosCtr, isTiming, isProtected, i, nLeft, nTop, inAgnRange, cornerAlignmentCenter, protectorStyle, i, j, agnX, agnY, timingScale, timingXyOffset, i, cornerAlignmentScale, cornerAlignmentXyOffset, alignmentScale, alignmentXyOffset, i, j, agnX, agnY, logoImage, logoScale, logoMargin, logoCornerRadius, logoSize, x, y, oldGlobalCompositeOperation, gifOutput_1, backgroundCanvas_1, backgroundCanvasContext_1, patchCanvas_1, patchCanvasContext_1, patchData_1, u8array, binary, outCanvas, outCanvasContext; return __generator(this, function (_v) { switch (_v.label) { case 0: nCount = (_a = this.qrCode) === null || _a === void 0 ? void 0 : _a.moduleCount; rawSize = this.options.size; rawMargin = this.options.margin; if (rawMargin < 0 || rawMargin * 2 >= rawSize) { rawMargin = 0; } margin = Math.ceil(rawMargin); rawViewportSize = rawSize - 2 * rawMargin; whiteMargin = this.options.whiteMargin; backgroundDimming = this.options.backgroundDimming; nSize = Math.ceil(rawViewportSize / nCount); viewportSize = nSize * nCount; size = viewportSize + 2 * margin; mainCanvas = canvas_1.createCanvas(size, size); mainCanvasContext = mainCanvas.getContext("2d"); this._clear(); // Translate to make the top and left margins off the viewport mainCanvasContext.save(); mainCanvasContext.translate(margin, margin); backgroundCanvas = canvas_1.createCanvas(size, size); backgroundCanvasContext = backgroundCanvas.getContext("2d"); parsedGIFBackground = null; gifFrames = []; if (!!!this.options.gifBackground) return [3 /*break*/, 1]; gif = gifuct_js_1.parseGIF(this.options.gifBackground); parsedGIFBackground = gif; gifFrames = gifuct_js_1.decompressFrames(gif, true); if (this.options.autoColor) { r = 0, g = 0, b = 0; count = 0; for (i = 0; i < gifFrames[0].colorTable.length; i++) { c = gifFrames[0].colorTable[i]; if (c[0] > 200 || c[1] > 200 || c[2] > 200) continue; if (c[0] === 0 && c[1] === 0 && c[2] === 0) continue; count++; r += c[0]; g += c[1]; b += c[2]; } r = ~~(r / count); g = ~~(g / count); b = ~~(b / count); this.options.colorDark = "rgb(" + r + "," + g + "," + b + ")"; } return [3 /*break*/, 4]; case 1: if (!!!this.options.backgroundImage) return [3 /*break*/, 3]; return [4 /*yield*/, canvas_1.loadImage(this.options.backgroundImage)]; case 2: backgroundImage = _v.sent(); if (this.options.autoColor) { avgRGB = AwesomeQR._getAverageRGB(backgroundImage); this.options.colorDark = "rgb(" + avgRGB.r + "," + avgRGB.g + "," + avgRGB.b + ")"; } backgroundCanvasContext.drawImage(backgroundImage, 0, 0, backgroundImage.width, backgroundImage.height, 0, 0, size, size); backgroundCanvasContext.rect(0, 0, size, size); backgroundCanvasContext.fillStyle = backgroundDimming; backgroundCanvasContext.fill(); return [3 /*break*/, 4]; case 3: backgroundCanvasContext.rect(0, 0, size, size); backgroundCanvasContext.fillStyle = this.options.colorLight; backgroundCanvasContext.fill(); _v.label = 4; case 4: alignmentPatternCenters = qrcode_1.QRUtil.getPatternPosition(this.qrCode.typeNumber); dataScale = ((_c = (_b = this.options.components) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.scale) || defaultScale; dataXyOffset = (1 - dataScale) * 0.5; for (row = 0; row < nCount; row++) { for (col = 0; col < nCount; col++) { bIsDark = this.qrCode.isDark(row, col); isBlkPosCtr = (col < 8 && (row < 8 || row >= nCount - 8)) || (col >= nCount - 8 && row < 8); isTiming = (row == 6 && col >= 8 && col <= nCount - 8) || (col == 6 && row >= 8 && row <= nCount - 8); isProtected = isBlkPosCtr || isTiming; for (i = 1; i < alignmentPatternCenters.length - 1; i++) { isProtected = isProtected || (row >= alignmentPatternCenters[i] - 2 && row <= alignmentPatternCenters[i] + 2 && col >= alignmentPatternCenters[i] - 2 && col <= alignmentPatternCenters[i] + 2); } nLeft = col * nSize + (isProtected ? 0 : dataXyOffset * nSize); nTop = row * nSize + (isProtected ? 0 : dataXyOffset * nSize); mainCanvasContext.strokeStyle = bIsDark ? this.options.colorDark : this.options.colorLight; mainCanvasContext.lineWidth = 0.5; mainCanvasContext.fillStyle = bIsDark ? this.options.colorDark : "rgba(255, 255, 255, 0.6)"; if (alignmentPatternCenters.length === 0) { if (!isProtected) { mainCanvasContext.fillRect(nLeft, nTop, (isProtected ? (isBlkPosCtr ? 1 : 1) : dataScale) * nSize, (isProtected ? (isBlkPosCtr ? 1 : 1) : dataScale) * nSize); } } else { inAgnRange = col < nCount - 4 && col >= nCount - 4 - 5 && row < nCount - 4 && row >= nCount - 4 - 5; if (!isProtected && !inAgnRange) { // if align pattern list is empty, then it means that we don't need to leave room for the align patterns mainCanvasContext.fillRect(nLeft, nTop, (isProtected ? (isBlkPosCtr ? 1 : 1) : dataScale) * nSize, (isProtected ? (isBlkPosCtr ? 1 : 1) : dataScale) * nSize); } } } } cornerAlignmentCenter = alignmentPatternCenters[alignmentPatternCenters.length - 1]; protectorStyle = "rgba(255, 255, 255, 0.6)"; // - FINDER PROTECTORS mainCanvasContext.fillStyle = protectorStyle; mainCanvasContext.fillRect(0, 0, 8 * nSize, 8 * nSize); mainCanvasContext.fillRect(0, (nCount - 8) * nSize, 8 * nSize, 8 * nSize); mainCanvasContext.fillRect((nCount - 8) * nSize, 0, 8 * nSize, 8 * nSize); // - TIMING PROTECTORS if ((_e = (_d = this.options.components) === null || _d === void 0 ? void 0 : _d.timing) === null || _e === void 0 ? void 0 : _e.protectors) { mainCanvasContext.fillRect(8 * nSize, 6 * nSize, (nCount - 8 - 8) * nSize, nSize); mainCanvasContext.fillRect(6 * nSize, 8 * nSize, nSize, (nCount - 8 - 8) * nSize); } // - CORNER ALIGNMENT PROTECTORS if ((_g = (_f = this.options.components) === null || _f === void 0 ? void 0 : _f.cornerAlignment) === null || _g === void 0 ? void 0 : _g.protectors) { AwesomeQR._drawAlignProtector(mainCanvasContext, cornerAlignmentCenter, cornerAlignmentCenter, nSize); } // - ALIGNMENT PROTECTORS if ((_j = (_h = this.options.components) === null || _h === void 0 ? void 0 : _h.alignment) === null || _j === void 0 ? void 0 : _j.protectors) { for (i = 0; i < alignmentPatternCenters.length; i++) { for (j = 0; j < alignmentPatternCenters.length; j++) { agnX = alignmentPatternCenters[j]; agnY = alignmentPatternCenters[i]; if (agnX === 6 && (agnY === 6 || agnY === cornerAlignmentCenter)) { continue; } else if (agnY === 6 && (agnX === 6 || agnX === cornerAlignmentCenter)) { continue; } else if (agnX === cornerAlignmentCenter && agnY === cornerAlignmentCenter) { continue; } else { AwesomeQR._drawAlignProtector(mainCanvasContext, agnX, agnY, nSize); } } } } // - FINDER mainCanvasContext.fillStyle = this.options.colorDark; mainCanvasContext.fillRect(0, 0, 7 * nSize, nSize); mainCanvasContext.fillRect((nCount - 7) * nSize, 0, 7 * nSize, nSize); mainCanvasContext.fillRect(0, 6 * nSize, 7 * nSize, nSize); mainCanvasContext.fillRect((nCount - 7) * nSize, 6 * nSize, 7 * nSize, nSize); mainCanvasContext.fillRect(0, (nCount - 7) * nSize, 7 * nSize, nSize); mainCanvasContext.fillRect(0, (nCount - 7 + 6) * nSize, 7 * nSize, nSize); mainCanvasContext.fillRect(0, 0, nSize, 7 * nSize); mainCanvasContext.fillRect(6 * nSize, 0, nSize, 7 * nSize); mainCanvasContext.fillRect((nCount - 7) * nSize, 0, nSize, 7 * nSize); mainCanvasContext.fillRect((nCount - 7 + 6) * nSize, 0, nSize, 7 * nSize); mainCanvasContext.fillRect(0, (nCount - 7) * nSize, nSize, 7 * nSize); mainCanvasContext.fillRect(6 * nSize, (nCount - 7) * nSize, nSize, 7 * nSize); mainCanvasContext.fillRect(2 * nSize, 2 * nSize, 3 * nSize, 3 * nSize); mainCanvasContext.fillRect((nCount - 7 + 2) * nSize, 2 * nSize, 3 * nSize, 3 * nSize); mainCanvasContext.fillRect(2 * nSize, (nCount - 7 + 2) * nSize, 3 * nSize, 3 * nSize); timingScale = ((_l = (_k = this.options.components) === null || _k === void 0 ? void 0 : _k.timing) === null || _l === void 0 ? void 0 : _l.scale) || defaultScale; timingXyOffset = (1 - timingScale) * 0.5; for (i = 0; i < nCount - 8; i += 2) { AwesomeQR._drawDot(mainCanvasContext, 8 + i, 6, nSize, timingXyOffset, timingScale); AwesomeQR._drawDot(mainCanvasContext, 6, 8 + i, nSize, timingXyOffset, timingScale); } cornerAlignmentScale = ((_o = (_m = this.options.components) === null || _m === void 0 ? void 0 : _m.cornerAlignment) === null || _o === void 0 ? void 0 : _o.scale) || defaultScale; cornerAlignmentXyOffset = (1 - cornerAlignmentScale) * 0.5; AwesomeQR._drawAlign(mainCanvasContext, cornerAlignmentCenter, cornerAlignmentCenter, nSize, cornerAlignmentXyOffset, cornerAlignmentScale, this.options.colorDark, ((_q = (_p = this.options.components) === null || _p === void 0 ? void 0 : _p.cornerAlignment) === null || _q === void 0 ? void 0 : _q.protectors) || false); alignmentScale = ((_s = (_r = this.options.components) === null || _r === void 0 ? void 0 : _r.alignment) === null || _s === void 0 ? void 0 : _s.scale) || defaultScale; alignmentXyOffset = (1 - alignmentScale) * 0.5; for (i = 0; i < alignmentPatternCenters.length; i++) { for (j = 0; j < alignmentPatternCenters.length; j++) { agnX = alignmentPatternCenters[j]; agnY = alignmentPatternCenters[i]; if (agnX === 6 && (agnY === 6 || agnY === cornerAlignmentCenter)) { continue; } else if (agnY === 6 && (agnX === 6 || agnX === cornerAlignmentCenter)) { continue; } else if (agnX === cornerAlignmentCenter && agnY === cornerAlignmentCenter) { continue; } else { AwesomeQR._drawAlign(mainCanvasContext, agnX, agnY, nSize, alignmentXyOffset, alignmentScale, this.options.colorDark, ((_u = (_t = this.options.components) === null || _t === void 0 ? void 0 : _t.alignment) === null || _u === void 0 ? void 0 : _u.protectors) || false); } } } // Fill the margin if (whiteMargin) { mainCanvasContext.fillStyle = "#FFFFFF"; mainCanvasContext.fillRect(-margin, -margin, size, margin); mainCanvasContext.fillRect(-margin, viewportSize, size, margin); mainCanvasContext.fillRect(viewportSize, -margin, margin, size); mainCanvasContext.fillRect(-margin, -margin, margin, size); } if (!!!this.options.logoImage) return [3 /*break*/, 6]; return [4 /*yield*/, canvas_1.loadImage(this.options.logoImage)]; case 5: logoImage = _v.sent(); logoScale = this.options.logoScale; logoMargin = this.options.logoMargin; logoCornerRadius = this.options.logoCornerRadius; if (logoScale <= 0 || logoScale >= 1.0) { logoScale = 0.2; } if (logoMargin < 0) { logoMargin = 0; } if (logoCornerRadius < 0) { logoCornerRadius = 0; } logoSize = viewportSize * logoScale; x = 0.5 * (size - logoSize); y = x; // Restore the canvas // After restoring, the top and left margins should be taken into account mainCanvasContext.restore(); // Clean the area that the logo covers (including margins) mainCanvasContext.fillStyle = "#FFFFFF"; mainCanvasContext.save(); AwesomeQR._prepareRoundedCornerClip(mainCanvasContext, x - logoMargin, y - logoMargin, logoSize + 2 * logoMargin, logoSize + 2 * logoMargin, logoCornerRadius + logoMargin); mainCanvasContext.clip(); oldGlobalCompositeOperation = mainCanvasContext.globalCompositeOperation; mainCanvasContext.globalCompositeOperation = "destination-out"; mainCanvasContext.fill(); mainCanvasContext.globalCompositeOperation = oldGlobalCompositeOperation; mainCanvasContext.restore(); // Draw logo image mainCanvasContext.save(); AwesomeQR._prepareRoundedCornerClip(mainCanvasContext, x, y, logoSize, logoSize, logoCornerRadius); mainCanvasContext.clip(); mainCanvasContext.drawImage(logoImage, x, y, logoSize, logoSize); mainCanvasContext.restore(); // Re-translate the canvas to translate the top and left margins into invisible area mainCanvasContext.save(); mainCanvasContext.translate(margin, margin); _v.label = 6; case 6: if (!!parsedGIFBackground) { gifFrames.forEach(function (frame) { if (!gifOutput_1) { gifOutput_1 = new GIFEncoder_1.default(rawSize, rawSize); gifOutput_1.setDelay(frame.delay); gifOutput_1.setRepeat(0); } var _a = frame.dims, width = _a.width, height = _a.height; if (!backgroundCanvas_1) { backgroundCanvas_1 = canvas_1.createCanvas(width, height); backgroundCanvasContext_1 = backgroundCanvas_1.getContext("2d"); backgroundCanvasContext_1.rect(0, 0, backgroundCanvas_1.width, backgroundCanvas_1.height); backgroundCanvasContext_1.fillStyle = "#ffffff"; backgroundCanvasContext_1.fill(); } if (!patchCanvas_1 || !patchData_1 || width !== patchCanvas_1.width || height !== patchCanvas_1.height) { patchCanvas_1 = canvas_1.createCanvas(width, height); patchCanvasContext_1 = patchCanvas_1.getContext("2d"); patchData_1 = patchCanvasContext_1.createImageData(width, height); } patchData_1.data.set(frame.patch); patchCanvasContext_1.putImageData(patchData_1, 0, 0); backgroundCanvasContext_1.drawImage(patchCanvas_1, frame.dims.left, frame.dims.top); var unscaledCanvas = canvas_1.createCanvas(size, size); var unscaledCanvasContext = unscaledCanvas.getContext("2d"); unscaledCanvasContext.drawImage(backgroundCanvas_1, 0, 0, size, size); unscaledCanvasContext.rect(0, 0, size, size); unscaledCanvasContext.fillStyle = backgroundDimming; unscaledCanvasContext.fill(); unscaledCanvasContext.drawImage(mainCanvas, 0, 0, size, size); // Scale the final image var outCanvas = canvas_1.createCanvas(rawSize, rawSize); var outCanvasContext = outCanvas.getContext("2d"); outCanvasContext.drawImage(unscaledCanvas, 0, 0, rawSize, rawSize); gifOutput_1.addFrame(outCanvasContext.getImageData(0, 0, outCanvas.width, outCanvas.height).data); }); if (!gifOutput_1) { throw new Error("No frames."); } gifOutput_1.finish(); if (isElement(this.canvas)) { u8array = gifOutput_1.stream().toFlattenUint8Array(); binary = u8array.reduce(function (bin, u8) { return bin + String.fromCharCode(u8); }, ""); return [2 /*return*/, Promise.resolve("data:image/gif;base64," + window.btoa(binary))]; } return [2 /*return*/, Promise.resolve(Buffer.from(gifOutput_1.stream().toFlattenUint8Array()))]; } else { // Swap and merge the foreground and the background backgroundCanvasContext.drawImage(mainCanvas, 0, 0, size, size); mainCanvasContext.drawImage(backgroundCanvas, -margin, -margin, size, size); outCanvas = canvas_1.createCanvas(rawSize, rawSize); outCanvasContext = outCanvas.getContext("2d"); outCanvasContext.drawImage(mainCanvas, 0, 0, rawSize, rawSize); this.canvas = outCanvas; if (isElement(this.canvas)) { return [2 /*return*/, Promise.resolve(this.canvas.toDataURL())]; } return [2 /*return*/, Promise.resolve(this.canvas.toBuffer())]; } return [2 /*return*/]; } }); }); }; AwesomeQR.CorrectLevel = qrcode_1.QRErrorCorrectLevel; AwesomeQR.defaultComponentOptions = { data: { scale: 1, }, timing: { scale: 1, protectors: false, }, alignment: { scale: 1, protectors: false, }, cornerAlignment: { scale: 1, protectors: true, }, }; AwesomeQR.defaultOptions = { text: "", size: 400, margin: 20, colorDark: "#000000", colorLight: "#ffffff", correctLevel: qrcode_1.QRErrorCorrectLevel.M, backgroundImage: undefined, backgroundDimming: "rgba(0,0,0,0)", logoImage: undefined, logoScale: 0.2, logoMargin: 4, logoCornerRadius: 8, whiteMargin: true, components: AwesomeQR.defaultComponentOptions, autoColor: true, }; return AwesomeQR; }()); exports.AwesomeQR = AwesomeQR; function isElement(obj) { try { //Using W3 DOM2 (works for FF, Opera and Chrome) return obj instanceof HTMLElement; } catch (e) { //Browsers not supporting W3 DOM2 don't have HTMLElement and //an exception is thrown and we end up here. Testing some //properties that all elements have (works on IE7) return (typeof obj === "object" && obj.nodeType === 1 && typeof obj.style === "object" && typeof obj.ownerDocument === "object"); } }