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

Handle PNG alpha #21

Open
zimonitrome opened this issue Jun 15, 2023 · 2 comments
Open

Handle PNG alpha #21

zimonitrome opened this issue Jun 15, 2023 · 2 comments

Comments

@zimonitrome
Copy link

Hello,

Love this package.
My only issue is that alpha channel in png images are treated as #ffffff white, so doing a trace on a png image with white in it will treat the two colors the same. Preferably I would only want to trace the outline of the PNG (i.e. only use the alpha channel).

Is there a way to do this or could it be added?

@stemaDev
Copy link

with using "sharp" package, you can extract alpha channel and run trace only on that.

        const imgBuffer = await sharp(imagePath).extractChannel("alpha").negate().png().toBuffer()
        potrace.trace(imgBuffer, {}, (_, svg) => {
            fs.writeFileSync('./output.svg', svg)
        })

I just started using this potrace, I'm very happy that it exists, I still have to make change the stroke color and have fill to be "none"

@zimonitrome
Copy link
Author

Sharp seems nice, but I didn't manage to get it working client side.

Instead, I wrote my own "getAlpha" function which is probably slow since it uses canvases:

async function getAlpha(src: string): Promise<string> {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.crossOrigin = "Anonymous";
    img.onload = () => {
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      if (!ctx) {
        reject('Could not get canvas context');
        return;
      }

      canvas.width = img.width;
      canvas.height = img.height;

      ctx.drawImage(img, 0, 0);
      const imageData = ctx.getImageData(0, 0, img.width, img.height);
      const data = imageData.data;

      // Invert alpha and convert to grayscale
      for (let i = 0; i < data.length; i += 4) {
        const invertedAlpha = 255 - data[i + 3];
        data[i] = invertedAlpha; // Copy the alpha value to the red channel
        data[i + 1] = invertedAlpha; // Copy the alpha value to the green channel
        data[i + 2] = invertedAlpha; // Copy the alpha value to the blue channel
        // Set alpha channel to fully opaque
        data[i + 3] = 255;
      }

      ctx.putImageData(imageData, 0, 0);

      // Convert the canvas to a data URL
      resolve(canvas.toDataURL('image/png'));
    };

    img.onerror = (error) => reject(error);
    img.src = src;
  });
}

Usage:

        const imgBuffer = await getAlpha(imagePath);
        potrace.trace(imgBuffer, {}, (_, svg) => {
            fs.writeFileSync('./output.svg', svg)
        })

But I would still prefer if potrace could do this internally.

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

No branches or pull requests

2 participants