
org.monte.media.avi.ZMBVCodec Maven / Gradle / Ivy
The newest version!
package org.monte.media.avi;
import java.awt.image.DataBufferUShort;
import java.awt.Point;
import java.awt.image.DirectColorModel;
import org.monte.media.AbstractVideoCodec;
import org.monte.media.Buffer;
import org.monte.media.Format;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.IndexColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.util.Hashtable;
import static java.lang.Math.*;
import static org.monte.media.VideoFormatKeys.*;
import static org.monte.media.BufferFlag.*;
public class ZMBVCodec extends AbstractVideoCodec {
private ZMBVCodecCore state;
private Object oldPixels;
private Object newPixels;
public ZMBVCodec() {
super(new Format[]{
new Format(MediaTypeKey, MediaType.VIDEO,
EncodingKey, ENCODING_AVI_DOSBOX_SCREEN_CAPTURE, DataClassKey, byte[].class, FixedFrameRateKey, true),
},
new Format[]{
new Format(MediaTypeKey, MediaType.VIDEO, MimeTypeKey, MIME_JAVA,
EncodingKey, ENCODING_BUFFERED_IMAGE, FixedFrameRateKey, true),
});
name = "ZMBV Codec";
}
@Override
public int process(Buffer in, Buffer out) {
return decode(in,out);
}
public int decode(Buffer in, Buffer out) {
out.setMetaTo(in);
if (in.isFlag(DISCARD)) {
return CODEC_OK;
}
out.format = outputFormat;
out.length = 1;
out.offset = 0;
int width = outputFormat.get(WidthKey);
int height = outputFormat.get(HeightKey);
if (state == null) {
state = new ZMBVCodecCore();
}
Object[] newPixelHolder = new Object[]{newPixels};
Object[] oldPixelHolder = new Object[]{oldPixels};
int result = state.decode((byte[]) in.data, in.offset, in.length, newPixelHolder, oldPixelHolder, width, height, false);
boolean isKeyframe = result < 0;
int depth = abs(result);
newPixels = newPixelHolder[0];
oldPixels = oldPixelHolder[0];
MyBufferedImage img = null;
if (out.data instanceof MyBufferedImage) {
img = (MyBufferedImage) out.data;
}
switch (depth) {
case 8: {
int imgType = BufferedImage.TYPE_BYTE_INDEXED;
if (img == null || img.getWidth() != width || img.getHeight() != height || img.getType() != imgType) {
int[] cmap = new int[256];
IndexColorModel icm = new IndexColorModel(8, 256, cmap, 0, false, -1, DataBuffer.TYPE_BYTE);
img = new MyBufferedImage(width, height, imgType, icm);
} else {
MyBufferedImage oldImg = img;
img = new MyBufferedImage(oldImg.getColorModel(), oldImg.getRaster(), oldImg.isAlphaPremultiplied(), null);
}
int[] cmap = state.getPalette();
IndexColorModel icm = new IndexColorModel(8, 256, cmap, 0, false, -1, DataBuffer.TYPE_BYTE);
img.setColorModel(icm);
byte[] pixels = ((DataBufferByte) img.getRaster().getDataBuffer()).getData();
System.arraycopy((byte[]) newPixels, 0, pixels, 0, width * height);
}
break;
case 15: {
int imgType = BufferedImage.TYPE_USHORT_555_RGB;
if (img == null || img.getWidth() != width || img.getHeight() != height || img.getType() != imgType) {
DirectColorModel cm = new DirectColorModel(15, 0x1f << 10, 0x1f << 5, 0x1f << 0);
img = new MyBufferedImage(cm, Raster.createWritableRaster(cm.createCompatibleSampleModel(width, height), new Point(0, 0)), false, new Hashtable());
} else {
MyBufferedImage oldImg = img;
img = new MyBufferedImage(oldImg.getColorModel(), oldImg.getRaster(), oldImg.isAlphaPremultiplied(), null);
}
short[] pixels = ((DataBufferUShort) img.getRaster().getDataBuffer()).getData();
System.arraycopy((short[]) newPixels, 0, pixels, 0, width * height);
}
break;
case 16: {
int imgType = BufferedImage.TYPE_USHORT_565_RGB;
if (img == null || img.getWidth() != width || img.getHeight() != height || img.getType() != imgType) {
DirectColorModel cm = new DirectColorModel(15, 0x1f << 11, 0x3f << 5, 0x1f << 0);
img = new MyBufferedImage(cm, Raster.createWritableRaster(cm.createCompatibleSampleModel(width, height), new Point(0, 0)), false, new Hashtable());
} else {
MyBufferedImage oldImg = img;
img = new MyBufferedImage(oldImg.getColorModel(), oldImg.getRaster(), oldImg.isAlphaPremultiplied(), null);
}
short[] pixels = ((DataBufferUShort) img.getRaster().getDataBuffer()).getData();
System.arraycopy((short[]) newPixels, 0, pixels, 0, width * height);
}
break;
case 32:
default:
throw new UnsupportedOperationException("Unsupported depth:" + depth);
}
Object swap=oldPixels;
oldPixels=newPixels; newPixels=swap;
out.setFlag(KEYFRAME, isKeyframe);
out.data = img;
return CODEC_OK;
}
private static class MyBufferedImage extends BufferedImage {
private ColorModel colorModel;
public MyBufferedImage(ColorModel cm, WritableRaster raster, boolean isRasterPremultiplied, Hashtable, ?> properties) {
super(cm, raster, isRasterPremultiplied, properties);
colorModel = cm;
}
public MyBufferedImage(int width, int height, int imageType, IndexColorModel cm) {
super(width, height, imageType, cm);
colorModel = cm;
}
public MyBufferedImage(int width, int height, int imageType) {
super(width, height, imageType);
}
@Override
public ColorModel getColorModel() {
return colorModel;
}
public void setColorModel(ColorModel newValue) {
this.colorModel = newValue;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy