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 动画作为叠加