I have some URL with an image there. This image updates during each request (that is, each request to the (same) URL returns a new image). Say, this URL points to CAPTCHA.
My goal is to load and display several such images in my program.
The following code loads these images to my local filesystem and works OK (that is, all the images are different, unique):
String filePath;
String urlPath;
int numOfFilesToDownload;
//Here filePath and urlPath are initialized.
//filePath points to the directory, where to save images
//urlPath is the url from where to download images
//numOfFilesToDownload is the number of files to download
for(int i = 0; i < numOfFilesToDownload; i++){
//Initializing connection
URL url = new URL(urlPath);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//Downloading image
try(InputStream is = conn.getInputStream();
FileOutputStream os = new FileOutputStream(filePath + "img" + i + ".jpg")){
int b;
while((b = is.read()) != -1)
os.write(b);
}
}
But something weird happens, when I try the following thing:
for(int i = 0; i < numOfFilesToDownload; i++){
//Initializing image from the url
URL url = new URL(urlPath);
javax.swing.ImageIcon ico = new javax.swing.ImageIcon(url);
//Showing the graphical dialog window with the image
javax.swing.JOptionPane.showMessageDialog(null, ico);
}
In the latter case, each dialog contains the same image, namely the one, downloaded during the very first iteration.
Also, the experiments show, that if you concatenate "?r=" to the urlPath (that is, a simple GET request parameter), the url will still be valid.
And the following code appears to be valid and does exactly what it has (namely each image shown is different from the previous):
for(int i = 0; i < numOfFilesToDownload; i++){
//Initializing image from the url
URL url = new URL(urlPath + "?r=" + i);
javax.swing.ImageIcon ico = new javax.swing.ImageIcon(url);
//Showing the graphical dialog window with the image
javax.swing.JOptionPane.showMessageDialog(null, ico);
}
Hence I can make a conclusion, that ImageIcon somehow remembers the URLs it handled and simply does not bother to perform the same work twice... Why and how? There's nothing in javadocs about it.
When I tried a variation of your code, it worked fine. My SSCCE:
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
public class TestUrls {
public static final String BASE_URL_PATH = "http://static.ed.edmunds-media.com/" +
"unversioned/adunit/homepage_showcase/";
public static final String[] URL_PATHS = {
"honda-odyssey-2013.png",
"chevrolet-impala-2013.png",
"mazda-cx9-2013.png",
"toyota-rav4-2013-2.png"
};
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
for (String urlPath : URL_PATHS) {
String fullUrlPath = BASE_URL_PATH + urlPath;
try {
URL url = new URL(fullUrlPath);
BufferedImage img = ImageIO.read(url);
ImageIcon icon = new ImageIcon(img);
JOptionPane.showMessageDialog(null, icon);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
}
}
Related
I am trying to implement Remote FrameBuffer Protocol using Java socket programming.
I have a server side program that takes screenshot of the entire screen using robot and store it in BufferedImage .Then I converted it into a byte array and sending it to the client .
Objective :
To display the entire screen of the server side machine in a Swing GUI of the client side.
Problem i am facing :
i am able to send the image in bytes from server and receive it from the server by the client (client.java) and convert it into a jpg image (output.jpg) using ImageIO and put that image in a Swing frame.
But i am able to see the first image in the Swing and whenever the image gets updated ,the image in the Swing is not updating or refreshing .
What I want :
I want the image to refresh and show updated image every time the server sends the image data .
client.java
package remoteclient;
import java.lang.*;
import javax.imageio.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import java.net.*;
import java.io.*;
public class client {
public static void main(String args[])throws Exception{
Socket s=new Socket("localhost",5900);
DataInputStream din=new DataInputStream(s.getInputStream());
DataOutputStream dout=new DataOutputStream(s.getOutputStream());
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int width=0,height=0;
try {
width = din.readInt(); //getting width and height from server thru socket.
height = din.readInt();
} catch (Exception e) {
e.printStackTrace();
}
JFrame f = new JFrame("Client");
JLabel label = new JLabel();
f.setSize(width, height);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
boolean continueLoop = true;
while(continueLoop)
{
try {
int len = din.readInt();
byte[] imageInByte = new byte[len];
System.out.println(len);
din.readFully(imageInByte);
System.out.println(imageInByte);
ByteArrayInputStream bis = new ByteArrayInputStream(imageInByte);
BufferedImage bImage2 = ImageIO.read(bis);
// Image im1 = bImage2.getScaledInstance(width,height, Image.SCALE_SMOOTH);
ImageIO.write(bImage2, "jpg", new File("output.jpg") );
bImage2 = ImageIO.read(new File("output.jpg"));
label.setIcon(new ImageIcon(im1));
ImageIcon icon = new ImageIcon(bImage2);
icon.getImage().flush();
label.setIcon( icon );
f.getContentPane().add(label, BorderLayout.CENTER);
f.pack();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
What I want :
I want the image to refresh and show updated image every time the server sends the image data .
Updated code with comments about demo code that should be removed from your working code:
Here's an example, using default UIManager icons, and SwingWorker, as noted in the comments to the original posting. You would instead use images from your server connection.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
public class SwingLabelWithUpdatedImage {
public static void main(String args[]) throws Exception {
final JLabel label = new JLabel("", SwingConstants.CENTER);
final JFrame frame = new JFrame("Client");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(label, BorderLayout.CENTER);
final Dimension preferredSize = new Dimension(200, 100);
frame.setPreferredSize(preferredSize);
frame.setVisible(true);
frame.pack();
final ImageUpdateWorker task = new ImageUpdateWorker(label);
task.execute();
}
public static class ImageUpdateWorker extends SwingWorker<Void, IconInfo> {
// iconInfoList is not need in your code. It's here so I can
// supply a dummy set of icons to demonstrate UI updates.
final List<IconInfo> iconInfoList;
private JLabel label;
ImageUpdateWorker(JLabel label) {
this.label = label;
// Delete this in your code
this.iconInfoList = initIconInfoList();
}
#Override
public Void doInBackground() {
boolean isTrue = true;
while (isTrue) {
// Put your socket code to read the next icon from a server.
// You don't need to do the ImageIO.write(), ImageIO.read() dance,
// unless you must save the icon to disk. In that case, you don't need
// to read it back in.
// Here, I just rotate the iconInfoList to make it
// appear as though a new icon was received.
// Your code will not have any need to do this.
Collections.rotate(iconInfoList, -1);
// Just publish the icon you create from the image
// you receive from your remote server.
publish(iconInfoList.get(0));
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void process(List<IconInfo> icons) {
// You might check for an empty list.
// #kleopatra's suggestion to get the last icon is correct.
// See https://docs.oracle.com/javase/tutorial/uiswing/concurrency/interim.html
IconInfo iconInfo = icons.get(icons.size() - 1);
label.setIcon(iconInfo.icon);
// Your code will not do this
label.setText(iconInfo.name);
// You can get the icon dimensions just from the icon,
// so you don't really need the IconInfo class.
label.setSize(iconInfo.dimension);
}
/** Demo code only. It doesn't belong in your working code.
*/
protected List<IconInfo> initIconInfoList() {
// Just a quick way to get some icons; don't need to
// fetch from a server just to demonstrate how to
// refresh the UI.
List<IconInfo> iconInfoList = UIManager.getDefaults().keySet().stream()
.filter(this::isIconKey)
.map(IconInfo::new)
.filter(iconInfo -> iconInfo.icon != null)
.collect(Collectors.toList());
return iconInfoList;
}
/** Demo code only. It doesn't belong in your working code.
*/
protected boolean isIconKey(Object key) {
return String.class.isAssignableFrom(key.getClass())
&& ((String) key).toLowerCase().contains("icon");
}
}
/** This is just a convenience to convey
* the icon and its UIManager key (i.e., name).
* Your remote server doesn't supply a name,
* so you don't really need this class.
* It's just to make the demo more expressive.
*/
public static class IconInfo {
final private String name;
final private Icon icon;
final private Dimension dimension;
IconInfo(Object name) {
this.name = name.toString();
icon = UIManager.getIcon(name);
dimension = icon == null
? new Dimension(32, 32)
: new Dimension(icon.getIconWidth(), icon.getIconHeight());
}
}
}
I am trying to download High resolution Image from URL using Java Code.
but after download to local machine, the resolution of image is decrease.
I am using below code to download, can anybody suggest me where I am making mistake.
String url = "https://s3.eu-central-1.amazonaws.com/euroc-inspect/processing/E1039585_TOP_3_1.jpg";
URL liveUrl = new URL(url);
BufferedImage bimg = ImageIO.read(liveUrl);
int width = bimg.getWidth();
int height = bimg.getHeight();
ImageIO.write(bimg, "jpg", new File("E:/img.jpg"));
System.out.println("Image Saved");
Getting the exact same resolution:
2048x1425
ImageDownloader.java:
import java.net.URL;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;
public class ImageDownloader {
public static void main(String[] args) throws Exception{
if(args.length<2) {
System.out.println("Usage: ImageDownloader <url> <localfilename>");
System.exit(1);
}
String url = args[0] ;
String targetFile = args[1];
URL liveUrl = new URL(url);
BufferedImage bimg = ImageIO.read(liveUrl);
int width = bimg.getWidth();
int height = bimg.getHeight();
ImageIO.write(bimg, targetFile.substring(targetFile.indexOf(".")), new File(targetFile));
System.out.printf("Image %s saved. (size: %dx%d)",targetFile, width, height);
}
}
original image
I'm working on a project and the goal is to have all images read with ImageIO. This seems to work for everything except GIF images (which display as a static image of the initial frame). I have seen other answers on Stack Overflow and from a thread on the Oracle forums but most require using Java's File class which I can't access due to the program's SecurityManager. I've been able to break the GIF down into an Image array and edit the metadata, but after stitching everything back together I can only display a single image.
Below is a SSCCE for the program:
import java.awt.Image;
import java.awt.Toolkit;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class GifRenderer {
public static void main(String[] args) throws Exception {
Image image = null;
byte[] imageByteArray = null;
try {
String location = "http://i.imgur.com/Ejh5gJa.gif";
imageByteArray = createByteArray(location);
// This works, but I'm trying to use ImageIO
//image = Toolkit.getDefaultToolkit().createImage(imageByteArray);
InputStream in = new ByteArrayInputStream(imageByteArray);
image = ImageIO.read(in);
} catch (IOException e) {
e.printStackTrace();
}
JFrame frame = new JFrame();
frame.setSize(300, 300);
JLabel label = new JLabel(new ImageIcon(image));
frame.add(label);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
// Constraint: This method simulates how the image is originally received
private static byte[] createByteArray(String urlString) throws IOException {
URL url = new URL(urlString);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = null;
try {
is = url.openStream ();
byte[] byteChunk = new byte[4096];
int n;
while ( (n = is.read(byteChunk)) > 0 ) {
baos.write(byteChunk, 0, n);
}
} catch (IOException e) {
e.printStackTrace ();
} finally {
if (is != null) { is.close(); }
}
return baos.toByteArray();
}
}
Some constraints worth mentioning that might not be clear:
The image is originally received as a byte array
The image should be read by ImageIO
The final result should be an Image object
The File class can't be accessed
Given these constraints is there still a way to use ImageIO to display the GIF the same way Toolkit.getDefaultToolkit().createImage() would display the image?
I am trying to save a resized picture to the user's desktop but not sure how to do that.
Here's my code so far:
mi.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String userhome = System.getProperty("user.home");
fileChooser = new JFileChooser(userhome + "\\Desktop");
fileChooser.setAutoscrolls(true);
switch (fileChooser.showOpenDialog(f)) {
case JFileChooser.APPROVE_OPTION:
BufferedImage img = null;
try {
img = ImageIO.read(fileChooser.getSelectedFile());
} catch (IOException e1) {
e1.printStackTrace();
}
Image dimg = img.getScaledInstance(f.getWidth(),
f.getHeight(), Image.SCALE_SMOOTH);
path = new ImageIcon(dimg);
configProps.setProperty("Path", fileChooser
.getSelectedFile().getPath());
imBg.setIcon(path);
break;
}
}
});
The code above resizes the imaged selected to fit the size of the JFrame then sets it to the JLabel.
This all works well but I also want to output the file to a set location lets say to the users desktop to make it easier. I'm currently looking at output stream but can't quite get my head around it.
Any help would be great.
Get the current Icon from the JLabel...
Icon icon = imgBg.getIcon();
Paint the icon to a BufferedImage...
BufferedImage img = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
icon.paintIcon(null, g2d, 0, 0);
g2d.dispose();
Save the image to a file...
ImageIO.write(img, "png", new File("ResizedIcon.png"));
(and yes, you could use a JFileChooser to pick the file location/name)
You should also take a look at this for better examples of scaling an image, this way, you could scale the BufferedImage to another BufferedImage and save the hassle of having to re-paint the Icon
You might also like to take a look at Writing/Saving an Image
This is a example which is about saving images from Web to the local.
package cn.test.net;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class ImageRequest {
/**
* #param args
*/
public static void main(String[] args) throws Exception {
//a url from web
URL url = new URL("http://img.hexun.com/2011-06-21/130726386.jpg");
//open
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
//"GET"!
conn.setRequestMethod("GET");
//Timeout
conn.setConnectTimeout(5 * 1000);
//get data by InputStream
InputStream inStream = conn.getInputStream();
//to the binary , to save
byte[] data = readInputStream(inStream);
//a file to save the image
File imageFile = new File("BeautyGirl.jpg");
FileOutputStream outStream = new FileOutputStream(imageFile);
//write into it
outStream.write(data);
//close the Stream
outStream.close();
}
public static byte[] readInputStream(InputStream inStream) throws Exception{
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
//every time read length,if -1 ,end
int len = 0;
//a Stream read from buffer
while( (len=inStream.read(buffer)) != -1 ){
//mid parameter for starting position
outStream.write(buffer, 0, len);
}
inStream.close();
//return data
return outStream.toByteArray();
}
}
Hope this is helpful to you!
I am trying to extract an image from the requested website, then save it to a folder. The only problem is that the website I am pulling the image from has multiple image formats. So the extension for the image would be either png, jpg, or gif. I need to save all of these, but I do not know how to tell my program to extract multiple formats rather than just one..
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Main {
public static void main( String[] args )
{
int avatarnum = 1;
String extension = null;
BufferedImage image = null;
extension = "jpg";
while(avatarnum <= 1000){
try {
URL url = new URL("http://forum.blockland.us/avatarUpload/avatar_"+avatarnum+"."+extension);
image = ImageIO.read(url);
try{
ImageIO.write(image, extension,new File("C:\\test\\"+avatarnum+"."+extension));
System.out.println("Write successful");
avatarnum ++;
} catch(Exception e){
System.out.println("Printing stacktrace");
e.printStackTrace();
}
avatarnum ++;
} catch (IOException e) {
System.out.println("File not found! " + avatarnum);
System.out.println("Adding one to variable and retrying..");
avatarnum ++;
}
}
System.out.println("Done");
}
}
As of now, only jpg images are being extracted from the website and saved to the folder.
For testing purposes it will only pull 1,000 images from the site.
I will be using this to make an "avatar database" if anyone was wondering.
Thanks a ton guys!
You need iterate over multiple image formats (extensions):
public static void main(String[] args) {
int avatarnum = 1;
BufferedImage image = null;
String[] extensions = { "jpg", "png", "gif", "bmp" };
while (avatarnum <= 1000) {
for (String extension : extensions) {
try {
URL url = new URL("http://forum.blockland.us/avatarUpload/avatar_" + avatarnum + "." + extension);
image = ImageIO.read(url);
try {
ImageIO.write(image, extension, new File("C:\\test\\" + avatarnum + "." + extension));
System.out.println("Write successful");
} catch (Exception e) {
System.out.println("Error on save the image");
}
} catch (IOException e) {
System.out.println("File not found! " + avatarnum + "." + extension);
}
}
avatarnum++;
}
System.out.println("Done");
}
Use an array with all valid extensions
String[] extensions = {"jpg", "png", "gif" };
And loop over all of them when retreive the URL
try {
for (String extension: extensions){
try {
URL url = new URL("http://forum.blockland.us/avatarUpload/avatar_"+avatarnum+"."+extension);
image = ImageIO.read(url);
} catch (Exception e){
//Wrong extension (or other kind of error)
}
}
...
For every image, it will fail with the wrong extensions, but will retreive the one with the correct