MultiImages From Single File

The following source code will display individual images from a single .png file containing a grid of images. This obviates the need to include multiple image files in the sketch folder. This demo was developed in MacOS and therefore uses the Pages app to create the image grid. It is likely that other platforms have similar apps (not evaluated). Processing’s PImage get() function gets the pixels from a rectangular area defined by the user. By making each image grid cell a known size we can retrieve its image with code such as images.get(x,y,w,h). A grid cell size of 2 inches by 2 inches translates to an image size of 144x144 (72 pixels per inch). By knowing the x,y coordinates of the top, left corner of each grid cell we can get the image for that cell and use draw() to display it with image(myChoice, xOffset, yOffset).

The FX2D renderer was required in the default Processing window to use a JavaFX ComboBox for image selection. Copy/paste myImages.png shown below into your sketch folder.

Source code:


import javafx.scene.canvas.Canvas;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.Pane;
import javafx.collections.ObservableList;
import javafx.scene.control.ComboBox;

Canvas canvas;
StackPane root;
Pane pane;

PImage images;
PImage myChoice = null;

int _wndW = 400;
int _wndH = 300;

PImage getImage(int selectedIndex) {
  switch (selectedIndex) {
  case 0:
    myChoice = images.get(0, 0, 144, 144);
    break;
  case 1:
    myChoice = images.get(144, 0, 144, 144);
    break;
  case 2:
    myChoice = images.get(288, 0, 144, 144);
    break;
  case 3:
    myChoice = images.get(432, 0, 144, 144);
    break;
  case 4:
    myChoice = images.get(0, 144, 144, 144);
    break;
  case 5:
    myChoice = images.get(144, 144, 144, 144);
    break;
  case 6:
    myChoice = images.get(288, 144, 144, 144);
    break;
  case 7:
    myChoice = images.get(432, 144, 144, 144);
    break;
  case 8:
    myChoice = images.get(0, 288, 144, 144);
    break;
  case 9:
    myChoice = images.get(144, 288, 144, 144);
    break;
  case 10:
    myChoice = images.get(288, 288, 144, 144);
    break;
  case 11:
    myChoice = images.get(432, 288, 144, 144);
    break;
  case 12:
    myChoice = images.get(0, 432, 144, 144);
    break;
  case 13:
    myChoice = images.get(144, 432, 144, 144);
    break;
  case 14:
    myChoice = images.get(288, 432, 144, 144);
    break;
  case 15:
    myChoice = images.get(432, 432, 144, 144);
    break;
  };
  return myChoice;
}

void setup() {
  size(_wndW, _wndH, FX2D);
  background(255);
  surface.setTitle("JavaFX MultiImage Demo");
  canvas = (Canvas)surface.getNative();
  root = (StackPane)canvas.getParent();
  pane = new Pane();
  images = loadImage("myImages.png");

  // **** ComboBox **** //
  ComboBox<String> combo = new ComboBox<String>();
  combo.setPromptText("Select One");
  ObservableList<String> list = combo.getItems();
  list.add("Chess Board");
  list.add("Python");
  list.add("RGB");
  list.add("Arrow");
  list.add("Muskrat");
  list.add("Penguin");
  list.add("Dog");
  list.add("Coat of Arms");
  list.add("Encoder");
  list.add("Android ICON");
  list.add("EKG");
  list.add("Run Btn");
  list.add("Rocket");
  list.add("Safety Key");
  list.add("Puppy");
  list.add("Raccoon");
  combo.setLayoutX(240);
  combo.setLayoutY(10);
  combo.setMaxWidth(150);
  combo.setOnAction(e -> {
    int selectedIndex = combo.getSelectionModel().getSelectedIndex();
    getImage(selectedIndex);
  }
  );

  pane.getChildren().add(combo);
  root.getChildren().add(pane);
}

void draw() {
  if (myChoice != null) {
    image(myChoice, 50, 50);
  }
}

ImageGrid Instructions (MacOS Pages app):

1. Open the Pages app and select the "Blank" template.

2. In the File menu select the menu item "Convert to Page Layout".

3. In the View menu select "Show Ruler". This will give you the option of clicking in either the left margin or top ruler and dragging a guide onto the page to create the columns/rows of the image grid.

4. Drag your images onto the grid and resize each image to fit within its respective cell.

5. File/Export To -> PDF, then open that file into the Preview app and save as a JPEG or PNG for use in your app.

6. Include the .jpg or .png file in your sketch folder.

Grid Example:

myImages.png:

App Output:

3 Likes

Anyone get it work on Windows 10+ and Processing 4?

My simple code:

PImage images;
PImage myChoice = null;
int _wndW = 640;
int _wndH = 640;

String[] choices = { 
  "Chess Board", "Python", "RGB", "Arrow", "Muskrat",
  "Penguin", "Dog", "Coat of Arms", "Encoder", "Android ICON",
  "EKG", "Run Btn", "Rocket", "Safety Key", "Puppy", "Raccoon" 
};

int selectedIndex = 0;

void setup() {
  size(_wndW, _wndH);
  surface.setTitle("Processing MultiImage Demo");

  images = loadImage("myImages.png"); // musí byť v priečinku data
  getImage(selectedIndex);
}

void draw() {
  background(255);
  if (myChoice != null) {
    image(myChoice, 50, 50);
  }
  
  // tlačidlá pre výber
  fill(200);
  for (int i = 0; i < choices.length; i++) {
    int x = 10 + (i % 4) * 150;
    int y = 400 + (i / 4) * 30;
    if (i == selectedIndex) fill(100, 200, 100); // zvýrazni vybraný
    else fill(200);
    rect(x, y, 140, 25);
    fill(0);
    text(choices[i], x + 5, y + 17);
  }
}

void mousePressed() {
  for (int i = 0; i < choices.length; i++) {
    int x = 10 + (i % 4) * 150;
    int y = 400 + (i / 4) * 30;
    if (mouseX > x && mouseX < x + 140 && mouseY > y && mouseY < y + 25) {
      selectedIndex = i;
      getImage(selectedIndex);
    }
  }
}

void getImage(int idx) {
  if (images == null) return;
  int x = (idx % 4) * 144;
  int y = (idx / 4) * 144;
  myChoice = images.get(x, y, 144, 144);
}

Hey @Radim and welcome to the forum.

Could you share the exact error message you’re getting (if any)? That’ll make it much easier to figure out what’s going on.

1 Like

Works ok here on Windows 11 system with Processing 4.4.10. May have to rename image file to have .jpg extension (it may be changed from .png when you download it to your system).

I don’t have JavaFX installed on my offline PC.

I do now. So it works fine now.

Thanks!

It should also work without JavaFX; the above screenshot was taken on a Windows 11 system using the source code in your original post (buttons in lieu of a javafx control).