# Como carregar uma imagem de arquivo ou da rede

> Carregar um PNG/JPEG/GIF de um arquivo local ou baixado da rede e exibi-lo com ImageView.

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

# Como carregar uma imagem de arquivo ou da rede

**Propósito.** Carregar um arquivo de imagem (PNG, JPEG ou GIF) de um caminho local ou de bytes
baixados da rede e exibi-lo na tela com um `ImageView`. Este é o caminho mais comum para mostrar
fotos, ícones e ilustrações.

## APIs usadas
- `new Image(String path) throws ImageException, IOException` — carrega a imagem de um caminho de arquivo. Lança `ImageException` se o arquivo não for encontrado (quando `width == 0` após a leitura).
- `new Image(byte[] bytes) throws ImageException` — decodifica a imagem a partir de um array de bytes já em memória (PNG/JPEG/GIF). Use este construtor para dados baixados da rede.
- `new ImageView(Image image, ImageSize imageSize)` — cria o widget que desenha a imagem. Com `ImageSize.RATIO` a imagem é escalada uniformemente preservando a proporção (letter-boxing), sem cortar.
- `ImageView.imageSize(ImageSize)` / `.alignX(Position)` / `.alignY(Position)` — setters fluentes para ajustar o modo de dimensionamento e o alinhamento (padrão `Position.CENTER`).

> Divergência Javadoc×código: o Javadoc de `new Image(String)` diz "@throws ImageException When
> the file was not found", mas a assinatura real também declara `IOException`. Trate as duas.

## Exemplo completo (copiar, colar e rodar)

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

/** Tela principal executável. Aponte o launcher (classname) e rode: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   private ImageView imageView;

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

      // 1) A partir de um arquivo local
      try {
         Image img = new Image("/sdcard/foto.jpg");   // pode lançar ImageException / IOException
         ImageView iv = new ImageView(img, UIConstants.ImageSize.RATIO);
         add(LAY_FILL, iv);
      } catch (ImageException | IOException e) {
         // arquivo não encontrado ou corrompido
      }

      // 2) Da rede: baixe e decodifique fora da paint thread, depois atualize o widget
      imageView = new ImageView(null, UIConstants.ImageSize.RATIO);
      add(LAY_FILL, imageView);

      new Thread(() -> {
         try {
            byte[] data = baixarBytes("https://exemplo.com/foto.png"); // seu HTTP client
            Image img = new Image(data);              // decodifica fora da paint thread
            Main.runOnPaintThreadAndWait(() -> imageView.image(img));
         } catch (Exception e) {
            // trate erro de rede/decodificação
         }
      }).start();
   }

   /** Stub: substitua pelo seu cliente HTTP. */
   private byte[] baixarBytes(String url) throws IOException
   {
      return new byte[0];
   }
}
```

> O trecho abaixo mostra **só o miolo**. Para rodar, coloque-o no esqueleto `MainWindow` acima.

## Trecho mínimo

```java
// verificado na fonte: Image.java (linhas 403, 432) e ImageView.java (linha 72)
import dev.crossfly.ui.image.*;   // Image, ImageException
import dev.crossfly.ui.*;         // ImageView, UIConstants.ImageSize

// 1) A partir de um arquivo local
try {
   Image img = new Image("/sdcard/foto.jpg");   // pode lançar ImageException / IOException
   ImageView iv = new ImageView(img, UIConstants.ImageSize.RATIO);
   add(iv, /* posição/layout do seu container */);
} catch (ImageException | java.io.IOException e) {
   // arquivo não encontrado ou corrompido
}
```

### Da rede (baixe os bytes fora da paint thread)

`new Image(...)` decodifica pixels e é operação pesada. **Nunca** baixe nem decodifique na paint
thread. Baixe os bytes numa Thread de trabalho, crie a `Image` ali e só então atualize o widget.

```java
// verificado na fonte: new Image(byte[]) — Image.java linha 432
new Thread(() -> {
   try {
      byte[] data = baixarBytes("https://exemplo.com/foto.png"); // seu HTTP client
      Image img = new Image(data);              // decodifica fora da paint thread
      // agora agende a atualização da UI na paint thread
      Main.runOnPaintThreadAndWait(() -> imageView.image(img));
   } catch (Exception e) {
      // trate erro de rede/decodificação
   }
}).start();
```

## Aprofunde-se
- [Trabalho em segundo plano](/docs/data-and-services/background-work) — como sair da paint thread para baixar e decodificar.
- [Widget ImageView](/docs/ui/widgets/imageview) e [Imagens](/docs/ui/images-and-graphics/images) — modos de `ImageSize` e alinhamento.
- Receita irmã: [imagem-de-fundo.md](/docs/cookbook/images/imagem-de-fundo).
