sharp
sharp copied to clipboard
composing an image from multiple channels data
What are you trying to achieve? Extracting channels from an image, and re-composing them into a different setup
Have you searched for similar questions? yes
Are you able to provide a standalone code sample that demonstrates this question? yes
Are you able to provide a sample image that helps explain the question? no
I'm not sure if this is something that would warrant a new feature being added, or just some clarification to the documentation, but it took me quite some time (actually reading the test suite, rather than the documentation) to figure out that joinChannel keeps adding new channels to a file, despite the documentation appearing to suggest that if you give it an array form, it might replace/overwrite the channels, since you can specify [ red, green, blue, alpha ] format if your image is RGB.
That is clearly not how it works after reading the test suite.
Perhaps a "replaceChannel" function, or just explaining in joinChannel, that if you want to replace channels, you'll need to compose them together starting from a single channel image.
This is not ultimately, what my code will look like, i was just trying to get a 1:1 copy of the original image, and it took quite a while to figure out that this was the way. It extracts all the channels from a RGBA image, and then recomposes them back into the same image. Ultimately, it will end up taking the 4 channels from one image, and outputting them into different images in a different combination.
const width = 64;
const height = 64;
const source = sharp({
create: {
width,
height,
channels: 4,
background: {
r: 0,
g: 127,
b: 225,
alpha: 1.0,
},
},
}).png();
const sourceData = await source.toBuffer();
source.toFile('./source1.png');
const r = sharp(sourceData).extractChannel('red').toColorspace('b-w');
const g = sharp(sourceData).extractChannel('green').toColorspace('b-w');
const b = sharp(sourceData).extractChannel('blue').toColorspace('b-w');
const a = sharp(sourceData).extractChannel(3).toColorspace('b-w');
const rd = await r.raw().toBuffer({ resolveWithObject: true });
const gd = await g.raw().toBuffer({ resolveWithObject: true });
const bd = await b.raw().toBuffer({ resolveWithObject: true });
const ad = await a.raw().toBuffer({ resolveWithObject: true });
console.warn(rd, gd, bd, ad);
const dest = sharp(rd.data, { raw: { width, height, channels: 1 } });
dest.joinChannel([ gd.data, bd.data, ad.data ], { raw: { width, height, channels: 1 }}).png().toFile('./dest.png');
The JSDocs for joinChannel
could definitely benefit from some examples to help clarify its use. Happy to accept a PR if you're able.
https://github.com/lovell/sharp/blob/master/lib/channel.js#L80
/cc @mhirsch
I'm not sure that i'm well qualified enough to improve the doc based just on what I learned from getting what I needed to work... i know enough about it now to get what I needed, but not sure that's comprehensive enough to do it better.
The application I have in mind involves processing photo's from an infrared camera. A common transformation is to swap the red and blue channels. I tried reading the documentation, it seems like that should be possible, but there isn't enough there to explain how to get there.