У меня есть изображение, загруженное Image
и ImageView
.Как удалить цвет изображения с помощью JavaFx (сделать фон прозрачным)?
Я хочу сделать фоновое изображение, которое является белым, прозрачным, чтобы соответствовать фону.
У меня есть изображение, загруженное Image
и ImageView
.Как удалить цвет изображения с помощью JavaFx (сделать фон прозрачным)?
Я хочу сделать фоновое изображение, которое является белым, прозрачным, чтобы соответствовать фону.
См. Технику передискретизации с использованием PixelWriter и WritableImage, используемой в Reduce number of colors and get color of a single pixel. Вы можете использовать ту же технику и изменить белые пиксели (rgb 255,255,255) на прозрачные (rgba 0,0,0,0).
Вы также можете сделать это in an image editing program, прежде чем использовать изображение в своем приложении.
Вот пример изображения с Easily Remove White Or Black Backgrounds with Blending Sliders in Photoshop.
Простая реализация передискретизации показано ниже:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class XRayVision extends Application {
private static final int TOLERANCE_THRESHOLD = 0xFF;
private static final String BACKGROUND_IMAGE_LOC =
"http://imgs.abduzeedo.com/files/articles/20_beautiful_landscape_wallpapers/landscape-wallpaper-1.jpg";
private static final String ORIGINAL_IMAGE_LOC =
"http://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2011/01/toy.jpg";
private Image makeTransparent(Image inputImage) {
int W = (int) inputImage.getWidth();
int H = (int) inputImage.getHeight();
WritableImage outputImage = new WritableImage(W, H);
PixelReader reader = inputImage.getPixelReader();
PixelWriter writer = outputImage.getPixelWriter();
for (int y = 0; y < H; y++) {
for (int x = 0; x < W; x++) {
int argb = reader.getArgb(x, y);
int r = (argb >> 16) & 0xFF;
int g = (argb >> 8) & 0xFF;
int b = argb & 0xFF;
if (r >= TOLERANCE_THRESHOLD
&& g >= TOLERANCE_THRESHOLD
&& b >= TOLERANCE_THRESHOLD) {
argb &= 0x00FFFFFF;
}
writer.setArgb(x, y, argb);
}
}
return outputImage;
}
@Override
public void start(final Stage stage) throws Exception {
final Image backgroundImage = new Image(BACKGROUND_IMAGE_LOC);
final ImageView backgroundImageView = new ImageView(backgroundImage);
final Image originalImage = new Image(ORIGINAL_IMAGE_LOC);
final ImageView originalImageView = new ImageView(originalImage);
final Image resampledImage = makeTransparent(originalImage);
final ImageView resampledImageView = new ImageView(resampledImage);
final HBox images = new HBox(originalImageView, resampledImageView);
stage.getIcons().add(originalImage);
final StackPane layout = new StackPane(backgroundImageView, images);
stage.setScene(new Scene(layout));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Когда TOLERANCE_THRESHOLD установлен в 0xFF, только чистые белые пиксели будут заменены на прозрачные, и вы получите изображение, как показано ниже. Белая часть вокруг символа состоит в том, что некоторые из фона не совсем белые, но немного серые, поэтому повторная выборка не изменяет его значение альфа.
Уменьшения TOLERANCE_THRESHOLD к 0xCF создает изображение, как показано ниже, где некоторые из светло-серого фона становится прозрачными. Обратите внимание, что этот результат не идеален, поскольку вокруг персонажа все еще есть сглаженный серый контур, а белый шлем персонажа становится прозрачным. Вы можете модифицировать алгоритм, чтобы быть немного более интеллектуальным и действовать скорее как приложение lasso tool приложения для рисования изображений, однако это, вероятно, станет сложным и может по-прежнему совершать ошибки без участия человека. Если упрощенная программная процедура, описанная выше, недостаточна для правильной передискретизации вашего изображения по своему усмотрению, вам лучше всего настроить прозрачность заблаговременно в программе редактирования изображений (это то, что я бы рекомендовал в большинстве случаев в любом случае).
Зачем уменьшать количество цветов? – lelelo
@jewelsea: какой-либо причине вы не пишете, что в ответ? Я просто терял время, читая все это, только чтобы узнать, что вы уже дали ответ в качестве комментария. Я собирался написать то же самое, что и ответ, но теперь, если я напишу его, он, похоже, украл у вас :-( – Roland
Все, что вы хотите, прощай, Роланд, ответит. – jewelsea