Einzelne Pixel unsichtbar machen

sebbi1234

Grünschnabel
Hallo,

ich habe über ein ImageIcon ein Bild in ein JLabel geladen. Da diese Bild kreisförmig ist und über ein anderes Bild fliegen soll, stört selbstverständlich der eckige Rand. Jetzt frage ich mich, ob es möglich ist, festzulegen, dass bestimmte Pixel im JLabel unsichtbar sind, und sich somit dem Hintergrundbild an den betreffenen Stellen anpassen, während das eigentliche Bild dann weiterhin dargestellt wird.

Wenns da ne Möglichkeit gibt würde ich mich über Antworten freuen. Danke!

Gruß
 
Hallo,

schau mal hier:
Java:
/**
 * 
 */
package de.tutorials;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
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.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

/**
 * @author Tom
 */
public class TransparentImageExample extends JFrame {

  Image image;


  public TransparentImageExample() {
    super("TransparentImageExample");
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    try {
      BufferedImage tmp = ImageIO.read(new File("c:/tmp/tom_small.jpg"));
      final ColorRange range = new ColorRange(160, 255, 0, 70, 0, 70);

      ImageFilter transparencyFilter = new RGBImageFilter() {
        public final int filterRGB(int x, int y, int rgb) {
          if (range.contains(rgb | 0xFF000000)) {
            return 0x00FFFFFF & rgb;
          } else {
            return rgb;
          }
        }
      };
      ImageProducer imageProducer = new FilteredImageSource(tmp.getSource(), transparencyFilter);
      image = Toolkit.getDefaultToolkit().createImage(imageProducer);

    } catch (IOException e) {
      e.printStackTrace();
    }

    setSize(400, 300);
    setVisible(true);
  }


  @Override
  public void paint(Graphics g) {
    super.paint(g);
    if (null != image) {
      g.drawImage(image, 50, 50, null);
    }
  }


  /**
   * @param args
   */
  public static void main(String[] args) {
    new TransparentImageExample();
  }

  static class ColorRange {

    int redStart;
    int redEnd;
    int greenStart;
    int greenEnd;
    int blueStart;
    int blueEnd;


    public ColorRange(int redStart, int redEnd, int greenStart, int greenEnd, int blueStart, int blueEnd) {
      this.redStart = redStart;
      this.redEnd = redEnd;
      this.greenStart = greenStart;
      this.greenEnd = greenEnd;
      this.blueStart = blueStart;
      this.blueEnd = blueEnd;
    }


    public boolean contains(int rgb) {
      Color color = new Color(rgb);
      return isInRange(color.getRed(), redStart, redEnd) && isInRange(color.getGreen(), greenStart, greenEnd)
        && isInRange(color.getBlue(), blueStart, blueEnd);
    }


    private boolean isInRange(int value, int start, int end) {
      return value >= start && value <= end;
    }
  }
}

Ging IMHO aber auch über eine entsprechende ConvolveOp
http://java.sun.com/javase/6/docs/technotes/guides/2d/spec/j2d-image.html#wp63208

Gruß Tom
 

Anhänge

  • tom_small.jpg
    tom_small.jpg
    8,4 KB · Aufrufe: 287
  • tom_red_transparent.jpg
    tom_red_transparent.jpg
    3,5 KB · Aufrufe: 293
Danke schon mal für die Antworten.

Thomas, um ganz ehrlich zu sein kapier ich den Quelltext und die Erklärung auf der Seite nicht ganz.

Was ich noch zu meiner Frage hinzufügen sollte ist, dass die Anteile, bei dem Bild, das ich teilweise transparten machen möchte, alle die gleiche Farbe haben. Wie auf dem hier angehängten Bild möchte ich alle Pixel mit dem RGB-Code 238,238,238 durch transparente Pixel ersetzen.

Gibt es da keine einfachere Methode?

Gruß
Sebastian
 

Anhänge

  • eurofighter.jpg
    eurofighter.jpg
    19,3 KB · Aufrufe: 94
Hallo,

schau mal hier:
Java:
/**
 * 
 */
package de.tutorials;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
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.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

/**
 * @author Tom
 */
public class TransparentImageExample extends JFrame {

  Image image;


  public TransparentImageExample() {
    super("TransparentImageExample");
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    try {
      BufferedImage tmp = ImageIO.read(new File("c:/tmp/eurofighter.jpg"));
      Color color = new Color(238, 238, 238);
      final int referenceRgb = color.getRGB();
      ImageFilter transparencyFilter = new RGBImageFilter() {
        public final int filterRGB(int x, int y, int rgb) {
          if (referenceRgb == (rgb | 0xFF000000)) {
            return 0x00FFFFFF & rgb;
          } else {
            return rgb;
          }
        }
      };
      ImageProducer imageProducer = new FilteredImageSource(tmp.getSource(), transparencyFilter);
      image = Toolkit.getDefaultToolkit().createImage(imageProducer);

    } catch (IOException e) {
      e.printStackTrace();
    }

    setSize(400, 300);
    setVisible(true);
  }


  @Override
  public void paint(Graphics g) {
    super.paint(g);
    g.setColor(Color.ORANGE);
    g.fillRect(0, 0, getWidth(), getHeight());
    if (null != image) {
      g.drawImage(image, 50, 50, null);
    }
  }


  /**
   * @param args
   */
  public static void main(String[] args) {
    new TransparentImageExample();
  }
}

Nur diese eine Farbe zu ersetzen reicht leider nicht, da sich die RGB Werte vor allen an den Objekträndern ein wenig "verzerren". Hier kannst du aber dann mit der oben gezeigten ColorRange arbeiten.

Gruß Tom
 

Anhänge

  • eurofighter_trans.jpg
    eurofighter_trans.jpg
    4,3 KB · Aufrufe: 28
Oder direkt ein png benutzen. Kommt aufs gleiche raus:

Java:
/**
 * 
 */
package de.tutorials;

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Image;
import java.awt.Toolkit;
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.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;

public class Transparency {

	public static void main(String[] args) {
		JFrame window = new JFrame("Transparency");
		window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		window.setLayout(new FlowLayout( ));

		JLabel jpgLabel = new JLabel("jpg", new ImageIcon("eurofighter.jpg"),
				SwingConstants.CENTER);
		jpgLabel.setBackground(Color.RED);
		jpgLabel.setOpaque(true);
		window.getContentPane( ).add(jpgLabel);

		JLabel pngLabel = new JLabel("png", new ImageIcon("eurofighter.png"),
				SwingConstants.CENTER);
		pngLabel.setBackground(Color.RED);
		pngLabel.setOpaque(true);
		window.getContentPane( ).add(pngLabel);

		BufferedImage tmp;
		try {
			tmp = ImageIO.read(new File("eurofighter.jpg"));
			final ColorRange range = new ColorRange(238, 238, 238, 238, 238,
					238);

			ImageFilter transparencyFilter = new RGBImageFilter( ) {

				public final int filterRGB(int x, int y, int rgb) {
					if (range.contains(rgb | 0xFF000000)) {
						return 0x00FFFFFF & rgb;
					}
					else {
						return rgb;
					}
				}
			};
			ImageProducer imageProducer = new FilteredImageSource(tmp
					.getSource( ), transparencyFilter);
			Image filtered = Toolkit.getDefaultToolkit( ).createImage(
					imageProducer);

			JLabel filteredLabel = new JLabel("filtered", new ImageIcon(
					filtered), SwingConstants.CENTER);
			filteredLabel.setBackground(Color.RED);
			filteredLabel.setOpaque(true);
			window.getContentPane( ).add(filteredLabel);
		}
		catch (IOException e) {
			e.printStackTrace( );
		}

		window.setSize(300, 300);
		window.pack( );
		window.setVisible(true);
	}

	static class ColorRange {

		int redStart;
		int redEnd;
		int greenStart;
		int greenEnd;
		int blueStart;
		int blueEnd;

		public ColorRange(int redStart, int redEnd, int greenStart,
				int greenEnd, int blueStart, int blueEnd) {
			this.redStart = redStart;
			this.redEnd = redEnd;
			this.greenStart = greenStart;
			this.greenEnd = greenEnd;
			this.blueStart = blueStart;
			this.blueEnd = blueEnd;
		}

		public boolean contains(int rgb) {
			Color color = new Color(rgb);
			return isInRange(color.getRed( ), redStart, redEnd)
					&& isInRange(color.getGreen( ), greenStart, greenEnd)
					&& isInRange(color.getBlue( ), blueStart, blueEnd);
		}

		private boolean isInRange(int value, int start, int end) {
			return value >= start && value <= end;
		}
	}
}
 

Anhänge

  • result.jpg
    result.jpg
    11,3 KB · Aufrufe: 57
Vielen Dank für eure Antworten. Ich hab das jetzt soweit in mein Programm eingefügt, dass ich den Hintergrund des Flugzeugs also in alle Farben umwandeln kann. Wie schaffe ich es jetzt aber diesen Bereich, den ich über setBackground(Color.Green) z.B. grün machen kann nun transparent zu bekommen. Ich nehm mal an dafür muss ich Color.Translucent verwenden, oder? Wenn ich jedoch
filteredLabel.setBackground(Color.Translucent);
benutze funktioniert das jedoch nicht. Da man ja den Transparenzwert noch angeben muss kann es ja auch nicht funktionieren. Wie aber gibt man es dann korrekt an, so dass der Bereich vollkommen transparent wird?

Viele Grüße
Sebastian
 
Zurück