diff --git a/README.md b/README.md index 5d382bd..0a85258 100644 --- a/README.md +++ b/README.md @@ -57,9 +57,14 @@ const decode = require('heic-decode'); data // Uint8ClampedArray containing pixel data } = await image.decode(); } + + // when you are done, make sure to free all memory used to convert the images + images.dispose(); })(); ``` +> Note: when decoding a single image (i.e. using `decode`), all resources are freed automatically after the conversion. However, when decoding all images in a file (i.e. using `decode.all`), you can decode the images at any time, so there is no safe time for the library to free resources -- you need to make sure to call `dispose` once you are done. + When the images are decoded, the return value is a plain object in the format of [`ImageData`](https://developer.mozilla.org/en-US/docs/Web/API/ImageData). You can use this object to integrate with other imaging libraries for processing. _Note that while the decoder returns a Promise, it does the majority of the work synchronously, so you should consider using a worker thread in order to not block the main thread in highly concurrent production environments._ diff --git a/lib.js b/lib.js index 44d054f..efa6537 100644 --- a/lib.js +++ b/lib.js @@ -53,20 +53,37 @@ module.exports = libheif => { const decoder = new libheif.HeifDecoder(); const data = decoder.decode(buffer); + const dispose = () => { + for (const image of data) { + image.free(); + } + + decoder.decoder.delete(); + }; + if (!data.length) { throw new Error('HEIF image not found'); } if (!all) { - return await decodeImage(data[0]); + try { + return await decodeImage(data[0]); + } finally { + dispose(); + } } - return data.map(image => { + return Object.defineProperty(data.map(image => { return { width: image.get_width(), height: image.get_height(), decode: async () => await decodeImage(image) }; + }), 'dispose', { + enumerable: false, + configurable: false, + writable: false, + value: dispose }); }; diff --git a/package.json b/package.json index de0fc8b..28219b3 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ }, "homepage": "https://github.com/catdad-experiments/heic-decode#readme", "dependencies": { - "libheif-js": "^1.17.1" + "libheif-js": "^1.19.8" }, "devDependencies": { "buffer-to-uint8array": "^1.1.0", diff --git a/test/index.test.js b/test/index.test.js index e16e66f..173760d 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -63,6 +63,7 @@ function runTests(decode) { const images = await decode.all({ buffer }); expect(images).to.have.lengthOf(3); + expect(images).to.have.property('dispose').and.to.be.a('function'); const controls = await Promise.all([ readControl('0003-0-control.png'), @@ -86,6 +87,8 @@ function runTests(decode) { compare(control.data, image.data, control.width, control.height, `actual image at index ${i} did not match control`); } + + images.dispose(); }); it('throws if data other than a HEIC image is passed in', async () => {