How to download animated gif from URL with Java? [duplicate] - java

This question already has answers here:
Displaying Gif animation in java
(4 answers)
Closed 8 years ago.
I have tried a lot but, all i can get is just the first image and not the animated gif.
The best solution at the moment was load an animated gif into icon, but i need the file. Here the code:
final URL url = new URL("http://www.freeallimages.com/wp-content/uploads/2014/09/animated-gif-images-2.gif");
JLabel l = new JLabel(new ImageIcon(url));
JOptionPane.showMessageDialog(null, l);
Can anyone help here?
This code just get the first image of gif (not animated):
public static void saveImage(String imageUrl, String destinationFile) throws IOException {
URL url = new URL(imageUrl);
InputStream is = url.openStream();
File file = new File(destinationFile);
file.getParentFile().mkdirs();
file.createNewFile();
OutputStream os = new FileOutputStream(destinationFile );
byte[] b = new byte[2048];
int length;
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
is.close();
os.close();
}

As far as the code is concerned, it is fine and the GIF should get downloaded properly.(Compare sizes of the original and downloaded GIF for confirmation). Now there are two points:
1. Windows Photo Viewer can not display animated GiF's, use Internet Explorer instead of it.
2. In java do not use Event-Dispatcher thread to display any animated GIF, it will not animate for sure. Try using another thread for displaying any frame containing animated GIF.
As is clear from your code, you have initialized a dialog from JOptionPane soon after initializing a JLabel with animated GIF, don't do this. All dialogs in JOptionPane are modal which will block your current thread execution and therefore you will not see any animation.

Related

How to make Java URI class to stop using a file

I have a small Java desktop application, it reads some image files and displays them. The problem is when I want to execute something (let me say, an exiftool operation) on these files, it denies because Java is still using them.
edit: This happens only on Windows, you can't write on an animated GIF file (converted to a URL object) which is being processed (being displayed) by Java, but on Ubuntu you can edit that file Metadata, system does not think the file is being processed.
Here is that part of my code.
I read the file;
ImageInputStream iis = null;
ImageReader reader = null;
iis = ImageIO.createImageInputStream(
f);
Iterator<ImageReader> imageReaders = ImageIO.getImageReaders(iis);
reader = (ImageReader) imageReaders.next();
Path pathe = f.toPath();
String mimeType = Files.probeContentType(pathe);
ImageIcon icon = null;
Here is the part I process images, resize them and make JLabel to view them.
The reason why I am not just using Java ImageIO to fill that label with an image, ImageIO can only display the first frame of an animated GIF file. Converting an image to URL this way keep the image animated (even after resized).
ImageIcon icon = null;
Integer labelWidth = this.imageLabel.getWidth();
Integer labelHeight = this.imageLabel.getHeight();
URI img;
img = f.toURI();
URL umg = img.toURL();
icon = new ImageIcon(umg);
//some calculations for setting labelWidth and labelHeight here
icon.setImage(icon.getImage().getScaledInstance(labelWidth, labelHeight,
Image.SCALE_DEFAULT));
At the end, streams are closed.
this.imageLabel.setIcon(icon);
iis.close();
reader.dispose();
And then I try to execute some exiftool commands via a process, it succesfully reads the image Metadata. But when updating the data, it says "Error renaming temporary file to C:/Users/path..." if the image is an animated GIF.
No problems occur if the image is a non animated image, JPEG, PNG or GIF, it can read and update the Metadata, I guess .
When I cancel the image displaying part of the code, I can write on the image Metadata without errors. If I read a JPEG file and display it, still no problems. If I read an animated GIF and display it (animated, does it keep the file connection open?) no modifications on this file can be done, not in my program nor on cmd.exe while the debugging session is not closed. After I quit debugging, exiftool process on cmd.exe starts working normally.
Closing ImageInputStream or ImageReader did not help.
Is there a way to make Java process (if the file is animated, I use URI, URL classes) release the file after read operation? Do these classes I mentioned have methods for releasing, closing, shutting down, kill process etc. I need to read the animated images and display them animated and make update operations on them.
thanks for the comments, here is the problem and the solution.
First of all I removed the unnecessary parts from the code. ImageInputStream and ImageReader were used to check image validation and detect image format (had to use different operations to GIF files) which I do not need anymore.
I still need to use File->URI->URL convertion to display animated GIFs. This is my old code.
URI img = f.toURI();
URL umg = img.toURL();
icon = new ImageIcon(umg);
This code kept connection to file open and blocked other processes editing the image file. (Only animated GIF files, on Windows system)
Here is the new code:
//these 2 lines are same
URI img = f.toURI();
URL umg = img.toURL();
InputStream is = umg.openStream();
byte[] byteChunk = new byte[4096];
int n;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ((n = is.read(byteChunk)) > 0)
{
baos.write(byteChunk, 0, n);
}
byte[] dd= baos.toByteArray();
icon = new ImageIcon(dd);
is.close();
With this approach URI(image) is read via stream and ImageIcon is created from image file's byte array not directly from URL, and after that operation InputStream is closed, so the block on that file is released. (If "is.close()" line is not executed, file is still being processed and blocked for other write operations)
Have you tried to load the image with Toolkit.createImage method?
Give this a go:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.io.File;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Main {
private static class DrawPanel extends JPanel {
private Image i = null;
public void loadImage(final File f) {
//Most important point: load image via Toolkit.
//I think it must support GIF, JPEG and PNG.
i = getToolkit().createImage(f.getAbsolutePath());
repaint();
}
#Override
protected void paintComponent(final Graphics g) {
super.paintComponent(g);
if (i != null) {
//g.drawImage(i, 0, 0, this); //Draw full scale image.
g.drawImage(i, 0, 0, getWidth(), getHeight(), this); //Draw scaled/streched image.
//Supplying 'this' in place of ImageObserver argument to the drawImage method is also very important!
}
}
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(() -> {
final DrawPanel imagePanel = new DrawPanel();
imagePanel.setPreferredSize(new Dimension(500, 350));
final JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
fileChooser.setMultiSelectionEnabled(true);
final JButton load = new JButton("Load");
load.addActionListener(e -> {
if (fileChooser.showOpenDialog(imagePanel) == JFileChooser.APPROVE_OPTION)
imagePanel.loadImage(fileChooser.getSelectedFile());
});
final JPanel contents = new JPanel(new BorderLayout());
contents.add(imagePanel, BorderLayout.CENTER);
contents.add(load, BorderLayout.PAGE_END);
final JFrame frame = new JFrame("Images");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(contents);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
There are several createImage methods to choose from.
I think they support animated GIFs, and non-animated JPGs and PNGs. I tested only for a GIF, but I have also worked with this in the past for JPGs and PNGs.
I think the animated image is completely loaded into memory (all frames). So you shouldn't have problem modifying the image after reading it.
Get the Toolkit related to the Component which will display the Image. I think also the Toolkit.getDefaultToolkit should do the job under certain circumstances. Then use the drawImage method of the Graphics object to draw the image. There are several drawImage methods to choose from. You can you use for example the one that scales the image on the fly for you (by supplying new width and height along with the draw location). Important: make sure you supply the drawImage with the component which renders it as the ImageObserver (note Component implements ImageObserver).

Writing a GIF image over PNG image

I wonder if there is a way in java to put a gif image over png image at particular location (say at particular value of x,y). If so please help me through this.
This is the case :
I have a base Image which is of png type. and I have gif images of size 62*62. I wanted to put several such gif images on png image and I need to render the png image on front end at every 5 seconds..
To extract image from GIF file.. This save the first image into png file from GIF.
try {
ImageReader reader = ImageIO.getImageReadersByFormatName("gif").next();
ImageInputStream stream = ImageIO.createImageInputStream(new File("c:/aaa.gif");
reader.setInput(stream);
int count = reader.getNumImages(true);
if(count>0){
BufferedImage frame = reader.read(0);
ImageIO.write(frame, "png", new File(filePath+fileName+".png"));
System.out.println("Donesss");
}
} catch (IOException ex) {
}

How to save an image received through network in java

image is successfully received at the server side and I can display it on label
but my Problem is how to save that image
I have used
JFileChooser.showSaveDialog()
I tried printstream. I can save the file but whenever I opened the file in image viewer it is showing as this type of file is cant be opened
BufferedImage img=ImageIO.read(ImageIO.createImageInputStream(sock.getInputStream()));
System.out.println("Image received!!!!");
JFileChooser fc = new JFileChooser();
int i=fc.showSaveDialog(null);
if( i == JFileChooser.APPROVE_OPTION ) {
PrintStream ps = new PrintStream(fc.getSelectedFile());
// ImageIO.write(bimg,"JPG",fc.getInputStream());
ps.print( img);
ps.close();
lblNewLabel.setIcon(new ImageIcon(img)); //image is successfully displaying on the label
}
You're writing the "object" representation of the image, only if your load it through PrintStream would you have a chance of seeing it again.
Try using something like...
ImageIO.write(img,"JPG",fc.getSelectedFile());
instead

Understand an gif is animated or not in JAVA

I have a gif image and I would like to be able to detect whether the gif is an animated gif or not using JAVA. This question is about detection rather than displaying the gif.
I see that MIME type of animated gif isn't different of static gif.
How I can do it?
You need an ImageReader. if size is 1 its not animated, everything above is animated.
Check this out:
public Snippet() {
File f = new File("test.gif");
ImageReader is = ImageIO.getImageReadersBySuffix("GIF").next();
ImageInputStream iis;
try {
iis = ImageIO.createImageInputStream(f);
is.setInput(iis);
int images= is.getNumImages(true);
} catch (IOException e) {
e.printStackTrace();
}
}

Resize image java with Scalr, Incorrect output image, grey [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Resize an image in Java - Any Open Source Library?
I wish I could resize the image just before recording! I tried several times but without success. Could you tell me the procedure. I would like to use imgscarlr or better. thank you
private static void getImages(String src,String Name) throws IOException {
String folder = null;
//Exctract the name of the image from the src attribute
int indexname = src.lastIndexOf("/");
if (indexname == src.length()) {
src = src.substring(1, indexname);
}
indexname = src.lastIndexOf("/");
String name = src.substring(indexname, src.length());
System.out.println(name);
//Open a URL Stream
URL url = new URL(src);
InputStream in = url.openStream();
OutputStream out = new BufferedOutputStream(new FileOutputStream( folderPath+ name));
for (int b; (b = in.read()) != -1;) {
out.write(b);
}
BufferedImage originalImage = ImageIO.read(new File(folderPath+name));
BufferedImage scaledImage = Scalr.resize(originalImage, 200);
ImageIO.write(scaledImage, "jpg", new File(folderPath+name));
}
}
I'ts ok but according to the pictures, I have a problem with sampling the gray part !!!
You'd need to "load" the image first, take a look at ImageIO API for more details, after that, depending on your needs, it's relatively simple to scale the image
UPDATE
Reading image from URL
Image scaling API
Multi-step, hi-quality scaling
I had forget out.close(); now it's work

Categories

Resources