# Display Orientation ## Purpose Allow the user to configure the physical orientation of the Inky Impression display so that images are displayed upright regardless of how the panel is mounted. The orientation setting also drives the Unsplash orientation filter so fetched photos match the display's effective aspect ratio (portrait vs. landscape). ## Configuration A new `display.orientation` key (integer, degrees clockwise) in `config.yaml` / `DEFAULT_CONFIG`: ```yaml display: orientation: 0 # 0, 90, 180, 270 ``` | Value | Unsplash filter | Effective aspect | |-------|----------------|------------------| | 0 | landscape | width > height | | 90 | portrait | height > width | | 180 | landscape | width > height | | 270 | portrait | height > width | The old `unsplash.orientation` config key is **no longer used** by `refresh()` — orientation is now derived from `display.orientation` + `display.resolution`. ## Image Processing Pipeline 1. **Fetch** raw photo from Unsplash (with orientation filter already matching the effective aspect ratio — see below). 2. **`process_image()`** in `InkyDisplay`: - Compute effective width/height by swapping physical dimensions when orientation is 90° or 270°. - Crop to effective aspect ratio. - Resize to effective dimensions. - Rotate by `-orientation` degrees (so the result matches the physical resolution of the display panel). 3. **`show()`** sends the processed (and rotated) image to `inky.set_image()`. No additional transformation is needed — the panel hardware always expects its native `width × height` pixel grid. ## Unsplash Filter Derivation In `cli.py:refresh()`, after reading `display.orientation` and `display.resolution`: 1. If orientation is 90 or 270, swap width ↔ height to get effective dimensions. 2. If effective height > effective width → request `"portrait"`. 3. If effective width > effective height → request `"landscape"`. 4. If roughly equal → request `"squarish"`. This means the Unsplash API is sent `orientation=portrait` when the display is mounted vertically, which returns taller photos that need less cropping. ## Hot-Reload `_reload_config()` in `cli.py` detects changes to `display.orientation` and updates `display.orientation` live. The next `process_image()` call uses the new orientation. No display loop restart is needed. ## Library Caching `_save_to_library()` passes the **effective** width/height to `save_unsplash_image()` (swapped when orientation is 90/270). The stored image is processed to the effective dimensions at orientation=0 (no rotation). This keeps library images in their "natural" viewing orientation. The preview endpoint (`/api/preview/`) creates an `InkyDisplay` with the current orientation, so the preview matches what the physical display shows. ## UI Settings page (Display article) shows a `