/*
 * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

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 WritableImage class represents a custom graphical image that is constructed from pixels supplied by the application, and possibly from PixelReader objects from any number of sources, including images read from a file or URL.
Since:JavaFX 2.2
/** * 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).
Params:
  • width – the desired width of the writable image
  • height – the desired height of the desired image
Throws:
/** * 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 <code>(&gt;&nbsp;0)</code>. * * @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 PixelReader. The image will initially be filled with data returned from the PixelReader. If the PixelReader accesses a surface that does not contain the necessary number of pixel rows and columns then an 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).
Params:
  • reader – the PixelReader to construct from
  • width – the desired width of the writable image and the width of the region to be read from the reader
  • height – the desired height of the desired image and the width of the region to be read from the reader
Throws:
/** * 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 <code>(&gt;&nbsp;0)</code>. * * @param reader the {@code PixelReader} to construct from * @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 PixelReader. The image will initially be filled with data returned from the PixelReader for the specified region. If the PixelReader accesses a surface that does not contain the necessary number of pixel rows and columns then an 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).
Params:
  • reader – the PixelReader to construct from
  • x – the X coordinate of the upper left corner of the region to read from the reader
  • y – the Y coordinate of the upper left corner of the region to read from the reader
  • width – the desired width of the writable image and the width of the region to be read from the reader
  • height – the desired height of the desired image and the width of the region to be read from the reader
Throws:
/** * 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 <code>(&gt;&nbsp;0)</code>. * * @param reader the {@code PixelReader} to construct from * @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 PixelWriter that provides access to write the pixels of the image.
Returns:the PixelWriter for writing pixels to the image
/** * 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<PlatformImage> 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 <T extends Buffer> void setPixels(int x, int y, int w, int h, PixelFormat<T> 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<ByteBuffer> 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<IntBuffer> 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; } }