2

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?
Binamra
  • 164
  • 1
  • 9
Crih.exe
  • 502
  • 4
  • 16
  • javaCV is the undocumented junk of some guy - so go and figure. Of course you know the movie is a sequence of images. But if you want a movie to play within your java program there are some .....libraries - and ffmpeg can do it! – gpasch Jan 04 '21 at 21:13
  • @Marcinator The pixel format of the frames returned by FFmpeg is probably RGBA, not ARGB. Try to flip the channels by calling `Java2DFrameConverter.copy(frame, bi, 1.0, true, null)` instead. – Samuel Audet Jan 12 '21 at 03:19
  • @SamuelAudet I just tried it but nothing has changed :( – Crih.exe Jan 13 '21 at 08:30
  • 1
    It's impossible that it changes _nothing_. It must be changing something, just not the right thing. You'll need to align the pixel formats of FFmpeg and Java2D. We can change the one for FFmpegFrameGrabber before calling start() with setPixelFormat() and one of the values from here this list: https://github.com/bytedeco/javacpp-presets/blob/master/ffmpeg/src/gen/java/org/bytedeco/ffmpeg/global/avutil.java#L2354-L2868 – Samuel Audet Jan 13 '21 at 23:31
  • 1
    @SamuelAudet Ok thanks I solved by calling setPixelFormat with AV_PIX_FMT_ARGB and restoring the .copy method without flipping the channels. Another time, thanks a lot!!! I'm quite new on stack overflow so, should I create an answer solving my problem? – Crih.exe Jan 14 '21 at 07:50
  • Oh, great, you found a solution. Yes, please post it as an answer! Thanks – Samuel Audet Jan 15 '21 at 00:24

1 Answers1

1

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();
Crih.exe
  • 502
  • 4
  • 16