package com.sun.prism;
import javafx.scene.image.PixelReader;
import javafx.scene.image.WritablePixelFormat;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import com.sun.javafx.iio.ImageFrame;
import com.sun.javafx.iio.ImageStorage;
import com.sun.javafx.image.BytePixelGetter;
import com.sun.javafx.image.BytePixelSetter;
import com.sun.javafx.image.ByteToBytePixelConverter;
import com.sun.javafx.image.ByteToIntPixelConverter;
import com.sun.javafx.image.IntPixelGetter;
import com.sun.javafx.image.IntPixelSetter;
import com.sun.javafx.image.IntToBytePixelConverter;
import com.sun.javafx.image.IntToIntPixelConverter;
import com.sun.javafx.image.PixelConverter;
import com.sun.javafx.image.PixelGetter;
import com.sun.javafx.image.PixelSetter;
import com.sun.javafx.image.PixelUtils;
import com.sun.javafx.image.impl.ByteBgra;
import com.sun.javafx.image.impl.ByteBgraPre;
import com.sun.javafx.image.impl.ByteGray;
import com.sun.javafx.image.impl.ByteGrayAlpha;
import com.sun.javafx.image.impl.ByteGrayAlphaPre;
import com.sun.javafx.image.impl.ByteRgb;
import com.sun.javafx.image.impl.ByteRgba;
import com.sun.javafx.tk.PlatformImage;
import com.sun.prism.impl.BufferUtil;
public class Image implements PlatformImage {
static final javafx.scene.image.WritablePixelFormat<ByteBuffer> FX_ByteBgraPre_FORMAT =
javafx.scene.image.PixelFormat.getByteBgraPreInstance();
static final javafx.scene.image.WritablePixelFormat<IntBuffer> FX_IntArgbPre_FORMAT =
javafx.scene.image.PixelFormat.getIntArgbPreInstance();
static final javafx.scene.image.PixelFormat<ByteBuffer> FX_ByteRgb_FORMAT =
javafx.scene.image.PixelFormat.getByteRgbInstance();
private final Buffer pixelBuffer;
private final int minX;
private final int minY;
private final int width;
private final int height;
private final int scanlineStride;
private final PixelFormat pixelFormat;
private final float pixelScale;
int serial[] = new int[1];
public static Image fromIntArgbPreData(int[] pixels, int width, int height) {
return new Image(PixelFormat.INT_ARGB_PRE, pixels, width, height);
}
public static Image fromIntArgbPreData(IntBuffer pixels, int width, int height) {
return new Image(PixelFormat.INT_ARGB_PRE, pixels, width, height);
}
public static Image fromIntArgbPreData(IntBuffer pixels, int width, int height, int scanlineStride) {
return new Image(PixelFormat.INT_ARGB_PRE, pixels, width, height, 0, 0, scanlineStride);
}
public static Image fromIntArgbPreData(IntBuffer pixels,
int width, int height, int scanlineStride,
float pixelScale)
{
return new Image(PixelFormat.INT_ARGB_PRE, pixels,
width, height, 0, 0, scanlineStride,
pixelScale);
}
public static Image fromByteBgraPreData(byte[] pixels, int width, int height) {
return new Image(PixelFormat.BYTE_BGRA_PRE, pixels, width, height);
}
public static Image fromByteBgraPreData(byte[] pixels,
int width, int height,
float pixelScale)
{
return new Image(PixelFormat.BYTE_BGRA_PRE, ByteBuffer.wrap(pixels),
width, height, 0, 0, 0,
pixelScale);
}
public static Image fromByteBgraPreData(ByteBuffer pixels, int width, int height) {
return new Image(PixelFormat.BYTE_BGRA_PRE, pixels, width, height);
}
public static Image fromByteBgraPreData(ByteBuffer pixels, int width, int height, int scanlineStride) {
return new Image(PixelFormat.BYTE_BGRA_PRE, pixels, width, height, 0, 0, scanlineStride);
}
public static Image fromByteBgraPreData(ByteBuffer pixels,
int width, int height, int scanlineStride,
float pixelScale)
{
return new Image(PixelFormat.BYTE_BGRA_PRE, pixels,
width, height, 0, 0, scanlineStride,
pixelScale);
}
public static Image fromByteRgbData(byte[] pixels, int width, int height) {
return new Image(PixelFormat.BYTE_RGB, pixels, width, height);
}
public static Image fromByteRgbData(ByteBuffer pixels, int width, int height) {
return new Image(PixelFormat.BYTE_RGB, pixels, width, height);
}
public static Image fromByteRgbData(ByteBuffer pixels, int width, int height, int scanlineStride) {
return new Image(PixelFormat.BYTE_RGB, pixels, width, height, 0, 0, scanlineStride);
}
public static Image fromByteRgbData(ByteBuffer pixels,
int width, int height, int scanlineStride,
float pixelScale)
{
return new Image(PixelFormat.BYTE_RGB, pixels,
width, height, 0, 0, scanlineStride,
pixelScale);
}
public static Image fromByteGrayData(byte[] pixels, int width, int height) {
return new Image(PixelFormat.BYTE_GRAY, pixels, width, height);
}
public static Image fromByteGrayData(ByteBuffer pixels, int width, int height) {
return new Image(PixelFormat.BYTE_GRAY, pixels, width, height);
}
public static Image fromByteGrayData(ByteBuffer pixels, int width, int height, int scanlineStride) {
return new Image(PixelFormat.BYTE_GRAY, pixels, width, height, 0, 0, scanlineStride);
}
public static Image fromByteGrayData(ByteBuffer pixels,
int width, int height, int scanlineStride,
float pixelScale)
{
return new Image(PixelFormat.BYTE_GRAY, pixels,
width, height, 0, 0, scanlineStride,
pixelScale);
}
public static Image fromByteAlphaData(byte[] pixels, int width, int height) {
return new Image(PixelFormat.BYTE_ALPHA, pixels, width, height);
}
public static Image fromByteAlphaData(ByteBuffer pixels, int width, int height) {
return new Image(PixelFormat.BYTE_ALPHA, pixels, width, height);
}
public static Image fromByteAlphaData(ByteBuffer pixels, int width, int height, int scanlineStride) {
return new Image(PixelFormat.BYTE_ALPHA, pixels, width, height, 0, 0, scanlineStride);
}
public static Image fromByteApple422Data(byte[] pixels, int width, int height) {
return new Image(PixelFormat.BYTE_APPLE_422, pixels, width, height);
}
public static Image fromByteApple422Data(ByteBuffer pixels, int width, int height) {
return new Image(PixelFormat.BYTE_APPLE_422, pixels, width, height);
}
public static Image fromByteApple422Data(ByteBuffer pixels, int width, int height, int scanlineStride) {
return new Image(PixelFormat.BYTE_APPLE_422, pixels, width, height, 0, 0, scanlineStride);
}
public static Image fromFloatMapData(FloatBuffer pixels, int width, int height) {
return new Image(PixelFormat.FLOAT_XYZW, pixels, width, height);
}
public static Image convertImageFrame(ImageFrame frame) {
ByteBuffer buffer = (ByteBuffer) frame.getImageData();
ImageStorage.ImageType type = frame.getImageType();
int w = frame.getWidth(), h = frame.getHeight();
int scanBytes = frame.getStride();
float ps = frame.getPixelScale();
switch (type) {
case GRAY:
return Image.fromByteGrayData(buffer, w, h, scanBytes, ps);
case RGB:
return Image.fromByteRgbData(buffer, w, h, scanBytes, ps);
case RGBA:
ByteBgra.ToByteBgraPreConverter().convert(buffer, 0, scanBytes,
buffer, 0, scanBytes,
w, h);
case RGBA_PRE:
ByteRgba.ToByteBgraConverter().convert(buffer, 0, scanBytes,
buffer, 0, scanBytes,
w, h);
return Image.fromByteBgraPreData(buffer, w, h, scanBytes, ps);
case GRAY_ALPHA:
ByteGrayAlpha.ToByteGrayAlphaPreConverter().convert(buffer, 0, scanBytes,
buffer, 0, scanBytes,
w, h);
case GRAY_ALPHA_PRE:
if (scanBytes != w * 2) {
throw new AssertionError("Bad stride for GRAY_ALPHA");
};
byte newbuf[] = new byte[w * h * 4];
ByteGrayAlphaPre.ToByteBgraPreConverter().convert(buffer, 0, scanBytes,
newbuf, 0, w*4,
w, h);
return Image.fromByteBgraPreData(newbuf, w, h, ps);
default:
throw new RuntimeException("Unknown image type: " + type);
}
}
private Image(PixelFormat pixelFormat, int[] pixels,
int width, int height)
{
this(pixelFormat, IntBuffer.wrap(pixels), width, height, 0, 0, 0, 1.0f);
}
private Image(PixelFormat pixelFormat, byte[] pixels,
int width, int height)
{
this(pixelFormat, ByteBuffer.wrap(pixels), width, height, 0, 0, 0, 1.0f);
}
private Image(PixelFormat pixelFormat, Buffer pixelBuffer,
int width, int height)
{
this(pixelFormat, pixelBuffer, width, height, 0, 0, 0, 1.0f);
}
private Image(PixelFormat pixelFormat, Buffer pixelBuffer,
int width, int height, int minX, int minY, int scanlineStride)
{
this(pixelFormat, pixelBuffer, width, height, minX, minY, scanlineStride, 1.0f);
}
private Image(PixelFormat pixelFormat, Buffer pixelBuffer,
int width, int height, int minX, int minY,
int scanlineStride, float pixelScale)
{
if (pixelFormat == PixelFormat.MULTI_YCbCr_420) {
throw new IllegalArgumentException("Format not supported "+pixelFormat.name());
}
if (scanlineStride == 0) {
scanlineStride = width * pixelFormat.getBytesPerPixelUnit();
}
if (pixelBuffer == null) {
throw new IllegalArgumentException("Pixel buffer must be non-null");
}
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException("Image dimensions must be > 0");
}
if (minX < 0 || minY < 0) {
throw new IllegalArgumentException("Image minX and minY must be >= 0");
}
if (((minX+width)*pixelFormat.getBytesPerPixelUnit()) > scanlineStride) {
throw new IllegalArgumentException("Image scanlineStride is too small");
}
if (scanlineStride % pixelFormat.getBytesPerPixelUnit() != 0) {
throw new IllegalArgumentException(
"Image scanlineStride must be a multiple of the pixel stride");
}
this.pixelFormat = pixelFormat;
this.pixelBuffer = pixelBuffer;
this.width = width;
this.height = height;
this.minX = minX;
this.minY = minY;
this.scanlineStride = scanlineStride;
this.pixelScale = pixelScale;
}
public PixelFormat getPixelFormat() {
return pixelFormat;
}
public PixelFormat.DataType getDataType() {
return pixelFormat.getDataType();
}
public int getBytesPerPixelUnit() {
return pixelFormat.getBytesPerPixelUnit();
}
public Buffer getPixelBuffer() {
return pixelBuffer;
}
public int getMinX() {
return minX;
}
public int getMinY() {
return minY;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public int getScanlineStride() {
return scanlineStride;
}
@Override
public float getPixelScale() {
return pixelScale;
}
public int getRowLength() {
return scanlineStride / pixelFormat.getBytesPerPixelUnit();
}
public boolean isTightlyPacked() {
return minX == 0 && minY == 0 && width == getRowLength();
}
public Image createSubImage(int x, int y, int w, int h) {
if (w <= 0 || h <= 0) {
throw new IllegalArgumentException("Subimage dimensions must be > 0");
}
if (x < 0 || y < 0) {
throw new IllegalArgumentException("Subimage minX and minY must be >= 0");
}
if (x+w > this.width) {
throw new IllegalArgumentException(
"Subimage minX+width must be <= width of parent image");
}
if (y+h > this.height) {
throw new IllegalArgumentException(
"Subimage minY+height must be <= height of parent image");
}
Image subimg = new Image(pixelFormat, pixelBuffer, w, h,
minX+x, minY+y, scanlineStride);
subimg.serial = this.serial;
return subimg;
}
public Image createPackedCopy() {
int newBytesPerRow = width * pixelFormat.getBytesPerPixelUnit();
Buffer newBuf = createPackedBuffer(pixelBuffer, pixelFormat,
minX, minY, width, height,
scanlineStride);
return new Image(pixelFormat, newBuf, width, height, 0, 0, newBytesPerRow);
}
public Image createPackedCopyIfNeeded() {
int newBytesPerRow = width * pixelFormat.getBytesPerPixelUnit();
if (newBytesPerRow == scanlineStride && minX == 0 && minY == 0) {
return this;
}
return createPackedCopy();
}
public static Buffer createPackedBuffer(Buffer pixels,
PixelFormat format,
int minX, int minY,
int width, int height,
int scanlineStride)
{
if (scanlineStride % format.getBytesPerPixelUnit() != 0) {
throw new IllegalArgumentException(
"Image scanlineStride must be a multiple of the pixel stride");
}
if (format == PixelFormat.MULTI_YCbCr_420) {
throw new IllegalArgumentException("Format unsupported "+format);
}
int elemsPerPixel = format.getElemsPerPixelUnit();
int oldRowLength = scanlineStride / format.getBytesPerPixelUnit();
int oldElemsPerRow = oldRowLength * elemsPerPixel;
int newElemsPerRow = width * elemsPerPixel;
int newSizeInElems = newElemsPerRow * height;
int oldpos = (minX*elemsPerPixel) + (minY*oldElemsPerRow);
int newpos = 0;
Buffer newBuf;
switch (format.getDataType()) {
case BYTE:
ByteBuffer oldbbuf = (ByteBuffer)pixels;
ByteBuffer newbbuf = BufferUtil.newByteBuffer(newSizeInElems);
for (int y = 0; y < height; y++) {
oldbbuf.limit(oldpos + newElemsPerRow);
oldbbuf.position(oldpos);
newbbuf.limit(newpos + newElemsPerRow);
newbbuf.position(newpos);
newbbuf.put(oldbbuf);
oldpos += oldElemsPerRow;
newpos += newElemsPerRow;
}
newBuf = newbbuf;
break;
case INT:
IntBuffer oldibuf = (IntBuffer)pixels;
IntBuffer newibuf = BufferUtil.newIntBuffer(newSizeInElems);
for (int y = 0; y < height; y++) {
oldibuf.limit(oldpos + newElemsPerRow);
oldibuf.position(oldpos);
newibuf.limit(newpos + newElemsPerRow);
newibuf.position(newpos);
newibuf.put(oldibuf);
oldpos += oldElemsPerRow;
newpos += newElemsPerRow;
}
newBuf = newibuf;
break;
case FLOAT:
FloatBuffer oldfbuf = (FloatBuffer)pixels;
FloatBuffer newfbuf = BufferUtil.newFloatBuffer(newSizeInElems);
for (int y = 0; y < height; y++) {
oldfbuf.limit(oldpos + newElemsPerRow);
oldfbuf.position(oldpos);
newfbuf.limit(newpos + newElemsPerRow);
newfbuf.position(newpos);
newfbuf.put(oldfbuf);
oldpos += oldElemsPerRow;
newpos += newElemsPerRow;
}
newBuf = newfbuf;
break;
default:
throw new InternalError("Unknown data type");
}
pixels.limit(pixels.capacity());
pixels.rewind();
newBuf.limit(newBuf.capacity());
newBuf.rewind();
return newBuf;
}
public Image iconify(ByteBuffer iconBuffer, int twidth, int theight) {
if (pixelFormat == PixelFormat.MULTI_YCbCr_420) {
throw new IllegalArgumentException("Format not supported "+pixelFormat);
}
int tnumBands = this.getBytesPerPixelUnit();
int tscanlineStride = twidth * tnumBands;
ByteToIntPixelConverter converter;
if (tnumBands == 1) {
converter = ByteGray.ToIntArgbPreConverter();
} else if (pixelFormat == PixelFormat.BYTE_BGRA_PRE) {
converter = ByteBgraPre.ToIntArgbPreConverter();
} else {
converter = ByteRgb.ToIntArgbPreConverter();
}
int[] newImage = new int[twidth*theight];
converter.convert(iconBuffer, 0, tscanlineStride,
newImage, 0, twidth,
twidth, theight);
return new Image(PixelFormat.INT_ARGB_PRE, newImage, twidth, theight);
}
@Override
public String toString() {
return super.toString()+
" [format=" + pixelFormat + " width=" + width + " height=" + height+
" scanlineStride=" + scanlineStride +
" minX=" + minX + " minY=" + minY +
" pixelBuffer=" + pixelBuffer +
" bpp=" + getBytesPerPixelUnit() + "]";
}
public int getSerial() {
return serial[0];
}
public Image promoteByteRgbToByteBgra() {
ByteBuffer oldbuf = (ByteBuffer) pixelBuffer;
ByteBuffer newbuf = ByteBuffer.allocate(width * height * 4);
int oldpos = minY * scanlineStride + minX * 3;
ByteRgb.ToByteBgraPreConverter().convert(oldbuf, oldpos, scanlineStride,
newbuf, 0, width * 4,
width, height);
return new Image(PixelFormat.BYTE_BGRA_PRE, newbuf,
width, height, 0, 0, width * 4, getPixelScale());
}
private Accessor<?> pixelaccessor;
private Accessor<?> getPixelAccessor() {
if (pixelaccessor == null) {
switch (getPixelFormat()) {
case BYTE_ALPHA:
case BYTE_APPLE_422:
case FLOAT_XYZW:
case MULTI_YCbCr_420:
default:
pixelaccessor = new UnsupportedAccess();
break;
case BYTE_GRAY:
pixelaccessor = new ByteAccess(getGrayFXPixelFormat(),
ByteGray.getter, null,
(ByteBuffer) pixelBuffer, 1);
break;
case BYTE_RGB:
pixelaccessor = new ByteRgbAccess((ByteBuffer) pixelBuffer);
break;
case BYTE_BGRA_PRE:
pixelaccessor = new ByteAccess(FX_ByteBgraPre_FORMAT,
(ByteBuffer) pixelBuffer, 4);
break;
case INT_ARGB_PRE:
pixelaccessor = new IntAccess(FX_IntArgbPre_FORMAT,
(IntBuffer) pixelBuffer);
break;
}
}
if (pixelaccessor != null && pixelScale != 1.0f) {
pixelaccessor = new ScaledAccessor<>(pixelaccessor, pixelScale);
}
return pixelaccessor;
}
@Override
public javafx.scene.image.PixelFormat<?> getPlatformPixelFormat() {
return getPixelAccessor().getPlatformPixelFormat();
}
@Override
public boolean isWritable() {
return getPixelAccessor().isWritable();
}
@Override
public PlatformImage promoteToWritableImage() {
return getPixelAccessor().promoteToWritableImage();
}
@Override
public int getArgb(int x, int y) {
return getPixelAccessor().getArgb(x, y);
}
@Override
public void setArgb(int x, int y, int argb) {
getPixelAccessor().setArgb(x, y, argb);
serial[0]++;
}
@Override
public <T extends Buffer>
void getPixels(int x, int y, int w, int h,
javafx.scene.image.WritablePixelFormat<T> pixelformat,
T pixels, int scanlineBytes)
{
getPixelAccessor().getPixels(x, y, w, h, pixelformat,
pixels, scanlineBytes);
}
@Override
public void getPixels(int x, int y, int w, int h,
WritablePixelFormat<ByteBuffer> pixelformat,
byte[] pixels, int offset, int scanlineBytes)
{
getPixelAccessor().getPixels(x, y, w, h, pixelformat,
pixels, offset, scanlineBytes);
}
@Override
public void getPixels(int x, int y, int w, int h,
WritablePixelFormat<IntBuffer> pixelformat,
int[] pixels, int offset, int scanlineInts)
{
getPixelAccessor().getPixels(x, y, w, h, pixelformat,
pixels, offset, scanlineInts);
}
@Override
public <T extends Buffer>
void setPixels(int x, int y, int w, int h,
javafx.scene.image.PixelFormat<T> pixelformat,
T pixels, int scanlineBytes)
{
getPixelAccessor().setPixels(x, y, w, h, pixelformat,
pixels, scanlineBytes);
serial[0]++;
}
@Override
public void setPixels(int x, int y, int w, int h,
javafx.scene.image.PixelFormat<ByteBuffer> pixelformat,
byte[] pixels, int offset, int scanlineBytes)
{
getPixelAccessor().setPixels(x, y, w, h, pixelformat,
pixels, offset, scanlineBytes);
serial[0]++;
}
@Override
public void setPixels(int x, int y, int w, int h,
javafx.scene.image.PixelFormat<IntBuffer> pixelformat,
int[] pixels, int offset, int scanlineInts)
{
getPixelAccessor().setPixels(x, y, w, h, pixelformat,
pixels, offset, scanlineInts);
serial[0]++;
}
@Override
public void setPixels(int dstx, int dsty, int w, int h,
PixelReader reader, int srcx, int srcy)
{
getPixelAccessor().setPixels(dstx, dsty, w, h, reader, srcx, srcy);
serial[0]++;
}
public boolean isOpaque() {
return pixelFormat.isOpaque();
}
abstract class Accessor<I extends Buffer> {
public abstract int getArgb(int x, int y);
public abstract void setArgb(int x, int y, int argb);
public abstract javafx.scene.image.PixelFormat<I> getPlatformPixelFormat();
public abstract boolean isWritable();
public abstract PlatformImage promoteToWritableImage();
public abstract <T extends Buffer>
void getPixels(int x, int y, int w, int h,
WritablePixelFormat<T> pixelformat,
T pixels, int scanlineElems);
public abstract
void getPixels(int x, int y, int w, int h,
WritablePixelFormat<ByteBuffer> pixelformat,
byte[] pixels, int offset, int scanlineBytes);
public abstract
void getPixels(int x, int y, int w, int h,
WritablePixelFormat<IntBuffer> pixelformat,
int[] pixels, int offset, int scanlineInts);
public abstract <T extends Buffer>
void setPixels(int x, int y, int w, int h,
javafx.scene.image.PixelFormat<T> pixelformat,
T pixels, int scanlineBytes);
public abstract
void setPixels(int x, int y, int w, int h,
javafx.scene.image.PixelFormat<ByteBuffer> pixelformat,
byte[] pixels, int offset, int scanlineBytes);
public abstract
void setPixels(int x, int y, int w, int h,
javafx.scene.image.PixelFormat<IntBuffer> pixelformat,
int[] pixels, int offset, int scanlineInts);
public abstract
void setPixels(int dstx, int dsty, int w, int h,
PixelReader reader, int srcx, int srcy);
}
class ScaledAccessor<I extends Buffer> extends Accessor<I> {
Accessor<I> theDelegate;
float pixelScale;
ScaledAccessor(Accessor<I> delegate, float pixelScale) {
this.theDelegate = delegate;
this.pixelScale = pixelScale;
}
private int scale(int v) {
return (int) ((v + 0.5f) * pixelScale);
}
@Override
public int getArgb(int x, int y) {
return theDelegate.getArgb(scale(x), scale(y));
}
@Override
public void setArgb(int x, int y, int argb) {
throw new UnsupportedOperationException("Pixel setting for scaled images not supported yet");
}
@Override
public javafx.scene.image.PixelFormat<I> getPlatformPixelFormat() {
return theDelegate.getPlatformPixelFormat();
}
@Override
public boolean isWritable() {
return theDelegate.isWritable();
}
@Override
public PlatformImage promoteToWritableImage() {
throw new UnsupportedOperationException("Pixel setting for scaled images not supported yet");
}
@Override
public <T extends Buffer>
void getPixels(int x, int y, int w, int h,
WritablePixelFormat<T> pixelformat,
T pixels, int scanlineElems)
{
PixelSetter<T> setter = PixelUtils.getSetter(pixelformat);
int offset = pixels.position();
int numElem = setter.getNumElements();
for (int rely = 0; rely < h; rely++) {
int sy = scale(y + rely);
int rowoff = offset;
for (int relx = 0; relx < w; relx++) {
int sx = scale(x + relx);
setter.setArgb(pixels, rowoff, theDelegate.getArgb(sx, sy));
rowoff += numElem;
}
offset += scanlineElems;
}
}
@Override
public void getPixels(int x, int y, int w, int h,
WritablePixelFormat<ByteBuffer> pixelformat,
byte[] pixels, int offset, int scanlineBytes)
{
ByteBuffer bb = ByteBuffer.wrap(pixels);
bb.position(offset);
getPixels(x, y, w, h, pixelformat, bb, scanlineBytes);
}
@Override
public void getPixels(int x, int y, int w, int h,
WritablePixelFormat<IntBuffer> pixelformat,
int[] pixels, int offset, int scanlineInts)
{
IntBuffer ib = IntBuffer.wrap(pixels);
ib.position(offset);
getPixels(x, y, w, h, pixelformat, ib, scanlineInts);
}
@Override
public <T extends Buffer>
void setPixels(int x, int y, int w, int h,
javafx.scene.image.PixelFormat<T> pixelformat,
T pixels, int scanlineElems)
{
throw new UnsupportedOperationException("Pixel setting for scaled images not supported yet");
}
@Override
public void setPixels(int x, int y, int w, int h,
javafx.scene.image.PixelFormat<ByteBuffer> pixelformat,
byte[] pixels, int offset, int scanlineBytes)
{
throw new UnsupportedOperationException("Pixel setting for scaled images not supported yet");
}
@Override
public void setPixels(int x, int y, int w, int h,
javafx.scene.image.PixelFormat<IntBuffer> pixelformat,
int[] pixels, int offset, int scanlineInts)
{
throw new UnsupportedOperationException("Pixel setting for scaled images not supported yet");
}
@Override
public void setPixels(int dstx, int dsty, int w, int h,
PixelReader reader, int srcx, int srcy)
{
throw new UnsupportedOperationException("Pixel setting for scaled images not supported yet");
}
}
static <I extends Buffer> PixelSetter<I>
getSetterIfWritable(javafx.scene.image.PixelFormat<I> theFormat)
{
if (theFormat instanceof WritablePixelFormat) {
return PixelUtils.getSetter((WritablePixelFormat) theFormat);
}
return null;
}
abstract class BaseAccessor<I extends Buffer> extends Accessor<I> {
javafx.scene.image.PixelFormat<I> theFormat;
PixelGetter<I> theGetter;
PixelSetter<I> theSetter;
I theBuffer;
int pixelElems;
int scanlineElems;
int offsetElems;
BaseAccessor(javafx.scene.image.PixelFormat<I> theFormat, I buffer, int pixelStride) {
this(theFormat, PixelUtils.getGetter(theFormat), getSetterIfWritable(theFormat),
buffer, pixelStride);
}
BaseAccessor(javafx.scene.image.PixelFormat<I> theFormat,
PixelGetter<I> getter, PixelSetter<I> setter,
I buffer, int pixelStride)
{
this.theFormat = theFormat;
this.theGetter = getter;
this.theSetter = setter;
this.theBuffer = buffer;
this.pixelElems = pixelStride;
this.scanlineElems = scanlineStride / pixelFormat.getDataType().getSizeInBytes();
this.offsetElems = minY * scanlineElems + minX * pixelStride;
}
public int getIndex(int x, int y) {
if (x < 0 || y < 0 || x >= width || y >= height) {
throw new IndexOutOfBoundsException(x + ", " + y);
}
return offsetElems + y * scanlineElems + x * pixelElems;
}
public I getBuffer() {
return theBuffer;
}
public PixelGetter<I> getGetter() {
if (theGetter == null) {
throw new UnsupportedOperationException("Unsupported Image type");
}
return theGetter;
}
public PixelSetter<I> getSetter() {
if (theSetter == null) {
throw new UnsupportedOperationException("Unsupported Image type");
}
return theSetter;
}
@Override
public javafx.scene.image.PixelFormat<I> getPlatformPixelFormat() {
return theFormat;
}
@Override
public boolean isWritable() {
return theSetter != null;
}
@Override
public PlatformImage promoteToWritableImage() {
return Image.this;
}
@Override
public int getArgb(int x, int y) {
return getGetter().getArgb(getBuffer(), getIndex(x, y));
}
@Override
public void setArgb(int x, int y, int argb) {
getSetter().setArgb(getBuffer(), getIndex(x, y), argb);
}
@Override
public <T extends Buffer>
void getPixels(int x, int y, int w, int h,
WritablePixelFormat<T> pixelformat,
T dstbuf, int dstScanlineElems)
{
PixelSetter<T> setter = PixelUtils.getSetter(pixelformat);
PixelConverter<I, T> converter =
PixelUtils.getConverter(getGetter(), setter);
int dstoff = dstbuf.position();
converter.convert(getBuffer(), getIndex(x, y), scanlineElems,
dstbuf, dstoff, dstScanlineElems,
w, h);
}
@Override
public <T extends Buffer>
void setPixels(int x, int y, int w, int h,
javafx.scene.image.PixelFormat<T> pixelformat,
T srcbuf, int srcScanlineBytes)
{
PixelGetter<T> getter = PixelUtils.getGetter(pixelformat);
PixelConverter<T, I> converter =
PixelUtils.getConverter(getter, getSetter());
int srcoff = srcbuf.position();
converter.convert(srcbuf, srcoff, srcScanlineBytes,
getBuffer(), getIndex(x, y), scanlineElems,
w, h);
}
}
class ByteAccess extends BaseAccessor<ByteBuffer> {
ByteAccess(javafx.scene.image.PixelFormat<ByteBuffer> fmt,
PixelGetter<ByteBuffer> getter, PixelSetter<ByteBuffer> setter,
ByteBuffer buffer, int numbytes)
{
super(fmt, getter, setter, buffer, numbytes);
}
ByteAccess(javafx.scene.image.PixelFormat<ByteBuffer> fmt,
ByteBuffer buffer, int numbytes)
{
super(fmt, buffer, numbytes);
}
@Override
public void getPixels(int x, int y, int w, int h,
WritablePixelFormat<ByteBuffer> pixelformat,
byte[] dstarr, int dstoff, int dstScanlineBytes)
{
BytePixelSetter setter = PixelUtils.getByteSetter(pixelformat);
ByteToBytePixelConverter b2bconverter =
PixelUtils.getB2BConverter(getGetter(), setter);
b2bconverter.convert(getBuffer(), getIndex(x, y), scanlineElems,
dstarr, dstoff, dstScanlineBytes,
w, h);
}
@Override
public void getPixels(int x, int y, int w, int h,
WritablePixelFormat<IntBuffer> pixelformat,
int[] dstarr, int dstoff, int dstScanlineInts)
{
IntPixelSetter setter = PixelUtils.getIntSetter(pixelformat);
ByteToIntPixelConverter b2iconverter =
PixelUtils.getB2IConverter(getGetter(), setter);
b2iconverter.convert(getBuffer(), getIndex(x, y), scanlineElems,
dstarr, dstoff, dstScanlineInts,
w, h);
}
@Override
public void setPixels(int x, int y, int w, int h,
javafx.scene.image.PixelFormat<ByteBuffer> pixelformat,
byte srcarr[], int srcoff, int srcScanlineBytes)
{
BytePixelGetter getter = PixelUtils.getByteGetter(pixelformat);
ByteToBytePixelConverter b2bconverter =
PixelUtils.getB2BConverter(getter, getSetter());
b2bconverter.convert(srcarr, srcoff, srcScanlineBytes,
getBuffer(), getIndex(x, y), scanlineElems,
w, h);
}
@Override
public void setPixels(int x, int y, int w, int h,
javafx.scene.image.PixelFormat<IntBuffer> pixelformat,
int srcarr[], int srcoff, int srcScanlineInts)
{
IntPixelGetter getter = PixelUtils.getIntGetter(pixelformat);
IntToBytePixelConverter i2bconverter =
PixelUtils.getI2BConverter(getter, getSetter());
i2bconverter.convert(srcarr, srcoff, srcScanlineInts,
getBuffer(), getIndex(x, y), scanlineElems,
w, h);
}
@Override
public void setPixels(int dstx, int dsty, int w, int h,
PixelReader reader, int srcx, int srcy) {
ByteBuffer b = theBuffer.duplicate();
b.position(b.position() + getIndex(dstx, dsty));
reader.getPixels(srcx, srcy, w, h,
(WritablePixelFormat) theFormat,
b, scanlineElems);
}
}
class IntAccess extends BaseAccessor<IntBuffer> {
IntAccess(javafx.scene.image.PixelFormat<IntBuffer> fmt, IntBuffer buffer) {
super(fmt, buffer, 1);
}
@Override
public void getPixels(int x, int y, int w, int h,
WritablePixelFormat<ByteBuffer> pixelformat,
byte dstarr[], int dstoff, int dstScanlineBytes)
{
BytePixelSetter setter = PixelUtils.getByteSetter(pixelformat);
IntToBytePixelConverter i2bconverter =
PixelUtils.getI2BConverter(getGetter(), setter);
i2bconverter.convert(getBuffer(), getIndex(x, y), scanlineElems,
dstarr, dstoff, dstScanlineBytes,
w, h);
}
@Override
public void getPixels(int x, int y, int w, int h,
WritablePixelFormat<IntBuffer> pixelformat,
int dstarr[], int dstoff, int dstScanlineInts)
{
IntPixelSetter setter = PixelUtils.getIntSetter(pixelformat);
IntToIntPixelConverter i2iconverter =
PixelUtils.getI2IConverter(getGetter(), setter);
i2iconverter.convert(getBuffer(), getIndex(x, y), scanlineElems,
dstarr, dstoff, dstScanlineInts,
w, h);
}
@Override
public void setPixels(int x, int y, int w, int h,
javafx.scene.image.PixelFormat<ByteBuffer> pixelformat,
byte srcarr[], int srcoff, int srcScanlineBytes)
{
BytePixelGetter getter = PixelUtils.getByteGetter(pixelformat);
ByteToIntPixelConverter b2iconverter =
PixelUtils.getB2IConverter(getter, getSetter());
b2iconverter.convert(srcarr, srcoff, srcScanlineBytes,
getBuffer(), getIndex(x, y), scanlineElems,
w, h);
}
@Override
public void setPixels(int x, int y, int w, int h,
javafx.scene.image.PixelFormat<IntBuffer> pixelformat,
int srcarr[], int srcoff, int srcScanlineInts)
{
IntPixelGetter getter = PixelUtils.getIntGetter(pixelformat);
IntToIntPixelConverter i2iconverter =
PixelUtils.getI2IConverter(getter, getSetter());
i2iconverter.convert(srcarr, srcoff, srcScanlineInts,
getBuffer(), getIndex(x, y), scanlineElems,
w, h);
}
@Override
public void setPixels(int dstx, int dsty, int w, int h,
PixelReader reader, int srcx, int srcy) {
IntBuffer b = theBuffer.duplicate();
b.position(b.position() + getIndex(dstx, dsty));
reader.getPixels(srcx, srcy, w, h,
(WritablePixelFormat) theFormat,
b, scanlineElems);
}
}
static javafx.scene.image.PixelFormat<ByteBuffer> FX_ByteGray_FORMAT;
static javafx.scene.image.PixelFormat<ByteBuffer> getGrayFXPixelFormat() {
if (FX_ByteGray_FORMAT == null) {
int grays[] = new int[256];
int gray = 0xff000000;
for (int i = 0; i < 256; i++) {
grays[i] = gray;
gray += 0x00010101;
}
FX_ByteGray_FORMAT =
javafx.scene.image.PixelFormat.createByteIndexedPremultipliedInstance(grays);
}
return FX_ByteGray_FORMAT;
}
class UnsupportedAccess extends ByteAccess {
private UnsupportedAccess() {
super(null, null, null, null, 0);
}
}
class ByteRgbAccess extends ByteAccess {
public ByteRgbAccess(ByteBuffer buffer) {
super(FX_ByteRgb_FORMAT, buffer, 3);
}
@Override
public PlatformImage promoteToWritableImage() {
return promoteByteRgbToByteBgra();
}
}
}