javafx argb 到灰度转换
javafx argb to grayscale conversion
我知道有类似的问题,但那些没有回答我的问题。如标题所示,我使用的是 JavaFX Image class,而不是 bufferedImage。
我使用了 this 其他问题的答案,但生成的图像是空的。
这是我的代码:
public static Image toGrayScale(Image sourceImage) {
PixelReader pixelReader = sourceImage.getPixelReader();
int width = (int) sourceImage.getWidth();
int height = (int) sourceImage.getHeight();
WritableImage grayImage = new WritableImage(width, height);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int pixel = pixelReader.getArgb(x, y);
int red = ((pixel >> 16) & 0xff);
int green = ((pixel >> 8) & 0xff);
int blue = (pixel & 0xff);
int grayLevel = (int) (0.2162 * red + 0.7152 * green + 0.0722 * blue) / 3;
int gray = (grayLevel << 16) + (grayLevel << 8) + grayLevel;
grayImage.getPixelWriter().setArgb(x, y, gray);
}
return grayImage;
}
谁能告诉我问题出在哪里。
我通过执行以下操作让您的代码正常工作,但我还没有完全弄清楚为什么一定要这样。与Image中存储所需的int值有关。您需要反转灰度值并存储 -gray 整数。可能是 Little/Big Endian 问题。使用 ColorAdjust.
可能更安全
// Put this outside the loops
// so we have easier access to the writer.
PixelWriter pixelWriter = grayImage.getPixelWriter();
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int pixel = pixelReader.getArgb(x, y);
int red = ((pixel >> 16) & 0xff);
int green = ((pixel >> 8) & 0xff);
int blue = (pixel & 0xff);
int grayLevel = (int) (0.2162 * (double)red + 0.7152 * (double)green + 0.0722 * (double)blue) / 3;
grayLevel = 255 - grayLevel; // Inverted the grayLevel value here.
int gray = (grayLevel << 16) + (grayLevel << 8) + grayLevel;
pixelWriter.setArgb(x, y, -gray); // AMENDED TO -gray here.
}
}
更新,这个答案仍然有效,它给出的黑白单色图像非常接近灰度图像,但是它与灰度图像不完全相同应用于图像的灰度函数。要查看差异,请查看此问题中的示例图像:
- Desaturation effect washes away contrast
ColorAdjust 用于调整色调、饱和度、亮度 (HSB) 值,而不是红色、绿色蓝色 (RGB) 值。典型的 grayscale algorithm 将 RGB 值乘以特定常数来生成灰度图像。
因此,如果您需要或想要真正的灰度图像,请执行其他答案中概述的像素操作,而不是此答案中的 ColorAdjust 效果建议。
要从图像中获取灰度,我只需应用 desaturation effect。
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.effect.ColorAdjust;
import javafx.scene.image.*;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Desaturation extends Application {
@Override
public void start(Stage stage) throws Exception {
Image image = new Image(
"http://www.iamqurat.com/wp-content/uploads/2016/02/National_Flower_Rose_flickr_20140901.jpg",
200,
0,
true,
true
);
ImageView original = new ImageView(image);
ImageView desaturated = new ImageView(image);
ColorAdjust desaturate = new ColorAdjust();
desaturate.setSaturation(-1);
desaturated.setEffect(desaturate);
Scene scene = new Scene(new HBox(original, desaturated));
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
如果也考虑了alpha,并且加权和不除以3就有效:
public static Image toGrayScale(Image sourceImage) {
PixelReader pixelReader = sourceImage.getPixelReader();
int width = (int) sourceImage.getWidth();
int height = (int) sourceImage.getHeight();
WritableImage grayImage = new WritableImage(width, height);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int pixel = pixelReader.getArgb(x, y);
int alpha = ((pixel >> 24) & 0xff);
int red = ((pixel >> 16) & 0xff);
int green = ((pixel >> 8) & 0xff);
int blue = (pixel & 0xff);
int grayLevel = (int) (0.2162 * red + 0.7152 * green + 0.0722 * blue);
int gray = (alpha << 24) + (grayLevel << 16) + (grayLevel << 8) + grayLevel;
grayImage.getPixelWriter().setArgb(x, y, gray);
}
}
return grayImage;
}
我知道有类似的问题,但那些没有回答我的问题。如标题所示,我使用的是 JavaFX Image class,而不是 bufferedImage。
我使用了 this 其他问题的答案,但生成的图像是空的。
这是我的代码:
public static Image toGrayScale(Image sourceImage) {
PixelReader pixelReader = sourceImage.getPixelReader();
int width = (int) sourceImage.getWidth();
int height = (int) sourceImage.getHeight();
WritableImage grayImage = new WritableImage(width, height);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int pixel = pixelReader.getArgb(x, y);
int red = ((pixel >> 16) & 0xff);
int green = ((pixel >> 8) & 0xff);
int blue = (pixel & 0xff);
int grayLevel = (int) (0.2162 * red + 0.7152 * green + 0.0722 * blue) / 3;
int gray = (grayLevel << 16) + (grayLevel << 8) + grayLevel;
grayImage.getPixelWriter().setArgb(x, y, gray);
}
return grayImage;
}
谁能告诉我问题出在哪里。
我通过执行以下操作让您的代码正常工作,但我还没有完全弄清楚为什么一定要这样。与Image中存储所需的int值有关。您需要反转灰度值并存储 -gray 整数。可能是 Little/Big Endian 问题。使用 ColorAdjust.
可能更安全 // Put this outside the loops
// so we have easier access to the writer.
PixelWriter pixelWriter = grayImage.getPixelWriter();
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int pixel = pixelReader.getArgb(x, y);
int red = ((pixel >> 16) & 0xff);
int green = ((pixel >> 8) & 0xff);
int blue = (pixel & 0xff);
int grayLevel = (int) (0.2162 * (double)red + 0.7152 * (double)green + 0.0722 * (double)blue) / 3;
grayLevel = 255 - grayLevel; // Inverted the grayLevel value here.
int gray = (grayLevel << 16) + (grayLevel << 8) + grayLevel;
pixelWriter.setArgb(x, y, -gray); // AMENDED TO -gray here.
}
}
更新,这个答案仍然有效,它给出的黑白单色图像非常接近灰度图像,但是它与灰度图像不完全相同应用于图像的灰度函数。要查看差异,请查看此问题中的示例图像:
- Desaturation effect washes away contrast
ColorAdjust 用于调整色调、饱和度、亮度 (HSB) 值,而不是红色、绿色蓝色 (RGB) 值。典型的 grayscale algorithm 将 RGB 值乘以特定常数来生成灰度图像。
因此,如果您需要或想要真正的灰度图像,请执行其他答案中概述的像素操作,而不是此答案中的 ColorAdjust 效果建议。
要从图像中获取灰度,我只需应用 desaturation effect。
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.effect.ColorAdjust;
import javafx.scene.image.*;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Desaturation extends Application {
@Override
public void start(Stage stage) throws Exception {
Image image = new Image(
"http://www.iamqurat.com/wp-content/uploads/2016/02/National_Flower_Rose_flickr_20140901.jpg",
200,
0,
true,
true
);
ImageView original = new ImageView(image);
ImageView desaturated = new ImageView(image);
ColorAdjust desaturate = new ColorAdjust();
desaturate.setSaturation(-1);
desaturated.setEffect(desaturate);
Scene scene = new Scene(new HBox(original, desaturated));
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
如果也考虑了alpha,并且加权和不除以3就有效:
public static Image toGrayScale(Image sourceImage) {
PixelReader pixelReader = sourceImage.getPixelReader();
int width = (int) sourceImage.getWidth();
int height = (int) sourceImage.getHeight();
WritableImage grayImage = new WritableImage(width, height);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int pixel = pixelReader.getArgb(x, y);
int alpha = ((pixel >> 24) & 0xff);
int red = ((pixel >> 16) & 0xff);
int green = ((pixel >> 8) & 0xff);
int blue = (pixel & 0xff);
int grayLevel = (int) (0.2162 * red + 0.7152 * green + 0.0722 * blue);
int gray = (alpha << 24) + (grayLevel << 16) + (grayLevel << 8) + grayLevel;
grayImage.getPixelWriter().setArgb(x, y, gray);
}
}
return grayImage;
}