From b2bc8c5f7b9533b700d63e2b82c3d1f419e17acf Mon Sep 17 00:00:00 2001 From: Jozef Izso Date: Fri, 11 Oct 2024 18:04:57 +0200 Subject: [PATCH] Implement `canvas.renderToBlob()` function to export QR Code as blob data --- lib/renderer/canvas.js | 18 +++++++++++ test/unit/renderer/canvas.test.js | 54 +++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/lib/renderer/canvas.js b/lib/renderer/canvas.js index 42050cf5..1902fd61 100644 --- a/lib/renderer/canvas.js +++ b/lib/renderer/canvas.js @@ -61,3 +61,21 @@ exports.renderToDataURL = function renderToDataURL (qrData, canvas, options) { return canvasEl.toDataURL(type, rendererOpts.quality) } + +exports.renderToBlob = function renderToBlob (cb, qrData, canvas, options) { + let opts = options + + if (typeof opts === 'undefined' && (!canvas || !canvas.getContext)) { + opts = canvas + canvas = undefined + } + + if (!opts) opts = {} + + const canvasEl = exports.render(qrData, canvas, opts) + + const type = opts.type || 'image/png' + const rendererOpts = opts.rendererOpts || {} + + canvasEl.toBlob(cb, type, rendererOpts.quality) +} diff --git a/test/unit/renderer/canvas.test.js b/test/unit/renderer/canvas.test.js index 08652df9..3f4ad00e 100644 --- a/test/unit/renderer/canvas.test.js +++ b/test/unit/renderer/canvas.test.js @@ -145,3 +145,57 @@ test('CanvasRenderer renderToDataURL to provided canvas', function (t) { t.end() }) + +test('CanvasRenderer renderToBlob', function (t) { + // Mock document object + global.document = { + createElement: function (el) { + if (el === 'canvas') { + const canvas = createCanvas(200, 200) + + // The `HTMLCanvas` element has a `toBlob()` method + // to export content as image bytes. The equivalent + // methos in `canvas` library is the `toBuffer()`. + canvas.toBlob = (cb, mimeType, config) => { + const buffer = canvas.toBuffer(mimeType, config) + const blob = new Blob([buffer], { type: mimeType }) + cb(blob) + } + + return canvas + } + } + } + + t.plan(6) + + const sampleQrData = QRCode.create('sample text', { version: 2 }) + let imageBlob + + t.doesNotThrow(function () { CanvasRenderer.renderToBlob((blob) => {}, sampleQrData) }, + 'Should not throw if canvas is not provided') + + t.doesNotThrow(function () { + CanvasRenderer.renderToBlob((blob) => { + imageBlob = blob + + t.type(imageBlob, 'Blob', + 'Should return a Blob object') + + t.equal(imageBlob.toString('base64'), '[object Blob]', + 'Blob data cannot be converted to base64 econding') + + t.equal(imageBlob.size % 4, 0, + 'Should have a correct size') + + t.equal(imageBlob.type, 'image/png', + 'Should have a correct type value') + }, sampleQrData, { + margin: 10, + scale: 1, + type: 'image/png' + }) + }, 'Should not throw with options param') + + global.document = undefined +})