From e77e87b936786a6221eb2df2ceda1b245ea2f5dc Mon Sep 17 00:00:00 2001 From: Mert <101130780+mertalev@users.noreply.github.com> Date: Sun, 16 Jun 2024 11:45:58 -0400 Subject: [PATCH] fix(server): orientation handling for person thumbnails (#10382) fix orientation handling --- server/src/interfaces/media.interface.ts | 4 +++ server/src/services/person.service.spec.ts | 6 ++--- server/src/services/person.service.ts | 30 ++++++---------------- server/test/fixtures/face.stub.ts | 4 +-- 4 files changed, 17 insertions(+), 27 deletions(-) diff --git a/server/src/interfaces/media.interface.ts b/server/src/interfaces/media.interface.ts index 11ee525f8a..fdf70865ef 100644 --- a/server/src/interfaces/media.interface.ts +++ b/server/src/interfaces/media.interface.ts @@ -47,6 +47,10 @@ export interface ImageDimensions { height: number; } +export interface InputDimensions extends ImageDimensions { + inputPath: string; +} + export interface VideoInfo { format: VideoFormat; videoStreams: VideoStreamInfo[]; diff --git a/server/src/services/person.service.spec.ts b/server/src/services/person.service.spec.ts index bb76bc38a3..bf6fc8207e 100644 --- a/server/src/services/person.service.spec.ts +++ b/server/src/services/person.service.spec.ts @@ -917,9 +917,9 @@ describe(PersonService.name, () => { colorspace: Colorspace.P3, crop: { left: 0, - top: 428, - width: 1102, - height: 1102, + top: 85, + width: 510, + height: 510, }, }, ); diff --git a/server/src/services/person.service.ts b/server/src/services/person.service.ts index e3e78b48f2..57940f3113 100644 --- a/server/src/services/person.service.ts +++ b/server/src/services/person.service.ts @@ -41,13 +41,12 @@ import { } from 'src/interfaces/job.interface'; import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { BoundingBox, IMachineLearningRepository } from 'src/interfaces/machine-learning.interface'; -import { CropOptions, IMediaRepository, ImageDimensions } from 'src/interfaces/media.interface'; +import { CropOptions, IMediaRepository, ImageDimensions, InputDimensions } from 'src/interfaces/media.interface'; import { IMoveRepository } from 'src/interfaces/move.interface'; import { IPersonRepository, UpdateFacesData } from 'src/interfaces/person.interface'; import { ISearchRepository } from 'src/interfaces/search.interface'; import { IStorageRepository } from 'src/interfaces/storage.interface'; import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface'; -import { Orientation } from 'src/services/metadata.service'; import { CacheControl, ImmichFileResponse } from 'src/utils/file'; import { mimeTypes } from 'src/utils/mime-types'; import { isFacialRecognitionEnabled } from 'src/utils/misc'; @@ -520,7 +519,7 @@ export class PersonService { return JobStatus.FAILED; } - const { width, height, inputPath } = await this.getInputDimensions(asset); + const { width, height, inputPath } = await this.getInputDimensions(asset, { width: oldWidth, height: oldHeight }); const thumbnailPath = StorageCore.getPersonThumbnailPath(person); this.storageCore.ensureFolders(thumbnailPath); @@ -601,7 +600,7 @@ export class PersonService { return person; } - private async getInputDimensions(asset: AssetEntity): Promise { + private async getInputDimensions(asset: AssetEntity, oldDims: ImageDimensions): Promise { if (!asset.exifInfo?.exifImageHeight || !asset.exifInfo.exifImageWidth) { throw new Error(`Asset ${asset.id} dimensions are unknown`); } @@ -611,10 +610,11 @@ export class PersonService { } if (asset.type === AssetType.IMAGE) { - const { width, height } = this.withOrientation(asset.exifInfo.orientation as Orientation, { - width: asset.exifInfo.exifImageWidth, - height: asset.exifInfo.exifImageHeight, - }); + let { exifImageWidth: width, exifImageHeight: height } = asset.exifInfo; + if (oldDims.height > oldDims.width !== height > width) { + [width, height] = [height, width]; + } + return { width, height, inputPath: asset.originalPath }; } @@ -622,20 +622,6 @@ export class PersonService { return { width, height, inputPath: asset.previewPath }; } - private withOrientation(orientation: Orientation, { width, height }: ImageDimensions): ImageDimensions { - switch (orientation) { - case Orientation.MirrorHorizontalRotate270CW: - case Orientation.Rotate90CW: - case Orientation.MirrorHorizontalRotate90CW: - case Orientation.Rotate270CW: { - return { width: height, height: width }; - } - default: { - return { width, height }; - } - } - } - private getCrop(dims: { old: ImageDimensions; new: ImageDimensions }, { x1, y1, x2, y2 }: BoundingBox): CropOptions { const widthScale = dims.new.width / dims.old.width; const heightScale = dims.new.height / dims.old.height; diff --git a/server/test/fixtures/face.stub.ts b/server/test/fixtures/face.stub.ts index 2d2acec40d..5ecb5701ce 100644 --- a/server/test/fixtures/face.stub.ts +++ b/server/test/fixtures/face.stub.ts @@ -72,8 +72,8 @@ export const faceStub = { boundingBoxY1: 5, boundingBoxX2: 505, boundingBoxY2: 505, - imageHeight: 1000, - imageWidth: 1000, + imageHeight: 2880, + imageWidth: 2160, }), middle: Object.freeze>({ id: 'assetFaceId6',