Skip to content

Commit 1883354

Browse files
ikraamgclaude
andcommitted
Added ImageMagick 7 Q16-HDRI for consistent dithering
Debian apt only provides ImageMagick 6 which produces different dithering output than local dev environments running IM7. This caused visual inconsistencies between development and production. Changes: - Multi-stage build copies IM7 from dpokidov/imagemagick - Wrapper script filters deprecation warnings from gm package - Documentation recommends docker-dev.sh for version parity Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent f0d5b8a commit 1883354

3 files changed

Lines changed: 98 additions & 8 deletions

File tree

CLAUDE.md

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Home Assistant add-on for TRMNL e-ink displays. Captures HA dashboard screenshot
88

99
**Runtime:** Bun 1.3.5+ (not Node.js)
1010
**Language:** TypeScript with strict type checking
11-
**Image Processing:** ImageMagick via `gm` package
11+
**Image Processing:** ImageMagick 7 Q16-HDRI via `gm` package
1212

1313
## Development Commands
1414

@@ -121,11 +121,37 @@ Error hierarchy:
121121

122122
## Local Development Setup
123123

124+
### Recommended: Docker Dev (ensures ImageMagick version parity)
125+
126+
```bash
127+
cd trmnl-ha/ha-trmnl
128+
cp options-dev.json.example options-dev.json
129+
# Edit options-dev.json with your HA URL and token
130+
./scripts/docker-dev.sh
131+
```
132+
133+
This runs the app inside Docker with hot-reload, using the **exact same ImageMagick 7 Q16-HDRI** version as production. This ensures dithering output is identical between dev and prod.
134+
135+
### Alternative: Native Bun (requires local ImageMagick 7)
136+
137+
If you prefer running outside Docker, you need ImageMagick 7 installed locally:
138+
139+
```bash
140+
# macOS
141+
brew install imagemagick
142+
143+
# Verify version (must be 7.x with Q16-HDRI)
144+
convert -version | head -1
145+
# Should show: Version: ImageMagick 7.x.x Q16-HDRI
146+
```
147+
148+
Then:
124149
1. Copy `options-dev.json.example` to `options-dev.json`
125150
2. Add your HA URL and access token
126151
3. Run `bun run dev`
127152

128-
For development without real Home Assistant:
153+
### Mock HA Server (for development without real HA)
154+
129155
```bash
130156
# Terminal 1: Mock HA server
131157
bun run mock:server
@@ -180,5 +206,5 @@ log.error`Failed: ${error.message}`
180206

181207
- Base: `debian:bookworm-slim` (multi-stage build)
182208
- Chromium for headless browser
183-
- ImageMagick for image processing
209+
- ImageMagick 7 Q16-HDRI (copied from `dpokidov/imagemagick` for consistent dithering)
184210
- Health check: `GET /health` on port 10000

trmnl-ha/Dockerfile

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,16 @@
44
# Uses Debian Bookworm for updated packages and better security
55

66
# =============================================================================
7-
# STAGE 1: DEPENDENCY BUILDER
7+
# STAGE 1: IMAGEMAGICK 7 SOURCE
8+
# =============================================================================
9+
# NOTE: Using dpokidov's IM7 image to ensure consistent dithering between
10+
# local dev (IM7) and Docker. Debian apt only provides IM6 which has different
11+
# algorithm implementations, colorspace handling, and HDRI support.
12+
# See: https://github.com/dooman87/imagemagick-docker
13+
FROM dpokidov/imagemagick:7.1.1-47-bookworm AS imagemagick
14+
15+
# =============================================================================
16+
# STAGE 2: DEPENDENCY BUILDER
817
# =============================================================================
918
# NOTE: Using official Bun image which ships with baseline x64 builds for maximum
1019
# CPU compatibility (supports Synology DS918+, older Proxmox VMs, CPUs without AVX2)
@@ -25,14 +34,14 @@ RUN --mount=type=cache,target=/root/.bun/install/cache \
2534
bun install --frozen-lockfile --production
2635

2736
# =============================================================================
28-
# STAGE 2: RUNTIME
37+
# STAGE 3: RUNTIME
2938
# =============================================================================
3039
FROM debian:bookworm-slim
3140

3241
ENV DEBIAN_FRONTEND=noninteractive
3342
ENV TZ=Etc/UTC
3443

35-
# Install only runtime dependencies
44+
# Install only runtime dependencies (ImageMagick copied from stage 1)
3645
# NOTE: Grouped by purpose for clarity and maintainability
3746
# NOTE: Using BuildKit cache mounts for apt to speed up rebuilds
3847
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
@@ -46,8 +55,41 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
4655
ca-certificates \
4756
# CJK font support for international dashboards
4857
fonts-noto-cjk \
49-
# Image processing for dithering algorithms
50-
imagemagick
58+
# ImageMagick 7 runtime dependencies (binaries copied from stage 1)
59+
libgomp1 \
60+
libomp5 \
61+
libjpeg62-turbo \
62+
libpng16-16 \
63+
libtiff6 \
64+
libwebp7 \
65+
libwebpmux3 \
66+
libwebpdemux2 \
67+
libheif1 \
68+
libraw20 \
69+
liblcms2-2 \
70+
libfreetype6 \
71+
libfontconfig1 \
72+
libfftw3-double3 \
73+
liblqr-1-0 \
74+
libltdl7 \
75+
libopenjp2-7 \
76+
libxml2 \
77+
libzip4
78+
79+
# Copy ImageMagick 7 binaries and libraries from stage 1
80+
# NOTE: This gives us IM7 with Q16-HDRI for consistent dithering with local dev
81+
COPY --from=imagemagick /usr/local/bin/magick /usr/local/bin/
82+
COPY --from=imagemagick /usr/local/lib/ /usr/local/lib/
83+
COPY --from=imagemagick /usr/local/etc/ImageMagick-7/ /usr/local/etc/ImageMagick-7/
84+
85+
# Set up ImageMagick 7 CLI compatibility
86+
# The gm package calls 'convert', but IM7 uses 'magick' and shows deprecation warnings
87+
# We use a wrapper script that filters out the warning while preserving functionality
88+
COPY ha-trmnl/scripts/imagemagick-wrapper.sh /usr/local/bin/convert
89+
RUN chmod +x /usr/local/bin/convert && \
90+
ln -s /usr/local/bin/magick /usr/local/bin/identify && \
91+
ln -s /usr/local/bin/magick /usr/local/bin/mogrify && \
92+
ldconfig
5193

5294
# Copy Bun runtime from builder stage
5395
# NOTE: /usr/local/bin is already in PATH, no additional ENV needed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/bin/sh
2+
# ImageMagick 7 wrapper script
3+
# Suppresses the "convert command is deprecated" warning from IM7
4+
# The gm npm package calls 'convert', but IM7 wants 'magick'
5+
#
6+
# This wrapper:
7+
# 1. Calls 'magick' with all arguments passed through
8+
# 2. Filters out only the deprecation warning from stderr
9+
# 3. Preserves stdout (for binary image data) and exit codes
10+
11+
# Create a temp file for filtered stderr
12+
tmpfile=$(mktemp)
13+
trap 'rm -f "$tmpfile"' EXIT
14+
15+
# Run magick, capture stderr to temp, let stdout pass through
16+
/usr/local/bin/magick "$@" 2>"$tmpfile"
17+
exit_code=$?
18+
19+
# Output filtered stderr (remove deprecation warning)
20+
grep -v "The convert command is deprecated" "$tmpfile" >&2
21+
22+
exit $exit_code

0 commit comments

Comments
 (0)