Dislan
Dislan

Reputation: 21

Java. Broken image from URL

I am trying to load this image from URL, but receive image like this.

Code:

@Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D)g;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            try {
                URL url = new URL("http://s.developers.org.ua/img/announces/java_1.jpg");
                BufferedInputStream in = new BufferedInputStream(url.openStream());
                byte[] b = new byte[512];
                while (in.read(b)!=-1)
                    out.write(b);
                Image img = ImageIO.read(new ByteArrayInputStream(out.toByteArray()));
                g2.drawImage(img, 0, 0, getWidth(), getHeight(), null);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

Upvotes: 1

Views: 1107

Answers (3)

Harald K
Harald K

Reputation: 27113

  1. Don't read images inside the paintComponent method, it will make your application appear sluggish, as the method is executed on the event dispatcher thread (EDT). Also, it will be re-read, whenever your component is re-painted, meaning you'll download the image over and over. Instead, read it up front, or in a separate thread (ie. use a SwingWorker), and only invoke g.drawImage(...) from inside the paintComponent method.

  2. The reason for the broken image is your byte copying code, where you don't pay attention to how many bytes are read (as long as the value isn't -1), but instead unconditionally copy 512 bytes. However, you don't need to do that here, you can simply pass the stream to ImageIO.read, like this, making the code simpler and more readable:

    URL url = new URL("http://s.developers.org.ua/img/announces/java_1.jpg");
    try (BufferedInputStream in = new BufferedInputStream(url.openStream())) {
        BufferedImage img = ImageIO.read(in);
    }
    

    Adding the extra try (try-with-resources) block makes sure your stream is also properly closed to avoid resource leaks.

  3. For completeness, to fix the byte copying code, the correct version would be:

    // ... as above ...
    byte[] b = new byte[512];
    int bytesRead; // Keep track of the number of bytes read into 'b'
    while ((bytesRead = in.read(b)) != -1)
        out.write(b, 0, bytesRead);
    

Upvotes: 2

Gilad
Gilad

Reputation: 841

I don't know if this is the only problem, but you might write more than you get. I suggest that you change your writing code to:

int len;
while ((len=in.read(b))!=-1)
    out.write(b, 0, len);

Otherwise, if the last buffer is not exactly 512 bytes long, you'll write too much

Upvotes: 1

ag3ng
ag3ng

Reputation: 66

I have some code copy file from URL to Local.. So far the result is same like actual source. Just do some modification maybe can help to solved it.

import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import org.apache.commons.io.FilenameUtils;
import javax.imageio.ImageIO;

public class ImagesUrlToImagesLocal {
    public ArrayList<String> getIt(ArrayList<String> urlFile)
    {
        ArrayList<String> strResult = new ArrayList<String>();
        Image imagesUrl = null;
        String baseName = null;
        String extension = null;
        File outputfile = null;
        try {
            for (int i = 0; i < urlFile.size(); i++)
            {
                URL url = new URL(urlFile.get(i));
                baseName = FilenameUtils.getBaseName(urlFile.get(i));
                extension = FilenameUtils.getExtension(urlFile.get(i));
                imagesUrl = ImageIO.read(url);
                BufferedImage image = (BufferedImage) imagesUrl;
                outputfile = new File("temp_images/" + baseName + "." + extension);
                ImageIO.write(image, extension, outputfile);
                strResult.add("temp_images/" + baseName + "." + extension);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return strResult;
    }
}

Upvotes: 0

Related Questions