# cv

Canvas-based image utilities: loading images from data URLs, resizing, and cropping.

---

## Functions

### `imageFromDataUrl(dataUrl: string): Promise<HTMLImageElement>`

Loads an image from a data URL and resolves with the resulting `HTMLImageElement`. Rejects if the URL is invalid or the image fails to load.

```typescript
const img = await imageFromDataUrl("data:image/png;base64,abc...");
console.log(img.naturalWidth);
```

---

### `resizeImage(img: HTMLImageElement, width?: number, height?: number): HTMLImageElement | HTMLCanvasElement`

Resizes an image to the given dimensions.

- If both `width` and `height` match the image's natural size, the original `img` element is returned unchanged.
- Otherwise, a new `HTMLCanvasElement` with the specified dimensions is returned.
- If only `width` is provided, `height` is inferred from the aspect ratio.
- If only `height` is provided, `width` is inferred from the aspect ratio.
- Throws `Failed2DContextError` if a 2D canvas context cannot be obtained.

```typescript
const canvas = resizeImage(img, 200);         // width=200, height inferred
const canvas2 = resizeImage(img, 200, 100);   // explicit width and height
```

---

### `cropImage(img: HTMLImageElement, sx: number, sy: number, width: number, height: number): HTMLCanvasElement`

Crops a rectangular region from an image and returns it as an `HTMLCanvasElement`.

| Parameter | Description |
|-----------|-------------|
| `img` | Source image |
| `sx` | X offset in the source image |
| `sy` | Y offset in the source image |
| `width` | Width of the crop region |
| `height` | Height of the crop region |

Throws `Failed2DContextError` if a 2D canvas context cannot be obtained.

```typescript
const cropped = cropImage(img, 10, 10, 80, 60);
```

---

### `imageFromCanvas(canvas: HTMLCanvasElement): Promise<HTMLImageElement>`

Converts a canvas to an `HTMLImageElement` by reading its data URL.

---

## Errors

### `Failed2DContextError`

Thrown by `resizeImage` and `cropImage` when `canvas.getContext('2d')` returns `null`.

```typescript
import { Failed2DContextError, resizeImage } from "./cv";

try {
    const result = resizeImage(img, 400, 300);
} catch (e) {
    if (e instanceof Failed2DContextError) {
        console.error("Canvas 2D context unavailable");
    }
}
```

---

## Example

```typescript
import { imageFromDataUrl, resizeImage, cropImage } from "./cv";

const img = await imageFromDataUrl(dataUrl);

// Resize to max width 800, keep aspect ratio
const resized = resizeImage(img, 800);

// Crop a 100×100 region starting at (50, 50)
const cropped = cropImage(img, 50, 50, 100, 100);
```
