How to change color of image in JavaFX

2019-01-18 07:22发布

I have a PNG image like this:

png image

I want to change image to something like this:

enter image description here

How can I do this in JavaFX?

2条回答
再贱就再见
2楼-- · 2019-01-18 08:11

As you don't care if it is a vector shape or a bitmap, I'll just outline solutions using a bitmap here. If you actually wanted a vector shape, I believe you would need to work with vector input to get a good result.


Use a ColorAdjust effect with the brightness set to minimum (-1). Cache the result for SPEED.

speed

Here is a sample which creates a shadow outline of an image:

import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.effect.ColorAdjust;
import javafx.scene.image.*;
import javafx.stage.Stage;

public class Shadow extends Application {
    @Override 
    public void start(Stage stage) throws Exception {
        ImageView imageView = new ImageView(
            new Image(
                "http://i.stack.imgur.com/jbT1H.png"
            )
        );

        ColorAdjust blackout = new ColorAdjust();
        blackout.setBrightness(-1.0);

        imageView.setEffect(blackout);
        imageView.setCache(true);
        imageView.setCacheHint(CacheHint.SPEED);

        stage.setScene(new Scene(new Group(imageView)));
        stage.show();
    }

    public static void main(String[] args) {
        Application.launch();
    }
}

Here is another sample which adjusts the color of an image, hover over smurfette to make her blush.

smurfette blushing smurfette

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.scene.*;
import javafx.scene.effect.*;
import javafx.scene.image.*;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class Shadow extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        Image image = new Image(
                "http://icons.iconarchive.com/icons/designbolts/smurfs-movie/128/smurfette-icon.png"
        );

        ImageView imageView = new ImageView(image);
        imageView.setClip(new ImageView(image));

        ColorAdjust monochrome = new ColorAdjust();
        monochrome.setSaturation(-1.0);

        Blend blush = new Blend(
                BlendMode.MULTIPLY,
                monochrome,
                new ColorInput(
                        0,
                        0,
                        imageView.getImage().getWidth(),
                        imageView.getImage().getHeight(),
                        Color.RED
                )
        );

        imageView.effectProperty().bind(
                Bindings
                    .when(imageView.hoverProperty())
                        .then((Effect) blush)
                        .otherwise((Effect) null)
        );

        imageView.setCache(true);
        imageView.setCacheHint(CacheHint.SPEED);

        stage.setScene(new Scene(new Group(imageView), Color.AQUA));
        stage.show();
    }

    public static void main(String[] args) {
        Application.launch();
    }
}
查看更多
Melony?
3楼-- · 2019-01-18 08:20

The below code will replace one pixel color with another. If you run that multiple times over your original image replacing gray scale values with color values you should be set. To save memory you might want to adapt the code to reuse the writeable image for each loop.

/**
   * reColor the given InputImage to the given color
   * inspired by https://stackoverflow.com/a/12945629/1497139
   * @param inputImage
   * @param oldColor
   * @param newColor 
   * @return reColored Image
   * 
   */
  public static Image reColor(Image inputImage, Color oldColor, Color newColor) {
    int W = (int) inputImage.getWidth();
    int H = (int) inputImage.getHeight();
    WritableImage outputImage = new WritableImage(W, H);
    PixelReader reader = inputImage.getPixelReader();
    PixelWriter writer = outputImage.getPixelWriter();
    int ob=(int) oldColor.getBlue()*255;
    int or=(int) oldColor.getRed()*255;
    int og=(int) oldColor.getGreen()*255;
    int nb=(int) newColor.getBlue()*255;
    int nr=(int) newColor.getRed()*255;
    int ng=(int) newColor.getGreen()*255;
    for (int y = 0; y < H; y++) {
      for (int x = 0; x < W; x++) {
        int argb = reader.getArgb(x, y);
        int a = (argb >> 24) & 0xFF;
        int r = (argb >> 16) & 0xFF;
        int g = (argb >>  8) & 0xFF;
        int b =  argb        & 0xFF;
        if (g==og && r==or && b==ob) {
          r=nr;
          g=ng;
          b=nb;
        }

        argb = (a << 24) | (r << 16) | (g << 8) | b;
        writer.setArgb(x, y, argb);
      }
    }
    return outputImage;
  }
查看更多
登录 后发表回答