# How to capture a screenshot of the screen

> Capture the current backbuffer as an Image with Main.getScreenShot and save it.

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

# How to capture a screenshot of the screen

**Purpose.** Obtain an `Image` with the current screen content (the OpenGL backbuffer), without repainting
anything, and optionally save it. Useful for diagnostics, visual tests, and sharing.

## APIs used
- `static Image Main.getScreenShot(boolean... opaque)` — captures the **current frame**. `opaque=true` removes the alpha channel (makes everything opaque). It is the most common static convenience. Internally it calls the instance version on the paint thread via `runOnPaintThreadAndWait`.
- `Image Main.getScreenShot(boolean opaque)` (instance) — same capture; schedules the read on the paint thread and blocks until it finishes.
- `Image Main.getNextScreenShot(boolean opaque)` (instance) — forces a repaint and captures the **next** frame. Use it when you have just changed the UI and want to ensure the change shows up in the screenshot; if called off the paint thread, it repaints/updates in a loop until it gets the frame.
- `String Image.toPng(String... prefix)` / `String Image.toJpg(int... quality)` — to save the result (see [salvar-imagem.md](/docs/cookbook/images/salvar-imagem)).

## Complete example (copy, paste and run)

```java
package com.exemplo;

import dev.crossfly.*;                        // Main
import dev.crossfly.ui.*;                     // Window, Button
import dev.crossfly.ui.layout.*;             // VerticalLayout, LAY_AUTO
import dev.crossfly.ui.image.*;              // Image
import dev.crossfly.util.*;                  // Debug

/** 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());

      Button b = new Button("Capturar tela");
      b.onAction(origin ->
      {
         // Captures the current frame, opaque (no alpha), and saves a PNG:
         Image shot = Main.getScreenShot(true);   // true = removes alpha
         String path = shot.toPng("screen_");     // e.g.: .../screen_20260706153000.png
         Debug.log("Screenshot salvo em: " + path);

         // If you just changed the UI and want the NEXT rendered frame:
         Image next = Main.instance.getNextScreenShot(false);  // keeps alpha
      });
      add(LAY_AUTO, b);
   }
}
```

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

## Minimal snippet

```java
// verified in source: Main.java getScreenShot (533, 667) and getNextScreenShot (541)
import dev.crossfly.Main;
import dev.crossfly.ui.image.Image;

// Captures the current frame, opaque (no alpha), and saves a PNG:
Image shot = Main.getScreenShot(true);   // true = removes alpha
String path = shot.toPng("screen_");     // e.g.: .../screen_20260706153000.png

// If you just changed the UI and want the NEXT rendered frame:
Image next = Main.instance.getNextScreenShot(false);  // keeps alpha
```

> Implementation notes (source):
> - The captured image has `alreadyScreenScaled = true` and undergoes `flipY()` (the OpenGL backbuffer comes
>   vertically inverted).
> - On the **WebGL** platform, `opaque=true` does **not** apply `setOpaque()` (explicit guard in the code);
>   the alpha is kept even when opaque is requested.
> - `getScreenShot` differs from `Component.toImage()`: here there is **no** painting/render — the backbuffer
>   of the current frame is captured.
> - For cross-platform comparisons (e.g., tests), fix the font with
>   `Styles.setDefaultFont(Font.getFont(false, 20))`, since font rendering varies per device.

## Dive deeper
- Sibling recipe: [salvar-imagem.md](/docs/cookbook/images/salvar-imagem) — save the screenshot as PNG/JPEG.
- [Custom drawing](/docs/ui/images-and-graphics/custom-drawing) — paint thread and `runOnPaintThreadAndWait`.
