-2

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: original picture

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..

dan-i
  • 11
  • 4
  • Haven't tested anything, but perhaps using [Color#grayscale()](https://openjfx.io/javadoc/17/javafx.graphics/javafx/scene/paint/Color.html#grayscale()) would work? – Slaw Dec 23 '21 at 19:42
  • thanks for your comment. i tried it now, the same problem stays. i wonder if it's a genral problem with those algorithms either it's some problem relating to MY computer / environment – dan-i Dec 23 '21 at 19:54
  • Why did you use this, `double sum = c.getRed() + c.getBlue() + c.getGreen();` when you calculated red, blue, green values? – matt Dec 23 '21 at 20:22
  • couse this methods returns double... see here: https://openjfx.io/javadoc/17/javafx.graphics/javafx/scene/paint/Color.html#getRed() – dan-i Dec 23 '21 at 20:25
  • 1
    @trashgod thank you for your comment. about the first link (problem) : it sends me to a search content but the problems there are varied and i can't find the answer, moreover i can't find what the problem you're talking about. about the 3rd link: he suggest another tecniqe, but im not sure if it's worth trying and mess all of my code again. after all, i did exactly what it's necessary to do and yet im getting a dufferent result. i need to figure out what is the problem – dan-i Dec 23 '21 at 21:12
  • 1
    Is this a duplicate if [javafx argb to grayscale conversion](https://stackoverflow.com/questions/36314805/javafx-argb-to-grayscale-conversion)? – jewelsea Dec 24 '21 at 08:24
  • [mcve] please .. mind the __M__ while still being reproducible! And one problem per question (conversion and _showing_ vs. _saving_) – kleopatra Dec 24 '21 at 11:02

2 Answers2

1

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

dan-i
  • 11
  • 4
0

I decided to work in awt, then create a javafx image.

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();
    }

}

Both methods work for me, so I'm not sure if this helps you. I can save the result too.

System.out.println("saving " +
                ImageIO.write(img2, "PNG", new File("tested.png")) );

If you're using oracles jdk, I think you can save JPEG. I am using OpenJDK which doesn't seem to be able to write JPEG.

matt
  • 10,892
  • 3
  • 22
  • 34
  • Hi, thank you. As you can see in the comments, i have tried them both (use explicit calc. and use the setGrayscale() method, but unfortunatley, it's didn't wotk ): about your comment about the "archtype", i feel a shame to admit, but i didn't understand a word from all you did there ): BTW, im using java 8.1 since javaFX is built-in in that version – dan-i Dec 23 '21 at 22:05
  • i meant to the comment of Slaw on this post. he suggested your solution. but ill take your suggestion and try to add the full code, despite i don't think it matters, the compete code is long and tedius, but all i do in the context of this method is to get the image and save it to a file with the following code: – dan-i Dec 23 '21 at 22:23
  • it's been more than 5 min. so im not allowed to edit anymore, but ill edit the original post soon – dan-i Dec 23 '21 at 22:29
  • What about the code I provided? Isn't that easy to compile and run with javafx 8? I tried to download oracles jdk but I am not going to create an account. The easiest thing is to upgrade to java 11 + javafx 11. I suspect that will solve your problem. – matt Dec 23 '21 at 22:31
  • about the "Java" code you've provided, i have tried it, and still same problem. about updating javaFX, i have tried it but Eclipse is so complicated to work with and there was a lot of problems o could'nt resolve. but it's worth trying again – dan-i Dec 23 '21 at 22:35
  • I must to say a Huge thanks for yout huge help. thank you buddy – dan-i Dec 23 '21 at 22:38
  • Did you check out this site? https://openjfx.io/openjfx-docs/ It seems to have issues if you use javafx 17, but if you use javafx 11 everything seems to work well. They also have an eclipse section. (I don't use eclipse.) – matt Dec 23 '21 at 22:42
  • i tried again with javafx 17 and java17 and java16 and java12, nothing helped, about javafx11, you can't download it without register/pay to somone there. anyway, here in my country is 1:04 PM, so the bed is calling me loud, @matt thank you for your help, im really appraciate that, ill try tomorrow to follow your instructions – dan-i Dec 23 '21 at 23:03
  • @dan-i I updated my example. It now converts the image to grayscale in awt, then creates a javafx image. It saves the image in BW just fine. – matt Dec 23 '21 at 23:25