
org.monte.media.imgseq.ImageSequenceWriter Maven / Gradle / Ivy
/*
* @(#)ImageSequenceWriter.java 1.0 2011-04-20
*
* Copyright (c) 2011 Werner Randelshofer, Goldau, Switzerland.
* All rights reserved.
*
* You may not use, copy or modify this file, except in compliance with the
* license agreement you entered into with Werner Randelshofer.
* For details see accompanying license terms.
*/
package org.monte.media.imgseq;
import org.monte.media.math.Rational;
import org.monte.media.Buffer;
import org.monte.media.Codec;
import org.monte.media.Format;
import org.monte.media.MovieWriter;
import org.monte.media.jpeg.JPEGCodec;
import org.monte.media.png.PNGCodec;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import static org.monte.media.VideoFormatKeys.*;
import static org.monte.media.BufferFlag.*;
/**
* {@code ImageSequenceWriter}.
*
* @author Werner Randelshofer
* @version 1.0 2011-04-20 Created.
*/
public class ImageSequenceWriter implements MovieWriter {
private Format fileFormat = new Format(MediaTypeKey,MediaType.FILE);
@Override
public int addTrack(Format format) throws IOException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Format getFileFormat() throws IOException {
return fileFormat;
}
@Override
public int getTrackCount() {
return 1;
}
@Override
public Format getFormat(int track) {
throw new UnsupportedOperationException("Not supported yet.");
}
private class VideoTrack {
Format videoFormat;
File dir;
String nameFormat;
int count;
Codec codec;
Buffer inputBuffer;
Buffer outputBuffer;
int width;
int height;
public VideoTrack(File dir, String filenameFormatter, Format fmt, Codec codec, int width, int height) {
this.dir = dir;
this.nameFormat = filenameFormatter;
this.videoFormat = fmt;
this.codec = codec;
this.width = width;
this.height = height;
}
}
private ArrayList tracks = new ArrayList();
/** Adds a video track.
* @param dir The output directory.
* @param filenameFormatter a format string for a filename with a number,
* for example "frame_%d0000$.png";
*
* @param width the image width
* @param height the image height
*
* @return Returns the track index.
*
* @throws IllegalArgumentException if the width or the height is smaller
* than 1.
*/
public int addVideoTrack(File dir, String filenameFormatter, int width, int height) {
VideoTrack t;
Format fmt = filenameFormatter.toLowerCase().endsWith(".png")//
? new Format(MediaTypeKey,MediaType.VIDEO,EncodingKey,ENCODING_QUICKTIME_PNG, WidthKey, width, HeightKey, height, DepthKey, 24) //
: new Format(MediaTypeKey,MediaType.VIDEO,EncodingKey,ENCODING_QUICKTIME_JPEG, WidthKey, width, HeightKey, height, DepthKey, 24) //
;
tracks.add(t = new VideoTrack(dir, filenameFormatter,
fmt,
null, width, height));
createCodec(t);
return tracks.size() - 1;
}
private void createCodec(VideoTrack vt) {
Format fmt = vt.videoFormat;
String enc = fmt.get(EncodingKey);
if (enc.equals(ENCODING_AVI_MJPG)//
|| enc.equals(ENCODING_QUICKTIME_JPEG)//
) {
vt.codec = new JPEGCodec();
} else if (enc.equals(ENCODING_AVI_PNG)//
|| enc.equals(ENCODING_QUICKTIME_PNG)//
) {
vt.codec = new PNGCodec();
}
vt.codec.setInputFormat(fmt.prepend(MediaTypeKey,MediaType.VIDEO,MimeTypeKey,MIME_JAVA,EncodingKey,ENCODING_BUFFERED_IMAGE,DataClassKey, BufferedImage.class));
vt.codec.setOutputFormat(fmt.prepend(MediaTypeKey,MediaType.VIDEO,EncodingKey,enc, DataClassKey ,byte[].class));
// vt.codec.setQuality(vt.videoQuality);
}
public void write(int track, BufferedImage image, long duration) throws IOException {
VideoTrack t = tracks.get(track);
if (t.inputBuffer == null) {
t.inputBuffer = new Buffer();
}
if (t.outputBuffer == null) {
t.outputBuffer = new Buffer();
}
t.inputBuffer.setFlagsTo(KEYFRAME);
t.inputBuffer.data = image;
t.codec.process(t.inputBuffer, t.outputBuffer);
write(track, t.outputBuffer);
}
@Override
public void write(int track, Buffer buf) throws IOException {
VideoTrack t = tracks.get(track);
if (buf.isFlag(DISCARD)) {
return;
}
File file = new File(t.dir, String.format(t.nameFormat, t.count + 1));
if (buf.data instanceof byte[]) {
FileOutputStream out = new FileOutputStream(file);
try {
out.write((byte[]) buf.data, buf.offset, buf.length);
} finally {
out.close();
}
} else if (buf.data instanceof File) {
FileInputStream in = new FileInputStream((File) buf.data);
try {
FileOutputStream out = new FileOutputStream(file);
try {
byte[] b = new byte[2048];
int len;
while ((len = in.read(b)) != -1) {
out.write(b, 0, len);
}
} finally {
out.close();
}
} finally {
in.close();
}
} else {
throw new IllegalArgumentException("Can't process buffer data:" + buf.data);
}
t.count++;
}
public void writeSample(int track, byte[] data, int off, int len, long duration, boolean isSync) throws IOException {
VideoTrack t = tracks.get(track);
File file = new File(t.dir, String.format(t.nameFormat, t.count + 1));
FileOutputStream out = new FileOutputStream(file);
try {
out.write((byte[]) data, off, len);
} finally {
out.close();
}
t.count++;
}
public void writeSamples(int track, int sampleCount, byte[] data, int off, int len, long sampleDuration, boolean isSync) throws IOException {
for (int i = 0; i < sampleCount; i++) {
writeSample(track, data, off, len / sampleCount, sampleDuration, isSync);
off += len / sampleCount;
}
}
@Override
public void close() throws IOException {
//nothing to do
}
public boolean isVFRSupported() {
return false;
}
@Override
public boolean isDataLimitReached() {
return false;
}
/** Returns the sampleDuration of the track in seconds. */
@Override
public Rational getDuration(int track) {
VideoTrack tr=tracks.get(track);
return new Rational(tr.count,30);
}
@Override
public boolean isEmpty(int track) {
return tracks.get(track).count==0;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy