diff --git a/src/magick-image.ts b/src/magick-image.ts index 9bec3de..ce26428 100644 --- a/src/magick-image.ts +++ b/src/magick-image.ts @@ -1691,6 +1691,24 @@ export interface IMagickImage extends IDisposable { */ strip(): void; + /** + * Transforms the image from the colorspace of the source profile to the target profile. This + * requires the image to have a color profile. Nothing will happen if the image has no color profile. + * @param target The target color profile. + * @returns A value indicating whether the transformation was successful. + */ + transformColorSpace(target: IColorProfile): boolean; + + /** + * Transforms the image from the colorspace of the source profile to the target profile. The + * source profile will only be used if the image does not contain a color profile. Nothing + * will happen if the source profile has a different colorspace then that of the image. + * @param source The source color profile. + * @param target The target color profile. + * @returns A value indicating whether the transformation was successful. + */ + transformColorSpace(source: IColorProfile, target: IColorProfile): boolean; + /** * Threshold image. * @param percentage The threshold percentage. @@ -3241,6 +3259,34 @@ export class MagickImage extends NativeInstance implements IMagickImage { }); } + transformColorSpace(target: IColorProfile): boolean; + transformColorSpace(source: IColorProfile, target: IColorProfile): boolean; + transformColorSpace(sourceOrTarget: IColorProfile, targetOrUndefined?: IColorProfile): boolean { + const source = sourceOrTarget; + let target: IColorProfile | undefined = undefined; + if (targetOrUndefined !== undefined) + target = targetOrUndefined; + + const hasColorProfile = this.hasProfile('icc') || this.hasProfile('icm'); + if (target === undefined) { + if (!hasColorProfile) + return false; + + target = source; + } + else { + if (source.colorSpace !== this.colorSpace) + return false; + + if (!hasColorProfile) + this.setProfile(source); + } + + this.setProfile(target); + + return true; + } + threshold(percentage: Percentage): void threshold(percentage: Percentage, channels: Channels): void threshold(percentage: Percentage, channelsOrUndefined?: Channels): void { diff --git a/tests/magick-image/transform-color-space.spec.ts b/tests/magick-image/transform-color-space.spec.ts new file mode 100644 index 0000000..2c3bb86 --- /dev/null +++ b/tests/magick-image/transform-color-space.spec.ts @@ -0,0 +1,42 @@ +/* + Copyright Dirk Lemstra https://github.com/dlemstra/magick-wasm. + Licensed under the Apache License, Version 2.0. +*/ + +import { TestFiles } from '@test/test-files'; + +describe('MagickImage#transformColorSpace', () => { + it('should return false when the image has no color profile', () => { + TestFiles.Images.Builtin.logo.use((image) => { + const target = TestFiles.Profiles.Color.sRGB.load(); + const result = image.transformColorSpace(target); + expect(result).toBe(false); + }); + }); + + it('should use the color profile of the image', () => { + TestFiles.Images.fujiFilmFinePixS1ProJpg.use((image) => { + const target = TestFiles.Profiles.Color.USWebCoatedSWOP.load(); + const result = image.transformColorSpace(target); + expect(result).toBe(true); + }); + }); + + it('should return false when the source profile color space is different', () => { + TestFiles.Images.fujiFilmFinePixS1ProJpg.use((image) => { + const source = TestFiles.Profiles.Color.USWebCoatedSWOP.load(); + const target = TestFiles.Profiles.Color.sRGB.load(); + const result = image.transformColorSpace(source, target); + expect(result).toBe(false); + }); + }); + + it('should return true when the the colorspace could be transformed', () => { + TestFiles.Images.fujiFilmFinePixS1ProJpg.use((image) => { + const source = TestFiles.Profiles.Color.sRGB.load(); + const target = TestFiles.Profiles.Color.USWebCoatedSWOP.load(); + const result = image.transformColorSpace(source, target); + expect(result).toBe(true); + }); + }); +});