This commit is contained in:
Holegots 2026-08-15 12:35:12 +02:00 committed by GitHub
commit 97a3a11ca4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 65 additions and 2 deletions

View file

@ -92,8 +92,18 @@ export class MetadataRepository {
/* eslint unicorn/no-array-callback-reference: off, unicorn/no-array-method-this-argument: off */
geoTz: (lat, lon) => geotz.find(lat, lon)[0],
geolocation: true,
// Enable exiftool LFS to parse metadata for files larger than 2GB.
readArgs: ['-api', 'largefilesupport=1', '--ICC_Profile:DeviceManufacturer', '--ICC_Profile:DeviceModelName'],
readArgs: [
// Enable exiftool LFS to parse metadata for files larger than 2GB.
'-api',
'largefilesupport=1',
'--ICC_Profile:DeviceManufacturer',
'--ICC_Profile:DeviceModelName',
// Ignore embedded thumbnail dimensions/orientation for the main asset.
'--IFD1:Orientation',
'--MWG:Orientation',
'--IFD1:ImageWidth',
'--IFD1:ImageHeight',
],
writeArgs: ['-api', 'largefilesupport=1', '-overwrite_original'],
taskTimeoutMillis: 2 * 60 * 1000,
});

View file

@ -151,6 +151,59 @@ describe(MetadataService.name, () => {
// note that this date is technically wrong. it does not throw though and should get the user's attention either way.
).resolves.toEqual({ dateTimeOriginal: new Date('4260-03-05T04:04:12.000Z') });
});
it('should ignore IFD1 thumbnail orientation when extracting metadata', async () => {
const { sut, ctx } = setup();
ctx.getMock(EventRepository).emit.mockResolvedValue();
const { filePath } = await createTestFile({ 'IFD1:Orientation#': 6 });
const { user } = await ctx.newUser();
const { asset } = await ctx.newAsset({ originalPath: filePath, ownerId: user.id });
await ctx.newExif({ assetId: asset.id, description: '' });
await sut.handleMetadataExtraction({ id: asset.id });
await expect(
ctx.database
.selectFrom('asset_exif')
.select('orientation')
.where('assetId', '=', asset.id)
.executeTakeFirstOrThrow(),
).resolves.toEqual({ orientation: null });
});
it('should ignore IFD1 thumbnail dimensions when extracting metadata', async () => {
const { sut, ctx } = setup();
ctx.getMock(EventRepository).emit.mockResolvedValue();
const { filePath } = await createTestFile({ 'IFD1:ImageWidth#': 160, 'IFD1:ImageHeight#': 120 });
const { user } = await ctx.newUser();
const { asset } = await ctx.newAsset({ originalPath: filePath, ownerId: user.id });
await ctx.newExif({ assetId: asset.id, description: '' });
await sut.handleMetadataExtraction({ id: asset.id });
await expect(ctx.get(AssetRepository).getById(asset.id)).resolves.toEqual(
expect.objectContaining({ width: 1, height: 1 }),
);
});
it('should keep IFD0 orientation when extracting metadata', async () => {
const { sut, ctx } = setup();
ctx.getMock(EventRepository).emit.mockResolvedValue();
const { filePath } = await createTestFile({ 'IFD0:Orientation#': 6 });
const { user } = await ctx.newUser();
const { asset } = await ctx.newAsset({ originalPath: filePath, ownerId: user.id });
await ctx.newExif({ assetId: asset.id, description: '' });
await sut.handleMetadataExtraction({ id: asset.id });
await expect(
ctx.database
.selectFrom('asset_exif')
.select('orientation')
.where('assetId', '=', asset.id)
.executeTakeFirstOrThrow(),
).resolves.toEqual({ orientation: '6' });
});
});
it('should handle float lens models (#30492)', async () => {