web-dev-qa-db-fra.com

Comment rendre une couleur transparente dans une BufferedImage et l'enregistrer au format PNG

J'ai cherché sur le Web pour cela, mais je n'ai trouvé aucune aide décente.

J'ai un BufferedImage, que j'ai lu avec ImageIO. Maintenant, je voudrais rendre une certaine couleur de cette image transparente et enregistrer l'image au format PNG.

Je sais que je ne peux pas simplement "peindre" la couleur transparente pour des raisons évidentes, donc je suppose que j'ai besoin d'une sorte de filtre.

Quelqu'un a obtenu un exemple de code pour cela?

24
corgrath

Je l'ai fait récemment, pour répondre à une question de mon chef de projet.
La fonction transformant le gris en transparence est:

  private Image TransformGrayToTransparency(BufferedImage image)
  {
    ImageFilter filter = new RGBImageFilter()
    {
      public final int filterRGB(int x, int y, int rgb)
      {
        return (rgb << 8) & 0xFF000000;
      }
    };

    ImageProducer ip = new FilteredImageSource(image.getSource(), filter);
    return Toolkit.getDefaultToolkit().createImage(ip);
  }

En fait, il agit sur une image de niveau de gris, donc je copie simplement un composant RVB (le R) en alpha, en éliminant les autres qui sont identiques dans mon cas.
Vous pouvez l'adapter pour filtrer une couleur spécifique, par exemple. avec un test d'égalité ou de plage, etc.
Bien sûr, BufferedImage doit être de type BufferedImage.TYPE_INT_ARGB.

Je n'aborde pas la question de l'enregistrement, car c'est assez trivial, mais je peux également ajouter cette page de code.

[EDIT] Pour convertir l'image en BufferedImage:

BufferedImage dest = new BufferedImage(
    imageWidth, imageHeight,
    BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = dest.createGraphics();
g2.drawImage(image, 0, 0, null);
g2.dispose();

[EDIT 2] Je viens après que Christoffer a posté sa solution complète, mais voici la mienne, je montre comment rendre transparente une gamme de couleurs. Peut être amélioré, par exemple. en utilisant des composants HSB à la place.

import Java.awt.*;
import Java.awt.image.BufferedImage;
import Java.awt.image.FilteredImageSource;
import Java.awt.image.ImageFilter;
import Java.awt.image.ImageProducer;
import Java.awt.image.RGBImageFilter;
import Java.io.*;

import javax.imageio.ImageIO;

public class AddTransparency
{
  AddTransparency() throws IOException
  {
    String imagePath = "E:/Documents/images/";
    File inFile = new File(imagePath, "map.png");
    BufferedImage image = ImageIO.read(inFile);

    Image transpImg1 = TransformGrayToTransparency(image);
    BufferedImage resultImage1 = ImageToBufferedImage(transpImg1, image.getWidth(), image.getHeight());

    File outFile1 = new File(imagePath, "map_with_transparency1.png");
    ImageIO.write(resultImage1, "PNG", outFile1);

    Image transpImg2 = TransformColorToTransparency(image, new Color(0, 50, 77), new Color(200, 200, 255));
    BufferedImage resultImage2 = ImageToBufferedImage(transpImg2, image.getWidth(), image.getHeight());

    File outFile2 = new File(imagePath, "map_with_transparency2.png");
    ImageIO.write(resultImage2, "PNG", outFile2);
  }

  private Image TransformGrayToTransparency(BufferedImage image)
  {
    ImageFilter filter = new RGBImageFilter()
    {
      public final int filterRGB(int x, int y, int rgb)
      {
        return (rgb << 8) & 0xFF000000;
      }
    };

    ImageProducer ip = new FilteredImageSource(image.getSource(), filter);
      return Toolkit.getDefaultToolkit().createImage(ip);
  }

  private Image TransformColorToTransparency(BufferedImage image, Color c1, Color c2)
  {
    // Primitive test, just an example
    final int r1 = c1.getRed();
    final int g1 = c1.getGreen();
    final int b1 = c1.getBlue();
    final int r2 = c2.getRed();
    final int g2 = c2.getGreen();
    final int b2 = c2.getBlue();
    ImageFilter filter = new RGBImageFilter()
    {
      public final int filterRGB(int x, int y, int rgb)
      {
        int r = (rgb & 0xFF0000) >> 16;
        int g = (rgb & 0xFF00) >> 8;
        int b = rgb & 0xFF;
        if (r >= r1 && r <= r2 &&
            g >= g1 && g <= g2 &&
            b >= b1 && b <= b2)
        {
          // Set fully transparent but keep color
          return rgb & 0xFFFFFF;
        }
        return rgb;
      }
    };

    ImageProducer ip = new FilteredImageSource(image.getSource(), filter);
      return Toolkit.getDefaultToolkit().createImage(ip);
  }

  private BufferedImage ImageToBufferedImage(Image image, int width, int height)
  {
    BufferedImage dest = new BufferedImage(
        width, height, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2 = dest.createGraphics();
    g2.drawImage(image, 0, 0, null);
    g2.dispose();
    return dest;
  }

  public static void main(String[] args) throws IOException
  {
    AddTransparency at = new AddTransparency();
  }
}
41
PhiLho

Merci à PhilLo voici une solution complète de mon application de démonstration.

public static void main(String[] args) throws Exception {

        File in = new File("C:\\Users\\Christoffer\\Desktop\\christoffer.jpg");
        BufferedImage source = ImageIO.read(in);

        int color = source.getRGB(0, 0);

        Image image = makeColorTransparent(source, new Color(color));

        BufferedImage transparent = imageToBufferedImage(image);

        File out = new File("C:\\Users\\Christoffer\\Desktop\\trans.PNG");
        ImageIO.write(transparent, "PNG", out);

    }

    private static BufferedImage imageToBufferedImage(Image image) {

        BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = bufferedImage.createGraphics();
        g2.drawImage(image, 0, 0, null);
        g2.dispose();

        return bufferedImage;

    }

    public static Image makeColorTransparent(BufferedImage im, final Color color) {
        ImageFilter filter = new RGBImageFilter() {

            // the color we are looking for... Alpha bits are set to opaque
            public int markerRGB = color.getRGB() | 0xFF000000;

            public final int filterRGB(int x, int y, int rgb) {
                if ((rgb | 0xFF000000) == markerRGB) {
                    // Mark the alpha bits as zero - transparent
                    return 0x00FFFFFF & rgb;
                } else {
                    // nothing to do
                    return rgb;
                }
            }
        };

        ImageProducer ip = new FilteredImageSource(im.getSource(), filter);
        return Toolkit.getDefaultToolkit().createImage(ip);
    }
17
corgrath