/*
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package javafx.scene.image;
import com.sun.javafx.tk.ImageLoader;
import com.sun.javafx.tk.PlatformImage;
import com.sun.javafx.tk.Toolkit;
import javafx.beans.NamedArg;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.scene.paint.Color;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
/**
* The {@code WritableImage} class represents a custom graphical image
* that is constructed from pixels supplied by the application, and possibly
* from {@code PixelReader} objects from any number of sources, including
* images read from a file or URL.
* @since JavaFX 2.2
*/
public class WritableImage extends Image {
static {
Toolkit.setWritableImageAccessor(new Toolkit.WritableImageAccessor() {
@Override public void loadTkImage(WritableImage wimg, Object loader) {
wimg.loadTkImage(loader);
}
@Override public Object getTkImageLoader(WritableImage wimg) {
return wimg.getTkImageLoader();
}
});
}
private ImageLoader tkImageLoader;
/**
* Construct an empty image of the specified dimensions.
* The image will initially be filled with transparent pixels.
* Images constructed this way will always be readable and writable
* so the corresponding getPixelReader() and getPixelWriter() will
* always return valid objects.
* The dimensions must both be positive numbers (> 0)
.
*
* @param width the desired width of the writable image
* @param height the desired height of the desired image
* @throws IllegalArgumentException if either dimension is negative or zero.
*/
public WritableImage(@NamedArg("width") int width, @NamedArg("height") int height) {
super(width, height);
}
/**
* Construct an image of the specified dimensions, initialized from
* the indicated {@link PixelReader}.
* The image will initially be filled with data returned from the
* {@code PixelReader}.
* If the {@code PixelReader} accesses a surface that does not contain
* the necessary number of pixel rows and columns then an
* {@link ArrayIndexOutOfBoundsException} will be thrown.
* Images constructed this way will always be readable and writable
* so the corresponding getPixelReader() and getPixelWriter() will
* always return valid objects.
* The dimensions must both be positive numbers (> 0)
.
*
* @param width the desired width of the writable image and the
* width of the region to be read from the {@code reader}
* @param height the desired height of the desired image and the
* width of the region to be read from the {@code reader}
* @throws ArrayIndexOutOfBoundsException if the {@code reader} does
* not access a surface of at least the requested dimensions
* @throws IllegalArgumentException if either dimension is negative or zero.
*/
public WritableImage(@NamedArg("reader") PixelReader reader, @NamedArg("width") int width, @NamedArg("height") int height) {
super(width, height);
getPixelWriter().setPixels(0, 0, width, height, reader, 0, 0);
}
/**
* Construct an image of the specified dimensions, initialized from
* the indicated region of the {@link PixelReader}.
* The image will initially be filled with data returned from the
* {@code PixelReader} for the specified region.
* If the {@code PixelReader} accesses a surface that does not contain
* the necessary number of pixel rows and columns then an
* {@link ArrayIndexOutOfBoundsException} will be thrown.
* Images constructed this way will always be readable and writable
* so the corresponding getPixelReader() and getPixelWriter() will
* always return valid objects.
* The dimensions must both be positive numbers (> 0)
.
*
* @param x the X coordinate of the upper left corner of the region to
* read from the {@code reader}
* @param y the Y coordinate of the upper left corner of the region to
* read from the {@code reader}
* @param width the desired width of the writable image and the
* width of the region to be read from the {@code reader}
* @param height the desired height of the desired image and the
* width of the region to be read from the {@code reader}
* @throws ArrayIndexOutOfBoundsException if the {@code reader} does
* not access a surface containing at least the indicated region
* @throws IllegalArgumentException if either dimension is negative or zero.
*/
public WritableImage(@NamedArg("reader") PixelReader reader,
@NamedArg("x") int x, @NamedArg("y") int y, @NamedArg("width") int width, @NamedArg("height") int height)
{
super(width, height);
getPixelWriter().setPixels(0, 0, width, height, reader, x, y);
}
@Override
boolean isAnimation() {
return true;
}
@Override
boolean pixelsReadable() {
return true;
}
private PixelWriter writer;
/**
* This method returns a {@code PixelWriter} that provides access to
* write the pixels of the image.
*
* @return the {@code PixelWriter} for writing pixels to the image
*/
public final PixelWriter getPixelWriter() {
if (getProgress() < 1.0 || isError()) {
return null;
}
if (writer == null) {
writer = new PixelWriter() {
ReadOnlyObjectProperty pimgprop =
acc_platformImageProperty();
@Override
public PixelFormat getPixelFormat() {
PlatformImage pimg = getWritablePlatformImage();
return pimg.getPlatformPixelFormat();
}
@Override
public void setArgb(int x, int y, int argb) {
getWritablePlatformImage().setArgb(x, y, argb);
pixelsDirty();
}
@Override
public void setColor(int x, int y, Color c) {
if (c == null) throw new NullPointerException("Color cannot be null");
int a = (int) Math.round(c.getOpacity() * 255);
int r = (int) Math.round(c.getRed() * 255);
int g = (int) Math.round(c.getGreen() * 255);
int b = (int) Math.round(c.getBlue() * 255);
setArgb(x, y, (a << 24) | (r << 16) | (g << 8) | b);
}
@Override
public
void setPixels(int x, int y, int w, int h,
PixelFormat pixelformat,
T buffer, int scanlineStride)
{
if (pixelformat == null) throw new NullPointerException("PixelFormat cannot be null");
if (buffer == null) throw new NullPointerException("Buffer cannot be null");
PlatformImage pimg = getWritablePlatformImage();
pimg.setPixels(x, y, w, h, pixelformat,
buffer, scanlineStride);
pixelsDirty();
}
@Override
public void setPixels(int x, int y, int w, int h,
PixelFormat pixelformat,
byte buffer[], int offset, int scanlineStride)
{
if (pixelformat == null) throw new NullPointerException("PixelFormat cannot be null");
if (buffer == null) throw new NullPointerException("Buffer cannot be null");
PlatformImage pimg = getWritablePlatformImage();
pimg.setPixels(x, y, w, h, pixelformat,
buffer, offset, scanlineStride);
pixelsDirty();
}
@Override
public void setPixels(int x, int y, int w, int h,
PixelFormat pixelformat,
int buffer[], int offset, int scanlineStride)
{
if (pixelformat == null) throw new NullPointerException("PixelFormat cannot be null");
if (buffer == null) throw new NullPointerException("Buffer cannot be null");
PlatformImage pimg = getWritablePlatformImage();
pimg.setPixels(x, y, w, h, pixelformat,
buffer, offset, scanlineStride);
pixelsDirty();
}
@Override
public void setPixels(int writex, int writey, int w, int h,
PixelReader reader, int readx, int ready)
{
if (reader == null) throw new NullPointerException("Reader cannot be null");
PlatformImage pimg = getWritablePlatformImage();
pimg.setPixels(writex, writey, w, h, reader, readx, ready);
pixelsDirty();
}
};
}
return writer;
}
private void loadTkImage(Object loader) {
if (!(loader instanceof ImageLoader)) {
throw new IllegalArgumentException("Unrecognized image loader: "
+ loader);
}
ImageLoader tkLoader = (ImageLoader)loader;
if (tkLoader.getWidth() != (int)this.getWidth()
|| tkLoader.getHeight() != (int)this.getHeight())
{
throw new IllegalArgumentException("Size of loader does not match size of image");
}
super.setPlatformImage(tkLoader.getFrame(0));
this.tkImageLoader = tkLoader;
}
private Object getTkImageLoader() {
return tkImageLoader;
}
}