Skip to content

Commit

Permalink
fix(server): wrong image dimensions for RAW files (RAF, CR2) (also fi…
Browse files Browse the repository at this point in the history
…xes face preview) (immich-app#13377)
  • Loading branch information
C-Otto authored and yosit committed Nov 21, 2024
1 parent 491846e commit c59ced6
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 3 deletions.
72 changes: 72 additions & 0 deletions e2e/src/api/specs/asset.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1148,6 +1148,78 @@ describe('/asset', () => {
},
},
},
{
input: 'formats/raw/Canon/PowerShot_G12.CR2',
expected: {
type: AssetTypeEnum.Image,
originalFileName: 'PowerShot_G12.CR2',
fileCreatedAt: '2015-12-27T09:55:40.000Z',
exifInfo: {
make: 'Canon',
model: 'Canon PowerShot G12',
exifImageHeight: 2736,
exifImageWidth: 3648,
exposureTime: '1/1000',
fNumber: 4,
focalLength: 18.098,
iso: 80,
lensModel: null,
fileSizeInByte: 11_113_617,
dateTimeOriginal: '2015-12-27T09:55:40.000Z',
latitude: null,
longitude: null,
orientation: '1',
},
},
},
{
input: 'formats/raw/Fujifilm/X100V_compressed.RAF',
expected: {
type: AssetTypeEnum.Image,
originalFileName: 'X100V_compressed.RAF',
fileCreatedAt: '2024-10-12T21:01:01.000Z',
exifInfo: {
make: 'FUJIFILM',
model: 'X100V',
exifImageHeight: 4160,
exifImageWidth: 6240,
exposureTime: '1/4000',
fNumber: 16,
focalLength: 23,
iso: 160,
lensModel: null,
fileSizeInByte: 13_551_312,
dateTimeOriginal: '2024-10-12T21:01:01.000Z',
latitude: null,
longitude: null,
orientation: '6',
},
},
},
{
input: 'formats/raw/Ricoh/GR3/Ricoh_GR3-450.DNG',
expected: {
type: AssetTypeEnum.Image,
originalFileName: 'Ricoh_GR3-450.DNG',
fileCreatedAt: '2024-06-08T13:48:39.000Z',
exifInfo: {
dateTimeOriginal: '2024-06-08T13:48:39.000Z',
exifImageHeight: 4064,
exifImageWidth: 6112,
exposureTime: '1/400',
fNumber: 5,
fileSizeInByte: 31_175_472,
focalLength: 18.3,
iso: 100,
latitude: 36.613_24,
lensModel: 'GR LENS 18.3mm F2.8',
longitude: -121.897_85,
make: 'RICOH IMAGING COMPANY, LTD.',
model: 'RICOH GR III',
orientation: '1',
},
},
},
];

it(`should upload and generate a thumbnail for different file types`, async () => {
Expand Down
19 changes: 17 additions & 2 deletions server/src/services/metadata.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ export class MetadataService extends BaseService {
const { dateTimeOriginal, localDateTime, timeZone, modifyDate } = this.getDates(asset, exifTags);
const { latitude, longitude, country, state, city } = await this.getGeo(exifTags, reverseGeocoding);

const { width, height } = this.getImageDimensions(exifTags);

const exifData: Partial<ExifEntity> = {
assetId: asset.id,

Expand All @@ -204,8 +206,8 @@ export class MetadataService extends BaseService {

// image/file
fileSizeInByte: stats.size,
exifImageHeight: validate(exifTags.ImageHeight),
exifImageWidth: validate(exifTags.ImageWidth),
exifImageHeight: validate(height),
exifImageWidth: validate(width),
orientation: validate(exifTags.Orientation)?.toString() ?? null,
projectionType: exifTags.ProjectionType ? String(exifTags.ProjectionType).toUpperCase() : null,
bitsPerSample: this.getBitsPerSample(exifTags),
Expand Down Expand Up @@ -333,6 +335,19 @@ export class MetadataService extends BaseService {
return JobStatus.SUCCESS;
}

private getImageDimensions(exifTags: ImmichTags): { width?: number; height?: number } {
/*
* The "true" values for width and height are a bit hidden, depending on the camera model and file format.
* For RAW images in the CR2 or RAF format, the "ImageSize" value seems to be correct,
* but ImageWidth and ImageHeight are not correct (they contain the dimensions of the preview image).
*/
let [width, height] = exifTags.ImageSize?.split('x').map((dim) => Number.parseInt(dim) || undefined) || [];
if (!width || !height) {
[width, height] = [exifTags.ImageWidth, exifTags.ImageHeight];
}
return { width, height };
}

private async getExifTags(asset: AssetEntity): Promise<ImmichTags> {
const mediaTags = await this.metadataRepository.readTags(asset.originalPath);
const sidecarTags = asset.sidecarPath ? await this.metadataRepository.readTags(asset.sidecarPath) : {};
Expand Down

0 comments on commit c59ced6

Please sign in to comment.