package net.sf.fmj.media.util;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.ComponentColorModel;
import java.awt.image.ComponentSampleModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.awt.image.DirectColorModel;
import javax.media.Buffer;
import javax.media.Format;
import javax.media.format.RGBFormat;
/**
* Implementation of javax.media.util.ImageToBuffer.
* TODO: need to take into account line stride, if it is different from what one would expect.
* @author Ken Larson
*
*/
public class ImageToBuffer
{
public ImageToBuffer()
{ super();
// no reason to ever instantiate this
}
public static Buffer createBuffer(java.awt.Image image, float frameRate)
{
final BufferedImage bi;
if (image instanceof BufferedImage)
{ bi = (BufferedImage) image;
}
else
{ bi = convert(image);
}
final DataBuffer dataBuffer = bi.getRaster().getDataBuffer();
final Object pixels;
final int pixelsLength;
final Class dataType;
if (dataBuffer instanceof DataBufferInt)
{
final int[] intPixels = ((DataBufferInt) dataBuffer).getData();
pixels = intPixels;
pixelsLength = intPixels.length;
dataType = Format.intArray;
}
else if (dataBuffer instanceof DataBufferByte)
{
final byte[] bytePixels = ((DataBufferByte) dataBuffer).getData();
pixels = bytePixels;
pixelsLength = bytePixels.length;
dataType = Format.byteArray;
}
else
{ throw new IllegalArgumentException("Unknown or unsupported data buffer type: " + dataBuffer);
}
final int bufferedImageType = bi.getType();
final Buffer result = new Buffer();
final Dimension size = new Dimension(bi.getWidth(), bi.getHeight());
final int maxDataLength = -1; // TODO
final int bitsPerPixel;
final int red;
final int green;
final int blue;
if (bufferedImageType == BufferedImage.TYPE_3BYTE_BGR)
{
bitsPerPixel = 24;
red = 1;
green = 2;
blue = 3;
}
else if (bufferedImageType == BufferedImage.TYPE_INT_BGR)
{
bitsPerPixel = 32;
// TODO: test
red = 0xFF;
green = 0xFF00;
blue = 0xFF0000;
}
else if (bufferedImageType == BufferedImage.TYPE_INT_RGB)
{
bitsPerPixel = 32;
red = 0xFF0000;
green = 0xFF00;
blue = 0xFF;
}
else if (bufferedImageType == BufferedImage.TYPE_INT_ARGB)
{
bitsPerPixel = 32;
red = 0xFF0000;
green = 0xFF00;
blue = 0xFF;
// just ignore alpha
}
else
{
if (bi.getColorModel() instanceof ComponentColorModel && bi.getSampleModel() instanceof ComponentSampleModel)
{
final ComponentColorModel componentColorModel = (ComponentColorModel) bi.getColorModel();
final ComponentSampleModel componentSampleModel = (ComponentSampleModel) bi.getSampleModel();
final int[] offsets = componentSampleModel.getBandOffsets();
if (dataBuffer instanceof DataBufferInt)
{
// TODO: untested
bitsPerPixel = 32;
red = 0xFF << offsets[0];
green = 0xFF << offsets[1];
blue = 0xFF << offsets[2];
}
else if (dataBuffer instanceof DataBufferByte)
{
bitsPerPixel = componentSampleModel.getPixelStride() * 8; // TODO: should it always be 24? or are the pixel stride and the bits per pixel unrelated?
red = 1 + offsets[0];
green = 1 + offsets[1];
blue = 1 + offsets[2];
}
else
throw new IllegalArgumentException("Unsupported buffered image type: " + bufferedImageType);
}
else if (bi.getColorModel() instanceof DirectColorModel)
{
// TODO: untested
final DirectColorModel directColorModel = (DirectColorModel) bi.getColorModel();
if (dataBuffer instanceof DataBufferInt)
{
bitsPerPixel = 32;
red = directColorModel.getRedMask();
green = directColorModel.getGreenMask();
blue = directColorModel.getBlueMask();
}
else
throw new IllegalArgumentException("Unsupported buffered image type: " + bufferedImageType);
}
else
throw new IllegalArgumentException("Unsupported buffered image type: " + bufferedImageType);
}
result.setFormat(new RGBFormat(size, maxDataLength, dataType, frameRate, bitsPerPixel, red, green, blue));
result.setData(pixels);
result.setLength(pixelsLength);
result.setOffset(0);
return result;
}
private static BufferedImage convert(Image im)
{
BufferedImage bi = new BufferedImage(im.getWidth(null), im.getHeight(null), BufferedImage.TYPE_INT_RGB);
Graphics bg = bi.getGraphics();
bg.drawImage(im, 0, 0, null);
bg.dispose();
return bi;
}
}