Tuesday, January 20, 2015

QRCode generator on JavaFX, using ZXing

This example show how to generate QR Code using ZXing, an open-source, multi-format 1D/2D barcode image processing library implemented in Java, with ports to other languages.

Before enter the code, you have to download, create and add the ZXing jars in Netbeans IDE.

package javafx_qrcodewriter;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

/**
 *
 * @web http://java-buddy.blogspot.com/
 */
public class JavaFX_QRCodeWriter extends Application {
    
    @Override
    public void start(Stage primaryStage) {
        
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        String myWeb = "http://java-buddy.blogspot.com/";
        int width = 300;
        int height = 300;
        String fileType = "png";
        
        BufferedImage bufferedImage = null;
        try {
            BitMatrix byteMatrix = qrCodeWriter.encode(myWeb, BarcodeFormat.QR_CODE, width, height);
            bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            bufferedImage.createGraphics();
            
            Graphics2D graphics = (Graphics2D) bufferedImage.getGraphics();
            graphics.setColor(Color.WHITE);
            graphics.fillRect(0, 0, width, height);
            graphics.setColor(Color.BLACK);
            
            for (int i = 0; i < height; i++) {
                for (int j = 0; j < width; j++) {
                    if (byteMatrix.get(i, j)) {
                        graphics.fillRect(i, j, 1, 1);
                    }
                }
            }
            
            System.out.println("Success...");
            
        } catch (WriterException ex) {
            Logger.getLogger(JavaFX_QRCodeWriter.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        ImageView qrView = new ImageView();
        qrView.setImage(SwingFXUtils.toFXImage(bufferedImage, null));
        
        StackPane root = new StackPane();
        root.getChildren().add(qrView);
        
        Scene scene = new Scene(root, 350, 350);
        
        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

The QR Code generated:


ands scanned:


5 comments:

  1. How to edit to generate a code that reads something other than java-buddy.blogspot.in

    ReplyDelete
  2. just replace code segment String myWeb ="enter your text "
    with any text you want

    ReplyDelete
  3. i want code for image based barcode or Qr code scanning with zxing library.somone pls help me...

    ReplyDelete
  4. This can be doen with _pure_ JavaFX as well: No need foor java.awt nor SwingFXUtils.

    Replace the code from line 32 (which is unused anyway) until line 60 with what is below.
    Notice how the same action plan is used as before (white rectange, filled in black bit by bit), but now using JavaFX objects instead of Swing.


    try {
    BitMatrix bitMatrix = qrCodeWriter.encode(inputUrl, BarcodeFormat.QR_CODE, width, height);

    //Create a Canvas (a place to draw on), with a 2D Graphic (a kind of drawing)
    Canvas canvas = new Canvas(width, height);
    GraphicsContext gc2D = canvas.getGraphicsContext2D();

    //in white, paint a rectangle on it, with the full size
    gc2D.setFill(javafx.scene.paint.Color.WHITE);
    gc2D.fillRect(0, 0, width, height);

    //start painting in black: each bit/pixel set in the bitMatix
    gc2D.setFill(javafx.scene.paint.Color.BLACK);
    for (int v = 0; v < height; v++) {
    for (int h = 0; h < width; h++) {
    if (bitMatrix.get(v, h)) {
    gc2D.fillRect(h, v, 1, 1);
    }
    }
    }

    //Take a snapshot of the canvas and set it as an image in the ImageView control
    qrView.setImage(canvas.snapshot(null, null));
    } catch (WriterException e) {
    e.printStackTrace();
    }


    Notes:
    1) you don't need to spell out the colors in full (javafx.scene.paint.Color.WHITE).
    I needed it since the swing/awt imports were still present and the wrong kind of Color was used...
    2) I created the ImageView (called qrView) elsewhere (using FXML) that is why there is no line
    ImageView qrView = new ImageView();
    in my code. It can be addes if needed, obviously.
    3) I moved the qrView.setImage() inside the try {}, since this was more convenient for me: the canvas lives only there.
    4) Imports:
    import com.google.zxing.BarcodeFormat;
    import com.google.zxing.WriterException;
    import com.google.zxing.common.BitMatrix;
    import com.google.zxing.qrcode.QRCodeWriter;
    import javafx.scene.canvas.Canvas;
    import javafx.scene.canvas.GraphicsContext;
    import javafx.scene.image.ImageView;
    import javafx.scene.paint.Color;
    Remove
    - java.awt.*
    - javafx.embed.swing.SwingFXUtils;
    5) I added some more comments to explain what is going on.
    6) Notice how I used "h" and "v" (for Horizontal and Vertical) instead of "i" and "j" as loop counters.
    This is more verbose and exposed that the original code has the axes flipped...
    I guess that caused no problems because it was done twice ("byteMatrix.get(i, j)" and "graphics.fillRect(i, j, 1, 1)") and/or since QR-codes still work when flipped and mirorred etc.

    ReplyDelete