Skip to content

Commit 1a16880

Browse files
Add option to keep orientation in metadata.strip() (#50)
1 parent 4801ef8 commit 1a16880

5 files changed

Lines changed: 70 additions & 8 deletions

File tree

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,10 @@ Strip metadata from an image returning a new image buffer.
172172
await image(path).metadata.strip().save(outPath)
173173
```
174174

175-
| Parameter | Type | Description |
176-
| ---------------- | ------- | ------------------------------------------------------------------- |
177-
| `opts.keepColor` | boolean | Keep color-transform metadata to avoid color shifts. Default `true` |
175+
| Parameter | Type | Description |
176+
| ---------------------- | ------- | ------------------------------------------------------------------- |
177+
| `opts.keepColor` | boolean | Keep color-transform metadata to avoid color shifts. Default `true` |
178+
| `opts.keepOrientation` | boolean | Keep orientation to avoid image rotations. Default `false` |
178179

179180
Check with `isStripMetadataSupported()` for supported types, only `jpeg` at the moment.
180181

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@
3131
"homepage": "https://github.com/holepunchto/bare-media#readme",
3232
"dependencies": {
3333
"bare-bmp": "^1.0.0",
34-
"bare-exif": "^1.0.0",
34+
"bare-exif": "^1.1.0",
3535
"bare-fetch": "^3.0.1",
3636
"bare-ffmpeg": "^1.2.1",
3737
"bare-fs": "^4.1.5",
3838
"bare-gif": "^1.1.2",
3939
"bare-heif": "^1.0.5",
4040
"bare-ico": "^1.0.0",
4141
"bare-image-resample": "^1.0.1",
42-
"bare-jpeg": "^1.1.0",
42+
"bare-jpeg": "^1.1.1",
4343
"bare-png": "^1.0.2",
4444
"bare-svg": "^1.0.1",
4545
"bare-tiff": "^1.0.1",

src/image/metadata.js

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,40 @@ async function metadata(buffer, opts = {}) {
7474
}
7575

7676
async function stripJPEG(buffer, opts = {}) {
77-
const { keepColor = true } = opts
77+
const { keepColor = true, keepOrientation = false } = opts
7878

7979
const jpeg = await import('bare-jpeg')
80+
const APP1 = 0xe1
8081
const APP14 = 0xee
82+
8183
const { markers } = jpeg.readHeader(buffer)
82-
const keep = keepColor ? markers.filter((m) => m.marker === APP14) : []
8384

84-
return jpeg.replaceMarkers(buffer, keep)
85+
let newMarkers = []
86+
87+
if (keepColor) {
88+
newMarkers = markers.filter((m) => m.marker === APP14)
89+
}
90+
91+
if (keepOrientation) {
92+
const exif = await import('bare-exif')
93+
const tags = exif.constants.tags
94+
const data = new exif.Data(buffer)
95+
96+
for (const tag of Object.values(tags)) {
97+
if (tag !== tags.ORIENTATION) {
98+
data.removeEntry(tag)
99+
}
100+
}
101+
102+
const rawExif = data.saveData()
103+
104+
newMarkers.push({
105+
marker: APP1,
106+
data: rawExif
107+
})
108+
}
109+
110+
return jpeg.replaceMarkers(buffer, newMarkers)
85111
}
86112

87113
async function strip(buffer, opts = {}) {

test/fixtures/exif.jpg

5.84 KB
Loading

test/image.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ test('image.metadata.strip() strips all metadata', async (t) => {
8686

8787
{
8888
const metadata = await image(newImage).metadata()
89+
90+
// no exif data is stored
8991
t.absent(metadata.exif.COLOR_SPACE)
9092
t.absent(metadata.exif.EXIF_VERSION)
9193
t.absent(metadata.exif.FLASH_PIX_VERSION)
@@ -95,6 +97,39 @@ test('image.metadata.strip() strips all metadata', async (t) => {
9597
}
9698
})
9799

100+
test('image.metadata.strip() strips all metadata, except orientation', async (t) => {
101+
const path = './test/fixtures/exif.jpg'
102+
103+
const metadata = await image(path).metadata()
104+
105+
t.ok(metadata.exif.COLOR_SPACE)
106+
t.ok(metadata.exif.EXIF_VERSION)
107+
t.ok(metadata.exif.FLASH_PIX_VERSION)
108+
t.ok(metadata.exif.RESOLUTION_UNIT)
109+
t.ok(metadata.exif.MAKE)
110+
t.ok(metadata.exif.LENS_MAKE)
111+
t.ok(metadata.exif.ARTIST)
112+
t.ok(metadata.exif.ORIENTATION)
113+
t.is(metadata.orientation, 6)
114+
115+
const newImage = await image(path).metadata.strip({ keepOrientation: true })
116+
117+
{
118+
const metadata = await image(newImage).metadata()
119+
120+
// some mandatory tags remain as for the spec
121+
t.ok(metadata.exif.COLOR_SPACE)
122+
t.ok(metadata.exif.EXIF_VERSION)
123+
t.ok(metadata.exif.FLASH_PIX_VERSION)
124+
t.ok(metadata.exif.RESOLUTION_UNIT)
125+
t.absent(metadata.exif.MAKE)
126+
t.absent(metadata.exif.LENS_MAKE)
127+
t.absent(metadata.exif.ARTIST)
128+
t.ok(metadata.exif.ORIENTATION)
129+
t.is(metadata.orientation, 6)
130+
}
131+
})
132+
98133
test('image.metadata.strip().save() strips all metadata and saves the file', async (t) => {
99134
const path = './test/fixtures/exif-orientation.jpg'
100135
const outPath = barePath.join(os.tmpdir(), randomFileName('jpg'))

0 commit comments

Comments
 (0)