# How to load an image from a file or from the network

> Load a PNG/JPEG/GIF from a local file or downloaded from the network and display it with ImageView.

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

# How to load an image from a file or from the network

**Purpose.** Load an image file (PNG, JPEG or GIF) from a local path or from bytes
downloaded from the network and display it on screen with an `ImageView`. This is the most common way to show
photos, icons, and illustrations.

## APIs used
- `new Image(String path) throws ImageException, IOException` — loads the image from a file path. Throws `ImageException` if the file is not found (when `width == 0` after reading).
- `new Image(byte[] bytes) throws ImageException` — decodes the image from a byte array already in memory (PNG/JPEG/GIF). Use this constructor for data downloaded from the network.
- `new ImageView(Image image, ImageSize imageSize)` — creates the widget that draws the image. With `ImageSize.RATIO` the image is scaled uniformly preserving the aspect ratio (letter-boxing), without cropping.
- `ImageView.imageSize(ImageSize)` / `.alignX(Position)` / `.alignY(Position)` — fluent setters to adjust the sizing mode and the alignment (default `Position.CENTER`).

> Javadoc×code divergence: the Javadoc of `new Image(String)` says "@throws ImageException When
> the file was not found", but the actual signature also declares `IOException`. Handle both.

## Complete example (copy, paste and run)

```java
package com.exemplo;

import java.io.IOException;

import dev.crossfly.Main;                    // runOnPaintThreadAndWait
import dev.crossfly.ui.*;                     // Window, Component, ImageView, UIConstants.ImageSize
import dev.crossfly.ui.layout.*;             // VerticalLayout, LAY_FILL
import dev.crossfly.ui.image.*;              // Image, ImageException

/** Runnable main screen. Point the launcher (classname) and run: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   private ImageView imageView;

   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      // 1) From a local file
      try {
         Image img = new Image("/sdcard/foto.jpg");   // may throw ImageException / IOException
         ImageView iv = new ImageView(img, UIConstants.ImageSize.RATIO);
         add(LAY_FILL, iv);
      } catch (ImageException | IOException e) {
         // file not found or corrupted
      }

      // 2) From the network: download and decode off the paint thread, then update the widget
      imageView = new ImageView(null, UIConstants.ImageSize.RATIO);
      add(LAY_FILL, imageView);

      new Thread(() -> {
         try {
            byte[] data = baixarBytes("https://exemplo.com/foto.png"); // your HTTP client
            Image img = new Image(data);              // decodes off the paint thread
            Main.runOnPaintThreadAndWait(() -> imageView.image(img));
         } catch (Exception e) {
            // handle network/decoding error
         }
      }).start();
   }

   /** Stub: replace with your HTTP client. */
   private byte[] baixarBytes(String url) throws IOException
   {
      return new byte[0];
   }
}
```

> 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 (lines 403, 432) and ImageView.java (line 72)
import dev.crossfly.ui.image.*;   // Image, ImageException
import dev.crossfly.ui.*;         // ImageView, UIConstants.ImageSize

// 1) From a local file
try {
   Image img = new Image("/sdcard/foto.jpg");   // may throw ImageException / IOException
   ImageView iv = new ImageView(img, UIConstants.ImageSize.RATIO);
   add(iv, /* your container's position/layout */);
} catch (ImageException | java.io.IOException e) {
   // file not found or corrupted
}
```

### From the network (download the bytes off the paint thread)

`new Image(...)` decodes pixels and is a heavy operation. **Never** download or decode on the paint
thread. Download the bytes on a worker Thread, create the `Image` there, and only then update the widget.

```java
// verified in source: new Image(byte[]) — Image.java line 432
new Thread(() -> {
   try {
      byte[] data = baixarBytes("https://exemplo.com/foto.png"); // your HTTP client
      Image img = new Image(data);              // decodes off the paint thread
      // now schedule the UI update on the paint thread
      Main.runOnPaintThreadAndWait(() -> imageView.image(img));
   } catch (Exception e) {
      // handle network/decoding error
   }
}).start();
```

## Dive deeper
- [Background work](/docs/data-and-services/background-work) — how to get off the paint thread to download and decode.
- [ImageView widget](/docs/ui/widgets/imageview) and [Images](/docs/ui/images-and-graphics/images) — `ImageSize` modes and alignment.
- Sibling recipe: [imagem-de-fundo.md](/docs/cookbook/images/imagem-de-fundo).
