Desidero essere in grado di prendere un GIF animato come input, contare i frame (e forse altri metadati) e convertirli ciascuno in uno BufferedImage
. Come posso fare questo?Converti ogni frame GIF animato in un'immagine Buffered separata
risposta
Se si desidera che tutti i fotogrammi siano della stessa dimensione (per ottimizzare GIF) provare qualcosa di simile:
try {
String[] imageatt = new String[]{
"imageLeftPosition",
"imageTopPosition",
"imageWidth",
"imageHeight"
};
ImageReader reader = (ImageReader)ImageIO.getImageReadersByFormatName("gif").next();
ImageInputStream ciis = ImageIO.createImageInputStream(new File("house2.gif"));
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);
if(nodeItem.getNodeName().equals("ImageDescriptor")){
Map<String, Integer> imageAttr = new HashMap<String, Integer>();
for (int k = 0; k < imageatt.length; k++) {
NamedNodeMap attr = nodeItem.getAttributes();
Node attnode = attr.getNamedItem(imageatt[k]);
imageAttr.put(imageatt[k], Integer.valueOf(attnode.getNodeValue()));
}
if(i==0){
master = new BufferedImage(imageAttr.get("imageWidth"), imageAttr.get("imageHeight"), BufferedImage.TYPE_INT_ARGB);
}
master.getGraphics().drawImage(image, imageAttr.get("imageLeftPosition"), imageAttr.get("imageTopPosition"), null);
}
}
ImageIO.write(master, "GIF", new File(i + ".gif"));
}
} catch (IOException e) {
e.printStackTrace();
}
destro, non ho mai fatto niente anche un po 'di simile prima, ma un po' di usare Google e giocherellare in Java mi ha fatto questo:
public ArrayList<BufferedImage> getFrames(File gif) throws IOException{
ArrayList<BufferedImage> frames = new ArrayList<BufferedImage>();
ImageReader ir = new GIFImageReader(new GIFImageReaderSpi());
ir.setInput(ImageIO.createImageInputStream(gif));
for(int i = 0; i < ir.getNumImages(true); i++)
frames.add(ir.getRawImageType(i).createBufferedImage(ir.getWidth(i), ir.getHeight(i)));
return frames;
}
Edit: vedere Ansel Zandegran's modification alla mia risposta.
Utilizzando c24w's solution, sostituire:
frames.add(ir.getRawImageType(i).createBufferedImage(ir.getWidth(i), ir.getHeight(i)));
Con:
frames.add(ir.read(i));
Nessuna delle risposte qui sono corrette e adatto per l'animazione. Ci sono molti problemi in ogni soluzione, quindi ho scritto qualcosa che funziona davvero con tutti i file gif. Ad esempio, questo prende in considerazione la larghezza e l'altezza effettive dell'immagine invece di prendere la larghezza e l'altezza del primo fotogramma assumendo che riempirà l'intera tela, no, sfortunatamente non è così semplice. In secondo luogo, questo non lascia sottaceti trasparenti. In terzo luogo, questo prende in considerazione i metodi di smaltimento. Quarto, questo ti dà ritardi tra i frame (* 10 se vuoi usarlo in Thread.sleep()).
private ImageFrame[] readGif(InputStream stream) throws IOException{
ArrayList<ImageFrame> frames = new ArrayList<ImageFrame>(2);
ImageReader reader = (ImageReader) ImageIO.getImageReadersByFormatName("gif").next();
reader.setInput(ImageIO.createImageInputStream(stream));
int lastx = 0;
int lasty = 0;
int width = -1;
int height = -1;
IIOMetadata metadata = reader.getStreamMetadata();
Color backgroundColor = null;
if(metadata != null) {
IIOMetadataNode globalRoot = (IIOMetadataNode) metadata.getAsTree(metadata.getNativeMetadataFormatName());
NodeList globalColorTable = globalRoot.getElementsByTagName("GlobalColorTable");
NodeList globalScreeDescriptor = globalRoot.getElementsByTagName("LogicalScreenDescriptor");
if (globalScreeDescriptor != null && globalScreeDescriptor.getLength() > 0){
IIOMetadataNode screenDescriptor = (IIOMetadataNode) globalScreeDescriptor.item(0);
if (screenDescriptor != null){
width = Integer.parseInt(screenDescriptor.getAttribute("logicalScreenWidth"));
height = Integer.parseInt(screenDescriptor.getAttribute("logicalScreenHeight"));
}
}
if (globalColorTable != null && globalColorTable.getLength() > 0){
IIOMetadataNode colorTable = (IIOMetadataNode) globalColorTable.item(0);
if (colorTable != null) {
String bgIndex = colorTable.getAttribute("backgroundColorIndex");
IIOMetadataNode colorEntry = (IIOMetadataNode) colorTable.getFirstChild();
while (colorEntry != null) {
if (colorEntry.getAttribute("index").equals(bgIndex)) {
int red = Integer.parseInt(colorEntry.getAttribute("red"));
int green = Integer.parseInt(colorEntry.getAttribute("green"));
int blue = Integer.parseInt(colorEntry.getAttribute("blue"));
backgroundColor = new Color(red, green, blue);
break;
}
colorEntry = (IIOMetadataNode) colorEntry.getNextSibling();
}
}
}
}
BufferedImage master = null;
boolean hasBackround = false;
for (int frameIndex = 0;; frameIndex++) {
BufferedImage image;
try{
image = reader.read(frameIndex);
}catch (IndexOutOfBoundsException io){
break;
}
if (width == -1 || height == -1){
width = image.getWidth();
height = image.getHeight();
}
IIOMetadataNode root = (IIOMetadataNode) reader.getImageMetadata(frameIndex).getAsTree("javax_imageio_gif_image_1.0");
IIOMetadataNode gce = (IIOMetadataNode) root.getElementsByTagName("GraphicControlExtension").item(0);
NodeList children = root.getChildNodes();
int delay = Integer.valueOf(gce.getAttribute("delayTime"));
String disposal = gce.getAttribute("disposalMethod");
if (master == null){
master = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
master.createGraphics().setColor(backgroundColor);
master.createGraphics().fillRect(0, 0, master.getWidth(), master.getHeight());
hasBackround = image.getWidth() == width && image.getHeight() == height;
master.createGraphics().drawImage(image, 0, 0, null);
}else{
int x = 0;
int y = 0;
for (int nodeIndex = 0; nodeIndex < children.getLength(); nodeIndex++){
Node nodeItem = children.item(nodeIndex);
if (nodeItem.getNodeName().equals("ImageDescriptor")){
NamedNodeMap map = nodeItem.getAttributes();
x = Integer.valueOf(map.getNamedItem("imageLeftPosition").getNodeValue());
y = Integer.valueOf(map.getNamedItem("imageTopPosition").getNodeValue());
}
}
if (disposal.equals("restoreToPrevious")){
BufferedImage from = null;
for (int i = frameIndex - 1; i >= 0; i--){
if (!frames.get(i).getDisposal().equals("restoreToPrevious") || frameIndex == 0){
from = frames.get(i).getImage();
break;
}
}
{
ColorModel model = from.getColorModel();
boolean alpha = from.isAlphaPremultiplied();
WritableRaster raster = from.copyData(null);
master = new BufferedImage(model, raster, alpha, null);
}
}else if (disposal.equals("restoreToBackgroundColor") && backgroundColor != null){
if (!hasBackround || frameIndex > 1){
master.createGraphics().fillRect(lastx, lasty, frames.get(frameIndex - 1).getWidth(), frames.get(frameIndex - 1).getHeight());
}
}
master.createGraphics().drawImage(image, x, y, null);
lastx = x;
lasty = y;
}
{
BufferedImage copy;
{
ColorModel model = master.getColorModel();
boolean alpha = master.isAlphaPremultiplied();
WritableRaster raster = master.copyData(null);
copy = new BufferedImage(model, raster, alpha, null);
}
frames.add(new ImageFrame(copy, delay, disposal, image.getWidth(), image.getHeight()));
}
master.flush();
}
reader.dispose();
return frames.toArray(new ImageFrame[frames.size()]);
}
E la classe ImageFrame:
import java.awt.image.BufferedImage;
public class ImageFrame {
private final int delay;
private final BufferedImage image;
private final String disposal;
private final int width, height;
public ImageFrame (BufferedImage image, int delay, String disposal, int width, int height){
this.image = image;
this.delay = delay;
this.disposal = disposal;
this.width = width;
this.height = height;
}
public ImageFrame (BufferedImage image){
this.image = image;
this.delay = -1;
this.disposal = null;
this.width = -1;
this.height = -1;
}
public BufferedImage getImage() {
return image;
}
public int getDelay() {
return delay;
}
public String getDisposal() {
return disposal;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
}
Gli altri metodi hanno prodotto risultati leggermente corrotti, questo ha funzionato perfettamente. – cen
Questo era da alcuni anni fa wow. Ad ogni modo, ho scritto un'implementazione gif completa in javascript. Se hai ancora problemi, posso portarlo via per te ed è garantito che funzioni. Ho notato che il built-in ImageReader per gif ha qualche problema a decodificare i dati reali dei pixel a volte, nulla può risolverli se non per una riscrittura. –
Ho dovuto mettere insieme alcune parti del codice SO per implementare un ridimensionamento e ritaglio per le GIF animate. Ho capito che funziona perfettamente con questo esempio. Per prima cosa ho provato il metodo di Francesco ma i primi fotogrammi di output avevano un po 'di rumore. Getterò la mia soluzione su Github nei prossimi giorni se qualche altra anima persa cerca di fare qualcosa di simile. Java e GIF sono una sorta di selvaggio west. – cen
risposta di Alex copre la maggior parte dei casi, ma ha un paio di problemi. Non gestisce correttamente la trasparenza (almeno secondo la convenzione comune) e applica il metodo di eliminazione del frame corrente al frame precedente che non è corretto. Ecco una versione che consente di gestire questi casi in modo corretto:
private ImageFrame[] readGIF(ImageReader reader) throws IOException {
ArrayList<ImageFrame> frames = new ArrayList<ImageFrame>(2);
int width = -1;
int height = -1;
IIOMetadata metadata = reader.getStreamMetadata();
if (metadata != null) {
IIOMetadataNode globalRoot = (IIOMetadataNode) metadata.getAsTree(metadata.getNativeMetadataFormatName());
NodeList globalScreenDescriptor = globalRoot.getElementsByTagName("LogicalScreenDescriptor");
if (globalScreenDescriptor != null && globalScreenDescriptor.getLength() > 0) {
IIOMetadataNode screenDescriptor = (IIOMetadataNode) globalScreenDescriptor.item(0);
if (screenDescriptor != null) {
width = Integer.parseInt(screenDescriptor.getAttribute("logicalScreenWidth"));
height = Integer.parseInt(screenDescriptor.getAttribute("logicalScreenHeight"));
}
}
}
BufferedImage master = null;
Graphics2D masterGraphics = null;
for (int frameIndex = 0;; frameIndex++) {
BufferedImage image;
try {
image = reader.read(frameIndex);
} catch (IndexOutOfBoundsException io) {
break;
}
if (width == -1 || height == -1) {
width = image.getWidth();
height = image.getHeight();
}
IIOMetadataNode root = (IIOMetadataNode) reader.getImageMetadata(frameIndex).getAsTree("javax_imageio_gif_image_1.0");
IIOMetadataNode gce = (IIOMetadataNode) root.getElementsByTagName("GraphicControlExtension").item(0);
int delay = Integer.valueOf(gce.getAttribute("delayTime"));
String disposal = gce.getAttribute("disposalMethod");
int x = 0;
int y = 0;
if (master == null) {
master = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
masterGraphics = master.createGraphics();
masterGraphics.setBackground(new Color(0, 0, 0, 0));
} else {
NodeList children = root.getChildNodes();
for (int nodeIndex = 0; nodeIndex < children.getLength(); nodeIndex++) {
Node nodeItem = children.item(nodeIndex);
if (nodeItem.getNodeName().equals("ImageDescriptor")) {
NamedNodeMap map = nodeItem.getAttributes();
x = Integer.valueOf(map.getNamedItem("imageLeftPosition").getNodeValue());
y = Integer.valueOf(map.getNamedItem("imageTopPosition").getNodeValue());
}
}
}
masterGraphics.drawImage(image, x, y, null);
BufferedImage copy = new BufferedImage(master.getColorModel(), master.copyData(null), master.isAlphaPremultiplied(), null);
frames.add(new ImageFrame(copy, delay, disposal));
if (disposal.equals("restoreToPrevious")) {
BufferedImage from = null;
for (int i = frameIndex - 1; i >= 0; i--) {
if (!frames.get(i).getDisposal().equals("restoreToPrevious") || frameIndex == 0) {
from = frames.get(i).getImage();
break;
}
}
master = new BufferedImage(from.getColorModel(), from.copyData(null), from.isAlphaPremultiplied(), null);
masterGraphics = master.createGraphics();
masterGraphics.setBackground(new Color(0, 0, 0, 0));
} else if (disposal.equals("restoreToBackgroundColor")) {
masterGraphics.clearRect(x, y, image.getWidth(), image.getHeight());
}
}
reader.dispose();
return frames.toArray(new ImageFrame[frames.size()]);
}
private class ImageFrame {
private final int delay;
private final BufferedImage image;
private final String disposal;
public ImageFrame(BufferedImage image, int delay, String disposal) {
this.image = image;
this.delay = delay;
this.disposal = disposal;
}
public BufferedImage getImage() {
return image;
}
public int getDelay() {
return delay;
}
public String getDisposal() {
return disposal;
}
}
V'è una buona descrizione di come animazioni GIF funzionano in this ImageMagick tutorial.
è necessario applicare alcune modifiche a questo codice. Se il ritardo è zero, impostalo su 100 o se è inferiore a 30 ms, quindi moltiplicalo con 10. Questo ha funzionato per me. – Soley
questo soution ha funzionato perfettamente per me – user3896501
Questo funziona diversamente dalla maggior parte degli altri qui, che ha posto un problema in un modo o nell'altro. –
ho scritto un decoder immagine GIF per conto mio e rilasciato sotto la licenza Apache 2.0 su GitHub. Puoi scaricarlo qui: https://github.com/DhyanB/Open-Imaging. Esempio di utilizzo:
void example(final byte[] data) throws Exception {
final GifImage gif = GifDecoder .read(data);
final int width = gif.getWidth();
final int height = gif.getHeight();
final int background = gif.getBackgroundColor();
final int frameCount = gif.getFrameCount();
for (int i = 0; i < frameCount; i++) {
final BufferedImage img = gif.getFrame(i);
final int delay = gif.getDelay(i);
ImageIO.write(img, "png", new File(OUTPATH + "frame_" + i + ".png"));
}
}
Il decoder supporta GIF87a, GIF89a, l'animazione, la trasparenza e l'interlacciamento. I fotogrammi avranno la larghezza e l'altezza dell'immagine stessa e saranno posizionati sulla posizione corretta sulla tela. Rispetta la trasparenza dei frame e i metodi di smaltimento. Controlla la descrizione del progetto per ulteriori dettagli come la gestione dei colori di sfondo.
Inoltre, il decodificatore non soffre di questo errore ImageIO
: ArrayIndexOutOfBoundsException: 4096 while reading gif file.
Sarei felice di ottenere un feedback. Ho provato con una serie di immagini rappresentative, tuttavia, alcuni test sul campo reali sarebbero buoni.
Per dividere una GIF animata in separati BufferedImage
cornici:
try {
ImageReader reader = ImageIO.getImageReadersByFormatName("gif").next();
File input = new File("input.gif");
ImageInputStream stream = ImageIO.createImageInputStream(input);
reader.setInput(stream);
int count = reader.getNumImages(true);
for (int index = 0; index < count; index++) {
BufferedImage frame = reader.read(index);
// Here you go
}
} catch (IOException ex) {
// An I/O problem has occurred
}
- 1. GIF animato in HTML5 canvas
- 2. Errore encoder gif animato
- 3. Supporto GIF animato Android
- 4. Split GIF in frame
- 5. Converti immagine GIF in NSData
- 6. Gif animato per avi su linux
- 7. Come dividere un file .gif in frame?
- 8. Ridimensionamento gif animato con sorl-thumbnail
- 9. Gif animato solo cicli una volta in Chrome e Firefox
- 10. Python: conversione di frame GIF in PNG
- 11. Java- Converti immagine buffered in byte [] senza scrivere sul disco
- 12. È possibile impostare un file GIF animato come sfondo animato in Android?
- 13. Sessione separata per ogni finestra
- 14. Accesso ai frame GIF con C#
- 15. Python, come posso ottenere i frame GIF
- 16. imagemagick convertire il singolo frame delay in gif
- 17. Schermo animato animato iOS
- 18. Come ridimensionare il file gif animato usando C#?
- 19. Creare un file .gif animato da .jpeg/png
- 20. Converti frame dati panda in serie
- 21. Converti l'immagine JPG/GIF in PNG in PHP?
- 22. Visualizzazione di testo animato animato Marker
- 23. Converti le gif ottimizzate in fotogrammi singoli usando ImageMagick
- 24. PIL Converti PNG o GIF con trasparenza in JPG senza
- 25. Git - cartella separata per ogni ramo. Configurazione
- 26. Converti oggetto igraph in un frame di dati in R
- 27. ListBox Double Buffered
- 28. Ogni ramo possibile in un metodo deve avere un'unità separata?
- 29. Come usare Buffered Reader in Java
- 30. Riproduzione di un file di immagine GIF animato in visualizzazione immagini
See: http://stackoverflow.com/questions/777947/creating-animated-gif-with-imageio – beerbajay
Questa libreria può anche aiutare: https://github.com/dragon66/icafe/wiki – dragon66