Results 1 to 8 of 8

Thread: scaling images

  1. #1
    willemjav is offline Senior Member
    Join Date
    Dec 2007
    Location
    Spain
    Posts
    1,038
    Rep Power
    8

    Default scaling images

    Scaling images, they say getScaledInstance is not ideal(?).
    But anyway my question is way I get an classcastexception:

    Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: apple.awt.OSXImage

    image = (BufferedImage) image.getScaledInstance(newwdth, newhdt, Image.SCALE_DEFAULT);

    (image is of Image)

    willemjav (I do understand now that SCALE_DEFAULT is a constant int of the class Image)

  2. #2
    willemjav is offline Senior Member
    Join Date
    Dec 2007
    Location
    Spain
    Posts
    1,038
    Rep Power
    8

    Default

    sorry, image is of BufferedImage image and not Image

  3. #3
    willemjav is offline Senior Member
    Join Date
    Dec 2007
    Location
    Spain
    Posts
    1,038
    Rep Power
    8

    Default

    If I do actually
    private pic Images;
    private image BufferedImage;

    pic = image.getScaledInstance(newwdth, newhdt, Image.SCALE_DEFAULT);

    and some later

    protected void paintComponent(Graphics g) {
    // This next line will fill component background
    // with background color specified in constructor
    // above.
    super.paintComponent(g);
    if(image != null) {
    int x = (getWidth() - image.getWidth())/2;
    int y = (getHeight() - image.getHeight())/2;
    g.drawImage(pic, x, y, this);

    }
    }

    Thinks do work.... but get pretty messy with pic on one hand and image on the other!

    So should I keep on working with BufferedImage or cast thinks into Image... what would be my criteria here?

    willemjav

  4. #4
    hardwired's Avatar
    hardwired is offline Senior Member
    Join Date
    Jul 2007
    Posts
    1,576
    Rep Power
    8

    Default

    Java Code:
    import java.awt.*;
    import java.awt.image.BufferedImage;
    import java.io.*;
    import javax.imageio.ImageIO;
    import javax.swing.*;
    
    public class ImageScaling {
        public static void main(String[] args) throws IOException {
            String path = "images/bison.jpg";
            BufferedImage image = ImageIO.read(new File(path));
            System.out.printf("src image width = %d  height = %d%n",
                               image.getWidth(), image.getHeight());
            long start = System.currentTimeMillis();
            EasyScalingPanel easy = new EasyScalingPanel(image);
            long easyEnd = System.currentTimeMillis();
            SlowScalingPanel slow = new SlowScalingPanel(image);
            long slowEnd = System.currentTimeMillis();
            System.out.printf("easy time = %.2f  slow time = %.2f%n",
                               (easyEnd-start)/1000.0,
                               (slowEnd-easyEnd)/1000.0);
            JPanel panel = new JPanel(new GridLayout(1,0));
            panel.add(easy);
            panel.add(slow);
            JOptionPane.showMessageDialog(null, panel, "", -1);        
        }
    }
    
    class EasyScalingPanel extends JPanel {
        BufferedImage image;
        final int WIDTH  = 100;
        final int HEIGHT = 125;
    
        public EasyScalingPanel(BufferedImage image) {
            this.image = image;
            setPreferredSize(new Dimension(100, 125));
        }
    
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            int x = (getWidth() - WIDTH)/2;
            int y = (getHeight() - HEIGHT)/2;
            // An easy way to scale an image on the fly.
            g.drawImage(image, x, y, WIDTH, HEIGHT, this);
        }        
    }
    
    class SlowScalingPanel extends JPanel {
        Image image;
        final int WIDTH  = 100;
        final int HEIGHT = 125;
    
        public SlowScalingPanel(BufferedImage src) {
            // Recommended for good quality.
            int hints = Image.SCALE_AREA_AVERAGING;
            image = src.getScaledInstance(WIDTH, HEIGHT, hints);
            // [i]getScaledInstance[/i] returns asynchronously
            // so we need to stop to load all the image data
            // before trying to access/use it.
            loadImage(image);
            setPreferredSize(new Dimension(100, 125));
        }
    
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            int x = (getWidth() - WIDTH)/2;
            int y = (getHeight() - HEIGHT)/2;
            g.drawImage(image, x, y, this);
        }
    
        private void loadImage(Image image) {
            MediaTracker mt = new MediaTracker(this);
            mt.addImage(image, 0);
            try {
                mt.waitForID(0);
            } catch(InterruptedException e) {
                System.out.println("load interrupted");
            }
        }
    }

  5. #5
    willemjav is offline Senior Member
    Join Date
    Dec 2007
    Location
    Spain
    Posts
    1,038
    Rep Power
    8

    Default hardwired and hardheaded monologue about scaling

    This Hardwired´s code is pretty straight foreward (the JList code, from before, contains several boxes in boxes…. like these Russian dolls, called matrioskas, you open one and find an other one, so it takes a little more to understand all).
    Especially the comment:


    // getScaledInstance returns asynchronously
    // so we need to stop to load all the image data
    // before trying to access/use it.


    Was very interesting because the scaling is controlled by a slider and each time one pulls the slide it shoots numbers at the getScaledInstance that spins nuds.
    So I repaired that in following way:

    public void stateChanged(ChangeEvent evt) {
    int scale=0;
    JSlider slidersource = (JSlider)evt.getSource();
    if (!slidersource.getValueIsAdjusting()) {
    scale = (int)slidersource.getValue();
    infotextPane.setText(" size " + scale);
    editImages.displayImage(scale);
    }

    }

    Of course I did my own (hardheaded) scaling code, which is not as correct as Hardwired´s but (again) it works (see down part). Sure I need BufferedImage/ image to get image.getWidth(); etc and later Image/ pic to do the actual scalling. Some later I will eventually crop the picture using:
    g.drawImage(img, dest_x1, dest_y1, dest_x2, dest_y2, source_x1, source_y1, source_x2, source_y2, this);
    and again later I should save the ¨new¨ image.
    I still do not have full rendiment from hardwired´s code but finally things will come together (I hope).

    so thanks again
    Hardwired,

    willemjav
    (and thanks, forum, remembering my birthday)






    protected void paintComponent(Graphics g) {
    // This next line will fill component background
    // with background color specified in constructor
    // above.
    super.paintComponent(g);
    if(image != null) {
    int x = (getWidth() - newwidth)/2;
    int y = (getHeight() - newheight)/2;
    g.drawImage(pic, x, y, this);
    drawframe(g, ((x + getWidth())/2)-(xframe/2), ((y + getHeight())/2)-(yframe/2), xframe, yframe); // here is still a small problem because the frame appears and disappears with the image


    }
    }

    public void setframe (int xframe, int yframe) {
    this.xframe = xframe;
    this.yframe = yframe;

    }


    public void displayImage(int sc) {
    this.setBackground(Color.WHITE);
    sc = sc + 1;
    if (sc < 51) {
    newwidth = (imgwidth*sc)/50; // the scaling is still a little strange
    newheight = (imgheight*sc)/50;
    }
    else {
    newwidth = (imgwidth*sc)/45;
    newheight = (imgheight*sc)/45;
    }

    Dimension d = new Dimension(newwidth,
    newheight);
    pic = image.getScaledInstance(newwidth, newheight, Image.SCALE_DEFAULT);

    setPreferredSize(d);
    revalidate();
    repaint();
    }

    public void drawframe(Graphics g, int x, int y, int wdth, int hght) {

    g.setColor(Color.RED); // the frame has the size of the applet
    g.drawRect(x, y, wdth, hght); // and will crop some later the image... still in process

    }

    }

  6. #6
    willemjav is offline Senior Member
    Join Date
    Dec 2007
    Location
    Spain
    Posts
    1,038
    Rep Power
    8

    Default

    (the slider runs from 0 to 100, 1-50 decrease, 50-100 increase)

  7. #7
    hardwired's Avatar
    hardwired is offline Senior Member
    Join Date
    Jul 2007
    Posts
    1,576
    Rep Power
    8

    Default

    Java Code:
    import java.awt.*;
    import java.awt.image.BufferedImage;
    import java.io.*;
    import java.util.Hashtable;
    import javax.imageio.ImageIO;
    import javax.swing.*;
    import javax.swing.event.*;
    
    public class SlidingScale extends JPanel {
        Dimension size = new Dimension(100,100);
        BufferedImage source;
        BufferedImage scaled;
        double scale = 1.0;
    
        public SlidingScale(BufferedImage image) {
            source = image;
            scaleImage();
        }
    
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            int x = (getWidth() - size.width)/2;
            int y = (getHeight() - size.height)/2;
            g.drawImage(scaled, x, y, this);
        }
    
        public Dimension getPreferredSize() {
            return size;
        }
    
        private void scaleImage() {
            int w = (int)(scale*source.getWidth());
            int h = (int)(scale*source.getHeight());
            int type = BufferedImage.TYPE_INT_RGB;
            scaled = new BufferedImage(w, h, type);
            Graphics2D g2 = scaled.createGraphics();
            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                                RenderingHints.VALUE_INTERPOLATION_BICUBIC);
            g2.drawImage(source, 0, 0, w, h, this);
            g2.dispose();
            size.setSize(w, h);
            revalidate();
            repaint();
        }
    
        private JSlider getSlider() {
            JSlider slider = new JSlider(25, 200, 100);
            slider.setMinorTickSpacing(5);
            slider.setMajorTickSpacing(25);
            slider.setPaintTicks(true);
            slider.setLabelTable(getLabelTable(25, 200, 25));
            slider.setPaintLabels(true);
            slider.addChangeListener(new ChangeListener() {
                public void stateChanged(ChangeEvent e) {
                    int value = ((JSlider)e.getSource()).getValue();
                    scale = value/100.0;
                    //System.out.printf("scale = %.2f%n", scale);
                    scaleImage();
                }
            });
            return slider;
        }
    
        private Hashtable getLabelTable(int min, int max, int step) {
            Hashtable<Integer, JLabel> ht = new Hashtable<Integer, JLabel>();
            for(int j = min; j <= max; j += step) {
                String s = String.format("%.2f", j/100.0);
                ht.put(Integer.valueOf(j), new JLabel(s));
            }
            return ht;
        }
    
        public static void main(String[] args) throws IOException {
            String path = "images/bison.jpg";
            BufferedImage image = ImageIO.read(new File(path));
            SlidingScale test = new SlidingScale(image);
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.add(new JScrollPane(test));
            f.add(test.getSlider(), "Last");
            f.setSize(400,400);
            f.setLocation(200,200);
            f.setVisible(true);
        }
    }

  8. #8
    willemjav is offline Senior Member
    Join Date
    Dec 2007
    Location
    Spain
    Posts
    1,038
    Rep Power
    8

    Default scaling comments

    -Since not only paint() calls the paintComponent but also the system it is probably better to put only the essential code here:

    protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    int x = (getWidth() - size.width)/2;
    int y = (getHeight() - size.height)/2;
    g.drawImage(scaled, x, y, this);
    }

    -The scale var runs (in my application) from .2 to 3.
    -I am aware of the Graphics2D class. Hardwired uses the class because its results are superior? At this moment to use more sophisticated resources means more trouble (for me) so I will go into that later. So for the moment I left out the Graphics2D class.
    -Personally I find the method

    private JSlider getSlider() {
    JSlider slider = new JSlider(25, 200, 100);
    slider.setMinorTickSpacing(5);
    slider.setMajorTickSpacing(25);
    slider.setPaintTicks(true);
    slider.setLabelTable(getLabelTable(25, 200, 25));
    slider.setPaintLabels(true);
    slider.addChangeListener(new ChangeListener() {
    public void stateChanged(ChangeEvent e) {
    int value = ((JSlider)e.getSource()).getValue();
    scale = value/100.0;
    //System.out.printf("scale = %.2f%n", scale);
    scaleImage();
    }
    });
    return slider;
    }

    very interesting and informative. This compact method returns the reference to a slider that is completely set and ready to function, I like that concept very much.
    -I also do understand now these small, tiny get and set (return/ this) methods. They are gateways to send information to other class objects. Since my application consists of several separated (package) classes these methods are are very useful (when creating class objects).

    Thanks to (the code virtuoso) hardwired


    willemjav

Similar Threads

  1. XML Images
    By JavaWizz in forum XML
    Replies: 1
    Last Post: 10-17-2008, 10:19 AM
  2. images
    By amith in forum AWT / Swing
    Replies: 1
    Last Post: 05-20-2008, 10:54 AM
  3. Help using images in Java
    By toby in forum Advanced Java
    Replies: 1
    Last Post: 08-07-2007, 05:54 AM
  4. Help with images...
    By toby in forum Java Applets
    Replies: 1
    Last Post: 08-04-2007, 05:25 AM
  5. Images in JSP
    By Daniel in forum JavaServer Pages (JSP) and JSTL
    Replies: 1
    Last Post: 06-05-2007, 06:01 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •