J'ai un programme Java qui crée plusieurs fichiers PNG (captures d'écran). Je dois maintenant trouver un moyen de créer un GIF animé à partir de ces fichiers et je n'ai aucune idée par où commencer. Comment convertir plusieurs fichiers PNG en GIF animé?Comment convertir plusieurs fichiers PNG en GIF animé?
Répondre
Adapté d'un ancien thread on Sun forums. Piles non incluses, toutes garanties & nul.
import java.awt.image.BufferedImage;
import java.io.File;
import org.w3c.dom.Node;
import javax.imageio.*;
import javax.imageio.metadata.*;
import javax.imageio.stream.ImageOutputStream;
/**
* Creates an animated GIF from GIF frames. A thin wrapper to code written by
* other people, as documented on the thread on the Sun forums 'Create animated
* GIF using imageio' http://forums.sun.com/thread.jspa?threadID=5395006 See the
* printUsage() method for details on paramaters required.
*
* @author Andrew Thompson
*/
class WriteAnimatedGif {
/**
* See http://forums.sun.com/thread.jspa?messageID=10755673#10755673
*
* @author Maxideon
* @param delayTime String Frame delay for this frame.
*/
public static void configure(IIOMetadata meta,
String delayTime,
int imageIndex) {
String metaFormat = meta.getNativeMetadataFormatName();
if (!"javax_imageio_gif_image_1.0".equals(metaFormat)) {
throw new IllegalArgumentException(
"Unfamiliar gif metadata format: " + metaFormat);
}
Node root = meta.getAsTree(metaFormat);
//find the GraphicControlExtension node
Node child = root.getFirstChild();
while (child != null) {
if ("GraphicControlExtension".equals(child.getNodeName())) {
break;
}
child = child.getNextSibling();
}
IIOMetadataNode gce = (IIOMetadataNode) child;
gce.setAttribute("userDelay", "FALSE");
gce.setAttribute("delayTime", delayTime);
//only the first node needs the ApplicationExtensions node
if (imageIndex == 0) {
IIOMetadataNode aes
= new IIOMetadataNode("ApplicationExtensions");
IIOMetadataNode ae
= new IIOMetadataNode("ApplicationExtension");
ae.setAttribute("applicationID", "NETSCAPE");
ae.setAttribute("authenticationCode", "2.0");
byte[] uo = new byte[]{
//last two bytes is an unsigned short (little endian) that
//indicates the the number of times to loop.
//0 means loop forever.
0x1, 0x0, 0x0
};
ae.setUserObject(uo);
aes.appendChild(ae);
root.appendChild(aes);
}
try {
meta.setFromTree(metaFormat, root);
} catch (IIOInvalidTreeException e) {
//shouldn't happen
throw new Error(e);
}
}
/**
* See http://forums.sun.com/thread.jspa?messageID=9988198
*
* @author GeoffTitmus
* @param file File A File in which to store the animation.
* @param frames BufferedImage[] Array of BufferedImages, the frames of the
* animation.
* @param delayTimes String[] Array of Strings, representing the frame delay
* times.
*/
public static void saveAnimate(
File file,
BufferedImage[] frames,
String[] delayTimes) throws Exception {
ImageWriter iw = ImageIO.getImageWritersByFormatName("gif").next();
ImageOutputStream ios = ImageIO.createImageOutputStream(file);
iw.setOutput(ios);
iw.prepareWriteSequence(null);
for (int i = 0; i < frames.length; i++) {
BufferedImage src = frames[i];
ImageWriteParam iwp = iw.getDefaultWriteParam();
IIOMetadata metadata = iw.getDefaultImageMetadata(
new ImageTypeSpecifier(src), iwp);
configure(metadata, delayTimes[i], i);
IIOImage ii = new IIOImage(src, null, metadata);
iw.writeToSequence(ii, null);
}
iw.endWriteSequence();
ios.close();
}
/**
* Dump the usage to the System.err stream.
*/
public static void printUsage() {
StringBuffer sb = new StringBuffer();
String eol = System.getProperty("line.separator");
sb.append("Usage: 2 forms each using 3 arguments");
sb.append(eol);
sb.append("1) output (animated GIF) file name");
sb.append(eol);
sb.append("2) input files (animation frames), separated by ','");
sb.append(eol);
sb.append("3) single frame rate, or comma separared list of frame rates");
sb.append(eol);
sb.append("java WriteAnimatedGif animate.gif frm1.gif,frm2.gif,..,frmN.gif 100");
sb.append(eol);
sb.append("java WriteAnimatedGif animate.gif frm1.gif,frm2.gif,..,frmN.gif 100,40,..,N");
sb.append(eol);
sb.append("The 2nd form must have exactly as many integers as there are frames.");
sb.append(eol);
sb.append("Frame rates are specified in increments of 1/100th second, NOT milliseconds.");
sb.append(eol);
System.err.print(sb);
}
/**
* Checks that a String intended as a delayTime is an integer>0. If not,
* dumps a warning message and the usage, then exits. If successful, returns
* the String unaltered.
*/
public static String checkDelay(String delay) {
try {
int val = Integer.parseInt(delay);
if (val < 1) {
System.err.println(
"Animation frame delay '"
+ val
+ "' is < 1!");
printUsage();
System.exit(1);
}
} catch (NumberFormatException nfe) {
System.err.println(
"Could not parse '"
+ delay
+ "' as an integer.");
printUsage();
System.exit(1);
}
return delay;
}
/**
* Parse the arguments and if successful, attempt to write the animated GIF.
*/
public static void main(String[] args) throws Exception {
if (args.length != 3) {
printUsage();
System.exit(1);
}
// deal with the output file name
File f = new File(args[0]);
// deal with the input file names
String[] names = args[1].split(",");
if (names.length < 2) {
System.err.println("An animation requires 2 or more frames!");
printUsage();
System.exit(1);
}
BufferedImage[] frames = new BufferedImage[names.length];
for (int ii = 0; ii < names.length; ii++) {
frames[ii] = ImageIO.read(new File(names[ii]));
}
// deal with the frame rates
String[] delays = args[2].split(",");
// note: length of names, not delays
String[] delayTimes = new String[names.length];
if (delays.length != names.length) {
System.err.println(delays.length
+ " delays specified for "
+ names.length
+ " frames!");
printUsage();
System.exit(1);
} else if (delays.length == 1) {
for (int ii = 0; ii < delayTimes.length; ii++) {
// fill all values with the single delayTime
delayTimes[ii] = checkDelay(delays[0]);
}
} else {
for (int ii = 0; ii < delayTimes.length; ii++) {
delayTimes[ii] = checkDelay(delays[ii]);
}
}
// save an animated GIF
saveAnimate(f, frames, delayTimes);
}
}
quelqu'un sait comment passer les paramètres? Je passe "a.png, b.png, c.png" sans les guillemets et il dit que c'est faux ... – Jas
@Jas Leur sont 5 arguments dans 'a.png, b.png, c.png' - deux d'entre eux sont les deux virgules. Ce serait trois arguments si c'était à la place 'a.png, b.png, c.png' (pas d'espace entre la valeur et', '). –
@andewv - Merci, mais ça ne marche toujours pas. Il continue à dire que j'ai juste une image quand j'en aurais 2 ou plus ... – Jas
Désolé, ce n'est pas le mode de fonctionnement de StackOverflow. Questions de la forme _ "Je veux faire X, s'il vous plaît donnez-moi des conseils et/ou un exemple de code" _ sont considérés comme hors sujet. S'il vous plaît visitez le [aide] et lisez [demander], et en particulier lire [Pourquoi est-ce que "Quelqu'un peut-il m'aider?" Pas une question réelle?] (Http://meta.stackoverflow.com/q/284236/18157) –
I Je n'ai aucune idée de la façon de le faire et google n'a pas aidé, alors comment dois-je demander? –
J'ai fait une serach de Google pour "convertir le png en animation gif java" et j'ai obtenu BEAUCOUP de hits. De toute évidence, vous n'avez fait aucune recherche. –