Thursday, June 30, 2016

93. Writing Pixels

Unlike the Image class, we can use WritableImage class to create an image which can be written to.


We can get a PixelWriter using getPixelWriter() method to write a byte array, for example. We fill the byte array using our getPixels() method in which we create a rainbow image. Finally the byte array is written to the WritableImage object using setPixels() method on the PixelWriter. We view the WritableImage using an ImageView.


In Java, a byte is signed (-128 to +127, 256 different numbers). A color component is from 0 to 255. This is logic to convert a color to byte: colors 0 to 127, unchanged, colors 128 to 255 (negative numbers, -128 to -1), that is color 255 is actually -1. This is the reason for the negative numbers in rainbow(). The function of rainbow() is to set colors. Even though the return type is void, it sets three global variables (r, g, b) which happen to be color components.


package ex93;

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelFormat;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class Ex93 extends Application {
    
    byte r, g, b;
    int w = 300, h = 280;
    
    public static void main(String[] args) {
        Application.launch(args);
    }
    
    @Override
    public void start(Stage stage) {
        WritableImage rainbowImage = new WritableImage(w, h);

        byte[] pixels = getPixels();

        PixelWriter pixelWriter = rainbowImage.getPixelWriter();

        pixelWriter.setPixels(0, 0,
                    w, h,
                    PixelFormat.getByteRgbInstance(),
                    pixels, 0,
                    w*3);

        ImageView newImageView = new ImageView(rainbowImage);

        HBox root = new HBox(newImageView);
        root.setAlignment(Pos.CENTER);
        root.setStyle("-fx-background-color: gray");
        
        Scene scene = new Scene(root,2*w,2*h);
        stage.setScene(scene);
        stage.setTitle("Example 93. Writing Pixels");
        stage.show();
    }

    private byte[] getPixels() {
        int d = h/7;
        byte[] px = new byte[w * h * 3];
        for (int y = 0; y < h; y++) {
            rainbow(y/d);
            for (int x = 0; x < w; x++) {
                int i = 3*y*w+x*3;
                px[i] = r; px[i+1] = g; px[i+2] = b;
            }
        }
        return px;
    }
    
    private void rainbow(int v) {
        switch (v) {
            case 0:
                r = -1; g = 0; b = 0; break;
            case 1:
                r = -1; g = 127; b = 0; break;
            case 2:
                r = -1; g = -1; b = 0; break;
            case 3:
                r = 0; g = -1; b = 0; break;
            case 4:
                r = 0; g = 0; b = -1; break;
            case 5:
                r = 75; g = 0; b = -126; break;
            case 6:
                r = -113; g = 0; b = -1; break;
        }
    }
}

This is the output:


No comments:

Post a Comment