在Java中加载时镜像动画gif-ImageIcon

在Java中加载时镜像动画gif-ImageIcon,第1张

在Java中加载时镜像动画gif-ImageIcon

正如您所指出的,问题是gif动画化。

除非您非常想承担必须自己渲染每个帧的工作,否则唯一的选择是AffineTransform在paint方法中使用with。

一般来说,您应该不会在渲染方面看到明显的不同。

如果您真的很绝望,则可以在外部预先渲染gif并提供镜像版本

更新了“一种”工作示例

这是一个组合,这个和这个答案,使用此GIF作家。

基本上,此示例所做的是读取原始gif图像,逐帧镜像,然后写回镜像文件。

然后,它会将原始文件和镜像文件都以ImageIcons的形式加载回去,这主要是因为我真的不愿意重新发明用于显示动画gif的轮子。是的,您可以执行此 *** 作,并且将在其中提供所需的一切。

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("java_animated.gif"), new File("Mirror.gif")); orig = new ImageIcon("java_animated.gif"); mirror = new ImageIcon("Mirror.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));  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;                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"); 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);        }                public void close() throws IOException { gifWriter.endWriteSequence();        }                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(); }        }                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);        }    }}

注意事项

Gif编写器当前仅适用于固定速率的gif。应该可以更改此设置,但是我没有时间。

基本上,据我了解,您需要将“帧”延迟传递给该writeToSquence方法。在这种方法中,您将需要构造IIOmetadata具有所有必需属性的适当属性,再加上帧延迟…

使用原始gif播放后更新

我正在玩的GIF已优化。也就是说,每个帧都“添加”到了动画中,而不是一个全新的帧。您的情况恰恰相反。每帧都是完整的图像。

现在,您可以通过多种方法进行检查,但是现在,我不会感到烦恼…

而是…在mirror(File, File)方法中,我对其进行了更改,以使每个帧都创建一个新的图像,而不是使用单个“主”图像BufferedImage

BufferedImage frame = new BufferedImage(imageAttr.get("imageWidth"), imageAttr.get("imageHeight"), BufferedImage.TYPE_INT_ARGB);Graphics2D g2d = frame.createGraphics();g2d.drawImage(image, imageAttr.get("imageLeftPosition"), imageAttr.get("imageTopPosition"), null);g2d.dispose();frame = mirror(frame);ImageIO.write(frame, "png", new File("img" + i + ".png"));images.add(frame);

我还更新了,GifSequenceWriter以将元数据设置为也更接近原始数据…

graphicsControlExtensionNode.setAttribute("disposalMethod", "restoreToBackgroundColor");graphicsControlExtensionNode.setAttribute("userInputFlag", "FALSE");graphicsControlExtensionNode.setAttribute(        "transparentColorFlag",        "TRUE");


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5427056.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-11
下一篇 2022-12-11

发表评论

登录后才能评论

评论列表(0条)

保存