2009-03-20 23 views
24

He estado buscando en la web para esto, pero no he encontró ninguna ayuda decente.Cómo hacer que un color transparente en un BufferedImage y guardar como PNG

Tengo un BufferedImage, lo que he leído en la ImageIO. Ahora me gustaría hacer que un determinado color en esa imagen sea transparente y guardar la imagen como PNG.

Yo sé que no puedo simplemente "pintar" el color transparente por razones obvias, así que supongo que necesito algún tipo de filtro.

¿Alguien tiene un código de muestra para esto?

Respuesta

39

lo hice hace poco, para responder a una pregunta de mi jefe de proyecto.
La función de la transformación de color gris a la transparencia es:

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 realidad, actúa una imagen de nivel gris en, por lo que sólo copiar un componente RGB (el R uno) a alfa, desechando los otros que son idénticos en mi caso.
Puede adaptarlo para filtrar un color específico, ej. con una prueba de igualdad o rango, etc.
Por supuesto, BufferedImage debe ser del tipo BufferedImage.TYPE_INT_ARGB.

que no abordan la cuestión de ahorro, ya que es bastante trivial, pero puedo añadir esta página de códigos también.

[Editar] para convertir una imagen a 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] Vengo después de Christoffer publicó su solución completa, pero aquí es mío, me muestran cómo hacer una gama de colores transparentes. Se puede mejorar, por ej. utilizando componentes HSB en su lugar.

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(); 
    } 
} 
+0

Hi PhiLho. ¿Eso significa que ahora puede responder a http://stackoverflow.com/questions/266486/in-java-how-do-you-write-a-java-awt-image-bufferedimage-to-an-8-bit-png -archivo ? ¿O esas dos preguntas no están relacionadas? – VonC

+0

Ok, entonces obtengo una Imagen, pero no puedo guardar Imágenes con ImageIO.write. Tengo que convertir una imagen a BufferedImage? Debe haber una manera más simple. – corgrath

+0

Si tiene un código de ejemplo sobre cómo guardar la imagen, o cualquier otra cosa elegante que pueda hacer con la imagen, sería increíble. – corgrath

16

Gracias a PhilLo aquí hay una solución completa de mi aplicación de demostración.

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); 
    } 
+0

Genial. Sin embargo, debe seleccionar la respuesta de PhiLho como la "oficial" (o al menos darle un voto favorable); – VonC

+0

Bueno, publiqué mi propio código de demostración, mostrando un filtro alternativo. – PhiLho

+0

Hecho. Creo que la respuesta de philhos seleccionada es la correcta. – corgrath

Cuestiones relacionadas