mirror of
https://github.com/immich-app/immich.git
synced 2025-01-27 17:28:09 +02:00
fix(server): don't associate assets with Null Island (#5623)
* Don't associate assets with Null Island * Fix lint
This commit is contained in:
parent
960b68b02f
commit
e3e4fb40fd
@ -304,6 +304,18 @@ describe(MetadataService.name, () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should discard latitude and longitude on null island', async () => {
|
||||||
|
assetMock.getByIds.mockResolvedValue([assetStub.withLocation]);
|
||||||
|
metadataMock.readTags.mockResolvedValue({
|
||||||
|
GPSLatitude: 0,
|
||||||
|
GPSLongitude: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
await sut.handleMetadataExtraction({ id: assetStub.image.id });
|
||||||
|
expect(assetMock.getByIds).toHaveBeenCalledWith([assetStub.image.id]);
|
||||||
|
expect(assetMock.upsertExif).toHaveBeenCalledWith(expect.objectContaining({ latitude: null, longitude: null }));
|
||||||
|
});
|
||||||
|
|
||||||
it('should not apply motion photos if asset is video', async () => {
|
it('should not apply motion photos if asset is video', async () => {
|
||||||
assetMock.getByIds.mockResolvedValue([{ ...assetStub.livePhotoMotionAsset, isVisible: true }]);
|
assetMock.getByIds.mockResolvedValue([{ ...assetStub.livePhotoMotionAsset, isVisible: true }]);
|
||||||
mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer);
|
mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer);
|
||||||
|
@ -432,35 +432,40 @@ export class MetadataService {
|
|||||||
|
|
||||||
this.logger.verbose('Exif Tags', tags);
|
this.logger.verbose('Exif Tags', tags);
|
||||||
|
|
||||||
return {
|
const exifData = {
|
||||||
exifData: {
|
// altitude: tags.GPSAltitude ?? null,
|
||||||
// altitude: tags.GPSAltitude ?? null,
|
assetId: asset.id,
|
||||||
assetId: asset.id,
|
bitsPerSample: this.getBitsPerSample(tags),
|
||||||
bitsPerSample: this.getBitsPerSample(tags),
|
colorspace: tags.ColorSpace ?? null,
|
||||||
colorspace: tags.ColorSpace ?? null,
|
dateTimeOriginal: this.getDateTimeOriginal(tags) ?? asset.fileCreatedAt,
|
||||||
dateTimeOriginal: this.getDateTimeOriginal(tags) ?? asset.fileCreatedAt,
|
exifImageHeight: validate(tags.ImageHeight),
|
||||||
exifImageHeight: validate(tags.ImageHeight),
|
exifImageWidth: validate(tags.ImageWidth),
|
||||||
exifImageWidth: validate(tags.ImageWidth),
|
exposureTime: tags.ExposureTime ?? null,
|
||||||
exposureTime: tags.ExposureTime ?? null,
|
fileSizeInByte: stats.size,
|
||||||
fileSizeInByte: stats.size,
|
fNumber: validate(tags.FNumber),
|
||||||
fNumber: validate(tags.FNumber),
|
focalLength: validate(tags.FocalLength),
|
||||||
focalLength: validate(tags.FocalLength),
|
fps: validate(tags.VideoFrameRate),
|
||||||
fps: validate(tags.VideoFrameRate),
|
iso: validate(tags.ISO),
|
||||||
iso: validate(tags.ISO),
|
latitude: validate(tags.GPSLatitude),
|
||||||
latitude: validate(tags.GPSLatitude),
|
lensModel: tags.LensModel ?? null,
|
||||||
lensModel: tags.LensModel ?? null,
|
livePhotoCID: (tags.ContentIdentifier || tags.MediaGroupUUID) ?? null,
|
||||||
livePhotoCID: (tags.ContentIdentifier || tags.MediaGroupUUID) ?? null,
|
longitude: validate(tags.GPSLongitude),
|
||||||
longitude: validate(tags.GPSLongitude),
|
make: tags.Make ?? null,
|
||||||
make: tags.Make ?? null,
|
model: tags.Model ?? null,
|
||||||
model: tags.Model ?? null,
|
modifyDate: exifDate(tags.ModifyDate) ?? asset.fileModifiedAt,
|
||||||
modifyDate: exifDate(tags.ModifyDate) ?? asset.fileModifiedAt,
|
orientation: validate(tags.Orientation)?.toString() ?? null,
|
||||||
orientation: validate(tags.Orientation)?.toString() ?? null,
|
profileDescription: tags.ProfileDescription || tags.ProfileName || null,
|
||||||
profileDescription: tags.ProfileDescription || tags.ProfileName || null,
|
projectionType: tags.ProjectionType ? String(tags.ProjectionType).toUpperCase() : null,
|
||||||
projectionType: tags.ProjectionType ? String(tags.ProjectionType).toUpperCase() : null,
|
timeZone: tags.tz ?? null,
|
||||||
timeZone: tags.tz ?? null,
|
|
||||||
},
|
|
||||||
tags,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (exifData.latitude === 0 && exifData.longitude === 0) {
|
||||||
|
console.warn('Exif data has latitude and longitude of 0, setting to null');
|
||||||
|
exifData.latitude = null;
|
||||||
|
exifData.longitude = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { exifData, tags };
|
||||||
}
|
}
|
||||||
|
|
||||||
private getDateTimeOriginal(tags: ImmichTags | Tags | null) {
|
private getDateTimeOriginal(tags: ImmichTags | Tags | null) {
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class DropNullIslandLatLong1702257380990 implements MigrationInterface {
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
'UPDATE "exif" SET latitude = NULL, longitude = NULL WHERE latitude = 0 AND longitude = 0;',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(): Promise<void> {
|
||||||
|
// There's no way to know which assets used to have 0/0 lat-long if we've
|
||||||
|
// already run this migration.
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user