Search code examples
javajavacvargbjwindow.mov

Play an ARGB .mov video in a transparent JWindow


I'm trying to code a splash screen for my program cause it takes too long to open.

I managed to do it with an image but I have no idea how to do it with an ARGB video.

First, I've tried with an image: (on a JWindow extended class)

JLabel l = new JLabel("");
JPanel p = new JPanel();

setSize(1024, 1024);
setBackground(new Color(0, 0, 0, 0));
setLocationRelativeTo(null);

l.setBounds(0, 0, 1024, 1024);
l.setIcon(new ImageIcon(ImageIO.read(getClass().getResourceAsStream("/" + splashName))));

p.setBounds(0, 0, 1024, 1024);
p.setBackground(new Color(0, 0, 0, 0));
p.add(l);

add(p);
setVisible(true);

Original splash image: example.png

Screenshot when I execute the code: screenshot.png

It worked perfectly.

After that, I made the splash screen animation with After Effects (The same splash image rotating). Yes, I surely exported the .mov video in RGB + Alpha and ffmpeg tells me the same.

So, I've tried with JavaCV library using FFmpegFrameGrabber.grabImage(); but the result is a lot strange. (i know the code isn't much good but I first wanna let it works)

JLabel l = new JLabel("");
JPanel p = new JPanel();

grabber = new FFmpegFrameGrabber(splashPath);

setSize(1024, 1024);
setLocationRelativeTo(null);

p.setBackground(new Color(0, 0, 0, 0));
p.setBounds(0, 0, 1024, 1024);

l.setIcon(new ImageIcon(ImageIO.read(getClass().getResourceAsStream("/icon4.png"))));
l.setBounds(0, 0, 1024, 1024);

p.add(l);

add(p);

grabber.start();

Frame frame;
BufferedImage bi = new BufferedImage(grabber.getImageWidth(), grabber.getImageHeight(), BufferedImage.TYPE_INT_ARGB);

while((frame = grabber.grabImage()) != null) {
    bi = new BufferedImage(grabber.getImageWidth(), grabber.getImageHeight(), BufferedImage.TYPE_INT_ARGB);
    Java2DFrameConverter.copy(frame, bi);
    showFrame(bi);
    Thread.sleep(16);
}
grabber.stop();




private void showFrame(BufferedImage frame) {
    p.removeAll();
    l.setIcon(new ImageIcon(frame));
    p.add(l);
    repaint();
}

Screenshot when I execute the code: screenshot2.png

From the screenshot, we can see that the video is resized (less width) and there are some strange transparent blue lines were other colors were supposed to be.

So my questions are:

  1. How can I fix it?
  2. Is JavaCV the issue?
  3. Is there any other way to play a transparent video as a splash screen in java?

Solution

  • Thanks to Samuel Audet, i figured out that The pixel format of the frames returned by FFmpeg is RGBA, not ARGB.

    We can easily change the FFMpegFrameGrabber's pixel format by calling setPixelFormat() before start().

    There is a list of every avaible pixel format here: list

    In my case, this is the final solution:

    grabber = new FFmpegFrameGrabber(splashPath);
    grabber.setPixelFormat(avutil.AV_PIX_FMT_ARGB);
    grabber.start();