JavaFX:将图像转换为灰度
JavaFX: Convert Image to Greysacale
我需要在我的程序中这样做。我必须通过两种方式来做到这一点:
1.) 自己的,代码如下:`
private Image convertToGrayScale(Image image) {
WritableImage result = new WritableImage((int) image.getWidth(), (int)
image.getHeight());
PixelReader preader = image.getPixelReader();
PixelWriter pwriter = result.getPixelWriter();
for (int i = 0; i < result.getWidth(); i++) {
for (int j = 0; j < result.getHeight(); j++) {
Color c = preader.getColor(i, j);
double red = (c.getRed() * 0.299);
double green = (c.getGreen() * 0.587);
double blue = (c.getBlue() * 0.114);
double sum = c.getRed() + c.getBlue() + c.getGreen();
pwriter.setColor(i , j, new Color(sum, sum, sum, 1.0));
}
}
return result;
}
2.) 在 openCV 库的帮助下,使用以下代码(几乎完美地从他们的站点复制):
public WritableImage loadAndConvert() throws Exception {
//Loading the OpenCV core library
System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
String input = "C:/Users/Dan Ivgy/eclipse-workspace/LuckyBride/sample/20180402_170204.jpg";
//Reading the image
Mat src = Imgcodecs.imread(input);
//Creating the empty destination matrix
Mat dst = new Mat();
//Converting the image to gray scale and saving it in the dst matrix
Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGB2GRAY);
// Imgcodecs.imwrite("C:/opencv/GeeksforGeeks.jpg", dst);
//Extracting data from the transformed image (dst)
byte[] data1 = new byte[dst.rows() * dst.cols() * (int)(dst.elemSize())];
dst.get(0, 0, data1);
//Creating Buffered image using the data
BufferedImage bufImage = new BufferedImage(dst.cols(),dst.rows(),
BufferedImage.TYPE_BYTE_GRAY);
//Setting the data elements to the image
bufImage.getRaster().setDataElements(0, 0, dst.cols(), dst.rows(), data1);
//Creating a WritableImage
WritableImage writableImage = SwingFXUtils.toFXImage(bufImage, null);
System.out.println("Converted to Grayscale");
return writableImage;
}
在这两种情况下,问题是我没有得到“灰度”输出,只是有些不同(在你之前
问:是的,我已经尝试在几张照片上这样做,而不仅仅是一张)
这是输入图片和输出图片:
好吧,如你所见,这不是灰度!也许是日落规模..
非常感谢您的帮助,谢谢 :)
(特别是如果有更快的东西,因为这些解决方案需要一段时间 运行)
如果有人知道,为什么 javaFX 中没有一些内置选项,因为有很多复杂的 imageview 效果,而这个效果又简单又流行。
更新:
我找到了一个网站,它做的事情与我所做的类似 - 但不知何故我得到了不同的输出!我不明白
这是 website.
这是我电脑的输出:
my output
更新#2:正如@matt 正确询问的那样,这是使用此方法的代码:
ImageIO.write(SwingFXUtils
.fromFXImage
(convertToGrayScale(new Image(getClass().getResource("1_CNc4RxV85YgthtvZh2xO5Q.jpeg").toExternalForm()) ), null), "jpg", file);
最初的目标是向用户显示图像,但问题就出在这里,所以我将代码更改为保存图像的代码,这样我就可以更轻松地隔离问题..
我决定在 awt 中工作,然后创建一个 javafx 图像。
public class App extends Application {
@Override
public void start(Stage stage) {
WritableImage gray = null;
try {
BufferedImage awtImage = ImageIO.read(new URL("https://i.stack.imgur.com/ysIrl.jpg"));
gray = new WritableImage(awtImage.getWidth(), awtImage.getHeight());
BufferedImage img2 = new BufferedImage(awtImage.getWidth(), awtImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
for(int i = 0; i<awtImage.getWidth(); i++){
for(int j = 0; j<awtImage.getHeight(); j++){
int c = awtImage.getRGB(i, j);
int r = (c>>16)&255;
int g = (c>>8)&255;
int b = (c)&255;
int s = (int)(r*0.299 + g*0.587 + b*0.114);
int gr = (255<<24) + (s<<16) + (s<<8) + s;
img2.setRGB(i, j, gr);
}
}
gray = SwingFXUtils.toFXImage(img2, gray);
} catch (IOException e) {
e.printStackTrace();
}
ImageView view = new ImageView(gray);
ScrollPane pane = new ScrollPane(view);
Scene scene = new Scene(new StackPane(pane), 640, 480);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
这两种方法都对我有用,所以我不确定这是否对你有帮助。我也可以保存结果。
System.out.println("saving " +
ImageIO.write(img2, "PNG", new File("tested.png")) );
如果您使用的是 oracles jdk,我认为您可以保存 JPEG。我正在使用 OpenJDK,它似乎无法编写 JPEG。
好的伙计们,经过一些研究和无数次的尝试,我得到了我需要的东西
为了解决这个问题,我在这里展示我的解决方案,并总结出我对这个问题的见解..
首先,我将区分“保存文件”和“在 ImageView 中设置文件”。
当我们只想在图像视图中显示它时,我使用此处建议的几乎所有解决方案都没有遇到任何问题。最简单、简短和甜蜜(在我看来)是以下一个:
private Image convertToGrayScale(Image image) {
WritableImage result = new WritableImage((int) image.getWidth(), (int) image.getHeight());
PixelReader preader = image.getPixelReader();
PixelWriter pwriter = result.getPixelWriter();
for (int i = 0; i < result.getWidth(); i++)
for (int j = 0; j < result.getHeight(); j++)
pwriter.setColor(i , j, preader.getColor(i, j).grayscale());
return result;
}
(为了方便,我忽略了异常处理)
当我将它与以下代码一起使用时,它工作正常:
Image img1 = convertToGrayScale(new Image(filepath);
imageView.setImage(img1);
关于保存此输出图像,经过一些研究并使用@trashgold 的参考资料,this important one:
我的解决方案如下:
private void saveBadImage(BufferedImage originalImage, File dest) throws IOException
{
// use the following line if you want the first parameter to be a filepath to src image instead of Image itself
//BufferedImage originalImage = ImageIO.read(file);
// jpg needs BufferedImage.TYPE_INT_RGB
// png needs BufferedImage.TYPE_INT_ARGB
// create a blank, RGB, same width and height
BufferedImage newBufferedImage = new BufferedImage(
originalImage.getWidth(),
originalImage.getHeight(),
BufferedImage.TYPE_INT_RGB);
// draw a white background and puts the originalImage on it.
newBufferedImage.createGraphics().drawImage(originalImage,0,0,null);
// save an image
ImageIO.write(newBufferedImage, "jpg", dest);
}
并且,我将它与以下代码一起使用:
Image img1 = convertToGrayScale(new Image(filepath));
BufferedImage img2 = new BufferedImage((int) img1.getWidth(), (int) img1.getHeight(), BufferedImage.TYPE_INT_ARGB);
saveBadImage(img2, file);
而且,它工作得很好!
谢谢大家,希望我的见解能对一些人有所帮助
我需要在我的程序中这样做。我必须通过两种方式来做到这一点:
1.) 自己的,代码如下:`
private Image convertToGrayScale(Image image) {
WritableImage result = new WritableImage((int) image.getWidth(), (int)
image.getHeight());
PixelReader preader = image.getPixelReader();
PixelWriter pwriter = result.getPixelWriter();
for (int i = 0; i < result.getWidth(); i++) {
for (int j = 0; j < result.getHeight(); j++) {
Color c = preader.getColor(i, j);
double red = (c.getRed() * 0.299);
double green = (c.getGreen() * 0.587);
double blue = (c.getBlue() * 0.114);
double sum = c.getRed() + c.getBlue() + c.getGreen();
pwriter.setColor(i , j, new Color(sum, sum, sum, 1.0));
}
}
return result;
}
2.) 在 openCV 库的帮助下,使用以下代码(几乎完美地从他们的站点复制):
public WritableImage loadAndConvert() throws Exception {
//Loading the OpenCV core library
System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
String input = "C:/Users/Dan Ivgy/eclipse-workspace/LuckyBride/sample/20180402_170204.jpg";
//Reading the image
Mat src = Imgcodecs.imread(input);
//Creating the empty destination matrix
Mat dst = new Mat();
//Converting the image to gray scale and saving it in the dst matrix
Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGB2GRAY);
// Imgcodecs.imwrite("C:/opencv/GeeksforGeeks.jpg", dst);
//Extracting data from the transformed image (dst)
byte[] data1 = new byte[dst.rows() * dst.cols() * (int)(dst.elemSize())];
dst.get(0, 0, data1);
//Creating Buffered image using the data
BufferedImage bufImage = new BufferedImage(dst.cols(),dst.rows(),
BufferedImage.TYPE_BYTE_GRAY);
//Setting the data elements to the image
bufImage.getRaster().setDataElements(0, 0, dst.cols(), dst.rows(), data1);
//Creating a WritableImage
WritableImage writableImage = SwingFXUtils.toFXImage(bufImage, null);
System.out.println("Converted to Grayscale");
return writableImage;
}
在这两种情况下,问题是我没有得到“灰度”输出,只是有些不同(在你之前 问:是的,我已经尝试在几张照片上这样做,而不仅仅是一张)
这是输入图片和输出图片:
好吧,如你所见,这不是灰度!也许是日落规模..
非常感谢您的帮助,谢谢 :)
(特别是如果有更快的东西,因为这些解决方案需要一段时间 运行)
如果有人知道,为什么 javaFX 中没有一些内置选项,因为有很多复杂的 imageview 效果,而这个效果又简单又流行。
更新: 我找到了一个网站,它做的事情与我所做的类似 - 但不知何故我得到了不同的输出!我不明白 这是 website.
这是我电脑的输出: my output
更新#2:正如@matt 正确询问的那样,这是使用此方法的代码:
ImageIO.write(SwingFXUtils
.fromFXImage
(convertToGrayScale(new Image(getClass().getResource("1_CNc4RxV85YgthtvZh2xO5Q.jpeg").toExternalForm()) ), null), "jpg", file);
最初的目标是向用户显示图像,但问题就出在这里,所以我将代码更改为保存图像的代码,这样我就可以更轻松地隔离问题..
我决定在 awt 中工作,然后创建一个 javafx 图像。
public class App extends Application {
@Override
public void start(Stage stage) {
WritableImage gray = null;
try {
BufferedImage awtImage = ImageIO.read(new URL("https://i.stack.imgur.com/ysIrl.jpg"));
gray = new WritableImage(awtImage.getWidth(), awtImage.getHeight());
BufferedImage img2 = new BufferedImage(awtImage.getWidth(), awtImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
for(int i = 0; i<awtImage.getWidth(); i++){
for(int j = 0; j<awtImage.getHeight(); j++){
int c = awtImage.getRGB(i, j);
int r = (c>>16)&255;
int g = (c>>8)&255;
int b = (c)&255;
int s = (int)(r*0.299 + g*0.587 + b*0.114);
int gr = (255<<24) + (s<<16) + (s<<8) + s;
img2.setRGB(i, j, gr);
}
}
gray = SwingFXUtils.toFXImage(img2, gray);
} catch (IOException e) {
e.printStackTrace();
}
ImageView view = new ImageView(gray);
ScrollPane pane = new ScrollPane(view);
Scene scene = new Scene(new StackPane(pane), 640, 480);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
这两种方法都对我有用,所以我不确定这是否对你有帮助。我也可以保存结果。
System.out.println("saving " +
ImageIO.write(img2, "PNG", new File("tested.png")) );
如果您使用的是 oracles jdk,我认为您可以保存 JPEG。我正在使用 OpenJDK,它似乎无法编写 JPEG。
好的伙计们,经过一些研究和无数次的尝试,我得到了我需要的东西 为了解决这个问题,我在这里展示我的解决方案,并总结出我对这个问题的见解..
首先,我将区分“保存文件”和“在 ImageView 中设置文件”。
当我们只想在图像视图中显示它时,我使用此处建议的几乎所有解决方案都没有遇到任何问题。最简单、简短和甜蜜(在我看来)是以下一个:
private Image convertToGrayScale(Image image) {
WritableImage result = new WritableImage((int) image.getWidth(), (int) image.getHeight());
PixelReader preader = image.getPixelReader();
PixelWriter pwriter = result.getPixelWriter();
for (int i = 0; i < result.getWidth(); i++)
for (int j = 0; j < result.getHeight(); j++)
pwriter.setColor(i , j, preader.getColor(i, j).grayscale());
return result;
}
(为了方便,我忽略了异常处理)
当我将它与以下代码一起使用时,它工作正常:
Image img1 = convertToGrayScale(new Image(filepath);
imageView.setImage(img1);
关于保存此输出图像,经过一些研究并使用@trashgold 的参考资料,this important one:
我的解决方案如下:
private void saveBadImage(BufferedImage originalImage, File dest) throws IOException
{
// use the following line if you want the first parameter to be a filepath to src image instead of Image itself
//BufferedImage originalImage = ImageIO.read(file);
// jpg needs BufferedImage.TYPE_INT_RGB
// png needs BufferedImage.TYPE_INT_ARGB
// create a blank, RGB, same width and height
BufferedImage newBufferedImage = new BufferedImage(
originalImage.getWidth(),
originalImage.getHeight(),
BufferedImage.TYPE_INT_RGB);
// draw a white background and puts the originalImage on it.
newBufferedImage.createGraphics().drawImage(originalImage,0,0,null);
// save an image
ImageIO.write(newBufferedImage, "jpg", dest);
}
并且,我将它与以下代码一起使用:
Image img1 = convertToGrayScale(new Image(filepath));
BufferedImage img2 = new BufferedImage((int) img1.getWidth(), (int) img1.getHeight(), BufferedImage.TYPE_INT_ARGB);
saveBadImage(img2, file);
而且,它工作得很好!
谢谢大家,希望我的见解能对一些人有所帮助