0

currently i am loading image in Jframe swing component through BufferedImage. Image loaded successfully but i want to make image stretchable when user select bottom-right corner of image & try to resize it then it would be make possible. & user can save that resized image but how to do that i dont't have exact idea. so if anyone guide me then i will be so thankful. i dont want whole code but i just want guidance and hint.

my code is as follow:

import java.io.File;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.color.ColorSpace;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.image.BufferedImage;
import java.awt.image.RescaleOp;
import javax.imageio.ImageIO;

@SuppressWarnings("serial")
public class Brighten extends JPanel{
   @Override
   public void paintComponent(Graphics g){
      Graphics2D g2d=(Graphics2D)g;
      try{

          //reading image data from file

          BufferedImage src=ImageIO.read(new File("src.jpg"));

          /* passing source image and brightening by 50%-value of 1.0f means original brightness */
          BufferedImage dest=changeBrightness(src,1.5f);

          //drawing new image on panel
          g2d.drawImage(dest,0,0,this);

          //writing new image to a file in jpeg format
          ImageIO.write(dest,"jpeg",new File("dest.jpg"));
      }catch(Exception e){
            e.printStackTrace();
      }
   }


   public BufferedImage changeBrightness(BufferedImage src,float val){
       RescaleOp brighterOp = new RescaleOp(val, 0, null);
       return brighterOp.filter(src,null); //filtering
   }

   public static void main (String[] args) {
       JFrame jf=new JFrame("BRIGHTEN");
       Brighten obj=new Brighten();
       jf.getContentPane().add(obj);
       jf.setVisible(true);
       jf.setSize(325,270);
       jf.setDefaultCloseOperation(jf.EXIT_ON_CLOSE);
    }
}

hope anyone help me soon..

  • You could start by taking a look at [maintaining aspect ratio of JPanel background image](http://stackoverflow.com/questions/11959758/java-maintaining-aspect-ratio-of-jpanel-background-image/11959928#11959928) and [How to write a Mouse Listener](http://docs.oracle.com/javase/tutorial/uiswing/events/mouselistener.html) – MadProgrammer Aug 05 '13 at 08:06
  • note: your implementation of paintComponent is violating the panel's opacity contract! Either set it to false or call super before your custom painting – kleopatra Aug 05 '13 at 08:29

2 Answers2

4

This is a basic example.

It uses a special ImagePanel that is responsible for rendering the image. It has it's own mouse listener to handle the changing of the cursor and resize operations.

The scaling algorithm is based a divide and conquer approach to provide a reasonably fast, but high quality scale.

I've not done the diagonal resize, I'll leave that to you ;)

enter image description here

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class ImageViewer {

    public static void main(String[] args) {
        new ImageViewer();
    }

    public ImageViewer() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new ViewPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class ViewPane extends JPanel {

        public ViewPane() {
            setLayout(null);
            ImagePane imagePane = new ImagePane();
            imagePane.setSize(imagePane.getPreferredSize());
            imagePane.setLocation(0, 0);
            add(imagePane);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

    public static class ImagePane extends JPanel {

        private BufferedImage bg;
        private BufferedImage scaled;

        public ImagePane() {
            try {
                bg = ImageIO.read(new File("C:\\hold\\thumbnails\\MT002.jpg"));
                scaled = getScaledInstanceToFit(bg, new Dimension(100, 100));
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            setBackground(Color.BLACK);

            MouseHandler handler = new MouseHandler();
            addMouseListener(handler);
            addMouseMotionListener(handler);
        }

        @Override
        public Dimension getPreferredSize() {
            return bg == null ? new Dimension(200, 200) : new Dimension(scaled.getWidth(), scaled.getHeight());
        }

        @Override
        public void invalidate() {
            super.invalidate();
            scaled = getScaledInstanceToFit(bg, getSize());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            int x = (getWidth() - scaled.getWidth()) / 2;
            int y = (getHeight() - scaled.getHeight()) / 2;
            g2d.drawImage(scaled, x, y, this);
            g2d.dispose();
        }

        public enum MouseAction {

            Move(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)),
            ResizeSouth(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR)),
            ResizeNorth(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR)),
            ResizeEast(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)),
            ResizeWest(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR)),
            ResizeNorthEast(Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR)),
            ResizeNorthWest(Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR)),
            ResizeSouthEast(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR)),
            ResizeSouthWest(Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR));

            private Cursor cursor;

            private MouseAction(Cursor cursor) {
                this.cursor = cursor;
            }

            public Cursor getCursor() {
                return cursor;
            }

        }

        public class MouseHandler extends MouseAdapter {

            private MouseAction action;
            private Point clickPoint;
            private Point offset;
            private boolean ignoreMoves;

            protected void updateAction(MouseEvent e) {
                int x = e.getX();
                int y = e.getY();

                int width = getWidth();
                int height = getHeight();

                if (x < 10 && y < 10) {
                    action = MouseAction.ResizeNorthWest;
                } else if (x > width - 10 && y < 10) {
                    action = MouseAction.ResizeNorthWest;
                } else if (y < 10) {
                    action = MouseAction.ResizeNorth;
                } else if (x < 10 && y > height - 10) {
                    action = MouseAction.ResizeSouthWest;
                } else if (x > width - 10 && y > height - 10) {
                    action = MouseAction.ResizeSouthEast;
                } else if (y > height - 10) {
                    action = MouseAction.ResizeSouth;
                } else if (x < 10) {
                    action = MouseAction.ResizeWest;
                } else if (x > width - 10) {
                    action = MouseAction.ResizeEast;
                } else {
                    action = MouseAction.Move;
                }
                setCursor(action.getCursor());
            }

            @Override
            public void mouseMoved(MouseEvent e) {
                if (!ignoreMoves) {
                    updateAction(e);
                }
            }

            @Override
            public void mousePressed(MouseEvent e) {
                updateAction(e);
                ignoreMoves = true;
                clickPoint = e.getPoint();
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                clickPoint = null;
                ignoreMoves = false;
            }

            @Override
            public void mouseDragged(MouseEvent e) {
                switch (action) {
                    case Move: {
                        Point p = e.getPoint();
                        p.x -= clickPoint.x;
                        p.y -= clickPoint.y;
                        p = SwingUtilities.convertPoint(ImagePane.this, p, getParent());
                        setLocation(p);
                    }
                    break;
                    case ResizeWest: {
                        Point p = e.getPoint();
                        int xDelta = p.x - clickPoint.x;
                        int width = getWidth() - xDelta;
                        int x = getX() + xDelta;
                        setSize(width, getHeight());
                        setLocation(x, getY());
                        revalidate();
                    }
                    break;
                    case ResizeEast: {
                        Point p = e.getPoint();
                        int xDelta = p.x - clickPoint.x;
                        int width = getWidth() + xDelta;
                        setSize(width, getHeight());
                        revalidate();
                        clickPoint = p;
                    }
                    break;
                    case ResizeNorth: {
                        Point p = e.getPoint();
                        int yDelta = p.y - clickPoint.y;
                        int height = getHeight() - yDelta;
                        int y = getY() + yDelta;
                        setSize(getWidth(), height);
                        setLocation(getX(), y);
                        revalidate();
                    }
                    break;
                    case ResizeSouth: {
                        Point p = e.getPoint();
                        int yDelta = p.y - clickPoint.y;
                        int height = getHeight() + yDelta;
                        setSize(getWidth(), height);
                        revalidate();
                        clickPoint = p;
                    }
                    break;
                }
            }

            @Override
            public void mouseExited(MouseEvent e) {
            }

        }

    }

    public static BufferedImage getScaledInstanceToFit(BufferedImage img, Dimension size) {
        double scaleFactor = getScaleFactorToFit(img, size);
        return getScaledInstance(img, scaleFactor);
    }

    public static BufferedImage getScaledInstance(BufferedImage img, double dScaleFactor) {
        BufferedImage imgBuffer = null;
        imgBuffer = getScaledInstance(img, dScaleFactor, RenderingHints.VALUE_INTERPOLATION_BILINEAR);

        return imgBuffer;
    }

    protected static BufferedImage getScaledInstance(BufferedImage img, double dScaleFactor, Object hint) {
        BufferedImage imgScale = img;
        int iImageWidth = (int) Math.round(img.getWidth() * dScaleFactor);
        int iImageHeight = (int) Math.round(img.getHeight() * dScaleFactor);

        if (dScaleFactor <= 1.0d) {
            imgScale = getScaledDownInstance(img, iImageWidth, iImageHeight, hint);
        } else {
            imgScale = getScaledUpInstance(img, iImageWidth, iImageHeight, hint);
        }
        return imgScale;
    }

    protected static BufferedImage getScaledDownInstance(BufferedImage img,
            int targetWidth,
            int targetHeight,
            Object hint) {

//        System.out.println("Scale down...");
        int type = (img.getTransparency() == Transparency.OPAQUE)
                ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;

        BufferedImage ret = (BufferedImage) img;

        if (targetHeight > 0 || targetWidth > 0) {
            int w, h;
            // Use multi-step technique: start with original size, then
            // scale down in multiple passes with drawImage()
            // until the target size is reached
            w = img.getWidth();
            h = img.getHeight();

            do {
                if (w > targetWidth) {
                    w /= 2;
                    if (w < targetWidth) {
                        w = targetWidth;
                    }
                }

                if (h > targetHeight) {
                    h /= 2;
                    if (h < targetHeight) {
                        h = targetHeight;
                    }
                }

                BufferedImage tmp = new BufferedImage(Math.max(w, 1), Math.max(h, 1), type);
                Graphics2D g2 = tmp.createGraphics();
                g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
                g2.drawImage(ret, 0, 0, w, h, null);
                g2.dispose();

                ret = tmp;
            } while (w != targetWidth || h != targetHeight);
        } else {
            ret = new BufferedImage(1, 1, type);
        }

        return ret;
    }

    protected static BufferedImage getScaledUpInstance(BufferedImage img,
            int targetWidth,
            int targetHeight,
            Object hint) {

        int type = BufferedImage.TYPE_INT_ARGB;

        BufferedImage ret = (BufferedImage) img;
        int w, h;
        w = img.getWidth();
        h = img.getHeight();

        do {
            if (w < targetWidth) {
                w *= 2;
                if (w > targetWidth) {
                    w = targetWidth;
                }
            }

            if (h < targetHeight) {
                h *= 2;
                if (h > targetHeight) {
                    h = targetHeight;
                }
            }

            BufferedImage tmp = new BufferedImage(w, h, type);
            Graphics2D g2 = tmp.createGraphics();
            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
            g2.drawImage(ret, 0, 0, w, h, null);
            g2.dispose();

            ret = tmp;
            tmp = null;
        } while (w != targetWidth || h != targetHeight);

        return ret;
    }

    public static double getScaleFactorToFit(BufferedImage img, Dimension size) {
        double dScale = 1;
        if (img != null) {
            int imageWidth = img.getWidth();
            int imageHeight = img.getHeight();
            dScale = getScaleFactorToFit(new Dimension(imageWidth, imageHeight), size);
        }
        return dScale;
    }

    public static double getScaleFactorToFit(Dimension original, Dimension toFit) {
        double dScale = 1d;
        if (original != null && toFit != null) {
            double dScaleWidth = getScaleFactor(original.width, toFit.width);
            double dScaleHeight = getScaleFactor(original.height, toFit.height);
            dScale = Math.min(dScaleHeight, dScaleWidth);
        }
        return dScale;
    }

    public static double getScaleFactor(int iMasterSize, int iTargetSize) {
        double dScale = 1;
        if (iMasterSize > iTargetSize) {
            dScale = (double) iTargetSize / (double) iMasterSize;
        } else {
            dScale = (double) iTargetSize / (double) iMasterSize;
        }
        return dScale;
    }
}

It would be better to have the mouse listener as part of the view panel instead of the image panel, that way you can get better reuse of the two, but I'll leave that to you

Caveats

It's important to know that when dealing with null layouts, you become responsible for the size and position of all components within the container. This increases the work load some what and should normally be avoided.

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • i have done it sir - MadProgrammer and that's only with your kind help. without it i can't reach out there. now i want to save new scaled image at predefined place then what i will have to do sir. any assistance ?? –  Aug 05 '13 at 09:29
  • 3
    You could a look at the [`Preferences` API](http://docs.oracle.com/javase/7/docs/technotes/guides/preferences/) or the [`Properties` API](http://docs.oracle.com/javase/tutorial/essential/environment/properties.html) – MadProgrammer Aug 05 '13 at 10:05
0

Check this answer to the similar question: Scala Java Image

Add the getScaledImage(...) method and instead of:

BufferedImage dest=changeBrightness(src,1.5f);

add this:

int width = this.getWidth();
int height = this.getHeight();
BufferedImage dest = getScaledImage(src, width, height);

Then you'll get a component, whose image is scaled on every repaint.

Community
  • 1
  • 1
Ostap Andrusiv
  • 4,827
  • 1
  • 35
  • 38