当前位置: 首页 > 面试题库 >

Java(swing)gif在不应被视为透明的情况下部分透明

赵星华
2023-03-14
问题内容

我正在尝试在Java应用程序中显示动画gif。到目前为止,它可以
显示和设置动画,但是在应该是全黑或
全白的情况下,它似乎变得透明了,我可以看到
下面绘制的矩形的颜色。例如,这是我正在使用的gif之一:

真正奇怪的是,它似乎在
第一帧中正确显示,然后才混乱。这是我
用来获取和绘制图像的方法:

//Draw title
img = new ImageIcon(Display.class.getResource(titlePath)).getImage();
g.drawImage(img, 404, 430, this);

我在扩展JPanel的类中重写paintcomponent,并且只
对该类调用一次repaint。

可能是什么原因造成的,这是一个已知问题,还是我在
实际绘制图像的方式上犯了一个错误?我没有
找到有关此问题的任何文档。

提前致谢!

这是两个原始gif
文件。

编辑:这是我编写的代码示例。我删除了所有不必要的代码以
使其简短,但保留与该问题相关的所有内容。这也可能是值得一
提的是,当我画一个PNG文件(这是用来创建帧中的一个
的GIF)用同样的方法也没有问题。如果相关,该gif是在
http://gifmaker.me/上制作的。

public class Display extends JPanel implements Constants{
    private GameData GD;
    private String currentImagePath;

    public Display(GameData gd){
        GD = gd;
        this.setPreferredSize(screenDimension);

        this.repaint();
    }

    public void draw(Location loc){
        currentImagePath = loc.getCurrentImagePath();

        this.repaint();
    }

    @Override
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.setColor(CYAN);
        g.fillRect(0, 0, screenW, screenH);

        Image img;

        if(OtherWorlds.isOnTitle == true){ //Title screen
            //Draw image
            img = new ImageIcon(Display.class.getResource(currentImagePath)).getImage();
            g.drawImage(img, 10, 10, this);

            //Draw other stuff

        {
        else{ //Regular location

            //Draw image
            img = new ImageIcon(Display.class.getResource(currentImagePath)).getImage();
            g.drawImage(img, 10, 10, this);

            //Other images and stuff in different areas
            //Drawn using the exact same method as above

            }

            //Random other lines and stuff
        }
    }
}

问题答案:

当你永远有这些类型的问题,你想开始玩弄与disposalMethod帧。

我跑了通过一些检查代码的GIF,发现disposalMethod到被设置为RESTORE_TO_BACKGROUND

所以,基本上,我把你的GIF和运行它通过下面的代码,它创建了一个新的GIF用disposalMethodnone

因此,原始图像位于顶部,“固定”图像位于底部。在
背景为红色来突出差异

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.imageio.IIOException;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.FileImageOutputStream;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class MirrorImage {

    public static void main(String[] args) {
        new MirrorImage();
    }

    public MirrorImage() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private ImageIcon orig;
        private ImageIcon mirror;

        public TestPane() {
            mirror(new File("Qzlxj.gif"), new File("Test.gif"));
            orig = new ImageIcon("Qzlxj.gif");
            mirror = new ImageIcon("Test.gif");
        }

        @Override
        public Dimension getPreferredSize() {
            return mirror == null ? new Dimension(200, 200) : new Dimension(orig.getIconWidth(), orig.getIconHeight() * 2);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (orig != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                int x = (getWidth() - orig.getIconWidth()) / 2;
                int y = (getHeight() - (orig.getIconHeight() * 2)) / 2;
                g2d.drawImage(orig.getImage(), x, y, this);

//                AffineTransform at = new AffineTransform();
//                at.setToScale(1, -1);
//                at.translate(0, -mirror.getIconHeight());
//                g2d.setTransform(at);
                g2d.drawImage(mirror.getImage(), x, y + mirror.getIconHeight(), this);
                g2d.dispose();
            }
        }
    }

    public static void mirror(File source, File dest) {

        List<BufferedImage> images = new ArrayList<>(25);
        List<Integer> delays = new ArrayList<>(25);
        int delay = 0;

        ImageOutputStream output = null;
        GifSequenceWriter writer = null;

        try {

            String[] imageatt = new String[]{
                "imageLeftPosition",
                "imageTopPosition",
                "imageWidth",
                "imageHeight"
            };

            ImageReader reader = (ImageReader) ImageIO.getImageReadersByFormatName("gif").next();
            ImageInputStream ciis = ImageIO.createImageInputStream(source);
            reader.setInput(ciis, false);
            int noi = reader.getNumImages(true);
            BufferedImage master = null;

            for (int i = 0; i < noi; i++) {

                BufferedImage image = reader.read(i);
                IIOMetadata metadata = reader.getImageMetadata(i);

                Node tree = metadata.getAsTree("javax_imageio_gif_image_1.0");
                NodeList children = tree.getChildNodes();
                for (int j = 0; j < children.getLength(); j++) {
                    Node nodeItem = children.item(j);
                    System.out.println(nodeItem.getNodeName());
                    if (nodeItem.getNodeName().equals("ImageDescriptor")) {
                        Map<String, Integer> imageAttr = new HashMap<String, Integer>();
                        NamedNodeMap attr = nodeItem.getAttributes();
//                        for (int index = 0; index < attr.getLength(); index++) {
//                            Node node = attr.item(index);
//                            System.out.println("----> " + node.getNodeName() + "=" + node.getNodeValue());
//                        }
                        for (int k = 0; k < imageatt.length; k++) {
                            Node attnode = attr.getNamedItem(imageatt[k]);
                            imageAttr.put(imageatt[k], Integer.valueOf(attnode.getNodeValue()));
                        }

                        if (master == null) {
                            master = new BufferedImage(imageAttr.get("imageWidth"), imageAttr.get("imageHeight"), BufferedImage.TYPE_INT_ARGB);
                        }

                        Graphics2D g2d = master.createGraphics();
                        g2d.drawImage(image, imageAttr.get("imageLeftPosition"), imageAttr.get("imageTopPosition"), null);
                        g2d.dispose();

//                        BufferedImage frame = mirror(copyImage(master));
                        BufferedImage frame = copyImage(master);
                        ImageIO.write(frame, "png", new File("img" + i + ".png"));
                        images.add(frame);

                    } else if (nodeItem.getNodeName().equals("GraphicControlExtension")) {
                        NamedNodeMap attr = nodeItem.getAttributes();
                        Node delayNode = attr.getNamedItem("delayTime");
                        if (delayNode != null) {
                            delay = Math.max(delay, Integer.valueOf(delayNode.getNodeValue()));
                            delays.add(delay);
                        }
                    }
                }

            }

            output = new FileImageOutputStream(dest);
            writer = new GifSequenceWriter(output, images.get(0).getType(), delay * 10, true);

            for (int i = 0; i < images.size(); i++) {
                BufferedImage nextImage = images.get(i);
                writer.writeToSequence(nextImage);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                writer.close();
            } catch (Exception e) {
            }
            try {
                output.close();
            } catch (Exception e) {
            }
        }
    }

    public static BufferedImage mirror(BufferedImage img) {

        BufferedImage mirror = createCompatibleImage(img);
        Graphics2D g2d = mirror.createGraphics();
        AffineTransform at = new AffineTransform();
        at.setToScale(1, -1);
        at.translate(0, -img.getHeight());
        g2d.setTransform(at);
        g2d.drawImage(img, 0, 0, null);
        g2d.dispose();

        return mirror;

    }

    public static BufferedImage copyImage(BufferedImage img) {
        int width = img.getWidth();
        int height = img.getHeight();

        BufferedImage newImage = createCompatibleImage(img);
        Graphics graphics = newImage.createGraphics();

        int x = (width - img.getWidth()) / 2;
        int y = (height - img.getHeight()) / 2;

        graphics.drawImage(img, x, y, img.getWidth(), img.getHeight(), null);
        graphics.dispose();

        return newImage;
    }

    public static BufferedImage createCompatibleImage(BufferedImage image) {
        return getGraphicsConfiguration().createCompatibleImage(image.getWidth(), image.getHeight(), image.getTransparency());
    }

    public static GraphicsConfiguration getGraphicsConfiguration() {
        return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
    }

    public static class GifSequenceWriter {

        protected ImageWriter gifWriter;
        protected ImageWriteParam imageWriteParam;
        protected IIOMetadata imageMetaData;

        /**
         * Creates a new GifSequenceWriter
         *
         * @param outputStream the ImageOutputStream to be written to
         * @param imageType one of the imageTypes specified in BufferedImage
         * @param timeBetweenFramesMS the time between frames in miliseconds
         * @param loopContinuously wether the gif should loop repeatedly
         * @throws IIOException if no gif ImageWriters are found
         *
         * @author Elliot Kroo (elliot[at]kroo[dot]net)
         */
        public GifSequenceWriter(
                ImageOutputStream outputStream,
                int imageType,
                int timeBetweenFramesMS,
                boolean loopContinuously) throws IIOException, IOException {
            // my method to create a writer
            gifWriter = getWriter();
            imageWriteParam = gifWriter.getDefaultWriteParam();
            ImageTypeSpecifier imageTypeSpecifier
                    = ImageTypeSpecifier.createFromBufferedImageType(imageType);

            imageMetaData
                    = gifWriter.getDefaultImageMetadata(imageTypeSpecifier,
                            imageWriteParam);

            String metaFormatName = imageMetaData.getNativeMetadataFormatName();

            IIOMetadataNode root = (IIOMetadataNode) imageMetaData.getAsTree(metaFormatName);

            IIOMetadataNode graphicsControlExtensionNode = getNode(
                    root,
                    "GraphicControlExtension");

            //restoreToBackgroundColor
            //restoreToPrevious
            graphicsControlExtensionNode.setAttribute("disposalMethod", "none");
            graphicsControlExtensionNode.setAttribute("userInputFlag", "FALSE");
            graphicsControlExtensionNode.setAttribute(
                    "transparentColorFlag",
                    "FALSE");
            graphicsControlExtensionNode.setAttribute(
                    "delayTime",
                    Integer.toString(timeBetweenFramesMS / 10));
            graphicsControlExtensionNode.setAttribute(
                    "transparentColorIndex",
                    "0");

            IIOMetadataNode commentsNode = getNode(root, "CommentExtensions");
            commentsNode.setAttribute("CommentExtension", "Created by MAH");

            IIOMetadataNode appEntensionsNode = getNode(
                    root,
                    "ApplicationExtensions");

            IIOMetadataNode child = new IIOMetadataNode("ApplicationExtension");

            child.setAttribute("applicationID", "NETSCAPE");
            child.setAttribute("authenticationCode", "2.0");

            int loop = loopContinuously ? 0 : 1;

            child.setUserObject(new byte[]{0x1, (byte) (loop & 0xFF), (byte) ((loop >> 8) & 0xFF)});
            appEntensionsNode.appendChild(child);

            imageMetaData.setFromTree(metaFormatName, root);

            gifWriter.setOutput(outputStream);

            gifWriter.prepareWriteSequence(null);
        }

        public void writeToSequence(RenderedImage img) throws IOException {
            gifWriter.writeToSequence(
                    new IIOImage(
                            img,
                            null,
                            imageMetaData),
                    imageWriteParam);
        }

        /**
         * Close this GifSequenceWriter object. This does not close the
         * underlying stream, just finishes off the GIF.
         */
        public void close() throws IOException {
            gifWriter.endWriteSequence();
        }

        /**
         * Returns the first available GIF ImageWriter using
         * ImageIO.getImageWritersBySuffix("gif").
         *
         * @return a GIF ImageWriter object
         * @throws IIOException if no GIF image writers are returned
         */
        private static ImageWriter getWriter() throws IIOException {
            Iterator<ImageWriter> iter = ImageIO.getImageWritersBySuffix("gif");
            if (!iter.hasNext()) {
                throw new IIOException("No GIF Image Writers Exist");
            } else {
                return iter.next();
            }
        }

        /**
         * Returns an existing child node, or creates and returns a new child
         * node (if the requested node does not exist).
         *
         * @param rootNode the <tt>IIOMetadataNode</tt> to search for the child
         * node.
         * @param nodeName the name of the child node.
         *
         * @return the child node, if found or a new node created with the given
         * name.
         */
        private static IIOMetadataNode getNode(
                IIOMetadataNode rootNode,
                String nodeName) {
            int nNodes = rootNode.getLength();
            for (int i = 0; i < nNodes; i++) {
                if (rootNode.item(i).getNodeName().compareToIgnoreCase(nodeName)
                        == 0) {
                    return ((IIOMetadataNode) rootNode.item(i));
                }
            }
            IIOMetadataNode node = new IIOMetadataNode(nodeName);
            rootNode.appendChild(node);
            return (node);
        }
    }
}

And finally, the “fixed” gif

Fixed01Fixed02

The above is based on the investigations from Mirroring animated gif on loadin Java - ImageIcon



 类似资料:
  • 我想创建一个包含透明和半透明部分的图像,这样如果我给,比如说颜色x作为背景,透明部分将显示x颜色,半透明部分将显示颜色x的渐变阴影。 我需要这样一个图像在模板中使用,将由客户谁将有不同的颜色主题使用。 编辑:问题是如何创建既透明 编辑:我让我的问题更清楚了。在附加的图像中,有一个透明区域。想法是在图像中有一个透明区域和一个半透明区域(指向指针的区域,目前这不是半透明的),这样如果我给红色作为bg颜

  • #klem1,#klem2 { opacity:0.4; filter:alpha(opacity=40); /* For IE8 and earlier */ } #klem1:hover,#klem2:hover { opacity:1.0; filter:alpha(opacity=100); /* For IE8 and earlier */ } div.background { widt

  • 本文向大家介绍在Java Swing中创建半透明窗口,包括了在Java Swing中创建半透明窗口的使用技巧和注意事项,需要的朋友参考一下 使用JDK 7,我们可以非常容易地使用swing创建半透明的窗口。使用以下代码,可以使JFrame半透明。 示例 参见下面具有55%半透明性的窗口的示例。 输出结果

  • 我需要将编码的视频拆分为帧,同时不失去透明度。我使用以下ffmpeg命令: 这将产生一个pngs目录,但为什么每个输出帧都缺少透明度? 我已经使用了这个示例视频,其中包含一个alpha通道。看到它在背景上播放。下面是FFMPEG的一个输出帧示例:

  • 问题内容: 我想在不影响IE 8中包含元素的情况下设置div背景的不透明度。有任何解决方案,并且不回答设置1 X 1 .png图像并设置该图像的不透明度,因为我使用的是动态不透明度,并且颜色管理可以更改那 我用过但在IE 8中无法使用 和 也。 问题答案: 该风格的影响在它整个元素和一切。正确的答案是改用rgba背景色。 CSS非常简单: …前三个数字是背景色的红色,绿色和蓝色值,第四个数字是“

  • 我正在尝试脚本创建视频使用ImageMagick创建一些覆盖,然后放在一个视频的顶部。 如果我尝试直接使用ImageMagick创建的图像,透明度会被绘制为不透明。 我已经使用ImageMagick绘制命令创建了一个透明的PNG。当加载到GIMP中并进行检查时,PNG具有alpha通道,并且每个透明像素看起来具有透明度:RGBA=0,0,0,0 我可以通过获取覆盖图像,在GIMP中加载它,然后选择