2D-Grafik Bild einfärben

0001001

Bekanntes Mitglied
Hallo,

ich habe hier folgende graue Grafik:
50px-Gnome-stock_person.svg.png


Ich würde diese Grafik in Java nun beliebig einfärben wollen, etwa so:
48pxgnomestockpersonsvg.png


Kann mir jemand weiterhelfen, wie man das machen könnte?
 
Hallo,

ja der Hintergrund ist transparent.

Ich würde das Ganze dann gerne auf einer GUI anordnen und brauche eine unbestimmte Anzahl an solchen Grafiken, daher kann ich nicht X zuvor eingefärbte Varianten vorhalten, sondern muss das zur Laufzeit einfärben.
 
Java:
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import javax.swing.*;
import javax.imageio.*;

class DyeImage
{
    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                try
                {
                    new DyeImage();
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        });

    }

    public DyeImage() throws Exception
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        BufferedImage image = ImageIO.read(new File("50px-Gnome-stock_person.svg.png"));
        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(255,0,0,128)))));
        panel.add(new JLabel(new ImageIcon(dye(image, new Color(255,0,0,32)))));
        panel.add(new JLabel(new ImageIcon(dye(image, new Color(0,128,0,32)))));
        panel.add(new JLabel(new ImageIcon(dye(image, new Color(0,0,255,32)))));
        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 dyed = new BufferedImage(w,h,BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = dyed.createGraphics();
        g.drawImage(image, 0,0, null);
        g.setComposite(AlphaComposite.SrcAtop);
        g.setColor(color);
        g.fillRect(0,0,w,h);
        g.dispose();
        return dyed;
    }

}
 
Zufälligerweise habe ich mir auch mal sowas für ein Projekt programmiert. Transparente Pixel werden ignoriert, Schatten bleiben erhalten.
Hier gibst Du die Farbe vor, die geändert werden soll und die Zielfarbe. Das ist also ein bisschen flexibler, falls nötig.

Java:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;

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

public class ColorChanger {
	
	public static final int ALPHA = 0;
	public static final int RED = 1;
	public static final int GREEN = 2;
	public static final int BLUE = 3;

	public static final int HUE = 0;
	public static final int SATURATION = 1;
	public static final int BRIGHTNESS = 2;

	public static final int TRANSPARENT = 0;

	public static void main(String[] args) {
		String filename = "img/schildkroete2.gif";
		BufferedImage image = null;
		try {

			image = ImageIO.read(new File(filename));
			image = new ColorChanger().changeColor(image, Color.white, Color.yellow);
			JFrame frame = new JFrame();
			frame.setVisible(true);
			frame.setSize(380, 220);
			frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
			frame.add(new JLabel(new ImageIcon(image)));
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public BufferedImage changeColor(BufferedImage image, Color mask,
			Color replacement) {
		BufferedImage destImage = new BufferedImage(image.getWidth(),
				image.getHeight(), BufferedImage.TYPE_INT_ARGB);

		Graphics2D g = destImage.createGraphics();
		g.drawImage(image, null, 0, 0);
		g.dispose();

		for (int i = 0; i < destImage.getWidth(); i++) {
			for (int j = 0; j < destImage.getHeight(); j++) {

				int destRGB = destImage.getRGB(i, j);

				if (matches(mask.getRGB(), destRGB)) {
					int rgbnew = getNewPixelRGB(replacement.getRGB(), destRGB);
					destImage.setRGB(i, j, rgbnew);
				}
			}
		}

		return destImage;
	}

	private int getNewPixelRGB(int replacement, int destRGB) {
		float[] destHSB = getHSBArray(destRGB);
		float[] replHSB = getHSBArray(replacement);

		int rgbnew = Color.HSBtoRGB(replHSB[HUE],
				replHSB[SATURATION], destHSB[BRIGHTNESS]);
		return rgbnew;
	}

	private boolean matches(int maskRGB, int destRGB) {
		float[] hsbMask = getHSBArray(maskRGB);
		float[] hsbDest = getHSBArray(destRGB);

		if (hsbMask[HUE] == hsbDest[HUE]
				&& hsbMask[SATURATION] == hsbDest[SATURATION]
				&& getRGBArray(destRGB)[ALPHA] != TRANSPARENT) {

			return true;
		}
		return false;
	}

	private int[] getRGBArray(int rgb) {
		return new int[] { (rgb >> 24) & 0xff, (rgb >> 16) & 0xff,
				(rgb >> 8) & 0xff, rgb & 0xff };
	}

	private float[] getHSBArray(int rgb) {
		int[] rgbArr = getRGBArray(rgb);
		return Color.RGBtoHSB(rgbArr[RED], rgbArr[GREEN], rgbArr[BLUE], null);
	}
}
 
Zuletzt bearbeitet:
Uff, ja. Als das Problem auftrat und ich nach möglichen Lösungen suchte, ist mir diese Klasse nie untergekommen.
 
Sooo viel gibt's (bei meinem) nicht zu verstehen: Das Bild wird überpinselt mit einem halbdurchsichtigen Rechteck, und durch das "AlphaComposite.SrcAtop" bleiben die vollkommen transparenten Teile auch nachher noch vollkommen transparent (die anderen werden mit der halbtransparenten Farbe "vermischt")
 

Neue Themen


Zurück
Oben