Java:在其他动画 gif 上叠加/覆盖动画 gif

Posted

技术标签:

【中文标题】Java:在其他动画 gif 上叠加/覆盖动画 gif【英文标题】:Java: Superimpose/overlay animated gif on other animated gif 【发布时间】:2013-08-28 07:12:27 【问题描述】:

我正在制作一个小游戏。它不是动作游戏,而是益智游戏,因此性能并不那么重要。 现在,我有了主要的游戏区域,一个背景图像。在某些情况下,我想在部分背景图像上绘制其他图像。 我的问题是背景图像和叠加图像都可以是动画 gif,帧数未知(基本上,用户选择)。

现在,我要做的基本上是:绘制背景图像并对其进行动画处理(如果是 gif),然后在其上绘制 0-n 个较小的动画 gif,相对于背景图像的位置,以像素为单位坐标。 此外,它应该可以调整大小,以便图像相应地缩放/移动。

最终结果的样子:http://i.stack.imgur.com/PxdDt.png(想象一下它是动画的)

我找到了一个解决方案,它通过将布局管理器设置为 null 并使用绝对定位的带有图标的 JLabels 来使它们动画化,使用一个作为背景,另一个作为前景添加到其中:

background.setSize(backgroundIcon.getIconWidth(), backgroundIcon.getIconHeight());
foreground.setSize(foregroundIcon.getIconWidth(), foregroundIcon.getIconHeight());
background.setLocation(0, 0);
foreground.setLocation(30, 30);
background.setLayout(null);
background.add(foreground);
frame.setLayout(null);
frame.add(background);

(完整代码如下)

据我所知,将布局管理器设置为 null 是有问题的(尤其是因为我想稍后在图像中添加一些文本,尽管我会在背景标签中使用另一个标签,而不是背景标签本身或其他东西),并且以这种方式调整大小似乎是不可能的,因为我无法调整 JLabels 图像图标的大小(找到一些解决方案,将 gif 拆分为每层一个 bufferedImage 并调整它们的大小,然后再将它们重新组合在一起,通过它它会丢失帧之间的特定延迟等)。此外,由于位置应该是像素完美的,因此即使可能调整大小也可能由于舍入误差而出现问题。

现在,有没有更好的方法来做到这一点? 我可以以某种方式加载动画 gif 并手动合并它们(即使它们可能有不同数量的层),所以我只需要绘制一个图像?是否有一个布局管理器,我可以在其中手动设置组件位置,但如果您调整窗口/面板的大小,它会自动缩放它?是否有第三方图形项目可以立即完成我想做的事情?

理想情况下,如果它们不是动画,我会做类似的事情,比如构建一个合并的图像,然后调整大小并显示该图像。

完整代码:

import java.awt.Dimension;
import java.net.MalformedURLException;
import java.net.URL;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

public final class Tester  extends JFrame 
    public static void main(String[] args) throws MalformedURLException 
        new Tester();
    

    private Tester() throws MalformedURLException 
        setTitle("Tester");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Icon backgroundIcon = new ImageIcon(new URL("http://s5.favim.com/orig/51/animated-gif-gif-hands-sign-language-Favim.com-542945.gif"));
        Icon foregroundIcon = new ImageIcon(new URL("http://i.imgur.com/89HANHg.gif"));

        JLabel background = new JLabel(backgroundIcon);
        JLabel foreground = new JLabel(foregroundIcon);

        // ugly
        background.setSize(backgroundIcon.getIconWidth(), backgroundIcon.getIconHeight());
        foreground.setSize(foregroundIcon.getIconWidth(), foregroundIcon.getIconHeight());
        background.setLocation(0, 0);
        foreground.setLocation(30, 30);
        background.setLayout(null);
        background.add(foreground);
        setLayout(null);
        add(background);

        // set size of frame to size of content
        setResizable(false);
        getContentPane().setPreferredSize(new Dimension(backgroundIcon.getIconWidth(), backgroundIcon.getIconHeight()));
        pack();

        setLocationRelativeTo(null);
        setVisible(true);
    

【问题讨论】:

在你的sscce,通过URL访问发布的图片,如图here或below;使用合成图像,如图here;或者使用UIManager图标,如图here。 【参考方案1】:

这对我有用。较小的轨道图像位于较大的月相图像的中心。

import java.awt.*;
import javax.swing.*;
import java.net.*;

public final class Tester  extends JFrame 
    public static void main(String[] args) throws MalformedURLException 
        new Tester();
    

    private Tester() throws MalformedURLException 
        setTitle("Tester");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Icon backgroundIcon = new ImageIcon(
                new URL("http://1point1c.org/gif/moon/moonphases.gif"));
        Icon foregroundIcon = new ImageIcon(
                new URL("http://1point1c.org/gif/thum/plnttm.gif"));

        JLabel background = new JLabel(backgroundIcon);
        JLabel foreground = new JLabel(foregroundIcon);

        background.setLayout(new GridBagLayout());
        background.add(foreground);
        add(background);

        pack();

        setLocationByPlatform(true);
        setVisible(true);
    

【讨论】:

如果前景图像应该居中,这(或其他布局管理器)会很好,但它必须位于非常特定的位置。例如,想象一下背景图像,显示带有空画框的墙壁,在鼠标悬停时,动画 gif 应该显示(覆盖)。它必须完全在框架内,因此我能想到的所有布局管理器都行不通。 什么,所以“空画框”(不管是什么)没有居中?它是移动的,还是在静止的位置? +1 表示sscce; Klaue:OverlayLayout 可能值得一看 提示:添加@trashgod(或重要的@)以通知此人有新评论。我认为这可能是“忘记布局管理器并将所有图像绘制到JLabel 中显示的单个BufferedImage”的情况。不过我喜欢trashgod的建议.. @Klaue:使用setSize()负责正确的大小;当心这个pitfall。

以上是关于Java:在其他动画 gif 上叠加/覆盖动画 gif的主要内容,如果未能解决你的问题,请参考以下文章

Fluent-ffmpeg:在 x 时间到 y 时间之间添加 gif 动画作为叠加

iOS 上视频的动画叠加

QLabel 在 gif 上覆盖 png

使用动画 UIImageView 作为 iPhone 相机覆盖

在 CSS 悬停效果上,无法选择/应用效果到特定元素?

在 SKSpriteNode 上叠加两个纹理