简体   繁体   中英

Change color of non-transparent parts of png in Java

I am trying to automatically change the color for a set of icons. Every icon has a white filled layer and the other part is transparent. Here is an example: (in this case it's green, just to make it visible)

图标搜索

I tried to do the following:

private static BufferedImage colorImage(BufferedImage image) {
        int width = image.getWidth();
        int height = image.getHeight();

        for (int xx = 0; xx < width; xx++) {
            for (int yy = 0; yy < height; yy++) {
                Color originalColor = new Color(image.getRGB(xx, yy));
                System.out.println(xx + "|" + yy + " color: " + originalColor.toString() + "alpha: "
                        + originalColor.getAlpha());
                if (originalColor.equals(Color.WHITE) && originalColor.getAlpha() == 255) {
                    image.setRGB(xx, yy, Color.BLUE.getRGB());
                }
            }
        }
        return image;
    }

The problem I have is that every pixel I get has the same value:

32|18 color: java.awt.Color[r=255,g=255,b=255]alpha: 255

So my result is just a colored square. How can I achieve to change the color of the non-transparent parts only? And why is it, that all pixels have even the same alpha value? I guess that's my main problem: That the alpha value isn't read correctly.

Why it doesn't work, I don't know, this will.

This changes all the pixles to blue, maintaining their alpha values...

在此处输入图片说明

import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class TestColorReplace {

    public static void main(String[] args) {
        try {
            BufferedImage img = colorImage(ImageIO.read(new File("NWvnS.png")));
            ImageIO.write(img, "png", new File("Test.png"));
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    private static BufferedImage colorImage(BufferedImage image) {
        int width = image.getWidth();
        int height = image.getHeight();
        WritableRaster raster = image.getRaster();

        for (int xx = 0; xx < width; xx++) {
            for (int yy = 0; yy < height; yy++) {
                int[] pixels = raster.getPixel(xx, yy, (int[]) null);
                pixels[0] = 0;
                pixels[1] = 0;
                pixels[2] = 255;
                raster.setPixel(xx, yy, pixels);
            }
        }
        return image;
    }
}

The problem is, that

Color originalColor = new Color(image.getRGB(xx, yy));

discards all the alpha values. Instead you have to use

 Color originalColor = new Color(image.getRGB(xx, yy), true);

to keep alpha values available.

If your bitmap is already set in an ImageView, just do :

imageView.setColorFilter(Color.RED);

to set all non transparent pixels to red.

Since we will always be replacing only the first three bands of the RGB pixel, more effective way to achieve the same without unnecessary allocation of new arrays would be:

private static void colorImageAndPreserveAlpha(BufferedImage img, Color c) {
    WritableRaster raster = img.getRaster();
    int[] pixel = new int[] {c.getRed(),c.getGreen(),c.getBlue()};
    for (int x = 0; x < raster.getWidth(); x++) 
        for (int y = 0; y < raster.getHeight(); y++)
            for (int b = 0; b < pixel.length; b++)
                raster.setSample(x,y,b,pixel[b]);    
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM