mirror of
				https://github.com/immich-app/immich.git
				synced 2025-10-30 18:22:37 -04:00 
			
		
		
		
	fix: use full-size image for non-web-compatible panoramas (#20359)
* fix(web): use full-size image for non-web-compatible panoramas * always generate full-size image for panoramas * add unit test * fix formatting --------- Co-authored-by: gergo= <gergo@pitty.hu>
This commit is contained in:
		
							parent
							
								
									42f46b11f4
								
							
						
					
					
						commit
						6973683ea7
					
				| @ -861,6 +861,37 @@ describe(MediaService.name, () => { | ||||
|       ); | ||||
|     }); | ||||
| 
 | ||||
|     it('should always generate full-size preview from non-web-friendly panoramas', async () => { | ||||
|       mocks.systemMetadata.get.mockResolvedValue({ image: { fullsize: { enabled: false } } }); | ||||
|       mocks.media.extract.mockResolvedValue({ buffer: extractedBuffer, format: RawExtractedFormat.Jpeg }); | ||||
|       mocks.media.getImageDimensions.mockResolvedValue({ width: 3840, height: 2160 }); | ||||
| 
 | ||||
|       mocks.assetJob.getForGenerateThumbnailJob.mockResolvedValue(assetStub.panoramaTif); | ||||
| 
 | ||||
|       await sut.handleGenerateThumbnails({ id: assetStub.image.id }); | ||||
| 
 | ||||
|       expect(mocks.media.decodeImage).toHaveBeenCalledOnce(); | ||||
|       expect(mocks.media.decodeImage).toHaveBeenCalledWith(assetStub.panoramaTif.originalPath, { | ||||
|         colorspace: Colorspace.Srgb, | ||||
|         orientation: undefined, | ||||
|         processInvalidImages: false, | ||||
|         size: undefined, | ||||
|       }); | ||||
| 
 | ||||
|       expect(mocks.media.generateThumbnail).toHaveBeenCalledTimes(3); | ||||
|       expect(mocks.media.generateThumbnail).toHaveBeenCalledWith( | ||||
|         rawBuffer, | ||||
|         { | ||||
|           colorspace: Colorspace.Srgb, | ||||
|           format: ImageFormat.Jpeg, | ||||
|           quality: 80, | ||||
|           processInvalidImages: false, | ||||
|           raw: rawInfo, | ||||
|         }, | ||||
|         expect.any(String), | ||||
|       ); | ||||
|     }); | ||||
| 
 | ||||
|     it('should respect encoding options when generating full-size preview', async () => { | ||||
|       mocks.systemMetadata.get.mockResolvedValue({ | ||||
|         image: { fullsize: { enabled: true, format: ImageFormat.Webp, quality: 90 } }, | ||||
|  | ||||
| @ -271,7 +271,9 @@ export class MediaService extends BaseService { | ||||
|     // Handle embedded preview extraction for RAW files
 | ||||
|     const extractEmbedded = image.extractEmbedded && mimeTypes.isRaw(asset.originalFileName); | ||||
|     const extracted = extractEmbedded ? await this.extractImage(asset.originalPath, image.preview.size) : null; | ||||
|     const generateFullsize = image.fullsize.enabled && !mimeTypes.isWebSupportedImage(asset.originalPath); | ||||
|     const generateFullsize = | ||||
|       (image.fullsize.enabled || asset.exifInfo.projectionType == 'EQUIRECTANGULAR') && | ||||
|       !mimeTypes.isWebSupportedImage(asset.originalPath); | ||||
|     const convertFullsize = generateFullsize && (!extracted || !mimeTypes.isWebSupportedImage(` .${extracted.format}`)); | ||||
| 
 | ||||
|     const { info, data, colorspace } = await this.decodeImage( | ||||
|  | ||||
							
								
								
									
										39
									
								
								server/test/fixtures/asset.stub.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										39
									
								
								server/test/fixtures/asset.stub.ts
									
									
									
									
										vendored
									
									
								
							| @ -866,4 +866,43 @@ export const assetStub = { | ||||
|     stackId: null, | ||||
|     visibility: AssetVisibility.Timeline, | ||||
|   }), | ||||
|   panoramaTif: Object.freeze({ | ||||
|     id: 'asset-id', | ||||
|     status: AssetStatus.Active, | ||||
|     deviceAssetId: 'device-asset-id', | ||||
|     fileModifiedAt: new Date('2023-02-23T05:06:29.716Z'), | ||||
|     fileCreatedAt: new Date('2023-02-23T05:06:29.716Z'), | ||||
|     owner: userStub.user1, | ||||
|     ownerId: 'user-id', | ||||
|     deviceId: 'device-id', | ||||
|     originalPath: '/original/path.tif', | ||||
|     checksum: Buffer.from('file hash', 'utf8'), | ||||
|     type: AssetType.Image, | ||||
|     files, | ||||
|     thumbhash: Buffer.from('blablabla', 'base64'), | ||||
|     encodedVideoPath: null, | ||||
|     createdAt: new Date('2023-02-23T05:06:29.716Z'), | ||||
|     updatedAt: new Date('2023-02-23T05:06:29.716Z'), | ||||
|     localDateTime: new Date('2023-02-23T05:06:29.716Z'), | ||||
|     isFavorite: true, | ||||
|     duration: null, | ||||
|     isExternal: false, | ||||
|     livePhotoVideo: null, | ||||
|     livePhotoVideoId: null, | ||||
|     sharedLinks: [], | ||||
|     originalFileName: 'asset-id.tif', | ||||
|     faces: [], | ||||
|     deletedAt: null, | ||||
|     sidecarPath: null, | ||||
|     exifInfo: { | ||||
|       fileSizeInByte: 5000, | ||||
|       projectionType: 'EQUIRECTANGULAR', | ||||
|     } as Exif, | ||||
|     duplicateId: null, | ||||
|     isOffline: false, | ||||
|     updateId: '42', | ||||
|     libraryId: null, | ||||
|     stackId: null, | ||||
|     visibility: AssetVisibility.Timeline, | ||||
|   }), | ||||
| }; | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| <script lang="ts"> | ||||
|   import { authManager } from '$lib/managers/auth-manager.svelte'; | ||||
|   import { getAssetOriginalUrl } from '$lib/utils'; | ||||
|   import { getAssetOriginalUrl, getAssetThumbnailUrl } from '$lib/utils'; | ||||
|   import { isWebCompatibleImage } from '$lib/utils/asset-utils'; | ||||
|   import { AssetMediaSize, viewAsset, type AssetResponseDto } from '@immich/sdk'; | ||||
|   import { LoadingSpinner } from '@immich/ui'; | ||||
| @ -25,7 +25,9 @@ | ||||
|   {:then [data, { default: PhotoSphereViewer }]} | ||||
|     <PhotoSphereViewer | ||||
|       panorama={data} | ||||
|       originalPanorama={isWebCompatibleImage(asset) ? getAssetOriginalUrl(asset.id) : undefined} | ||||
|       originalPanorama={isWebCompatibleImage(asset) | ||||
|         ? getAssetOriginalUrl(asset.id) | ||||
|         : getAssetThumbnailUrl({ id: asset.id, size: AssetMediaSize.Fullsize, cacheKey: asset.thumbhash })} | ||||
|     /> | ||||
|   {:catch} | ||||
|     {$t('errors.failed_to_load_asset')} | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user