# How to generate a thumbnail

> Resize an image to a thumbnail with resize(), choosing mode and quality.

Source: https://crossfly.dev/docs/cookbook/images/thumbnail — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# 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)

```java
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

```java
// 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](/docs/ui/images-and-graphics/images) — difference between destructive resize and render-scale.
- Sibling recipe: [salvar-imagem.md](/docs/cookbook/images/salvar-imagem) — save the thumbnail to disk after generating it.
