Transparentes Bild einfärben

_dome

Grünschnabel
Hallo zusammen,

ich möchte gern ein Bild z.b. das im Anhang mit einer beliebigen Farbe einfärben. Es soll nur der Rahmen eingefärbt werden und nicht das ganze Bild (also die ganz Transparenten stellen). Ich habe leider keine Idee wie ich das mit Java machen kann. Hab schon was von LookUpTables gelesen und auch schon ColorConvertOp aber ich weiß nicht wie ich es anstellen soll.

Code:
public BufferedImage grayOut(BufferedImage img) {
	        ColorConvertOp colorConvert = new ColorConvertOp(ColorSpace
	                .getInstance(ColorSpace.CS_GRAY),null);
	        colorConvert.filter(img, img);
Dieser Code färbt wunderbar ein Bild grau ein, aber denke, dass mir das beim Einfärben des Rahmens nicht weiter hilft.

Ich bin ganz neu im java2d Bereich. Wäre also froh, wenn mir jemand helfen könnte.


Gruß
_dome
 

Anhänge

  • outlines.png
    outlines.png
    73,4 KB · Aufrufe: 26

Maddin

Mitglied
Hi,

nur so als Gedankenanstoß.. evtl. geht's auch einfacher.

Schau dir alle Pixel des Bildes an und änder bei allen nicht-transparenten den RGB-Wert.

EDIT: Ich hab's mal probiert, das klappt ganz gut.

Gruß,
Martin
 
Zuletzt bearbeitet:

_dome

Grünschnabel
Danke für die Antwort. Habe es mal versucht, allerdings bekomme ich keine schönen Ergebnisse.
Vielleicht ein paar Tipps?

Hier mein versuch das Bild einzufärben (hier im Code rot)

Code:
public class Main
{

    /**
     * @param args
     */
    public static void main(String[] args)
    {

	BufferedImage image = null;
	BufferedImage image2 = null;

	try
	{
	    image = ImageIO.read(new File("/home/dome/Arbeitsfläche/outlines.png"));
	}
	catch (IOException ex)
	{
	    ex.printStackTrace();
	}
	if (image != null)
	{

	    image2 = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.BITMASK);

	    for (int x = 0; x < image.getWidth(); x++)
	    {
		for (int y = 0; y < image.getHeight(); y++)
		{

		    Color c = new Color(image.getRGB(x, y));

		    if (c.getAlpha() >= 0)
		    {
			int newred = 0, newgreen = 0, newblue = 0;
			int faktor_red = 50, faktor_green = -100, faktor_blue = -100;

			if (c.getRed() + faktor_red >= 0 && c.getRed() + faktor_red <= 255 && c.getGreen() + faktor_green >= 0 && c.getGreen() <= 255
				&& c.getBlue() + faktor_green >= 0 && c.getBlue() <= 255)
			{
			    newred = c.getRed() + faktor_red;
			    newgreen = c.getGreen() + faktor_green;
			    newblue = c.getBlue() + faktor_blue;
			}
			Color newcolor = new Color(newred, newgreen, newblue);
			image2.setRGB(x, y, newcolor.getRGB());

		    }
		}
	    }
	}

	try
	{
	    ImageIO.write(image2, "png", new File("/home/dome/Arbeitsfläche/outlines2.png"));
	}
	catch (IOException ex)
	{
	    ex.printStackTrace();
	}
    }
}

Ist das vom Prinzip her richtig?
Das Ergebnis ist wie schön erwähnt nicht toll:
outlines2.png
Der Hintergrund wird zudem auch von transparent zu schwarz gefärbt. Aber das ist jetzt erstmal nicht so wild. Erst sollte das mit dem Einfärben gut klappen.

Gruß
_dome

Hi,

nur so als Gedankenanstoß.. evtl. geht's auch einfacher.

Schau dir alle Pixel des Bildes an und änder bei allen nicht-transparenten den RGB-Wert.

EDIT: Ich hab's mal probiert, das klappt ganz gut.

Gruß,
Martin

Kannst du mir eventuell mal deinen Code zeigen? Oder sagen was ich noch falsch mache?

Gruß
_dome
 

Maddin

Mitglied
Mein Code ist eigentlich ziemlich ähnlich zu deinem. Ganz schön wird das Bild dadurch auch nicht, am Rand vom Rahmen sind leider ein paar unsaubere Stellen.

image.png
Code:
Java:
         BufferedImage image;
         // image = ...
         Graphics g = image.getGraphics();
		int width = image.getWidth(), height = image.getHeight();
		int[] pix = new int[width * height];
		PixelGrabber pg = new PixelGrabber(image, 0, 0, width, height, pix, 0,
				width);
		if (!pg.grabPixels())
			return null;

		for (int i = 0; i < pix.length; i++) {
			int rgb = pix[i];
			int alpha = (rgb >>> 24) & 0xFF;
			// not completely transparent
			if (alpha > 0) {
				int red = (rgb >>> 16) & 0xFF;
				int green = (rgb >>> 8) & 0xFF;
				int blue = (rgb >>> 0) & 0xFF;
				red +=50;
				if(red > 255)
					red = 255;
				Color col = new Color(red, green, blue);
				image.setRGB(i % width, i / width, col.getRGB());
			}
		}
 

_dome

Grünschnabel
Hm das ergibt alles kein schönes Ergebnis.

Neue Idee:
Wie wäre es wenn man das Transparente Bild auf eine in einer Farbe eingefärbte Fläche legt und dann die Bilder (quasi verschmelzen tut) und dann aber nur das ursprüngliche Bild also den Rahmen der nun unterlegt ist mit einer Farbe als neues Bild abspeichert? Ist das machbar und wenn ja wie?


EDIT:

Die Arbeitsschritte in GIMP wären:

- Rahmen in eine Ebene machen
- neue Ebene mit gewünschter Hintergrundfarbe einfärben
- Rahmen selektieren (also die Stellen die entfernt werden sollen)
- in der Anderen eben nun diese Selektion löschen
- Ebenen vereinen
 
Zuletzt bearbeitet:

_dome

Grünschnabel
Hab mal den Ansatz probiert mit den Bildern.
Tut im Prinzip. Das Ergebnis ist aber auch nicht ganz so schön.

Hier der Code:
Code:
  public static void main(String[] args) throws IOException
    {

	//Die Vorlage laden
	BufferedImage fahrradteil = ImageIO.read(new File("/home/dome/Arbeitsfläche/overlay.png"));
	//Bild für den Hinergrund erstellen
	BufferedImage hintergrund = new BufferedImage(fahrradteil.getWidth(), fahrradteil.getHeight(), BufferedImage.TYPE_INT_ARGB_PRE);

	Color Einfrärbfarbe = new Color(255, 0,0, 255);
	//Hintergrundbild einfärben
	for (int i = 0; i < hintergrund.getWidth(); i++)
	{
	    for (int z = 0; z < hintergrund.getHeight(); z++)
	    {		
		hintergrund.setRGB(i, z, Einfrärbfarbe.getRGB());	
	    }
	}

	//Das neue Bild erstellen was aus beiden Teilen besteht
	int w = Math.max(hintergrund.getWidth(), fahrradteil.getWidth());
	int h = Math.max(hintergrund.getHeight(), fahrradteil.getHeight());
	BufferedImage bildervereint = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE);	
	
	// Bilder vereinen
	Graphics g = bildervereint.getGraphics();
	g.drawImage(hintergrund, 0, 0, null);
	g.drawImage(fahrradteil, 0, 0, null);	
	
	//Farbe wieder entfernen
	for(int x = 0; x < bildervereint.getWidth(); x++)
	{
	    for(int y = 0; y < bildervereint.getHeight(); y++)
	    {
		Color c = new Color(bildervereint.getRGB(x, y));
		if(c.getRed() == 255)
		{
		    Color neu = new Color(0,0,0,0);
		    
		    bildervereint.setRGB(x, y, neu.getRGB());
		}
	    }
	}

	// Save as new image
	ImageIO.write(bildervereint, "PNG", new File("/home/dome/Arbeitsfläche/vereint.png"));

    }

Und hier noch das Ergebnis:
vereint.png

Eventuell liegt es auch an der Vorlage.
Eventuell hat noch jemand Anregungen?
 

_dome

Grünschnabel
Hab es jetzt so gelöst:

Code:
class Einfärber
{
    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                try
                {
                    new Einfärber(255,0,0,190);
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        });
 
    }
 
    public Einfärber(int red, int green, int blue, int alpha) throws Exception
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
        BufferedImage image = ImageIO.read(new File("/home/dome/Arbeitsfläche/rahmen.jpg"));
        JPanel panel = new JPanel(new GridLayout(1,0));
        panel.add(new JLabel(new ImageIcon(image)));       
        panel.add(new JLabel(new ImageIcon(dye(image, new Color(red,green,blue,alpha))))); 
        f.getContentPane().add(panel);
        f.pack();
        f.setVisible(true);
    }
 
    private static BufferedImage dye(BufferedImage image, Color color)
    {
        int w = image.getWidth();
        int h = image.getHeight();
        BufferedImage eingefärbt = new BufferedImage(w,h,BufferedImage.TYPE_INT_ARGB_PRE);
        Graphics2D g = eingefärbt.createGraphics();
        g.drawImage(image, 0,0, null);
        g.setComposite(AlphaComposite.SrcAtop);
        g.setColor(color);
        g.fillRect(0,0,w,h);
        g.dispose();
        return eingefärbt;
    }
 
}