|
@@ -1,6 +1,7 @@
|
|
import {
|
|
import {
|
|
AssetType,
|
|
AssetType,
|
|
Colorspace,
|
|
Colorspace,
|
|
|
|
+ ExifEntity,
|
|
SystemConfigKey,
|
|
SystemConfigKey,
|
|
ToneMapping,
|
|
ToneMapping,
|
|
TranscodeHWAccel,
|
|
TranscodeHWAccel,
|
|
@@ -204,6 +205,25 @@ describe(MediaService.name, () => {
|
|
|
|
|
|
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id/as/se');
|
|
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id/as/se');
|
|
expect(mediaMock.resize).toHaveBeenCalledWith('/original/path.jpg', 'upload/thumbs/user-id/as/se/asset-id.jpeg', {
|
|
expect(mediaMock.resize).toHaveBeenCalledWith('/original/path.jpg', 'upload/thumbs/user-id/as/se/asset-id.jpeg', {
|
|
|
|
+ size: 1440,
|
|
|
|
+ format: 'jpeg',
|
|
|
|
+ quality: 80,
|
|
|
|
+ colorspace: Colorspace.SRGB,
|
|
|
|
+ });
|
|
|
|
+ expect(assetMock.save).toHaveBeenCalledWith({
|
|
|
|
+ id: 'asset-id',
|
|
|
|
+ resizePath: 'upload/thumbs/user-id/asset-id.jpeg',
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ it('should generate a P3 thumbnail for a wide gamut image', async () => {
|
|
|
|
+ assetMock.getByIds.mockResolvedValue([
|
|
|
|
+ { ...assetStub.image, exifInfo: { profileDescription: 'Adobe RGB', bitsPerSample: 14 } as ExifEntity },
|
|
|
|
+ ]);
|
|
|
|
+ await sut.handleGenerateJpegThumbnail({ id: assetStub.image.id });
|
|
|
|
+
|
|
|
|
+ expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id');
|
|
|
|
+ expect(mediaMock.resize).toHaveBeenCalledWith('/original/path.jpg', 'upload/thumbs/user-id/asset-id.jpeg', {
|
|
size: 1440,
|
|
size: 1440,
|
|
format: 'jpeg',
|
|
format: 'jpeg',
|
|
quality: 80,
|
|
quality: 80,
|
|
@@ -287,7 +307,7 @@ describe(MediaService.name, () => {
|
|
format: 'webp',
|
|
format: 'webp',
|
|
size: 250,
|
|
size: 250,
|
|
quality: 80,
|
|
quality: 80,
|
|
- colorspace: Colorspace.P3,
|
|
|
|
|
|
+ colorspace: Colorspace.SRGB,
|
|
});
|
|
});
|
|
expect(assetMock.save).toHaveBeenCalledWith({
|
|
expect(assetMock.save).toHaveBeenCalledWith({
|
|
id: 'asset-id',
|
|
id: 'asset-id',
|
|
@@ -296,6 +316,22 @@ describe(MediaService.name, () => {
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
|
|
|
|
+ it('should generate a P3 thumbnail for a wide gamut image', async () => {
|
|
|
|
+ assetMock.getByIds.mockResolvedValue([
|
|
|
|
+ { ...assetStub.image, exifInfo: { profileDescription: 'Adobe RGB', bitsPerSample: 14 } as ExifEntity },
|
|
|
|
+ ]);
|
|
|
|
+ await sut.handleGenerateWebpThumbnail({ id: assetStub.image.id });
|
|
|
|
+
|
|
|
|
+ expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id');
|
|
|
|
+ expect(mediaMock.resize).toHaveBeenCalledWith('/original/path.jpg', 'upload/thumbs/user-id/asset-id.webp', {
|
|
|
|
+ format: 'webp',
|
|
|
|
+ size: 250,
|
|
|
|
+ quality: 80,
|
|
|
|
+ colorspace: Colorspace.P3,
|
|
|
|
+ });
|
|
|
|
+ expect(assetMock.save).toHaveBeenCalledWith({ id: 'asset-id', webpPath: 'upload/thumbs/user-id/asset-id.webp' });
|
|
|
|
+ });
|
|
|
|
+
|
|
describe('handleGenerateThumbhashThumbnail', () => {
|
|
describe('handleGenerateThumbhashThumbnail', () => {
|
|
it('should skip thumbhash generation if asset not found', async () => {
|
|
it('should skip thumbhash generation if asset not found', async () => {
|
|
assetMock.getByIds.mockResolvedValue([]);
|
|
assetMock.getByIds.mockResolvedValue([]);
|
|
@@ -1539,4 +1575,51 @@ describe(MediaService.name, () => {
|
|
},
|
|
},
|
|
);
|
|
);
|
|
});
|
|
});
|
|
|
|
+
|
|
|
|
+ describe('isSRGB', () => {
|
|
|
|
+ it('should return true for srgb colorspace', () => {
|
|
|
|
+ const asset = { ...assetStub.image, exifInfo: { colorspace: 'sRGB' } as ExifEntity };
|
|
|
|
+ expect(sut.isSRGB(asset)).toEqual(true);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ it('should return true for srgb profile description', () => {
|
|
|
|
+ const asset = { ...assetStub.image, exifInfo: { profileDescription: 'sRGB v1.31' } as ExifEntity };
|
|
|
|
+ expect(sut.isSRGB(asset)).toEqual(true);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ it('should return true for 8-bit image with no colorspace metadata', () => {
|
|
|
|
+ const asset = { ...assetStub.image, exifInfo: { bitsPerSample: 8 } as ExifEntity };
|
|
|
|
+ expect(sut.isSRGB(asset)).toEqual(true);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ it('should return true for image with no colorspace or bit depth metadata', () => {
|
|
|
|
+ const asset = { ...assetStub.image, exifInfo: {} as ExifEntity };
|
|
|
|
+ expect(sut.isSRGB(asset)).toEqual(true);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ it('should return false for non-srgb colorspace', () => {
|
|
|
|
+ const asset = { ...assetStub.image, exifInfo: { colorspace: 'Adobe RGB' } as ExifEntity };
|
|
|
|
+ expect(sut.isSRGB(asset)).toEqual(false);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ it('should return false for non-srgb profile description', () => {
|
|
|
|
+ const asset = { ...assetStub.image, exifInfo: { profileDescription: 'sP3C' } as ExifEntity };
|
|
|
|
+ expect(sut.isSRGB(asset)).toEqual(false);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ it('should return false for 16-bit image with no colorspace metadata', () => {
|
|
|
|
+ const asset = { ...assetStub.image, exifInfo: { bitsPerSample: 16 } as ExifEntity };
|
|
|
|
+ expect(sut.isSRGB(asset)).toEqual(false);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ it('should return true for 16-bit image with sRGB colorspace', () => {
|
|
|
|
+ const asset = { ...assetStub.image, exifInfo: { colorspace: 'sRGB', bitsPerSample: 16 } as ExifEntity };
|
|
|
|
+ expect(sut.isSRGB(asset)).toEqual(true);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ it('should return true for 16-bit image with sRGB profile', () => {
|
|
|
|
+ const asset = { ...assetStub.image, exifInfo: { profileDescription: 'sRGB', bitsPerSample: 16 } as ExifEntity };
|
|
|
|
+ expect(sut.isSRGB(asset)).toEqual(true);
|
|
|
|
+ });
|
|
|
|
+ });
|
|
});
|
|
});
|