Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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._
Expand Down
21 changes: 19 additions & 2 deletions lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
});
};

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
3 changes: 3 additions & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
Expand All @@ -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 () => {
Expand Down