Appliquer une teinte à une image en java

j'essaie de créer plusieurs styles visuels similaires pour mes programmes, chacun avec un thème de couleur différent. Pour ce faire, j'ai implémenté l'utilisation d'icônes pour représenter les différents états de JCheckBoxet JRadioButtons. Au lieu de faire un ensemble complet d'icônes pour chaque couleur possible, est-il possible que je peux prendre un jeu et de modifier la teinte/saturation/luminosité/alpha de l'image avant de l'afficher?

20
demandé sur Supuhstar 2010-11-22 20:11:51

7 réponses

il y a un moyen, mais vous devrez faire usage de quelques transformations de BufferedImage. Une fois que vous les créez, cache ou de les enregistrer pour être facilement réutilisées plus tard. Essentiellement, vous voulez commencer avec une image noire (couleur source #000000) qui n'utilise que la couche alpha pour désactiver les pixels (fournissant également un anti-aliasing lisse). Par exemple, dans votre image source, chaque pixel est noir, mais le canal alpha diffère du pixel au pixel.

tout d'abord, lire cet article pour certains Informations générales:http://www.javalobby.org/articles/ultimate-image/

une fois que vous avez terminé avec ce primer, vous devez charger votre image dans un BufferedImage:

BufferedImage loadImg = ImageUtil.loadImage("C:/Images/myimg.png");

ensuite, vous devez créer un nouveau BufferedImage pour faire la transformation en:

public BufferedImage colorImage(BufferedImage loadImg, int red, int green, int blue) {
    BufferedImage img = new BufferedImage(loadImg.getWidth(), loadImg.getHeight(),
        BufferedImage.TRANSLUCENT);
    Graphics2D graphics = img.createGraphics(); 
    Color newColor = new Color(red, green, blue, 0 /* alpha needs to be zero */);
    graphics.setXORMode(newColor);
    graphics.drawImage(loadImg, null, 0, 0);
    graphics.dispose();
    return img;
}

essentiellement, le setXORMode XORERA la couleur que vous fournissez avec la couleur dans l'image source. Si l'image source est noir, alors quelle que soit la couleur que vous fournissez sera écrit comme vous spécifiez. Avec la nouvelle couleur en utilisant "0" pour le canal alpha, les valeurs originales du canal alpha seront respectées. Le résultat final est le composite que vous recherchez.

Edit:

vous pouvez charger le tampon initial de deux façons. Le plus simple est D'utiliser la nouvelle API ImageIO de Java:http://download.oracle.com/javase/6/docs/api/javax/imageio/ImageIO.html pour charger le fichier directement dans un BufferedImage. L'appel aurait l'air quelque chose comme ceci:

BufferedImage img = ImageIO.read(url); 

alternativement, vous pouvez créer une méthode pour lire l'image en utilisant la boîte à outils.

public BufferedImage loadImage(String url) {
    ImageIcon icon = new ImageIcon(url);
    Image image = icon.getImage();

    // Create empty BufferedImage, sized to Image
    BufferedImage buffImage = 
      new BufferedImage(
        image.getWidth(null), 
        image.getHeight(null), 
        BufferedImage.TYPE_INT_ARGB);

    // Draw Image into BufferedImage
    Graphics g = buffImage.getGraphics();
    g.drawImage(image, 0, 0, null);
    return buffImage;
}

bien sûr, si vous faites attention, nous devons faire exactement la même chose pour lire l'image dans une image tamponnée que nous le faisons pour la teinte. En bref, si vous avez changé la signature du colorImage méthode pour accepter le Image object vous n'avez besoin que de faire quelques changements aux méthodes getWidth() et gethight() pour le faire fonctionner.

12
répondu Berin Loritsch 2010-11-23 17:24:06
public static void tint(BufferedImage img) {

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

            Color color = new Color(img.getRGB(x, y));

            // do something with the color :) (change the hue, saturation and/or brightness)
            // float[] hsb = new float[3];
            // Color.RGBtoHSB(color.getRed(), old.getGreen(), old.getBlue(), hsb);

            // or just call brighter to just tint it
            Color brighter = color.brighter();

            img.setRGB(x, y, brighter.getRGB());
        }
    }
}
4
répondu dacwe 2010-11-23 05:56:20

pour calculer la moyenne pour chaque composante de couleur et garder l'alpha original:

public static void tint(BufferedImage image, Color color) {
    for (int x = 0; x < image.getWidth(); x++) {
        for (int y = 0; y < image.getHeight(); y++) {
            Color pixelColor = new Color(image.getRGB(x, y), true);
            int r = (pixelColor.getRed() + color.getRed()) / 2;
            int g = (pixelColor.getGreen() + color.getGreen()) / 2;
            int b = (pixelColor.getBlue() + color.getBlue()) / 2;
            int a = pixelColor.getAlpha();
            int rgba = (a << 24) | (r << 16) | (g << 8) | b;
            image.setRGB(x, y, rgba);
        }
    }
}

cela fonctionne mieux pour mon cas.

3
répondu Oleg Mikhailov 2016-04-20 12:49:31

la façon la plus simple de faire cela serait d'utiliser le filtres D'Image par JH Labs. Vous pouvez simplement ajuster HSB en appelant,

public BufferedImage setHSB(BufferedImage source, float hValue, float sValue, float bValue) {        
    com.jhlabs.image.HSBAdjustFilter hsb hsb = new HSBAdjustFilter();
    BufferedImage destination = hsb.createCompatibleDestImage(source, null);
    hsb.setHFactor(hValue);
    hsb.setSFactor(sValue);
    hsb.setBFactor(bValue);
    BufferedImage result = hsb.filter(bi, destination);

    return result;
}
2
répondu RocketRuwan 2014-01-22 04:10:41

j'ai essayé toutes les solutions sur cette page, n'avait pas de chance. Le Xor one (réponse acceptée) n'a pas fonctionné pour moi - teinté une couleur jaune bizarre au lieu de la couleur que je donnais comme un argument, peu importe ce que l'argument. J'ai enfin trouvé une approche qui fonctionne pour moi, bien que ce soit un peu bordélique. J'ai pensé l'ajouter au cas où quelqu'un d'autre aurait les mêmes problèmes que moi avec les autres solutions. Acclamations!

/** Tints the given image with the given color.
 * @param loadImg - the image to paint and tint
 * @param color - the color to tint. Alpha value of input color isn't used.
 * @return A tinted version of loadImg */
public static BufferedImage tint(BufferedImage loadImg, Color color) {
    BufferedImage img = new BufferedImage(loadImg.getWidth(), loadImg.getHeight(),
            BufferedImage.TRANSLUCENT);
    final float tintOpacity = 0.45f;
    Graphics2D g2d = img.createGraphics(); 

    //Draw the base image
    g2d.drawImage(loadImg, null, 0, 0);
    //Set the color to a transparent version of the input color
    g2d.setColor(new Color(color.getRed() / 255f, color.getGreen() / 255f, 
        color.getBlue() / 255f, tintOpacity));

    //Iterate over every pixel, if it isn't transparent paint over it
    Raster data = loadImg.getData();
    for(int x = data.getMinX(); x < data.getWidth(); x++){
        for(int y = data.getMinY(); y < data.getHeight(); y++){
            int[] pixel = data.getPixel(x, y, new int[4]);
            if(pixel[3] > 0){ //If pixel isn't full alpha. Could also be pixel[3]==255
                g2d.fillRect(x, y, 1, 1);
            }
        }
    }
    g2d.dispose();
    return img;
}
1
répondu Mshnik 2014-12-20 03:05:33

ce n'est pas exactement de la teinture, c'est plus comme appliquer une autre couche dessus mais ça marche pour moi:

public static BufferedImage colorImage(BufferedImage loadImg, int red, int green, int blue, int alpha /*Also the intesity*/) {
    Graphics g = loadImg.getGraphics();
    g.setColor(new Color(red, green, blue, alpha));
    g.fillRect(0, 0, loadImg.getWidth(), loadImg.getHeight());
    g.dispose();
    return loadImg;
}
0
répondu APerson 2013-09-23 00:34:01

parce que toutes les méthodes que j'ai trouvées n'ont pas fonctionné pour moi pour quelque raison que ce soit, voici une façon facile d'aborder ceci (pas de libs supplémentaires nécessaires):

/**
 * Colors an image with specified color.
 * @param r Red value. Between 0 and 1
 * @param g Green value. Between 0 and 1
 * @param b Blue value. Between 0 and 1
 * @param src The image to color
 * @return The colored image
 */
protected BufferedImage color(float r, float g, float b, BufferedImage src) {

    // Copy image ( who made that so complicated :< )
    BufferedImage newImage = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TRANSLUCENT);
    Graphics2D graphics = newImage.createGraphics();
    graphics.drawImage(src, 0, 0, null);
    graphics.dispose();

    // Color image
    for (int i = 0; i < newImage.getWidth(); i++) {
        for (int j = 0; j < newImage.getHeight(); j++) {
            int ax = newImage.getColorModel().getAlpha(newImage.getRaster().getDataElements(i, j, null));
            int rx = newImage.getColorModel().getRed(newImage.getRaster().getDataElements(i, j, null));
            int gx = newImage.getColorModel().getGreen(newImage.getRaster().getDataElements(i, j, null));
            int bx = newImage.getColorModel().getBlue(newImage.getRaster().getDataElements(i, j, null));
            rx *= r;
            gx *= g;
            bx *= b;
            newImage.setRGB(i, j, (ax << 24) | (rx << 16) | (gx << 8) | (bx << 0));
        }
    }
    return newImage;
}

une image noire va toujours noire, mais une image blanche sera la couleur que vous spécifiez. Cette méthode parcourt chaque pixel et multiplie les valeurs rouge, verte et bleue de l'image avec les paramètres. C'est le comportement exact de L'OpenGL glColor3f () méthode. Les paramètres R, G et B doivent être de 0,0 F à 0,0 F 1.0 F.

Cette méthode n'a aucun problème avec les valeurs alpha.

0
répondu therealfarfetchd 2015-04-01 10:47:06