Image

JavaFX Image Example

This is a JavaFX Image example. JavaFX provides the Image API that lets you load and display images, and read/write raw image pixels. All classes are in the javafx.scene.image package. The API lets you:

  • Load an image in memory
  • Display an image as a node in a scene graph
  • Read pixels from an image
  • Write pixels to an image
  • Convert a node in a scene graph to an image and save it to the local file system

 
The following table shows an overview of the whole article:

The following examples uses Java SE 7 and JavaFX 2.2.

1. Loading and Viewing an Image

An instance of the Image class represents an image in memory. The class supports BMP, PNG, JPEG, and GIF image formats. You can construct an image in a JavaFX application by supplying pixels to a WritableImage instance. An ImageView is a Node. It is used to display an Image in a scene graph. If you want to display an image in an application, you need to load the image in an Image and display the Image in an ImageView.

1.1 The Code

FxImageExample1.java

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class FxImageExample1 extends Application
{
	public static void main(String[] args) 
	{
		Application.launch(args);
	}
	
	@Override
	public void start(Stage stage) 
	{
		// Load an image in the background		
		String imageUrl = "https://docs.oracle.com/javafx/javafx/images/javafx-documentation.png";
		Image image = new Image(imageUrl,160,60,false,true);
		
		// Create the ImageView
		ImageView imageView = new ImageView(image);
		
		// Create the HBox		
		HBox root = new HBox();
		// Add Children to the HBox
		root.getChildren().add(imageView);
		
		// Set the padding of the HBox
		root.setStyle("-fx-padding: 10;");
		// Set the border-style of the HBox
		root.setStyle("-fx-border-style: solid inside;");
		// Set the border-width of the HBox
		root.setStyle("-fx-border-width: 2;");
		// Set the border-insets of the HBox
		root.setStyle("-fx-border-insets: 5;");
		// Set the border-radius of the HBox
		root.setStyle("-fx-border-radius: 5;");
		// Set the border-color of the HBox
		root.setStyle("-fx-border-color: blue;");		
		// Set the size of the HBox
		root.setPrefSize(300, 200);
		
		// Create the Scene
		Scene scene = new Scene(root);
		// Add the scene to the Stage
		stage.setScene(scene);
		// Set the title of the Stage
		stage.setTitle("Displaying an Image");
		// Display the Stage
		stage.show();		
	}
}

1.2 Loading an Image

The following code snippet loads an image from a source, which can be specified as a String URL or an InputStream.

// Load an image in the background		
String imageUrl = "https://docs.oracle.com/javafx/javafx/images/javafx-documentation.png";

1.3 Specifying the Image-Loading Properties

Some constructors let you specify some image-loading properties to controls the quality of the image and the loading process:

  • requestedWidth
  • requestedHeight
  • preserveRatio
  • smooth
  • backgroundLoading

The requestedWidth and requestedHeight properties specify the scaled width and height of the image. By default, an image is loaded in its original size. The preserveRatio property specifies whether to preserve the aspect ratio of the image while scaling. By default, it is false. The smooth property specifies the quality of the filtering algorithm to be used in scaling. It´s default value is also false. If it is set to true, a better quality filtering algorithm is used, which slows down the image-loading process a bit. The backgroundLoading property specifies whether to load the image asynchronously. By default, the property is set to false and the image is loaded synchronously. The loading process starts when the Image object is created. If this property is set to true, the image is loaded asynchronously in a background thread.

Image image = new Image(imageUrl,160,60,false,true);

1.4 Viewing an Image

An instance of the ImageView class is used to display an image loaded in an Image object. The ImageView class inherits from the Node class, which makes an ImageView suitable to be added to a scene graph. The class contains several constructors:

  • ImageView()
  • ImageView(Image image)
  • ImageView(String url)

The no-args constructor creates an ImageView without an image. Use the image property to set an image. The second constructor accepts the reference of an Image. The third constructor lets you specify the URL of the image source. Internally, it creates an Image using the specified URL.

// Create the ImageView
ImageView imageView = new ImageView(image);

1.5 The GUI

The following graphics shows an example how an Image can be viewed in a HBox.

Displaying an Image
Displaying an Image

2. Multiple Views of an Image

An Image loads an image in memory from its source. You can have multiple views of the same Image. An ImageView provides one of the views. You have an option to resize the original image while loading, displaying, or at both times. Which option you choose to resize an image depends on the requirement at hand.

  • Resizing an image in an Image object resizes the image permanently in memory and all views of the image will use the resized image. Once an Image is resized, its size cannot be altered. You may want to reduce the size of an image in an Image object to save memory.
  • Resizing an image in an ImageView resizes the image only for this view. You can resize the view of an image in an ImageView even after the image has been displayed.

2.1 The Code

FxImageExample2.java

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class FxImageExample2 extends Application
{
	public static void main(String[] args) 
	{
		Application.launch(args);
	}
	
	@Override
	public void start(Stage stage) 
	{
		// Load an image in the background
		String imageUrl = "https://docs.oracle.com/javafx/javafx/images/javafx-documentation.png";
		Image image = new Image(imageUrl);
		
		// Create three views of different sizes of the same image
		ImageView view1 = getImageView(image, 100, 50, false);
		ImageView view2 = getImageView(image, 100, 50, true);
		ImageView view3 = getImageView(image, 100, 100, true);
		
		// Create the HBox		
		HBox root = new HBox(10);
		// Add Children to the HBox
		root.getChildren().addAll(view1, view2, view3);
		
		// Set the padding of the HBox
		root.setStyle("-fx-padding: 10;");
		// Set the border-style of the HBox
		root.setStyle("-fx-border-style: solid inside;");
		// Set the border-width of the HBox
		root.setStyle("-fx-border-width: 2;");
		// Set the border-insets of the HBox
		root.setStyle("-fx-border-insets: 5;");
		// Set the border-radius of the HBox
		root.setStyle("-fx-border-radius: 5;");
		// Set the border-color of the HBox
		root.setStyle("-fx-border-color: blue;");		
		// Set the size of the HBox
		root.setPrefSize(350, 200);
		
		// Create the Scene
		Scene scene = new Scene(root);
		// Add the scene to the Stage
		stage.setScene(scene);
		// Set the title of the Stage
		stage.setTitle("Multiple Views of an Image");
		// Display the Stage
		stage.show();		
	}
	
	private ImageView getImageView(Image image,	double fitWidth,
			double fitHeight, boolean preserveRation) 
	{
			// Create the ImageView
			ImageView view = new ImageView(image);
			// Set Properties Width, Height, Smooth and PreserveRatio
			view.setFitWidth(fitWidth);
			view.setFitHeight(fitHeight);
			view.setPreserveRatio(preserveRation);
			view.setSmooth(true);
			return view;
	}	
}

2.2 Specifying the Properties of an Image

We have already discussed how to resize an image in an Image object. In this section, we will discuss resizing an image in an ImageView. Similar to the Image class, the ImageView class contains the following four properties to control the resizing of view of an image.

  • fitWidth
  • fitHeight
  • preserveRatio
  • smooth

The fitWidth and fitHeight properties specify the resized width and height of the image, respectively. By default, they are zero, which means that the ImageView will use the width and height of the loaded image in the Image. The preserveRatio property specifies whether to preserve the aspect ratio of the image while resizing. By default, it is false. The smooth property specifies the quality of the filtering algorithm to be used in resizing. Its default value is platform dependent. If it is set to true, a better quality filtering algorithm is used.

The Method getImageView(Image image, double fitWidth, double fitHeight, boolean preserveRation) creates an ImageView and sets the described properties:

private ImageView getImageView(Image image,	double fitWidth,
		double fitHeight, boolean preserveRation) 
{
		// Create the ImageView
		ImageView view = new ImageView(image);
		// Set Properties Width, Height, Smooth and PreserveRatio
		view.setFitWidth(fitWidth);
		view.setFitHeight(fitHeight);
		view.setPreserveRatio(preserveRation);
		view.setSmooth(true);
		return view;
}	

2.3 The GUI

The following Image shows the effect of the differenet properties, which are applied to one original image.

Multiple Views of an Image
Multiple Views of an Image

3. Reading Pixels from an Image

Images are constructed from pixels. Data for pixels in an image may be stored in different formats. A PixelFormat defines how the data for a pixel for a given format is stored. A WritablePixelFormat represents a destination format to write pixels with full pixel color information.

The PixelReader and PixelWriter interfaces define methods to read from an Image and write data to a WritableImage. Besides an Image, you can read pixels from and write pixels to any surface that contain pixels.

3.1 The Code

FxImageExample3.java

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelFormat;
import javafx.scene.image.PixelReader;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class FxImageExample3 extends Application
{
	// Create the TextArea
	private final TextArea textArea = new TextArea();
	
	public static void main(String[] args) 
	{
		Application.launch(args);
	}
	
	@Override
	public void start(Stage stage) 
	{
		// Settings for TextArea
		textArea.setMinWidth(200);
		textArea.setMinHeight(600);
		
		// Load an image in the background		
		String imageUrl = "https://docs.oracle.com/javafx/javafx/images/javafx-documentation.png";
		Image image = new Image(imageUrl);
		
		// Create the ImageView		
		ImageView imageView = new ImageView(image);

		// Read pixels from the image
		this.readPixelsInfo(image);
		
		// Create the VBox
		VBox root = new VBox();
		// Add Children to the VBox
		root.getChildren().addAll(imageView,textArea);
		
		root.setAlignment(Pos.TOP_CENTER);
		// Set the padding of the VBox
		root.setStyle("-fx-padding: 10;");
		// Set the border-style of the VBox
		root.setStyle("-fx-border-style: solid inside;");
		// Set the border-width of the VBox
		root.setStyle("-fx-border-width: 2;");
		// Set the border-insets of the VBox
		root.setStyle("-fx-border-insets: 5;");
		// Set the border-radius of the VBox
		root.setStyle("-fx-border-radius: 5;");
		// Set the border-color of the VBox
		root.setStyle("-fx-border-color: blue;");		
		// Set the size of the VBox
		root.setPrefSize(200, 600);

		// Create the Scene
		Scene scene = new Scene(root);
		// Add the scene to the Stage
		stage.setScene(scene);
		// Set the title of the Stage
		stage.setTitle("Reading Pixels from an Image");
		// Display the Stage
		stage.show();		
	}
	
	@SuppressWarnings("rawtypes")
	private void readPixelsInfo(Image image) 
	{
		// Obtain the pixel reader from the image
		PixelReader pixelReader = image.getPixelReader();
	
		if (pixelReader == null) 
		{
			System.out.println("Connot read pixels from the image");
			return;
		}
		
		// Get Properties from the Image
		int width = (int)image.getWidth();
		int height = (int)image.getHeight();
		double progress = image.getProgress();
		double requWidth = image.getRequestedWidth();
		double requHeight = image.getRequestedHeight();
		
		PixelFormat format = pixelReader.getPixelFormat();
		PixelFormat.Type formatType = format.getType();

		// Write out the Properties to the TextArea
		this.writeInfoMessage("Image Width: " + width);
		this.writeInfoMessage("Image Height: " + height);
		this.writeInfoMessage("Progress: " + progress);
		this.writeInfoMessage("Requested Image Width: " + requWidth);
		this.writeInfoMessage("Requested Image Height: " + requHeight);
		this.writeInfoMessage("Pixel format type: " + formatType);
		
		
		// Read all pixels	
		for(int y = 0; y < height; y++) 
		{
			for(int x = 0; x < width; x++) 
			{
				Color color = pixelReader.getColor(x, y);
				this.writeInfoMessage("Color at (" + x + ", " + y + ") = " + color);
			}
		}
	}	
	
	// Method for Logging
	private void writeInfoMessage(String msg)
	{
		this.textArea.appendText(msg + "\n");
	}
	
}

3.2 Pixel Formats

The image API in JavaFX gives you access to each pixel in an image. A pixel stores information about its color (red, green, blue) and opacity (alpha). The pixel information can be stored in several formats. An instance the PixelFormat<T extends Buffer> represents the layout of data for a pixel. You need to know the pixel format when you read the pixels from an image. You need to specify the pixel format when you write pixels to an image.

In the above class, an own method was defined, which reads the information of an image and writes it into a TextArea.

@SuppressWarnings("rawtypes")
private void readPixelsInfo(Image image) 
{
	// Obtain the pixel reader from the image
	PixelReader pixelReader = image.getPixelReader();

	if (pixelReader == null) 
	{
		System.out.println("Connot read pixels from the image");
		return;
	}

	// Get Properties from the Image
	int width = (int)image.getWidth();
	int height = (int)image.getHeight();
	double progress = image.getProgress();
	double requWidth = image.getRequestedWidth();
	double requHeight = image.getRequestedHeight();

	PixelFormat format = pixelReader.getPixelFormat();
	PixelFormat.Type formatType = format.getType();

	// Write out the Properties to the TextArea
	this.writeInfoMessage("Image Width: " + width);
	this.writeInfoMessage("Image Height: " + height);
	this.writeInfoMessage("Progress: " + progress);
	this.writeInfoMessage("Requested Image Width: " + requWidth);
	this.writeInfoMessage("Requested Image Height: " + requHeight);
	this.writeInfoMessage("Pixel format type: " + formatType);


	// Read all pixels	
	for(int y = 0; y < height; y++) 
	{
		for(int x = 0; x < width; x++) 
		{
			Color color = pixelReader.getColor(x, y);
			this.writeInfoMessage("Color at (" + x + ", " + y + ") = " + color);
		}
	}
}	

3.3 The GUI

Reading Pixels from an Image
Reading Pixels from an Image

4. Writing Pixels to an Image

You can write pixels to an image or any surface that supports writing pixels. For example, you can write pixels to a WritableImage and a Canvas.

4.1 The Code

FxImageExample4.java

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelReader;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class FxImageExample4 extends Application
{
	public static void main(String[] args) 
	{
		Application.launch(args);
	}
	
	@Override
	public void start(Stage stage) 
	{
		// Load an image in the background
		String imageUrl = "https://docs.oracle.com/javafx/javafx/images/javafx-documentation.png";
		Image image = new Image(imageUrl);

		// Set the Width and Height of the Image
		int width = (int)image.getWidth();
		int height = (int)image.getHeight();

		// Create three WritableImage instances
		// One Image will be a darker, one brighter, and one semi-transparent
		WritableImage darkerImage = new WritableImage(width, height);
		WritableImage brighterImage = new WritableImage(width, height);
		WritableImage semiTransparentImage = new WritableImage(width, height);		
		
		// Copy source pixels to the destinations
		this.createImages(image, darkerImage, brighterImage, semiTransparentImage,width,height);
		
		// Create the ImageViews
		ImageView imageView = new ImageView(image);
		ImageView darkerView = new ImageView(darkerImage);
		ImageView brighterView = new ImageView(brighterImage);
		ImageView semiTransparentView = new ImageView(semiTransparentImage);
		
		// Create the VBox for the Original Image
		VBox originalViewBox = new VBox();
		// Add ImageView to the VBox
		originalViewBox.getChildren().addAll(imageView, new Text("Original"));
		
		// Create the VBox for the Darker Image
		VBox darkerViewBox = new VBox();
		// Add ImageView to the VBox
		darkerViewBox.getChildren().addAll(darkerView, new Text("Darker"));
		
		// Create the VBox for the Brighter Image
		VBox brighterViewBox = new VBox();
		// Add ImageView to the VBox
		brighterViewBox.getChildren().addAll(brighterView, new Text("Brighter"));

		// Create the VBox for the Semi-Transparent Image
		VBox transparentViewBox = new VBox();		
		// Add ImageView to the VBox
		transparentViewBox.getChildren().addAll(semiTransparentView, new Text("Semi-Transparent"));
		
		// Create the HBox
		HBox root = new HBox(10);
		// Add VBoxes to the HBox
		root.getChildren().addAll(originalViewBox,darkerViewBox,brighterViewBox,transparentViewBox);
		
		// Set the padding of the HBox
		root.setStyle("-fx-padding: 10;");
		// Set the border-style of the HBox
		root.setStyle("-fx-border-style: solid inside;");
		// Set the border-width of the HBox
		root.setStyle("-fx-border-width: 2;");
		// Set the border-insets of the HBox
		root.setStyle("-fx-border-insets: 5;");
		// Set the border-radius of the HBox
		root.setStyle("-fx-border-radius: 5;");
		// Set the border-color of the HBox
		root.setStyle("-fx-border-color: blue;");		
		// Set the size of the HBox
		root.setPrefSize(400, 200);
		
		// Create the Scene
		Scene scene = new Scene(root);
		// Add the scene to the Stage
		stage.setScene(scene);
		// Set the title of the Stage
		stage.setTitle("Writing Pixels to an Image");
		// Display the Stage
		stage.show();		
	}
	
	private void createImages(Image image, WritableImage darkerImage,WritableImage brighterImage,
			WritableImage semiTransparentImage,	int width, int height) 
	{
		// Obtain the pixel reader from the image
		PixelReader pixelReader = image.getPixelReader();
		PixelWriter darkerWriter = darkerImage.getPixelWriter();
		PixelWriter brighterWriter = brighterImage.getPixelWriter();
		PixelWriter semiTransparentWriter = semiTransparentImage.getPixelWriter();

		// Read one pixel at a time from the source and
		// write it to the destinations
		for(int y = 0; y < height; y++) 
		{
			for(int x = 0; x < width; x++) 
			{
				Color color = pixelReader.getColor(x, y);
				// Write a darker pixel to the new image
				darkerWriter.setColor(x, y, color.darker());
				// Write a brighter pixel to the new image
				brighterWriter.setColor(x, y, color.brighter());	
				// Write a semi-transparent pixel to the new image
				semiTransparentWriter.setColor(x, y, Color.color(color.getRed(), 
						color.getGreen(),color.getBlue(), 0.50));
			}
		}
	}				
}

An instance of the PixelWriter interface is used to write pixels to a surface. A PixelWriter is provided by the writable surface. For example, you can use the getPixelWriter() method of the Canvas and WritableImage to obtain a PixelWriter for them.

The following method creates different views on an image.

private void createImages(Image image, WritableImage darkerImage,WritableImage brighterImage,
		WritableImage semiTransparentImage,	int width, int height) 
{
	// Obtain the pixel reader from the image
	PixelReader pixelReader = image.getPixelReader();
	PixelWriter darkerWriter = darkerImage.getPixelWriter();
	PixelWriter brighterWriter = brighterImage.getPixelWriter();
	PixelWriter semiTransparentWriter = semiTransparentImage.getPixelWriter();

	// Read one pixel at a time from the source and
	// write it to the destinations
	for(int y = 0; y < height; y++) 
	{
		for(int x = 0; x < width; x++) 
		{
			Color color = pixelReader.getColor(x, y);
			// Write a darker pixel to the new image
			darkerWriter.setColor(x, y, color.darker());
			// Write a brighter pixel to the new image
			brighterWriter.setColor(x, y, color.brighter());	
			// Write a semi-transparent pixel to the new image
			semiTransparentWriter.setColor(x, y, Color.color(color.getRed(), 
					color.getGreen(),color.getBlue(), 0.50));
		}
	}
}				

Thereafter, a VBox will be craeted for each view. These VBoxes will be added to a HBox.

// Create the VBox for the Original Image
VBox originalViewBox = new VBox();
// Add ImageView to the VBox
originalViewBox.getChildren().addAll(imageView, new Text("Original"));

// Create the VBox for the Darker Image
VBox darkerViewBox = new VBox();
// Add ImageView to the VBox
darkerViewBox.getChildren().addAll(darkerView, new Text("Darker"));

// Create the VBox for the Brighter Image
VBox brighterViewBox = new VBox();
// Add ImageView to the VBox
brighterViewBox.getChildren().addAll(brighterView, new Text("Brighter"));

// Create the VBox for the Semi-Transparent Image
VBox transparentViewBox = new VBox();		
// Add ImageView to the VBox
transparentViewBox.getChildren().addAll(semiTransparentView, new Text("Semi-Transparent"));

// Create the HBox
HBox root = new HBox(10);
// Add VBoxes to the HBox
root.getChildren().addAll(originalViewBox,darkerViewBox,brighterViewBox,transparentViewBox);

4.2 The GUI

Writing Pixels to an Image
Writing Pixels to an Image

5. Download Java Source Code

This was an example of javafx.scene.control.Image

Download
You can download the full source code of this example here: JavaFxImageExample.zip

Andreas Pomarolli

Andreas has graduated from Computer Science and Bioinformatics at the University of Linz. During his studies he has been involved with a large number of research projects ranging from software engineering to data engineering and at least web engineering. His scientific focus includes the areas of software engineering, data engineering, web engineering and project management. He currently works as a software engineer in the IT sector where he is mainly involved with projects based on Java, Databases and Web Technologies.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button