From 2067323e61a52dd67d5707c6d6978db227c19aed 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 | 50 +++++++++++++++++++++++++++++++ 2 files changed, 68 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..ecb6b51d 100644 --- a/test/unit/renderer/canvas.test.js +++ b/test/unit/renderer/canvas.test.js @@ -145,3 +145,53 @@ 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) + cb(buffer) + } + + return canvas + } + } + } + + t.plan(5) + + 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, 'object', + 'Should return a Buffer object') + + t.equal(imageBlob.toString('base64'), 'iVBORw0KGgoAAAANSUhEUgAAAC0AAAAtCAYAAAA6GuKaAAAABmJLR0QA/wD/AP+gvaeTAAABfUlEQVRYhe2Z4Y4DIQiE18u9/ytzv2jIdBBQ6qWJkzRrXdb9RBRth4jI82X6+W+AFV3oU7rQp3ShT+lCn9Jv1nCM4d4Tkdd9TbBo79Uzm0hpaK9RC6Hw1s7CajlqJ1IJmkFimdVV2smoDF2FwLDpUNtEtJ5mIVIZ/khlT0ceU2DrYQa84/kS9MxbCKtgrH7X62nojGcwLPS5nUnHlI5pffEY461sYb2wYOs0a7MVGicYSyYzMGuDHROR0giMyhmRvcyL5VlHrFbCJQ3N0jKCR8+jzWqsl8JDr7gmIwCLe7W19aydVmgLjh6KYtKbDyvAZWiMafQcs8HRwD3KSpovLXnMK+hFlr5nYbAyEcsxbTugZbx6GTCqy2pr78F2c+yeZ48TtP0QsHLiYM9U4DyVVw/8MM28Ho1ARq0nl8iLHZPweRoPAV46Z0lpVx//CYFtmPBeNc7bTi5RSmbJR79/NKajk4uFyUw4ryMhx/374pAu9Cld6FO60Kd0oU/pD1hTe2vcG9EjAAAAAElFTkSuQmCC', + 'Should have correct content') + + t.equal(imageBlob.length % 4, 0, + 'Should have a correct length') + }, sampleQrData, { + margin: 10, + scale: 1, + type: 'image/png' + }) + }, 'Should not throw with options param') + + global.document = undefined +})