Skip to content
CrossFly is 100% open sourceFollow us on GitHub
CrossFlyCrossFly
Get started

This page was machine-translated from Portuguese and may contain errors. The Portuguese version is canonical.

How to generate a thumbnail

Purpose. Reduce a large image to a persistent thumbnail (a new Image with actually reduced pixels), instead of just scaling at draw time. This saves texture memory and GPU bandwidth when you display many thumbnails.

APIs used

  • Image resize(int newWidth, int newHeight, ResizeMode mode, ResizeQuality quality) throws ImageException — main entry point. Returns a new Image; the original is not modified.
  • Image resize(int newWidth, int newHeight, ResizeMode mode) — overload that uses ResizeQuality.SMOOTH.
  • Image resize(int newWidth, int newHeight) — overload that uses ResizeMode.STRETCH + ResizeQuality.SMOOTH.
  • Image resizeWidth(int newWidth[, ResizeQuality]) / Image resizeHeight(int newHeight[, ResizeQuality]) — resize preserving the aspect ratio from a target width or height (ideal for thumbnails).

Enums (verified in UIConstants)

ResizeMode { STRETCH, FIT, FILL }

  • STRETCH — forces exactly w×h (may distort).
  • FIT — keeps the aspect ratio and fits entirely within w×h (letter-box; the result may be smaller than the target).
  • FILL — keeps the aspect ratio and fills w×h, cropping the excess from the center.

ResizeQuality { FAST, SMOOTH, HARDWARE }

  • FAST — fast sampling (nearest); use for real-time caches.
  • SMOOTH — high-quality resampling; use for thumbnails that are saved/displayed.
  • HARDWARE — keeps the source pixels and delegates the scaling to the GPU at draw time (does not reduce pixmap memory).

Complete example (copy, paste and run)

package com.exemplo;

import java.io.IOException;

import dev.crossfly.ui.*;                     // Window, ImageView, UIConstants.ImageSize
import dev.crossfly.ui.layout.*;             // VerticalLayout, LAY_AUTO
import dev.crossfly.ui.image.*;              // Image, ImageException
import dev.crossfly.ui.UIConstants.ResizeMode;
import dev.crossfly.ui.UIConstants.ResizeQuality;

/** Runnable main screen. Point the launcher (classname) and run: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      try {
         Image original = new Image("/sdcard/foto.jpg");

         // 128x128 thumbnail filling and cropping the excess, with good quality:
         Image thumb = original.resize(128, 128, ResizeMode.FILL, ResizeQuality.SMOOTH);

         // Alternative preserving aspect ratio from the width (no cropping):
         Image thumbW = original.resizeWidth(128, ResizeQuality.SMOOTH);

         add(new ImageView(thumb, UIConstants.ImageSize.ORIGINAL), LAY_AUTO);
         add(new ImageView(thumbW, UIConstants.ImageSize.ORIGINAL), LAY_AUTO);
      } catch (ImageException | IOException e) {
         // file not found or resize failure (e.g.: "Out of memory")
      }
   }
}

The snippet below shows only the core. To run it, place it inside the MainWindow skeleton above.

Minimal snippet

// verified in source: Image.java resize(...) line 870; enums in UIConstants (795, 806)
import dev.crossfly.ui.image.*;   // Image, ImageException
import dev.crossfly.ui.UIConstants.ResizeMode;
import dev.crossfly.ui.UIConstants.ResizeQuality;

Image original = new Image("/sdcard/foto.jpg");

// 128x128 thumbnail filling and cropping the excess, with good quality:
Image thumb = original.resize(128, 128, ResizeMode.FILL, ResizeQuality.SMOOTH);

// Alternative preserving aspect ratio from the width (no cropping):
Image thumbW = original.resizeWidth(128, ResizeQuality.SMOOTH);

Implementation note (source): with ResizeMode.FIT/FILL, resize first scales uniformly and, in the FILL case, crops from the center via getArea(...). With STRETCH it directly calls the exact scaling. resize throws ImageException (e.g., “Out of memory” on very large images) and IllegalArgumentException if newWidth/newHeight ≤ 0.

Do not confuse resize(...) (creates new pixels) with renderScaleX/renderScaleY and setRenderScale(...), which only scale at draw time via GPU without changing the pixmap.

Dive deeper

  • Images — difference between destructive resize and render-scale.
  • Sibling recipe: salvar-imagem.md — save the thumbnail to disk after generating it.
Was this page helpful?