ImageIcon vs. BufferedImage

I'm making an applet that will be using a fair number of transparent gifs (a total of ~5-20 megs), and don't know which type of image object would be best suited. Each image will only be a few kilobytes in size and only a few of them need to be displayed at any given time (but the set being displayed will change every now and then).
I need thumbmails to be displayed centered in two columns and then displayed in full size seperately. To do this, I'm currently using JLabels with ImageIcons for the thumbnails. I change the set being displayed by using 'myJLabel.setIcon(myImageIcon)'. I have not yet implement the part to make them display at full size. Would I have to use something like this:
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(myImageIcon.getImage(), x, y, this);
Would this create a new Image object? And hence slow the applet (or would it be unnoticable if it's only a few images)? I need to be able to display the image at precise coordinates.
Would using BufferedImages better suite my needs? I understand that they will perform faster, but I'm not sure if they might cause a problem in terms of storage space. When a BufferedImage is created, is it stored in the user's computer's RAM or their local drive? How about ImageIcons, where are they stored? If the images total 5-20 megs, will either of these methords cause a problem?

Hi,
I'm making an applet that will be using a fair number
of transparent gifs (a total of ~5-20 megs), and don't
know which type of image object would be best suited.
Each image will only be a few kilobytes in size and
only a few of them need to be displayed at any given
time (but the set being displayed will change every
now and then).Normally, I would say definitely use ImageIcons because the images that they create can be hardware accelerated behind the scenes. However, transparency currently is not accelerated. This means that most likely, the images stored inside your ImageIcons, are going to be BufferedImages anyway :-)
>
I need thumbmails to be displayed centered in two
columns and then displayed in full size seperately. To
do this, I'm currently using JLabels with ImageIcons
for the thumbnails. I change the set being displayed
by using 'myJLabel.setIcon(myImageIcon)'. I have not
yet implement the part to make them display at full
size. Would I have to use something like this:
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(myImageIcon.getImage(), x, y, this);
}Sure, that's fine! ImageIcon is not going to create a new image every time. You can make the image larger too by using:
g.drawImage(image, x, y, w, h, this);
My article on The Swing Connection talks about a couple of the drawImage calls:
http://java.sun.com/products/jfc/tsc/articles/swing2d/index.html
>
Would this create a new Image object? And hence slow
the applet (or would it be unnoticable if it's only a
few images)? I need to be able to display the image at
precise coordinates.
Would using BufferedImages better suite my needs? I
understand that they will perform faster, but I'm not
sure if they might cause a problem in terms of storage
space. When a BufferedImage is created, is it stored
in the user's computer's RAM or their local drive? How
about ImageIcons, where are they stored? If the images
total 5-20 megs, will either of these methords cause a
problem?BufferedImages are stored in RAM, as are the images inside ImageIcons. ImageIcons CAN be faster for non-transparent images. They may currently perform slightly slower for transparent images. You might just have to test it out.
By the way, if you find you're running out of memory (ie. OutOfMemoryError), you can increase the Java heap size when you run your application.
Use the -Xms and -Xmx flags to set the initial and maximum heap sizes.
For example, to give your application 64 Megs of ram to start and allow up to 128 Megs:
java -Xms64M -Xmx128M YourClassName
Good luck!
Shannon Hickey (Swing Team)

Similar Messages

  • Parsing Problems? ImageIcon and BufferedImage

    Hi to everyone
    Could I ask if I will to send ImageIcon with BufferedImage as its arguement. Then what should I receieve from the server? ImageIcon only or ImageIcon with BufferedImage as its arugement?
    Any help will be appreciated. Thank You.

    I am sending ImageIcon over to the server, hence the server will receive as ImageIcon.
    However, when I want to pass the ImageIcon which being parse to Image, this step is ok. Lastly when I want to parse the Image to BufferedImage image, I am encountering parsing problems, hence could u advise me further.
    The error message "Receiving failed: java.lang.ClassCastException"
    Any help will be appreciated. Thank You.
         public void getImage()
              //Object input = null;
            Image images = null;
              try{
                   imgIcon = (ImageIcon)oin.readObject();
                   System.out.println("Icon Width: "+imgIcon.getIconWidth());
                   while((images = imgIcon.getImage()) != null)
                        System.out.println("Images Width: "+Image.getWidth(images));
                        BufferedImage bimage = (BufferedImage)images; // PROBLEM LIES HERE
                        System.out.println("Bimage Width: "+bimage.getWidth());
                        ImageServerConnection.writeImage(bimage, "happy.jpg");
                        //String fname = "joalicia";
                        //create an new folder to store those sent images.
                        //File f = new File ("c:\\Sweet", fname);
                        //create(f);
              }catch(Exception e){
                   System.err.println("Receiving failed: "+ e);
         }

  • Creating BufferedImage from Image

    I've figured out one way to create a BufferedImage from an Image, but I'm sure it's not the best way.Image im = Toolkit.getDefaultToolkit().getImage(files.getAbsolutePath());
    JLabel jl = new JLabel(new ImageIcon(im));
    BufferedImage bim = new BufferedImage(im.getWidth(null), im.getHeight(null), BufferedImage.TYPE_BYTE_INDEXED);
    Graphics g = bim.getGraphics();
    jl.paint(bim.getGraphics());
    This works, but I'm sure there has to be a better/easier way. Any suggestions?
    Thanks,
    m

    close, the best way is this...
    public BufferedImage createBufferedImage(Image img)
    BufferedImage bimg = new BufferedImage(img.getWidth(null),img.getHeight(null),BufferedImage.TYPE_INT_RGB);//or whatever type is appropriate
    bimg.getGraphics().drawImage(img,0,0,null);
    return bimg;
    }

  • Create image from byte[]array on server side

    Hello everyone..
    I'm developing an application which will take snapshots from a mobile device, and send it to my pc via bluetooth. I have my own midlet which uses the phone camera to take the snapshot, i want to transfer that snapshot to my pc.
    The snapshot is taken is stored in an array byte.
    The image can be created on the phone itself with no problem using : image.createImage(byte[])
    my problem is that when i send the array byte via bluetooth, and receive it on the server, i cannot create the image using the :image.createImage() code
    The connection is good since i have tested by writing the content of the array in a text file.
    Piece of midlet code:
                try{
                     stream = (StreamConnection)Connector.open(url);
                     OutputStream ggt = stream.openOutputStream();
                     ggt.write(str);
                     ggt.close();
                }catch(Exception e){
                     err1  = e.getMessage();
                }where str is my array byte containing the snapshot
    And on my server side:
    Thread th = new Thread(){
                   public void run(){
                        try{
                             while(true){
                                  byte[] b = new byte[in.read()];
                                  int x=0;
                                  System.out.println("reading");
                                  r = in.read(b,0,b.length);
                                  if (r!=0){
                                       System.out.println(r);     
                                       img = Image.createImage(b, 0, r);
                                                            //other codes
                                       i get this error message:
    Exception in thread "Thread-0" java.lang.UnsatisfiedLinkError: javax.microedition.lcdui.ImmutableImage.decodeImage([BII)V
         at javax.microedition.lcdui.ImmutableImage.decodeImage(Native Method)
         at javax.microedition.lcdui.ImmutableImage.<init>(Image.java:906)
         at javax.microedition.lcdui.Image.createImage(Image.java:367)
         at picserv2$1.run(picserv2.java:70)
    Please anyone can help me here? is this the way to create the image on the server side? thx a lot

    here is exactly how i did it :
    while(true){
                                  byte[] b = new byte[in.read()];
                                  System.out.println("reading");
                                  r = in.read(b, 0, b.length);
                                  if (r!=0){
                                       Toolkit toolkit = Toolkit.getDefaultToolkit();
                                       Image img = toolkit.createImage(b, 0, b.length);
                                       JLabel label = new JLabel(new ImageIcon(img) );
                                       BufferedImage bImage = new BufferedImage(img.getWidth(label),img.getHeight(label),BufferedImage.TYPE_INT_RGB);
                                       bImage.createGraphics().drawImage(img, 0,0,null);
                                       File xd = new File("D:/file.jpg");
                                       ImageIO.write(bImage, "jpg", xd);
                                       System.out.println("image sent");
                             }Edited by: jin_a on Mar 22, 2008 9:58 AM

  • JButton not working with for loop...

    I am still very new to Java and am having trouble grasping it. I am trying to put together a program that paints a graphic and then each time the "Press Me" button is pressed, an oval randomly appears giving the impression that the picture is 'disappearing' a little at a time. When I run it now, 20 ovals randomly appear all at once instead of waiting for the button to be pushed. Does anyone have any advice for me on how to modify the code? Here is what I have so far...
    import java.awt.*;
    import java.awt.event.*;
    import java.util.*;
    import javax.swing.*;
    import java.awt.geom.*;
    public class JEraseImage extends JApplet implements ActionListener
    private ImageIcon image1 = new ImageIcon("bear.jpg");
    int startPosX = 80;
    int startPosY = 80;
    int imageWidth = 275;
    int imageHeight = 250;
    Container con = getContentPane();
    private JButton pressMeButton = new JButton("Press Me");
    public void init()
    image1 = new ImageIcon("bear.jpg");
    con.setLayout(new FlowLayout());
    con.add(pressMeButton);
    pressMeButton.addActionListener(this);
    public void paint(Graphics gr)
    gr.drawImage(image1.getImage(), 80, 80, (this));
    Graphics2D gr2D = (Graphics2D)gr;
    pressMeButton.repaint();
    gr.setColor (Color.white);
    for(int count = 0; count < 20; ++count)
    int x = (int) (Math.random() * imageWidth) + startPosX;
    int y = (int) (Math.random() * imageHeight) + startPosY;
    gr.fillOval(x, y, 50, 40);
    public void actionPerformed(ActionEvent e)
    Object source = e.getSource();
    if(source == pressMeButton)
    repaint();

    Here ya go, I think this should do it:
    import java.awt.*;
    import java.awt.event.*;
    import java.awt.image.BufferedImage;
    import java.util.*;
    import javax.swing.*;
    import java.awt.geom.*;
    public class Junk extends JApplet implements ActionListener
        private ImageIcon image1;
        BufferedImage bi;
        Graphics g;
        int x;
        int y;
        int startPosX = 80;
        int startPosY = 80;
        int imageWidth;
        int imageHeight;
        Container con = getContentPane();
        JButton pressMeButton = new JButton("Press Me");
        public void init()
           image1 = new ImageIcon("bear.jpg");
           bi = new BufferedImage(image1.getIconWidth(), image1.getIconHeight(), BufferedImage.TYPE_INT_RGB);
           g = bi.getGraphics();
           g.drawImage(image1.getImage(), 0, 0, null);
           con.setLayout(new FlowLayout());
           con.add(pressMeButton);
           pressMeButton.addActionListener(this);
        public void paint(Graphics gr){
            super.paint(gr);
            gr.drawImage(bi, startPosX, startPosY, this);
        public void actionPerformed(ActionEvent e)
           g.setColor(Color.WHITE);
           Object source = e.getSource();
           if(source == pressMeButton)
           for(int count = 0; count < 20; ++count)
                     int x = (int) (Math.random() * imageWidth) + startPosX;
                     y = (int) (Math.random() * imageHeight) + startPosY;
                     g.fillOval(x, y, 50, 40);
                     repaint();
    }Note: I've not run this.

  • Resizing an image: am I doing this right?

    Hi All,
    I'm writing a small tool to resize images. Here's what I've come up with (for the purposes of example I've hardcoded the dimentions:
            try {
                //String source="input.jpg";
                //String destination="output.jpg";
                BufferedImage SourceImage;
                SourceImage = ImageIO.read(new File(source));
                Image ScaledImage = SourceImage.getScaledInstance(400, 267,
                        Image.SCALE_AREA_AVERAGING);
                // Create a BufferedImage of our resized image, that we can 
                // use with ImageIO.write()
                BufferedImage DestinationImageOut = new BufferedImage(ScaledImage
                        .getWidth(null), ScaledImage.getHeight(null), SourceImage.getType());
                Graphics g = DestinationImageOut.getGraphics();
                g.drawImage(ScaledImage, 0, 0, null);
                ImageIO.write( DestinationImageOut,"jpg",new File(destination));
            } catch (Exception e) {
                System.out.println(e.getMessage() + " was the message");
                e.printStackTrace();
            }Is this the proper way to handle image resizing? I'm fairly new to Java, and I've never touched the image processing stuff before. There were two items in particular I wasn't sure about:
    SourceImage.getType()I saw that the BufferedImage constructor needed an image type, as an integer, and I had no idea what to pass it. I thought to check and see if my source image had a getType() function that returned an int, and sure enough, it did. So it seems to work... but I don't even know what's being passed or what it signifies.
    ImageIO.write( DestinationImageOut,"jpg",new File(destination));What are valid values for that second parameter? I found this in the docs:
    http://java.sun.com/j2se/1.4.2/docs/api/javax/imageio/ImageIO.html#write(java.awt.image.RenderedImage,%20java.lang.String,%20java.io.File)
    But it doesn't tell me anything besides "a String containg the informal name of the format." I guessed that "jpg" might work, and again, it seems to work, but I really just took a stab at what to put, rather than really understanding what that parameter signifies.
    Thanks for any feedback!

    The old method "getScaledInstance" works okay. With a BufferedImage you can get software acceleration. Here's a suggestion.
    import java.awt.*;
    import java.awt.geom.AffineTransform;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import javax.imageio.ImageIO;
    import javax.swing.*;
    public class ImageScaling
        BufferedImage orig;
        public ImageScaling(BufferedImage image)
            orig = image;
            String[] names = ImageIO.getWriterFormatNames();
            System.out.println("ImageIO writer supported formats:");
            for(int j = 0; j < names.length; j++)
                System.out.print(names[j]);
                if(j < names.length-1)
                    System.out.print(", ");
             System.out.println();
        private BufferedImage getScaledImage(double scale)
            int w = (int)(scale * orig.getWidth());
            int h = (int)(scale * orig.getHeight());
            int type = BufferedImage.TYPE_INT_RGB;
                       // orig.getType();
                       // or choose from constants in Field Summary
                       // of BufferedImage api
            BufferedImage out = new BufferedImage(w, h, type);
            Graphics2D g2 = out.createGraphics();
            AffineTransform at = AffineTransform.getScaleInstance(scale, scale);
            g2.drawRenderedImage(orig, at);
            g2.dispose();
            return out;
        private Box getContent()
            JLabel left = new JLabel(new ImageIcon(orig));
            BufferedImage scaled = getScaledImage(0.75);
            JLabel right = new JLabel(new ImageIcon(scaled));
            Box box = Box.createHorizontalBox();
            box.add(Box.createHorizontalGlue());
            box.add(left);
            box.add(Box.createHorizontalGlue());
            box.add(right);
            box.add(Box.createHorizontalGlue());
            return box;
        public static void main(String[] args) throws IOException
            String path = "images/cougar.jpg";   // 195, 296
            ClassLoader cl = ImageScaling.class.getClassLoader();
            BufferedImage bi = ImageIO.read(cl.getResourceAsStream(path));
            ImageScaling imageScaling = new ImageScaling(bi);
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setContentPane(imageScaling.getContent());
            f.setSize(400,400);
            f.setLocation(200,200);
            f.setVisible(true);
    }The BufferedImage type constants are listed in the field summary of the class api.
    The supported readers and writers are available via ImageIO methods.

  • Dissapearing Image

    I am having trouble with the following code, which reads in a set of .png images that are named 1 -26 respectively, and outputs 25 of them in a grid. I draw each image to an offscreen image, back, which I then draw to the JFrame.
    When I run the program, I see the image for a second (actually much less time) and then it dissapears.
    import javax.swing.*;
    import java.awt.*;
    import java.awt.image.*;
    public class wordtest extends JFrame{
         ImageIcon lett;
         ImageIcon [] letters;
         ImageIcon correct;
         ImageIcon incorrect;
         ImageIcon outOfPlace;
        public wordtest() {
             letters = new ImageIcon [26];
             BufferedImage back = new BufferedImage(230,230,BufferedImage.TYPE_INT_ARGB_PRE); // image to which i draw the 25 sepatate images
             outOfPlace = new ImageIcon("outofplace.png");
             try{                               // loading the 26 images
                 for(int i = 0; i < 26; i++){
                      System.out.println("Image pre-Loaded");
                   lett = new ImageIcon((i +1) + ".png");
                   letters[i] = lett;
         catch(Exception e){
              System.out.println("File loading Exception");
              System.out.println(e);
         setSize(500,500);    //set size of JFrame
        //     validate();
             Graphics2D g =  back.createGraphics();  //get the graphics context for off screen image
             int curr = 0;     //counter for drawing each image from the array
             try{
             for(int j = 0; j < 5; j++){
                  for (int k = 0; k < 5; k++){
                       System.out.println("Image pre drawn");
                       g.drawImage(letters[curr].getImage(), j*46,k*46,null);
                       System.out.println("Image drawn");
                       curr++;
             catch(Exception e ){
                  System.out.println("printing exception");
                  System.out.println(e);
             g.dispose();
             setVisible(true);
             Graphics f = getGraphics();
             f.drawImage(back,10,10,null);  //draw offscreen image
             f.dispose();
        //     validate();
        public static void main(String[] args){
             wordtest larry = new wordtest();
    }

    import java.awt.*;
    import java.awt.font.*;
    import java.awt.image.*;
    import java.io.*;
    import javax.imageio.ImageIO;
    import javax.swing.*;
    public class WT extends JFrame{
        ImageIcon[] letters;
        ImageIcon outOfPlace;
        ImageComponent imageComponent;
        public WT() {
            generateImagesToLoad();
            ImageIcon[] icons = loadImages();
            BufferedImage image = makeImage(icons);
            imageComponent = new ImageComponent(image);
            getContentPane().add(imageComponent);
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            setSize(500,500);    //set size of JFrame
            setVisible(true);
        private ImageIcon[] loadImages() {
            ImageIcon[] letters = new ImageIcon [26];
            outOfPlace = new ImageIcon("outofplace.png");
            for(int j = 0; j < 26; j++){
                letters[j] = new ImageIcon("wtImages/" + (j+1) + ".png");
                int loadStatus = letters[j].getImageLoadStatus();
                // ImageIcon doesn't throw exceptions so you have to
                // check on the loading status/success on your own.
                if(loadStatus != MediaTracker.COMPLETE) {
                    String errorStr = "letters["+j+"] loadStatus = ";
                    switch(loadStatus) {
                        case MediaTracker.ABORTED:
                            errorStr += "ABORTED";
                            break;
                        case MediaTracker.ERRORED:
                            errorStr += "ERRORED";
                    System.out.println(errorStr);
            return letters;
        private BufferedImage makeImage(ImageIcon[] letters) {
            // image to which i draw the 25 sepatate images
            BufferedImage back = new BufferedImage(230,230,BufferedImage.TYPE_INT_ARGB_PRE);
            // get the graphics context for off screen image
            Graphics2D g = back.createGraphics();
            int curr = 0;     //counter for drawing each image from the array
            try{
                for(int j = 0; j < 5; j++){
                    for (int k = 0; k < 5; k++){
                        g.drawImage(letters[curr].getImage(), j*46,k*46,null);
                        curr++;
            } catch(Exception e ){
                System.out.println("printing exception");
                System.out.println(e);
            g.dispose();
            return back;
        private void generateImagesToLoad() {
            // Make up some images to save for loading above.
            int w = 46;
            int h = 46;
            BufferedImage[] toSave = new BufferedImage[26];
            for(int j = 0; j < toSave.length; j++) {
                int type = BufferedImage.TYPE_INT_ARGB_PRE;
                toSave[j] = new BufferedImage(w, h, type);
                Graphics2D g2 = toSave[j].createGraphics();
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                                    RenderingHints.VALUE_ANTIALIAS_ON);
                g2.setPaint(Color.blue);
                g2.drawRect(0,0,w-1,h-1);
                g2.setPaint(Color.red);
                g2.setFont(g2.getFont().deriveFont(16f));
                FontRenderContext frc = g2.getFontRenderContext();
                String s = String.valueOf(j+1);
                float sw = (float)g2.getFont().getStringBounds(s, frc).getWidth();
                float sh = g2.getFont().getLineMetrics(s, frc).getAscent();
                float x = (w - sw)/2;
                float y = (h + sh)/2;
                g2.drawString(s, x, y);
            // Save the images to file.
            File folder = new File("wtImages");
            if(!folder.exists()) {
                folder.mkdir();
                for(int j = 0; j < toSave.length; j++) {
                    File file = new File(folder, (j+1)+".png");
                    try {
                        ImageIO.write(toSave[j], "png", file);
                    } catch(IOException e) {
                        System.out.println("IO Error for " + file.getPath());
        public static void main(String[] args){
            WT larry = new WT();
    class ImageComponent extends JPanel {
        BufferedImage image;
        public ImageComponent(BufferedImage image) {
            this.image = image;
            setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            int x = (getWidth() - image.getWidth())/2;
            int y = (getHeight() - image.getHeight())/2;
            g.drawImage(image, x, y, this);
    }

  • Why won;t the images render on the screen?

    Nothing changes from the default white screen. Any help? And one of the images is a large background, and the other is a small "person"
    package game;
    public class Main {
         public static void main(String[] args) {
              new Thread(new GameEngine()).start();
    package game;
    import java.io.*;
    import javax.swing.*;
    import java.awt.*;
    public class GameEngine implements Runnable {
         public GameEngine() {
              GameEngine.engine = this;
         public void run() {
         private final Sprite[] loadSpriteCache() {
              try {
                   Sprite[] spriteCache = new Sprite[10];
                   spriteCache[0] = new Sprite(Util.getBytes("background.png"));
                   spriteCache[1] = new Sprite(Util.getBytes("person.png"));
                   return spriteCache;
              } catch(IOException e) {
                   e.printStackTrace();
                   return null;
         private final UserInterface createUserInterface() {
              return new UserInterface();
         public void paint(Graphics g) {
              for(Sprite s : spriteCache) {
                   if(s != null) {
                        s.drawSprite(g, 0, 0);
                        Util.println("Rendered");
         public static GameEngine getEngine() {
              return engine;
         private static GameEngine engine;
         private Sprite[] spriteCache = loadSpriteCache();;
         private final UserInterface ui = createUserInterface();
    package game;
    import javax.swing.*;
    import java.awt.*;
    public class UserInterface extends Canvas {
         public UserInterface() {
         @Override
         public void paint(Graphics g) {
              super.paint(g);
              GameEngine.getEngine().paint(g);
         @SuppressWarnings("deprecation")
         public final JFrame createFrame() {
              JFrame frame = new JFrame();
              frame.setTitle("Simple Graphics Application");
              frame.setResizable(false);
              frame.setPreferredSize(new Dimension(700, 500));
              frame.add((Canvas)this);
              frame.pack();
              frame.show();
              return frame;
         private final JFrame frame = createFrame();
    package game;
    import java.io.*;
    import javax.swing.*;
    import java.awt.*;
    public class Sprite {
         public Sprite(byte[] rawSprite) {
              this.rawSprite = rawSprite;
         public void drawSprite(Graphics g, int X, int Y) {
              g.drawImage(sprite, X, Y, null);
         private byte[] rawSprite;
         private Image sprite;
    package game;
    import java.io.*;
    public class Util {
         public static void println(String args) {
              System.out.println(args);
         public static byte[] getBytes(String name) throws IOException {
              try {
                   File file = new File(cachePath + name);
                   byte[] data = new byte[(int)file.length()];
                   new FileInputStream(file).read(data);
                   return data;
              } catch(FileNotFoundException e) {
                   println("Could not load: " + name);
                   e.printStackTrace();
                   return null;
         public static final String cachePath = "./data/";
    }

    This code is starting a thread with an empty run method :
    package game;
    public class Main {
         public static void main(String[] args) {
              new Thread(new GameEngine()).start();
    }-> GameEngine.java
    public void run() {
    }The singleton pattern used in GameEngine needs reworking (The constructor is not private), and getEngine() returns engine without checking if it exists.
    You should also not be overriding the paint methods, especially for a game as it can be called at random.
    The draw method in Sprite is drawing an Image but the Sprite constructor takes a byte [] and does not actually initialize the Image variable with the byte [].
    I also have absolutely no idea what the Util class is for ...
    Would loading your images as ImageIcons or BufferedImages not be easier?
    Edited by: Swordwrathe on Sep 2, 2009 2:58 AM

  • Efficient loading and rendering of multiple images: Need advice

    I have an application that allows the user to customize and display full-screen consoles of various information. The console can have a background image. Additionally, the console can contain any number of components...one of which is a "Image" component.
    Both the console background and the image component can refer to multiple images...if multiple images are referenced, the displayed image switches every X seconds.
    The application has a repository into which users can load their images so that they are managed by the app.
    Now, my problem:
    In the old version of my application, I loaded ALL images into memory at startup and when users added them to the repository. This way, each image was available for display very quickly. When it needed to be displayed, I'd just scale it appropriately and display it. Problem is that this used a LOT of memory...I have the full image in memory AND the scaled image in memory.
    In the newer version of my application, I now load images from disk on demand. When an image needs to be displayed, it's loaded from disk, scaled and displayed. This uses MUCH less memory...but I'm finding that it's slow and can block my user interface from updating...
    I guess I'm probably looking at something in between where I cache the images that MIGHT be displayed by a console. That's better than loading ALL images into memory, and it's better than ALWAYS going to disk. It's just a matter of the logic around finding out what images need to be loaded...loading them in a background thread, blah blah blah.
    Anyone had to deal with a problem like this? Any suggestions?
    Here's my class that acts as the proxy to the image on disk:
    public class ImageProxy extends PersistentComponent {
         public static final long serialVersionUID = 1L;
         public static final String PROP_URL = "URL";
         private URL url;
         public ImageProxy (URL url, String name) throws InstantiationException {
              this.setName(name);
              this.setURL(url);
         public void setURL (URL url) {
              URL oldURL = this.url;
              this.url = url;
              this.changes.firePropertyChange(PROP_URL, oldURL, url);
         public static ImageProxy createImageProxy(File file, XMLParseLog parseLog)
                   throws InstantiationException {
              parseLog.inform("Creating new image");
              parseLog.right();
              ImageProxy newImageProxy = null;
              try {
                   newImageProxy = new ImageProxy(file.toURL(), file.getName());
                   newImageProxy.setSizeOnDisk(file.length());
                   newImageProxy.setLastModified(new Date(file.lastModified()));
              } catch (InstantiationException e) {
                   parseLog.error(e.getMessage());
                   parseLog.left();
                   throw e;
              } catch (MalformedURLException e) {
                   parseLog.error(e.getMessage());
                   parseLog.left();
                   throw new InstantiationException(e.getMessage());
              parseLog.left();
              return newImageProxy;
          * Returns the theImage.
          * @return ImageIcon
         public BufferedImage getImage() {
              try {
                   return ImageIO.read(this.url);
              } catch (IOException e) {
                   return new BufferedImage(100,100,BufferedImage.TYPE_INT_RGB);
         public URL getURL() {
              return url;
    }The other option (and it's an easier option) I was thinking of was to have the image proxy class cache the BufferedImage itself upon the first request.
    That way, only used images are loaded into memory. I could also then have a thread that would occasionally sweep through all the image proxies and clear out the buffered images of the ones that haven't been requested in X minutes.
    Edited by: jneau on May 18, 2008 7:38 PM
    Edited by: jneau on May 18, 2008 7:45 PM

    I had a similar problem, but with prepared SQL statements--Our solution was similar to your last comment. Without going into the details, we basically made a circular queue that cached the prepared statements, in the system we were using a the time you could only have a set number of prepared statements--and it was not very many, the queue had an aging function so when we had to have a new prepared statement we would use the handle to the one that had the most ancient last referenced time. In this manner we made sure that those statements that were being referenced frequently were the ones that were available.
    This does have a few weaknesses:
    1 - you still have to stringently manage your limited resources, in your case you're going
    to have to tune and do trial and error to find that sweet spot to balance your app.
    2 - if you have a bunch of 1 timers, then there is no benefit.

  • Convert image from color to black&white

    Hi,
    I'd like to transform a colored picture (from a gif or jpeg file for
    exemple) in a Black and White image (wbmp format). I use a
    ColorConvertOp to do that, but I don't know how to param it to have a nice
    conversion, not a pixel level conversion. Here is the code I used:
    BufferedImage bi4 = new BufferedImage(bi3.getWidth(), bi3.getHeight(),
    BufferedImage.TYPE_BYTE_BINARY);
    ColorConvertOp cco2 = new
    ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
    cco2.filter(bi3, bi4);
    Where bi3 is my original BufferedImage.
    Do you know where I can find more information on this conversion, because in
    the help I don't understand everything (I have no knowledge on picture
    conversion)?
    Thanks for all
    Vincent

    Try this example
    regards
    Stas
    import javax.swing.*;
    import java.awt.*;
    import java.awt.image.*;
    import java.io.*;
    public class Test {
    JScrollPane scroll;
    JEditorPane edit=new JEditorPane();
    public Test() throws Exception {
    JFrame frame=new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    BufferedImage sourceImage=new BufferedImage(100,100,BufferedImage.TYPE_INT_RGB);
    Graphics g=sourceImage.getGraphics();
    g.setColor(Color.red);
    g.fillRect(0,0,100,100);
    g.setColor(Color.blue);
    g.fillRect(10,10,80,80);
    g.setColor(Color.yellow);
    g.fillRect(20,20,60,60);
    g.setColor(Color.white);
    g.drawString("test",5,15);
    frame.getContentPane().add(new JLabel(new ImageIcon(sourceImage)));
    BufferedImage grayImage=new BufferedImage(100,100,BufferedImage.TYPE_BYTE_GRAY);
    grayImage.getGraphics().drawImage(sourceImage,0,0,null);
    frame.getContentPane().add(new JLabel(new ImageIcon(grayImage)),BorderLayout.SOUTH);
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.show();
    public static void main(String[] args) throws Exception {
    new Test();

  • Save TIFF file loses quality

    Hi all! I'm facing this issue: I have to write something on an image (a rectangle and some words inside it) with different colors. I take the image from the imageIcon in which it is painted and I create a new BufferedImage Which I write over. I use this code:
    BufferedImage bi = new BufferedImage(imageIcon.getIconWidth(), imageIcon.getIconHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics2D imageGraphics = bi.createGraphics();
        imageGraphics.drawImage(imageIcon.getImage(), 0, 0, null);
        imageGraphics.setColor(Color.RED);
        imageGraphics.setFont(new Font("Arial", Font.BOLD, 30));
        imageGraphics.drawString("Vistato Da: " + JDoc.JDoc.getUser(), 210, 40);
        imageGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                           RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        imageGraphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
                           RenderingHints.VALUE_FRACTIONALMETRICS_ON);
        imageGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                             RenderingHints.VALUE_ANTIALIAS_ON);
        imageGraphics.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
                             RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
        imageGraphics.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
                             RenderingHints.VALUE_COLOR_RENDER_QUALITY);
        imageGraphics.setRenderingHint(RenderingHints.KEY_RENDERING,
                             RenderingHints.VALUE_RENDER_QUALITY); 
        imageGraphics.setRenderingHint(RenderingHints.KEY_DITHERING,
                             RenderingHints.VALUE_DITHER_ENABLE);   
        imageGraphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                             RenderingHints.VALUE_INTERPOLATION_BICUBIC);     
        imageGraphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
                             RenderingHints.VALUE_STROKE_PURE);
        imageGraphics.drawString("Note: Tutto ok", 210, 140);
        BasicStroke wideStroke = new BasicStroke(8.0f);
        imageGraphics.setStroke(wideStroke);
        imageGraphics.drawRect(0, 0, 550, 200);   
        imageIcon=new ImageIcon(bi);
        try{
          ByteArrayOutputStream baos = new ByteArrayOutputStream();
          ImageIO.write(bi, "tiff", baos);
          this.imgArray = baos.toByteArray();
        //Save the file through a FileOutputStreamThe problem is that I experience a worsening in the resultant image quality..
    May someone explain to me what should I do to have a better quality?
    Thanks very much!!

    The same answer applies to any kind of file.
    You need a Digital Rights Management solution. Very expensive.

  • Best way to alter Icon color/brightness

    Hello everyone,
    I would like to know what's the best/easiest way to alter the color and brightness of an Icon IE in a JLabel.
    I wish to do something like this:
    In a panel:
    JLabel picture = null;
    picture = new JLabel(new Icon(new BufferedImage(...));
    picture.setText("");
    add(picture);and then have two methods (IE: picture.shade() and picture.unshade()) to darken and brighten the icon in the JLabel at will, to simulate "active" and "not active" statuses.
    Thank you in advance!
    Fabio.

    FabioFranchello wrote:
    JLabel picture = null;
    picture = new JLabel(new Icon(new BufferedImage(...));
    You can't create an instance of Icon since it's an interface, you should create an ImageIcon:
    JLabel picture = new JLabel(new ImageIcon(new BufferedImage(...));
    picture.setText("");This is unnecessary - picture text is already the empty string.
    and then have two methods (IE: picture.shade() and picture.unshade()) to darken and brighten the icon in the JLabel at will, to simulate "active" and "not active" statuses.You will need to change the brightness of the image: [http://java.sun.com/developer/JDCTechTips/2004/tt0210.html]

  • BufferedImage displays as streaky; smooth image not produced

    Hi all,
    I have three classes that I'm working with. One is ImageProcessor, a Class I have to process images. Another is IMAQGUI, a GUI for my IMAQ service, and the third is IMAQIceStormService.
    In IMAQIceStormService, I am using ImageProcessor to create an image from a byte[] that gets sent to me, and I'm using IMAQGUI to display the image on my GUI.
    All this is working fine, except the image does not display properly. I am getting the proper data, as I have compared the camera image to my streaky image, and saw that they are the same. The width, height, depth, and stride should all be correct; 1000x1000 pixels, 8 bits per pixel, and a stride of 0. I recently changed my ImageProcessor code to make some methods static, and I may have broken something.
    Basically, can anyone take a look at my ImageProcessor methods, and possibly give any suggestions as to why the image is not displaying correctly?
    Here is the relevant part of IMAQIceStormService:
         public void imageAcquired(long id, IMAQTypes.ImageDesc imageDesc, byte[] imageData,
              Ice.Current current) {
              IMAQGUI.appendImage(ImageProcessor.createImage(imageData, imageDesc.width, imageDesc.height));
         }IMAQTypes.ImageDesc is simply the image description. It tells me the width, height, depth, and stride of the image. As you can see, I am telling IMAQGUI to appendImage based on what returns from ImageProcessor. First, here is the relevant code from IMAQGUI:
         private static JLabel imageViewer = new JLabel(); // this gets added to the main panel in a different method
         public static void appendImage(BufferedImage image) {
              imageViewer.setIcon(new ImageIcon(image));
              imageViewer.revalidate();
         }This just sets the icon to the new image, and revalidates the JLabel so it displays the new image.
    Finally, here is the most important part. This is the relevant code from ImageProcessor:
        public static BufferedImage toImage(byte[] data, int w, int h) {
            DataBuffer buffer = new DataBufferByte(data, data.length);
            WritableRaster raster = Raster.createInterleavedRaster(buffer, w, h, w,
            1, new int[] {
                0
            } , null);
            ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
            ColorModel cm = new ComponentColorModel(cs, false, true,
            Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
            return new BufferedImage(cm, raster, false, null);
        public static BufferedImage createImage(byte[] data, int width, int height) {
              BufferedImage im = toImage(data, width, height);
            //image = toImage(data, width, height);
            BufferedImage out = createRGBImage(im);
            return out;
        public static BufferedImage createRGBImage(BufferedImage in) {
            BufferedImage output = new BufferedImage(in.getWidth(), in.getHeight(), BufferedImage.TYPE_INT_RGB);
            Graphics2D g = output.createGraphics();
            g.drawRenderedImage(in, null);
            g.dispose();
            return output;
        }I am unsure of why ImageProcessor is creating a streaky image, especially because I know the image dimensions are correct. Is there something I am missing? Does anyone see any mistakes anywhere? Does anyone have any suggestions?
    I know this is a lot of information, so thanks a lot for any help you can provide.

    Hi again,
    I'm still unsure as to what the problem is here. I thought maybe it had something to do with the GUI container, but I saved the BufferedImage to the local filesystem using ImageIO.write(), and it looks the same.
    Although no one has apparently seen any obvious problems, can someone possibly let me know if the methods are correct for what I am trying to do: convert a byte[] to a BufferedImage of RGB format?

  • How to convert BufferedImage back to Image

    I have an Image from ImageIcon and i want to cut it using BufferedImage.getSubImage(...) and now from BufferedImage i want to turn it to Image again so that i can put in ImageIcon.
    Here is my code:
    URL img = new URL(location);
    ImageIcon imgIcon = new ImageIcon(img);
    Image image = imgIcon.getImage();
    //turn image into bufferedImage via graphic draw
    BufferedImage bi = new BufferedImage(..);
    Graphics g = bi.createGraphics();
    g.drawImage(image,0,0,null);
    bi.getSubImage(...);
    // how to turn bi back to Image newImage
    any ideas??

    More correctly, BufferedImage extends Image as Image is an abstract class and not an interface.
    Shaun

  • How to get a string or byte array representation of an Image/BufferedImage?

    I have a java.awt.Image object that I want to transfer to a server application (.NET) through a http post request.
    To do that I would like to encode the Image to jpeg format and convert it to a string or byte array to be able to send it in a way that the receiver application (.NET) could handle. So, I've tried to do like this.
    private void send(Image image) {
        int width = image.getWidth(null);
        int height = image.getHeight(null);
        try {
            BufferedImage buffImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            ImageIcon imageIcon = new ImageIcon(image);
            ImageObserver observer = imageIcon.getImageObserver();
            buffImage.getGraphics().setColor(new Color(255, 255, 255));
            buffImage.getGraphics().fillRect(0, 0, width, height);
            buffImage.getGraphics().drawImage(imageIcon.getImage(), 0, 0, observer);
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            JPEGImageEncoder jpeg = JPEGCodec.createJPEGEncoder(stream);
            jpeg.encode(buffImage);
            URL url = new URL(/* my url... */);
            URLConnection connection = url.openConnection();
            String boundary = "--------" + Long.toHexString(System.currentTimeMillis());
            connection.setRequestProperty("method", "POST");
            connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
            String output = "--" + boundary + "\r\n"
                          + "Content-Disposition: form-data; name=\"myImage\"; filename=\"myFilename.jpg\"\r\n"
                          + "Content-Type: image/jpeg\r\n"
                          + "Content-Transfer-Encoding: base64\r\n\r\n"
                          + new String(stream.toByteArray())
                          + "\r\n--" + boundary + "--\r\n";
            connection.setDoOutput(true);
            connection.getOutputStream().write(output.getBytes());
            connection.connect();
        } catch {
    }This code works, but the image I get when I save it from the receiver application is distorted. The width and height is correct, but the content and colors are really weird. I tried to set different image types (first line inside the try-block), and this gave me different distorsions, but no image type gave me the correct image.
    Maybe I should say that I can display the original Image object on screen correctly.
    I also realized that the Image object is an instance of BufferedImage, so I thought I could skip the first six lines inside the try-block, but that doesn't help. This way I don't have to set the image type in the constructor, but the result still is color distorted.
    Any ideas on how to get from an Image/BufferedImage to a string or byte array representation of the image in jpeg format?

    Here you go:
      private static void send(BufferedImage image) throws Exception
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ImageIO.write(image, "jpeg", byteArrayOutputStream);
        byte[] imageByteArray = byteArrayOutputStream.toByteArray();
        URL url = new URL("http://<host>:<port>");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoOutput(true);
        connection.setRequestMethod("POST");
        OutputStream outputStream = connection.getOutputStream();
        outputStream.write(imageByteArray, 0, imageByteArray.length);
        outputStream.close();
        connection.connect();
        // alternative to connect is to get & close the input stream
        // connection.getInputStream().close();
      }

Maybe you are looking for