Issue
I need to do that in my program. I have to do it in two ways:
1.) by my own, with the following code:`
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.) with the help of the openCV library, with the following code (it was copied almost perfectly from their site) :
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;
}
In both cases, the problem was that i have'nt got a "greyscale" output, just somthing different (and before you asked: yeas, i have tried to to do it on several pictures, not only one)
Here's the input picture and the output picture:
Well, as you can see, this is Not a greyscale! maybe a sunset-scale..
I'd really appraciate any help, Thank you :)
(espcially if there's something faster out there since those solutions rather takes a while to run)
If someone knows, why there is not some built in option in javaFX as there is a lot of sophisticated imageview effects and this one is so simple and so prevalent.
UPDATE: i found a website that do somthing similar to ehat i did - and somehow i got a different output! i don't get it here's the website.
and here's the output from my computer: my output
UPDATE#2: as @matt correctly asked, here's the code that use this method:
ImageIO.write(SwingFXUtils
.fromFXImage
(convertToGrayScale(new Image(getClass().getResource("1_CNc4RxV85YgthtvZh2xO5Q.jpeg").toExternalForm()) ), null), "jpg", file);
the original target was to show the image to rhe user, and the problem was there, so i changed the code to this one which save the image so i could isolate the problem more easly..
Solution
Ok guys, after some research, and endless number of attememts i got what i need to solve the problem ill show my solution here and come to a coclude of my insights about this issue..
first, ill give the the disticntion between "SAVING the file" and "Setting the file in the ImageView.
when we want just to show it in image view, i have'ne expereinced any problem using almost every solution suggested here. the most simple, short and sweet (in my opinion) is the following one:
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;
}
(for convinience, i ignored exception handling)
it works fine when i use it along when i use it along with the following code:
Image img1 = convertToGrayScale(new Image(filepath);
imageView.setImage(img1);
about SAVING this output image, after some research and using @trashgold 's references, and this important one :
i got my solution as the following:
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);
}
and, i use it with the following code:
Image img1 = convertToGrayScale(new Image(filepath));
BufferedImage img2 = new BufferedImage((int) img1.getWidth(), (int) img1.getHeight(), BufferedImage.TYPE_INT_ARGB);
saveBadImage(img2, file);
and, it works perfectly!
Thank you all guys, and i hope my insights will help to some people
Answered By - dan-i
Answer Checked By - David Marino (JavaFixing Volunteer)