I have this following code in my servlet
response.setContentType("image/gif");
String filepath = "PATH//TO//GIF.gif";
OutputStream out = response.getOutputStream();
File f = new File(filepath);
BufferedImage bi = ImageIO.read(f);
ImageIO.write(bi, "gif", out);
out.close();
This code is just returning first frame of the image.
How to achieve returning full GIF image ?
Your GIF does not animate, because you are sending only the first frame to the client. :-)
Actually, you are, because ImageIO.read reads only the first frame (and a BufferedImage can only contain a single frame/image). You are then writing that single frame to the servlet output stream, and the result will not animate (it should be possible to create animating GIFs using ImageIO, but the code to do so will be quite verbose, see How to encode an animated GIF in Java, using ImageWriter and ImageIO? and Creating animated GIF with ImageIO?).
The good news is, the solution is both simple, and will save you CPU cycles. There's no need to involve ImageIO here, if you just want to send an animated GIF that you have stored on disk. The same technique can be used to send any binary content, really.
Instead, simply do:
response.setContentType("image/gif");
String filepath = "PATH//TO//GIF.gif";
OutputStream out = response.getOutputStream();
InputStream in = new FileInputStream(new File(filepath));
try {
FileUtils.copy(in, out);
finally {
in.close();
}
out.close();
FileUtils.copy can be implemented as:
public void copy(final InputStream in, final OutputStream out) {
byte[] buffer = new byte[1024];
int count;
while ((count = in.read(buffer)) != -1) {
out.write(buffer, 0, count);
}
// Flush out stream, to write any remaining buffered data
out.flush();
}
Related
I am trying to write a simple server that uses sockets and reads images from disc when it receives http request from browser.
I am able to receive the request, read the image from disc and pass it to the browser (the browser then automatically downloads the image). However, when I try to open the downloaded image, it says:
Could not load image 'img.png'. Fatal error reading PNG image file: Not a PNG file
The same goes for all other types of extensions (jpg, jpeg, gif etc...)
Could you help me out and tell me what am I doing wrong? I suspect that there might be something wrong with the way I read the image or maybe some encoding has to be specified?
Reading the image from disc:
// read image and serve it back to the browser
public byte[] readImage(String path) {
File file = new File(FILE_PATH + path);
try {
BufferedImage image = ImageIO.read(file); // try reading the image first
// get DataBufferBytes from Raster
WritableRaster raster = image.getRaster();
DataBufferByte data = (DataBufferByte) raster.getDataBuffer();
return data.getData();
} catch (IOException ex) {
// handle exception...
}
return ("Could not read image").getBytes();
}
Writing the data via socket:
OutputStream output = clientSocket.getOutputStream();
output.write(result);
In this case, the result contains the byte array produced by the readImage method.
EDIT: second try with reading the image as normal file
FileReader reader = new FileReader(file);
char buf[] = new char[8192];
int len;
StringBuilder s = new StringBuilder();
while ((len = reader.read(buf)) >= 0) {
s.append(buf, 0, len);
byte[] byteArray = s.toString().getBytes();
}
return s.toString().getBytes();
You may use ByteArrayOutputStream, like,
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", byteArrayOutputStream);
and then you can write to socket as,
outputStream.write(byteArrayOutputStream.toByteArray());
I'm trying to use image4j 0.7 library to decode .ico file.
My code is here:
//File address
String sourceAddress="/home/tojandro/Desktop/favicon.ico";
//Read data
InputStream inputStream=new FileInputStream(sourceAddress);
ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
byte[] buffer=new byte[0xfff];
int length=-1;
while( (length=inputStream.read(buffer))>0 )
outputStream.write(buffer, 0, length);
outputStream.flush();
inputStream.close();
ByteArrayInputStream dataBuffer=new ByteArrayInputStream(outputStream.toByteArray());
//Try to decode
System.out.println("Decode begin.");
ICODecoder.read(dataBuffer); //This method could never been return.
//ICODecoder.read(new File(sourceAddress)); //This method works well.
System.out.println("Decode finished.");
My problem is:
When I decode image from file directly, the method works well;
But when I decode image from byte buffer, sometimes(some files ok and some files not) the method would never return.
Anybody could help me? Thanks.
How would I go about saving a BufferedImage straight to a zip file.
Here is my current code for saving my BufferedImage to a zip file but I do not know how to convert the BufferedImage to a InputStream so that it can be saved to the zip file.
If possible I need to save the BufferedImage straight from RAM without saving it to HDD first
byte[] buffer = new byte[1024];
try
{
FileOutputStream outputStream = new FileOutputStream(PathName + imageData.getFileNumber() + ".zip");
ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
ZipEntry imageZipOutput = new ZipEntry(imageData.getFileNumber() + ".png");
zipOutputStream.putNextEntry(imageZipOutput);
//the BufferedImage is stored in imageData.getImage();
//how would I parse the BufferedImage to the InputStream below without saving the png first but straight from RAM
InputStream in = new InputStream();
int len;
while ((len = in.read(buffer)) > 0)
{
zipOutputStream.write(buffer, 0, len);
}
in.close();
zipOutputStream.closeEntry();
zipOutputStream.close();
}
Use ImageIO.write(RenderedImage im,String formatName, OutputStream output) to write the output. Pass a ZipOutputStream for the OutputStream parameter.
Check this page for more info.
I want to show an image as it is downloading, I have the URL, and I am trying to get the image parts like this:
InputStream openStream = url.openStream();
DataInputStream dis = new DataInputStream(new BufferedInputStream(openStream));
ByteArrayOutputStream os = new ByteArrayOutputStream();
while ((s = dis.read(b)) != -1) {
os.write(b , 0, s);
support.firePropertyChange("stream", null, os);
}
This way, any listener get the stream and creates an image, this way:
if("stream".equals(evt.getPropertyName())){
try {
ByteArrayOutputStream stream = (ByteArrayOutputStream) evt.getNewValue();
byte[] byteArray = stream.toByteArray();
stream.flush();
Image createImage = Toolkit.getDefaultToolkit().createImage(byteArray);
this.getContentPane().add(new JLabel(new ImageIcon(createImage)));
} catch (IOException ex) {
Logger.getLogger(ImageTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
However, I am getting a "Premature end of JPEG file sun.awt.image.ImageFormatException: JPEG datastream contains no image" error, the image is a JPG image format, is there any library or method known to make something similar?
It would depend on the image decoder, but you could try ImageObserver. There's an example in Tracking Image Loading: MediaTracker and ImageObserver.
How can I get an InputStream from a BufferedImage object? I tried this but ImageIO.createImageInputStream() always returns NULL
BufferedImage bigImage = GraphicsUtilities.createThumbnail(ImageIO.read(file), 300);
ImageInputStream bigInputStream = ImageIO.createImageInputStream(bigImage);
The image thumbnail is being correctly generated since I can paint bigImage to a JPanel with success.
From http://usna86-techbits.blogspot.com/2010/01/inputstream-from-url-bufferedimage.html
It works very fine!
Here is how you can make an
InputStream for a BufferedImage:
URL url = new URL("http://www.google.com/intl/en_ALL/images/logo.gif");
BufferedImage image = ImageIO.read(url);
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(image, "gif", os);
InputStream is = new ByteArrayInputStream(os.toByteArray());
If you are trying to save the image to a file try:
ImageIO.write(thumb, "jpeg", new File(....));
If you just want at the bytes try doing the write call but pass it a ByteArrayOutputStream which you can then get the byte array out of and do with it what you want.
By overriding the method toByteArray(), returning the buf itself (not copying), you can avoid memory related problems. This will share the same array, not creating another of the correct size. The important thing is to use the size() method in order to control the number of valid bytes into the array.
final ByteArrayOutputStream output = new ByteArrayOutputStream() {
#Override
public synchronized byte[] toByteArray() {
return this.buf;
}
};
ImageIO.write(image, "png", output);
return new ByteArrayInputStream(output.toByteArray(), 0, output.size());