JavaFX Image Converter

Sometimes it is easier to grasp the concepts of a language or library such as JavaFX by seeing it in action. I’ve put together a JavaFX image converter application. This JavaFX app allows you to drag GIF’s, JPEG’s, BMP’s, or PNG’s onto the ImageView and then convert them and save them quickly as any of the other formats mentioned above.

JavaFX Image Converter
This JavaFX app allows quick conversion of BMP, GIF, JPG, and PNG files to any of the other formats and saving to your computer.

This JavaFX appĀ is a double-clickable JAR file. That means that if you want to run it from the JAR file, just make sure you have Java installed and double-click the JavaFX JAR named image-converter.jar.

Note: To see other JavaFX tutorials dealing with ImageViews, see my ImageView examples page. If you want to read more about dragging and dropping in JavaFX, check out my Dragboard tutorials list.

If all you want is the app, download this zip file, and uncompress it. Then double-click the *.jar file. It is JavaFX, so requires Java 8 or newer installed on your computer to run properly.

image-converter.jar

Here’s the ConverterController.java code.

package com.whatisjavafx;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.ResourceBundle;

import javax.imageio.ImageIO;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.embed.swing.SwingFXUtils;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;

public class ConverterController {
  
  HashMap<String, ExtensionFilter> filterMap;
  
  private Image defaultImage;
  private Image myImage;

  @FXML
  private ResourceBundle resources;

  @FXML
  private URL location;

  @FXML
  private ImageView myImageView;

  @FXML
  private Button resetButton;

  @FXML
  private Button convertButton;

  @FXML
  private ChoiceBox<String> myChoiceBox;

  @FXML
  void convertClicked(ActionEvent event) {
      try {
        FileChooser fileChooser = 
            new FileChooser();
        
        fileChooser
        .setTitle("Save Picture");
        
        fileChooser
        .getExtensionFilters()
        .addAll(
            filterMap
            .get( myChoiceBox.getValue() ));
        
        File imageFile = 
            fileChooser
            .showSaveDialog( Main.primaryStage );
    
        BufferedImage bufImage = 
            SwingFXUtils
            .fromFXImage(myImage, null);
        ImageIO
        .write(
            bufImage, 
            myChoiceBox.getValue(), 
            imageFile);
      } catch (IOException e) {
        e.printStackTrace();
      }
  }

  @FXML
  void imageDragDropped(DragEvent event) {
    try {
      Dragboard board = event.getDragboard();
      List<File> phil = board.getFiles();
      FileInputStream fis;
        fis = new FileInputStream(phil.get(0));
      myImage = new Image(fis);
      myImageView.setImage(myImage);
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }
  }

  @FXML
  void imageDragOver(DragEvent event) {
    Dragboard board = event.getDragboard();
    if (board.hasFiles()) {

      List<File> phil = board.getFiles();
      String path = phil
          .get(0)
          .toPath()
          .toString();

      if (
          path.endsWith(".jpg")  || 
          path.endsWith(".JPG")  || 
          path.endsWith(".jpeg") || 
          path.endsWith(".JPEG") || 
          path.endsWith(".gif")  || 
          path.endsWith(".GIF")  || 
          path.endsWith(".png")  || 
          path.endsWith(".PNG")  || 
          path.endsWith(".bmp")  || 
          path.endsWith(".BMP") 
          ) {
        event
        .acceptTransferModes(
            TransferMode.ANY);
      }        
    }
  }

  @FXML
  void resetClicked(ActionEvent event) {
    myImageView.setImage(defaultImage);
    myChoiceBox.setValue("png");
  }

  @FXML
  void initialize() {
    
    defaultImage = myImageView.getImage();
    myImage = defaultImage;
    
    ObservableList<String> typeList = 
      FXCollections.observableArrayList(
      "jpeg", "gif", "png", "bmp");
    
    myChoiceBox.setItems( typeList );
    myChoiceBox.setValue("png");
    
    filterMap = 
        new HashMap<String, ExtensionFilter>();
    filterMap.put(
        "jpeg", 
        new ExtensionFilter("JPEG", "*.jpg"));
    filterMap.put(
        "gif", 
        new ExtensionFilter("GIF", "*.gif"));
    filterMap.put(
        "png", 
        new ExtensionFilter("PNG", "*.png"));
    filterMap.put(
        "bmp", 
        new ExtensionFilter("BMP", "*.bmp"));
  }
}

 

Here’s the FXML.

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>

<GridPane
 maxHeight="-Infinity"
 maxWidth="-Infinity"
 minHeight="-Infinity"
 minWidth="-Infinity"
 prefHeight="600.0"
 prefWidth="800.0"
 xmlns="http://javafx.com/javafx/8.0.65"
 xmlns:fx="http://javafx.com/fxml/1"
 fx:controller="com.whatisjavafx.ConverterController">
 <columnConstraints>
  <ColumnConstraints
   hgrow="SOMETIMES"
   minWidth="10.0"
   prefWidth="100.0" />
 </columnConstraints>
 <rowConstraints>
  <RowConstraints
   minHeight="10.0"
   prefHeight="30.0"
   vgrow="SOMETIMES" />
  <RowConstraints
   maxHeight="50.0"
   minHeight="10.0"
   prefHeight="30.0"
   vgrow="SOMETIMES" />
 </rowConstraints>
 <children>
  <BorderPane
   prefHeight="200.0"
   prefWidth="200.0">
   <center>
    <ImageView
     fx:id="myImageView"
     fitHeight="550.0"
     fitWidth="700.0"
     onDragDropped="#imageDragDropped"
     onDragOver="#imageDragOver"
     pickOnBounds="true"
     preserveRatio="true"
     BorderPane.alignment="CENTER">
     <image>
      <Image url="@drop.jpg" />
     </image>
    </ImageView>
   </center>
  </BorderPane>
  <HBox
   nodeOrientation="RIGHT_TO_LEFT"
   prefHeight="100.0"
   prefWidth="200.0"
   spacing="5.0"
   GridPane.rowIndex="1">
   <children>
    <Button
     fx:id="resetButton"
     mnemonicParsing="false"
     onAction="#resetClicked"
     text="Reset" />
    <Button
     fx:id="convertButton"
     mnemonicParsing="false"
     onAction="#convertClicked"
     text="Convert" />
    <Separator
     opacity="0.0"
     prefWidth="200.0" />
    <ChoiceBox fx:id="myChoiceBox" />

   </children>
   <GridPane.margin>
    <Insets
     bottom="7.0"
     left="25.0"
     right="25.0"
     top="7.0" />
   </GridPane.margin>
  </HBox>
 </children>
</GridPane>

 

Here’s the Main class.

package com.whatisjavafx;

import java.net.URL;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;


public class Main extends Application {
  public static Stage primaryStage;

  @Override
  public void start(Stage stage) {

    primaryStage = stage;

    try {
      URL url = 
          getClass()
          .getResource("ConverterUI.fxml");
      GridPane root = FXMLLoader.load(url);

      Scene scene = new Scene(root);
      stage.setScene(scene);
      stage.setResizable(false);
      stage
      .setTitle("JavaFX Image Converter");
      stage.show();
    } catch(Exception e) {
      e.printStackTrace();
    }
  }

  public static void main(String[] args) {
    launch(args);
  }
}

 

Here’s the drop.jpg used by the application.

Drop Image Here
After looking through this JavaFX app’s source, you might want to compile it yourself. This is the drop.jpg that it uses.

After looking through the code and trying out this JavaFX app, you may realize that the app does not yet support alpha channels. If you want to get your hands dirty mucking about in the code, that would be a good assignment for you to implement, just to get a feel for working with JavaFX.

Leave a Reply

Your email address will not be published. Required fields are marked *