# Camera and barcode

> Capture photo/video with Camera.shot() and read codes with CameraBarcode.readBarcode.

Source: https://crossfly.dev/docs/data-and-services/device-camera — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Camera and barcode

## Capture a photo — `Camera.shot()`
```java
Camera cam = new Camera();
cam.cameraType = Camera.CameraType.PICKER;      // ⚠️ no default — always set it
cam.captureMode = Camera.Preview.PHOTO;

new Thread(() -> {
   String caminho = cam.shot();                 // file path, or null if cancelled
   if (caminho == null) return;
   Component.onUI(() -> {
      try { imageView.image(new Image(caminho)); Component.repaint(); }
      catch (Exception e) { Debug.log("erro: " + e); }
   });
}).start();
```
> ⚠️ **`click()` no longer exists** — the capture method is **`shot()`** (it returns a `String` with the path
> or `null` if the user cancels).

### Configuration
| Field | Values |
|---|---|
| `cameraType` | `DEFAULT` (built-in camera) · `PICKER` (PhotoPicker) · `GALLERY` (gallery) — **no default** |
| `captureMode` | `Preview.PHOTO` · `MUTED_VIDEO` · `AUDIO_VIDEO` |
| `videoQuality` | `AVQuality.HIGH/MEDIUM/LOW` |
| `resolutionWidth`/`Height` (static) | resolution (always in LANDSCAPE) |

## Read a barcode — `CameraBarcode.readBarcode(Image)`
Reads 1D and 2D (QR) from an already-captured **image** (via ZXing):
```java
Image img = new Image(caminho);
com.google.zxing.Result r = CameraBarcode.readBarcode(img);   // null if no code was found
if (r != null) {
   String codigo = r.getText();
   Debug.log("Código: " + codigo);
}
```

## Real limitations
- **`Camera.shot()`** opens native UI — call it **off the paint thread** and return with `onUI(...)`.
- **`CameraBarcode.readBarcode` is NOT thread-safe** — do not call it from several threads at once.
- `null` returns are normal (cancelled / no code found) — always check.
- On Mac ARM the capture may return `null` (platform limitation).

## Best practices
- **Always** set `cameraType` (there is no default).
- Handle the `null` return from `shot()` and from `readBarcode(...)`.
- To only pick from the gallery, use the [PhotoPicker](/docs/ui/widgets/photopicker).

## Common mistakes
- Calling `click()` (doesn't exist) instead of `shot()`.
- Not setting `cameraType`.
- Calling `readBarcode` concurrently (it is not thread-safe).

## See also
- [PhotoPicker](/docs/ui/widgets/photopicker) · [Images](/docs/ui/images-and-graphics/images) · [Per-platform permissions](/docs/platforms)
