Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace Color with transparency #1648

Closed
yasso1am opened this issue Apr 5, 2019 · 7 comments
Closed

Replace Color with transparency #1648

yasso1am opened this issue Apr 5, 2019 · 7 comments
Milestone

Comments

@yasso1am
Copy link

yasso1am commented Apr 5, 2019

What are you trying to achieve?

I have a known rgb value that surrounds the screenshot I am taking, and would like to replace it with a white, fully transparent background. I have not seen examples of how to do this.

Have you searched for similar questions?

Yes. It seems most people want to take a transparent background and provide it with a color. I am looking to take a known color and change it, as well as make it transparent.

Are you able to provide a standalone code sample that demonstrates this question?

const trimWhiteSpaceAndPad = (path) => {
    sharp(path)
    .trim()
    .resize(175, 180, {
        fit: 'contain',
        background: {
            r: 225,
            g: 227,
            b: 237,
        }
    })
    .extend({
        left: 5,
        right: 5,
        top: 0,
        bottom: 0,
        background: {
            r: 225,
            g: 227,
            b: 237,
            alpha: 0
        }
    })
    .toFile(`trimmed_${path}`, (err) => {
            err && console.log('Error trimming file:' + err)
        })
}

Are you able to provide a sample image that helps explain the question?

I would like to be able to take all of the off-white (225,227,237) area that edges up against the model of these teeth and turn it white and transparent. I acquired this photo with the code above.

Here is my input file:

beforeLower-6caee480-ab4e-11e8-a183-6d4ab07faa80

Here is my output file:

trimmed_beforeLower-6caee480-ab4e-11e8-a183-6d4ab07faa80

I would like if all the outside area was transparent. It would be great if I could call something like

.replace({ input: {// color I want to replace here}, output: {// color I want it to be} })

@lovell
Copy link
Owner

lovell commented Apr 5, 2019

Hello, although libvips provides some "flood fill" features, they are not yet exposed in sharp. I'll tag this as a future possible enhancement.

For now your best bet is to use raw pixel output then loop over and selectively replace values.

@yasso1am
Copy link
Author

yasso1am commented Apr 8, 2019

Hello, although libvips provides some "flood fill" features, they are not yet exposed in sharp. I'll tag this as a future possible enhancement.

For now your best bet is to use raw pixel output then loop over and selectively replace values.

lovell <- thank you so much for your quick response! I wasn't sure how to implement your suggestion, but it lead me to a new line of questioning and I ended up using the following package: https://github.com/turakvlad/replace-color

Perhaps it can be of use to you if building out this enhancement. I really appreciate all your awesome work and the use of your package!

@daton89
Copy link

daton89 commented Feb 2, 2020

I'm also looking forward to add the floodfill feature to this labrary, I was about to move from ImageMagick to Sharp, but without this feature I can't.
I would also help to have this feature!

@hengkx
Copy link

hengkx commented Jun 9, 2020

Any progress?

@BH4HPA
Copy link

BH4HPA commented Feb 28, 2023

For now your best bet is to use raw pixel output then loop over and selectively replace values.

thanks for providing an available idea
here's a possible solution for replacing the white color with transparency:

const HEX = '0123456789ABCDEF';
const toHex = (value: number) => {
  let rtn = '';
  while (value !== 0)
    rtn = HEX[value % 16] + rtn, value = Math.floor(value / 16);
  return rtn;
}
const { data, info } = await origImg
  .raw()
  .toBuffer({ resolveWithObject: true });
for (let i = 0; i < data.length; i += 4)
  if (`#${toHex(data[i])}${toHex(data[i + 1])}${toHex(data[i + 2])}` === '#FFFFFF')
    data[i + 3] = 0;
const alphaImg = sharp(data, {
  raw: {
    width: info.width,
    height: info.height,
    channels: 4
  }
}).toFormat('png').toBuffer();

@lovell lovell added this to the v0.32.1 milestone Apr 7, 2023
@lovell
Copy link
Owner

lovell commented Apr 27, 2023

v0.32.1 now available with unflatten() operation - see https://sharp.pixelplumbing.com/api-operation#unflatten

PRs with further enhancements to this experimental feature are welcome.

@vanling
Copy link

vanling commented Jan 5, 2025

@lovell What needs to happen to get this out of the 'experimental feature' status?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants