Java: drawImage animated gif is frozen on first frame - java

I got my code to draw my image in an applet, but it is an animated gif and it is stopped on the first frame as if it were a single image.
It is supposed to be the spooky scary skeleton dancing, but he's just standing still.
Here is my code:
import java.util.*;
import java.awt.*;
import java.applet.*;
import java.net.*;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.*;
public class Spooky extends Applet
{
Image scary, trumpet, walking;
MediaTracker mt;
AudioClip spoopy;
Graphics buffer;
Image offscreen;
Dimension dim;
public void init()
{
setLayout(null);
mt = new MediaTracker(this);
mt.addImage(scary,1);
mt.addImage(trumpet,1);
mt.addImage(walking,1);
spoopy = getAudioClip(getDocumentBase(),"spoopy.wav");
spoopy.loop();
}
public void paint(Graphics g)
{
try
{
URL url = this.getClass().getResource("spooky.gif");
BufferedImage img;
img = ImageIO.read(url);
mt.addImage(img,1);
g.drawImage(img,0,0,300,300,this);
}
catch(IOException e)
{
}
}
}

The problem is the ImageIO.read(url); method. Not sure how, but internally, it messes up the reading of the gif. Instead, construct an ImageIcon from the URL and use getImage() of the ImageIcon to get an Image
As an aside, don't load the image in the paint method. Load it in the init method.
public class Spooky extends Applet {
Image image;
public void init() {
URL url = this.getClass().getResource("spooky.gif");
image = new ImageIcon(url).getImage();
}
public void paint(Graphics g) {
super.paint(g);
g.drawImage(image, 0, 0, 300, 300, this);
}
}

I don't know if it helps but usually it is a problem of needing a separate Thread/Runnable for the animation and a separate for the rest of the code. At least that was a problem I had when I was making a small game. Try this one and let me know if it helps :)
Check this too: Displaying Gif animation in java
Update: An example I found (http://examples.oreilly.com/jswing2/code/) uses JApplet that supports gifs (Applet is the old one)
// AnimationApplet.java
// The classic animation applet rewritten to use an animated GIF.
//
import javax.swing.*;
public class AnimationApplet extends JApplet {
public void init() {
ImageIcon icon = new ImageIcon("images/rolling.gif"); // animated gif
getContentPane().add(new JLabel(icon));
}
}
Did you try not to put sound to see if animation works alone? It could be that sound needs a separate Runnable/Thread

I had a similar problem. Michail Michailidis's answer is one solution. However, if you are trying to load the GIF from an InputStream (which was the situation in my case) you will need a different solution. In this case, I would use the Toolkit class to load your image, more specifically, Toolkit#createImage(byte[]):
Image image;
try(InputStream stream = this.getClass().getResourceAsStream("/someImage.gif")) {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = stream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
image = Toolkit.getDefaultToolkit().createImage(buffer.toByteArray());
} catch (IOException e) {
e.printStackTrace();
}

Related

How to record video from a webcam in Java?

I'm developing a Java desktop application and can not find a way to record webcam video. I began using the Sarxos library to detect the connected cameras and to preview any you choose. But to get to the part of video recording in the example Xuggler is used, which is deprecated and not even you can download .. Somewhere I read that uses Humble-video, but the only example we have is to record screen, no camera ... Any help to find the way will be appreciated.
PS: I'm using JavaFX but if necessary I switch to Swing
This is a JavaCV implementation which maybe can help you:
import static com.googlecode.javacv.cpp.opencv_core.cvFlip;
import static com.googlecode.javacv.cpp.opencv_highgui.cvSaveImage;
import com.googlecode.javacv.CanvasFrame;
import com.googlecode.javacv.FrameGrabber;
import com.googlecode.javacv.VideoInputFrameGrabber;
import com.googlecode.javacv.cpp.opencv_core.IplImage;
public class GrabberShow implements Runnable {
//final int INTERVAL=1000;///you may use interval
IplImage image;
CanvasFrame canvas = new CanvasFrame("Web Cam");
public GrabberShow() {
canvas.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
}
#Override
public void run() {
FrameGrabber grabber = new VideoInputFrameGrabber(0);
int i=0;
try {
grabber.start();
IplImage img;
while (true) {
img = grabber.grab();
if (img != null) {
cvFlip(img, img, 1);// l-r = 90_degrees_steps_anti_clockwise
cvSaveImage((i++)+"-capture.jpg", img);
// show image on window
canvas.showImage(img);
}
//Thread.sleep(INTERVAL);
}
} catch (Exception e) {
}
}
}
You can modify the codes and be able to save the images in regular interval and do rest of the processing you want.
And here you can find another tutorial what could also be an option:
Java Swing Program for capturing webcam

How to keep the image onto the screen?

import java.applet.Applet;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.net.URL;
import javax.imageio.*;
import java.awt.Component;
public class ImageExample3 extends Applet
{
private BufferedImage img;
int counter = 0;
private BufferedImage next2;
Point lll;
public void init ()
{
resize (500, 500);
try
{
URL url = new URL (getCodeBase (), "Pacman.png");
img = ImageIO.read (url);
}
catch (IOException e)
{
}
repaint ();
}
public void paint (Graphics g)
{
if (counter == 0)
{
g.drawImage (img, 0, 0, null);
Dimension appletSize = this.getSize ();
lll = getLocationOnScreen ();
try
{
next2 = new Robot ().createScreenCapture (new Rectangle (lll.x, lll.y, 500, 500));
}
catch (java.awt.AWTException e)
{
}
g.drawImage (next2, 0, 0, null);
System.out.println (lll);
counter++;
}
}
}
What I am trying to do is to load a picture and then paint it, and then in the paint method, I used a point to tell me the location of the applet window on the screen and take a screenshot of it and then draw it on the applet. However, I want this to happen only once so I add a counter but whenever I run it, it draws the image and then gets replaced by a white box. What can I do to fix it?
The screen constantly needs to refresh. To show graphics, it paints an image every time the screen refreshes by calling the update method. The update method clears the screen by painting it white. Then, the update method calls the paint method (or repaint depending on context).
Because you only paint graphics once, your graphics are painted over by a blank screen and not refreshed. You need to paint your graphics every time that the screen refreshes, or they will be erased.
Always paint, but only take the screenshot once. Here's an example of the paint method:
public void paint (Graphics g)
{
g.drawImage (img, 0, 0, null);
Dimension appletSize = this.getSize ();
lll = getLocationOnScreen ();
if (counter == 0) //try taking the screenshot when counter is 0
{
try
{
next2 = new Robot ().createScreenCapture (new Rectangle (lll.x, lll.y, 500, 500));
}
catch (java.awt.AWTException e) {}
}
if (next2 != null) //if you took the screenshot and saved it to next2, draw it
g.drawImage (next2, 0, 0, null);
System.out.println (lll);
counter++;
}

Can't Load Image in Java

I want to Load an Image and use it as the Back Ground for my JPanel, This Code doesn't give me any errors or results.
I also Tried using BufferedImage and setting the File location to the path of the image, but i got an error "Can't read input file!", After some research i found this method and an easier alternative.
import javax.swing.ImageIcon;
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
public class drawArea extends JPanel {
public drawArea(){
init();
}
private void init(){
setPreferredSize( new Dimension( 570, 570 ) );
setVisible(true);
}
private void initializeGrid(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
Image img = new ImageIcon("/LinearEquations/src/exit.png").getImage();
g2d.drawImage(img, 0, 0, this);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
initializeGrid(g);
}
}
Thanks in Advance
Never ever read in an image in the paint or paintComponent method. Understand that this method largely determines the perceived responsiveness of your program, and if you slow it down by needlessly repeatedly reading in images, your users won't be happy.
Your problem is likely one of using the wrong relative path. I recommend that you try to read your image in in the init() method and storing it as a variable. Don't read it in as a File as you're doing but rather as a InputStream obtained from a class resource.
e.g.,
public class DrawArea extends JPanel {
// we've no idea if this is the correct path just yet.
private static final String IMG_PATH = "/exit.png";
public DrawArea() { // better have it throw the proper exceptions!
setPreferredSize( new Dimension( 570, 570 ) ); // not sure about this either
// setVisible(true); // no need for this
img = ImageIO.read(getClass().getResourceAsStream(IMG_PATH));
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, this);
}
}

Java Draw a GIF

I'm trying to draw a GIF using the Java Graphics API, but I'm not able to successfully draw a GIF using my below code. Only the first image or thumbnail of the GIF is drawn but it doesn't play.
public void paintComponent(Graphics g){
super.paintComponent(g);
BufferedImage img = null;
try {
URL url = new URL("GIF URL");
img = ImageIO.read(url);
} catch (Exception e) {
}
g.drawImage(img, 5, 5, this);
}
Essentially I am creating graphics for a login screen and I want to draw a GIF that loops.
EDIT: Updated my code and changed the question a bit.
You can load a gif into a BufferedImage object.
Then we paint the buffered image onto your swing component
Also one must better override the paintComponent method
It's perfectly possible to do this, you just need to have a proper way to load the frames for the image. The code I use to do this, is as so:
private static Image load(final String url) {
try {
final Toolkit tk = Toolkit.getDefaultToolkit();
final URL path = new URL(url); // Any URL would work here
final Image img = tk.createImage(path);
tk.prepareImage(img, -1, -1, null);
return img;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
This uses the Toolkit to load a gif image, since ImageIO can't properly load gifs at this time, if I recall correctly.
From there, it's so simple as doing the following in a (for example) JPanel:
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g); // clear up render
//...
g.drawImage(IMAGE, x, y, this); // ImageObserver necessary here to update
//...
}
Example:
import javax.swing.*;
import java.awt.*;
import java.net.URL;
public class GifAnimation {
public GifAnimation(){
JFrame frame = new JFrame("Gif Animation");
GifPanel panel = new GifPanel(load("http://www.thisiscolossal.com/wp-content/uploads/2013/01/3.gif"));
frame.add(panel);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
private static Image load(final String url) {
try {
final Toolkit tk = Toolkit.getDefaultToolkit();
final Image img = tk.createImage(new URL(url));
tk.prepareImage(img, -1, -1, null);
return img;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args){
EventQueue.invokeLater(new Runnable() {
public void run() {
new GifAnimation();
}
}
}
public class GifPanel extends JPanel {
private final Image image;
public GifPanel(Image image){
this.image = image;
}
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(image, 10, 10, this);
}
#Override
public Dimension getPreferredSize(){
return new Dimension(660, 660);
}
}
}
GIF animation is not directly possible by using paint method of JPanel.
I would suggest inserting a JEditorPane in the panel whenever you want to display it and show GIF in it using HTML.
Refer showing images on jeditorpane (java swing)
Although some might criticize it as a crude way, the animation works perfectly.
Hope this helps.

Sending Screen Image and Showing continuously

I am making a project for Controlling a PC from any other PC on a Network.
but when i send the image from server to client, it does not changed, just the first image is displayed.
So i am sending the captured images of server to client using GZIP compression.
Here is the Server's Code:
out = new DataOutputStream(s.getOutputStream());
zipout = new GZIPOutputStream(out);
while(true)
{
img = conn.getScreenImg(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
//Here conn is a Object of Robot Class
ImageIO.write(img, "jpeg", zipout);
Thread.sleep(200);
System.out.println("Success");
}
Client Code: displaying the Images sent by Server.
while(true)
{
try
{
img = ImageIO.read(zipin);
Graphics g = this.getGraphics();
g.drawImage(img, 0, 0, this);
Thread.sleep(100);
}
catch (Exception e)
{
e.printStackTrace();
}
}
I need Help with this. The image doesn't change on client.
and i want to know that if it is good to use GZIP here for compression for images to send over network , will it accelerate the process. or should i use some other method.
The way you are displaying the images on the client doesn't seem right to me. It would be a lot better to write a custom JPanel that would override the paintComponent method and that would handle the image rendering. Something like below:
class ImagePanel extends JPanel {
private BufferedImage image = null;
private void setImage(BufferedImage img) {
image = img;
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
if (image != null) {
g2.drawImage(image, 0, 0, null);
}
}
}
Inside your while loop you would call the setImage method on the panel. The panel in of course previously instantiated and added to a container.

Categories