mirror of
https://github.com/lovell/sharp.git
synced 2025-12-06 03:51:40 +01:00
Simplify ICC processing when retaining input profiles #4468
Takes advantage of libvips' improved ICC handling
This commit is contained in:
parent
4f9f8179a6
commit
e1628d8ef5
@ -201,7 +201,7 @@ const dataWithMergedExif = await sharp(inputWithExif)
|
|||||||
|
|
||||||
Keep ICC profile from the input image in the output image.
|
Keep ICC profile from the input image in the output image.
|
||||||
|
|
||||||
For non-RGB output use [toColourspace](/api-colour/#tocolourspace).
|
When input and output colour spaces differ, use with [toColourspace](/api-colour/#tocolourspace) and optionally [pipelineColourspace](/api-colour/#pipelinecolourspace).
|
||||||
|
|
||||||
|
|
||||||
**Since**: 0.33.0
|
**Since**: 0.33.0
|
||||||
@ -211,6 +211,14 @@ const outputWithIccProfile = await sharp(inputWithIccProfile)
|
|||||||
.keepIccProfile()
|
.keepIccProfile()
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
```
|
```
|
||||||
|
**Example**
|
||||||
|
```js
|
||||||
|
const cmykOutputWithIccProfile = await sharp(cmykInputWithIccProfile)
|
||||||
|
.pipelineColourspace('cmyk')
|
||||||
|
.toColourspace('cmyk')
|
||||||
|
.keepIccProfile()
|
||||||
|
.toBuffer();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## withIccProfile
|
## withIccProfile
|
||||||
|
|||||||
@ -16,3 +16,6 @@ slug: changelog/v0.34.5
|
|||||||
|
|
||||||
* Improve error messaging when only warnings issued.
|
* Improve error messaging when only warnings issued.
|
||||||
[#4465](https://github.com/lovell/sharp/issues/4465)
|
[#4465](https://github.com/lovell/sharp/issues/4465)
|
||||||
|
|
||||||
|
* Simplify ICC processing when retaining input profiles.
|
||||||
|
[#4468](https://github.com/lovell/sharp/issues/4468)
|
||||||
|
|||||||
@ -256,7 +256,7 @@ function withExifMerge (exif) {
|
|||||||
/**
|
/**
|
||||||
* Keep ICC profile from the input image in the output image.
|
* Keep ICC profile from the input image in the output image.
|
||||||
*
|
*
|
||||||
* For non-RGB output use {@link /api-colour/#tocolourspace toColourspace}.
|
* When input and output colour spaces differ, use with {@link /api-colour/#tocolourspace toColourspace} and optionally {@link /api-colour/#pipelinecolourspace pipelineColourspace}.
|
||||||
*
|
*
|
||||||
* @since 0.33.0
|
* @since 0.33.0
|
||||||
*
|
*
|
||||||
@ -265,6 +265,13 @@ function withExifMerge (exif) {
|
|||||||
* .keepIccProfile()
|
* .keepIccProfile()
|
||||||
* .toBuffer();
|
* .toBuffer();
|
||||||
*
|
*
|
||||||
|
* @example
|
||||||
|
* const cmykOutputWithIccProfile = await sharp(cmykInputWithIccProfile)
|
||||||
|
* .pipelineColourspace('cmyk')
|
||||||
|
* .toColourspace('cmyk')
|
||||||
|
* .keepIccProfile()
|
||||||
|
* .toBuffer();
|
||||||
|
*
|
||||||
* @returns {Sharp}
|
* @returns {Sharp}
|
||||||
*/
|
*/
|
||||||
function keepIccProfile () {
|
function keepIccProfile () {
|
||||||
|
|||||||
@ -797,20 +797,14 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
image = sharp::EnsureAlpha(image, baton->ensureAlpha);
|
image = sharp::EnsureAlpha(image, baton->ensureAlpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert image to sRGB, if not already
|
// Ensure output colour space
|
||||||
if (sharp::Is16Bit(image.interpretation())) {
|
if (sharp::Is16Bit(image.interpretation())) {
|
||||||
image = image.cast(VIPS_FORMAT_USHORT);
|
image = image.cast(VIPS_FORMAT_USHORT);
|
||||||
}
|
}
|
||||||
if (image.interpretation() != baton->colourspace) {
|
if (image.interpretation() != baton->colourspace) {
|
||||||
// Convert colourspace, pass the current known interpretation so libvips doesn't have to guess
|
|
||||||
image = image.colourspace(baton->colourspace, VImage::option()->set("source_space", image.interpretation()));
|
image = image.colourspace(baton->colourspace, VImage::option()->set("source_space", image.interpretation()));
|
||||||
// Transform colours from embedded profile to output profile
|
if (inputProfile.first && baton->withIccProfile.empty()) {
|
||||||
if ((baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) && baton->colourspacePipeline != VIPS_INTERPRETATION_CMYK &&
|
image = sharp::SetProfile(image, inputProfile);
|
||||||
baton->withIccProfile.empty() && sharp::HasProfile(image)) {
|
|
||||||
image = image.icc_transform(processingProfile, VImage::option()
|
|
||||||
->set("embedded", true)
|
|
||||||
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
|
||||||
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -845,8 +839,6 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
} catch(...) {
|
} catch(...) {
|
||||||
sharp::VipsWarningCallback(nullptr, G_LOG_LEVEL_WARNING, "Invalid profile", nullptr);
|
sharp::VipsWarningCallback(nullptr, G_LOG_LEVEL_WARNING, "Invalid profile", nullptr);
|
||||||
}
|
}
|
||||||
} else if (baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) {
|
|
||||||
image = sharp::SetProfile(image, inputProfile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Negate the colours in the image
|
// Negate the colours in the image
|
||||||
|
|||||||
@ -651,16 +651,27 @@ describe('Image metadata', () => {
|
|||||||
assert.strictEqual(description, 'Generic RGB Profile');
|
assert.strictEqual(description, 'Generic RGB Profile');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('keep existing ICC profile, ignore colourspace conversion', async () => {
|
it('keep existing CMYK input profile for CMYK output', async () => {
|
||||||
|
const data = await sharp(fixtures.inputJpgWithCmykProfile)
|
||||||
|
.keepIccProfile()
|
||||||
|
.toColourspace('cmyk')
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
const metadata = await sharp(data).metadata();
|
||||||
|
assert.strictEqual(metadata.channels, 4);
|
||||||
|
const { description } = icc.parse(metadata.icc);
|
||||||
|
assert.strictEqual(description, 'U.S. Web Coated (SWOP) v2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('transform with but discard existing RGB input profile for CMYK output', async () => {
|
||||||
const data = await sharp(fixtures.inputJpgWithExif)
|
const data = await sharp(fixtures.inputJpgWithExif)
|
||||||
.keepIccProfile()
|
.keepIccProfile()
|
||||||
.toColourspace('cmyk')
|
.toColourspace('cmyk')
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
|
|
||||||
const metadata = await sharp(data).metadata();
|
const metadata = await sharp(data).metadata();
|
||||||
assert.strictEqual(metadata.channels, 3);
|
assert.strictEqual(metadata.channels, 4);
|
||||||
const { description } = icc.parse(metadata.icc);
|
assert.strictEqual(metadata.icc, undefined);
|
||||||
assert.strictEqual(description, 'Generic RGB Profile');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('keep existing ICC profile, avoid colour transform', async () => {
|
it('keep existing ICC profile, avoid colour transform', async () => {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user