Skip to content

Commit d205a26

Browse files
committed
Add withDensity to set density in EXIF metadata #4496
1 parent ff4626d commit d205a26

File tree

6 files changed

+95
-2
lines changed

6 files changed

+95
-2
lines changed

docs/src/content/docs/api-output.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,30 @@ const base64String = data.toBase64();
149149
```
150150

151151

152+
## withDensity
153+
> withDensity(density) ⇒ <code>Sharp</code>
154+
155+
Set output density (DPI) in EXIF metadata.
156+
157+
158+
**Throws**:
159+
160+
- <code>Error</code> Invalid parameters
161+
162+
**Since**: 0.35.0
163+
164+
| Param | Type | Description |
165+
| --- | --- | --- |
166+
| density | <code>number</code> | Number of pixels per inch (DPI). |
167+
168+
**Example**
169+
```js
170+
const data = await sharp(input)
171+
.withDensity(96)
172+
.toBuffer();
173+
```
174+
175+
152176
## keepExif
153177
> keepExif() ⇒ <code>Sharp</code>
154178

docs/src/content/docs/changelog/v0.35.0.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,7 @@ slug: changelog/v0.35.0
5050
* Add image Media Type (MIME Type) to metadata response.
5151
[#4492](https://github.com/lovell/sharp/issues/4492)
5252

53+
* Add `withDensity` to set output density in EXIF metadata.
54+
[#4496](https://github.com/lovell/sharp/issues/4496)
55+
5356
* Add WebP `exact` option for control over transparent pixel colour values.

lib/index.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,14 @@ declare namespace sharp {
685685
*/
686686
toUint8Array(): Promise<{ data: Uint8Array; info: OutputInfo }>;
687687

688+
/**
689+
* Set output density (DPI) in EXIF metadata.
690+
* @param density Density in dots per inch (DPI).
691+
* @returns A sharp instance that can be used to chain operations
692+
* @throws {Error} Invalid parameters
693+
*/
694+
withDensity(density: number): Sharp;
695+
688696
/**
689697
* Keep all EXIF metadata from the input image in the output image.
690698
* EXIF metadata is unsupported for TIFF output.

lib/output.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,29 @@ function toUint8Array () {
199199
return this._pipeline(null, stack);
200200
}
201201

202+
/**
203+
* Set output density (DPI) in EXIF metadata.
204+
*
205+
* @since 0.35.0
206+
*
207+
* @example
208+
* const data = await sharp(input)
209+
* .withDensity(96)
210+
* .toBuffer();
211+
*
212+
* @param {number} density Number of pixels per inch (DPI).
213+
* @returns {Sharp}
214+
* @throws {Error} Invalid parameters
215+
*/
216+
function withDensity (density) {
217+
if (is.number(density) && density > 0) {
218+
this.options.withMetadataDensity = density;
219+
} else {
220+
throw is.invalidParameterError('density', 'positive number', density);
221+
}
222+
return this.keepExif();
223+
}
224+
202225
/**
203226
* Keep all EXIF metadata from the input image in the output image.
204227
*
@@ -1712,6 +1735,7 @@ module.exports = (Sharp) => {
17121735
toFile,
17131736
toBuffer,
17141737
toUint8Array,
1738+
withDensity,
17151739
keepExif,
17161740
withExif,
17171741
withExifMerge,

test/types/sharp.test-d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ sharp('input.png')
5353
// output.png is an image containing input.png along with all metadata(EXIF, ICC, XMP, IPTC) from input.png
5454
})
5555

56+
sharp(input).withDensity(300);
57+
5658
sharp('input.jpg')
5759
.resize(300, 200)
5860
.toFile('output.jpg', (err: Error) => {

test/unit/metadata.js

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -875,7 +875,7 @@ describe('Image metadata', () => {
875875
assert.strictEqual(parsedExif.Photo.ExposureTime, 0.2);
876876
});
877877

878-
it('Set density of JPEG', async () => {
878+
it('withMetadata - set density of JPEG', async () => {
879879
const data = await sharp({ create })
880880
.withMetadata({
881881
density: 300
@@ -887,7 +887,7 @@ describe('Image metadata', () => {
887887
assert.strictEqual(density, 300);
888888
});
889889

890-
it('Set density of PNG', async () => {
890+
it('withMetadata - set density of PNG', async () => {
891891
const data = await sharp({ create })
892892
.withMetadata({
893893
density: 96
@@ -899,6 +899,26 @@ describe('Image metadata', () => {
899899
assert.strictEqual(density, 96);
900900
});
901901

902+
it('withDensity - set density of JPEG', async () => {
903+
const data = await sharp({ create })
904+
.withDensity(300)
905+
.jpeg()
906+
.toBuffer();
907+
908+
const { density } = await sharp(data).metadata();
909+
assert.strictEqual(density, 300);
910+
});
911+
912+
it('withDensity - set density of PNG', async () => {
913+
const data = await sharp({ create })
914+
.withDensity(96)
915+
.png()
916+
.toBuffer();
917+
918+
const { density } = await sharp(data).metadata();
919+
assert.strictEqual(density, 96);
920+
});
921+
902922
it('chromaSubsampling 4:4:4:4 CMYK JPEG', () => sharp(fixtures.inputJpgWithCmykProfile)
903923
.metadata()
904924
.then((metadata) => {
@@ -1369,5 +1389,17 @@ describe('Image metadata', () => {
13691389
/Expected boolean for attach but received 1 of type number/
13701390
);
13711391
});
1392+
it('withDensity missing density', () => {
1393+
assert.throws(
1394+
() => sharp().withDensity(),
1395+
/Expected positive number for density but received undefined of type undefined/
1396+
);
1397+
});
1398+
it('withDensity invalid density', () => {
1399+
assert.throws(
1400+
() => sharp().withDensity('invalid'),
1401+
/Expected positive number for density but received invalid of type string/
1402+
);
1403+
});
13721404
});
13731405
});

0 commit comments

Comments
 (0)