当你永远有这些类型的问题,你想开始玩弄与
disposalMethod帧。
我跑了通过一些检查代码的GIF,发现
disposalMethod到被设置为
RESTORE_TO_BACKGROUND
所以,基本上,我把你的GIF和运行它通过下面的代码,它创建了一个新的GIF用
disposalMethod的
none
因此,原始图像位于顶部,“固定”图像位于底部。在
背景为红色来突出差异
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; 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); } 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); } }}
And finally, the “fixed” gif
The above is based on the investigations from Mirroring animated gif on loadin Java - ImageIcon
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)