0

I have a jframe with a button to crop image, and im using the Marvin libray to manipulate images. Whenever i clic the button the new cropped image is created in the folder after i close the jframe window. I have no idea why this is happening and how to make it work real time. Appreciate any help

Gui.java

      cropBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
               System.out.println("Cropped successfully");
           
             ImageManipulator.cropImage(60, 32, 182, 62);
           }
        });

Crop method

 static MarvinImage cropImage(int x, int y, int width, int height) {
        MarvinImage image = MarvinImageIO.loadImage("image.jpeg");
        crop(image.clone(), image, x, y, width, height);
        MarvinImageIO.saveImage(image, String.format("cropped-image-%s.%s", dateFormat.format(new Date()), format));
        return image;
    }
   public static void crop(MarvinImage imageIn, MarvinImage imageOut, int x, int y, int width, int height) {
        x = Math.min(Math.max(x, 0), imageIn.getWidth());
        y = Math.min(Math.max(y, 0), imageIn.getHeight());
        if (x + width > imageIn.getWidth()) {
            width = imageIn.getWidth() - x;
        }

        if (y + height > imageIn.getHeight()) {
            height = imageIn.getHeight() - y;
        }

        crop = checkAndLoadImagePlugin(crop, "org.marvinproject.image.segmentation.crop");
        crop.setAttribute("x", x);
        crop.setAttribute("y", y);
        crop.setAttribute("width", width);
        crop.setAttribute("height", height);
        crop.process(imageIn, imageOut);
    }
Rowan Frank
  • 117
  • 6
  • From the code snippets in your question, it looks like you are cropping the image clone but you are saving the same image that you loaded. – Abra Nov 23 '21 at 13:38
  • @abra, I imagine that the `crop()` function is overwriting the original image. My guess is that the arguments are something like (source, destination). Either way, that wouldn't explain OP's problem – thetechnician94 Nov 23 '21 at 13:47
  • 1
    *I have no idea why this is happening* - neither do we. This should happen real time unless the Marvin API does some kind of caching. You need to read the API as there is nothing that appears to be wrong with the posted code based on a best guess of how it should work. In the meantime there is no need to use the Marvin API. Just use the ImageIO class to read/write the Image. You can then use the BufferedImage class to crop the image. The code would be almost identical to the code posted here. – camickr Nov 23 '21 at 15:08

1 Answers1

0

I'm not 100% certain, but I think your problem is that you are running your cropping function on the event dispatch thread.

Try giving it its own thread:

  cropBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
               System.out.println("Cropped successfully");
               new Thread(new ImageThread()).start();
            }
        });

public class ImageThread implements Runnable{
   @Override
        public void run() {
            ImageManipulator.cropImage(60, 32, 182, 62);
         }
}
thetechnician94
  • 545
  • 2
  • 21
  • Thank you, unfortunately the issue persists – Rowan Frank Nov 23 '21 at 13:35
  • Hmm, Im still thinking something is happening on the event dispatch thread. That would make sense. Are you running your frame with `java.awt.EventQueue.invokeLater()`? – thetechnician94 Nov 23 '21 at 13:40
  • No, Im not using it – Rowan Frank Nov 23 '21 at 13:59
  • 1
    @RowanFrank, oh. Java Swing is not thread safe. Its a requirement to use invoke later. See here https://stackoverflow.com/questions/5780936/java-eventqueue-why-should-everything-be-in-invokelater-method – thetechnician94 Nov 23 '21 at 14:14
  • Let me see this, I didn't know about that. Thanks a bunch – Rowan Frank Nov 23 '21 at 14:17
  • Thank you, checking that out. So, the issue is caused by the lack of invoke later? – Rowan Frank Nov 23 '21 at 14:19
  • @RowanFrank, it could be. Running a swing app on the main thread is bound to create weirdness, but cant say for certain that will be your fix. For sure you need to do it though. I cant troubleshoot a program effectively that is unstable :) – thetechnician94 Nov 23 '21 at 14:21
  • Added the invokeLater part, still the same issue. This is tough – Rowan Frank Nov 23 '21 at 14:38
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/239487/discussion-between-thetechnician94-and-rowan-frank). – thetechnician94 Nov 23 '21 at 14:45
  • There should be no need to use invokeLater() or a separate Thread. Cropping an image is something that happens right away since you want to capture the frame as it currently is. Saving the image should also happen right away. If it doesn't, then the issue is with the Marvin library. – camickr Nov 23 '21 at 15:03
  • @camickr I doubt the issue is the library here, since the saving is happening during the clean up from the EDT (or main thread in his initial case). I dont think its a coincidence that the thread doing the IO is stuck waiting for the JFrame to terminate. – thetechnician94 Nov 23 '21 at 15:20