Commit Graph
508 Commits
Author SHA1 Message Date
SnapOtter d38101b8ea feat: add POST /api/v1/fetch-urls endpoint for server-side URL import
Accepts { urls: string[] } (1-50), fetches each URL with SSRF protection
via safeFetch, validates as image, saves to workspace, generates WebP
preview for non-browser formats, and returns results with download URLs.
Uses p-queue with concurrency 4 to parallelize fetches.
2026-05-11 21:24:56 +08:00
SnapOtter 488ed95686 feat: add SSRF validation utility for URL fetch 2026-05-11 21:18:23 +08:00
SnapOtter 694cc86aff feat: add content-aware-crop API route with async SSE processing 2026-05-11 21:12:00 +08:00
SnapOtter 9466df90e0 fix: extract first frame from multi-image FITS files
ImageMagick outputs numbered files (fits-out-0.png, fits-out-1.png)
for multi-image FITS, but decodeFits expected a single output file.
Added [0] selector to extract only the first frame, matching the
pattern used by DDS and PSD decoders.
2026-05-11 18:13:29 +08:00
SnapOtter 2acf0ea48a fix: fall back to Sharp when CLI decoders are unavailable
DNG and FITS previews showed "Preview not available" because their CLI
decoders (ExifTool/ImageMagick) were not installed. Sharp can read both
formats natively (DNG is TIFF-based, FITS via libvips fitsload).

Added Sharp fallback to the preview endpoint, batch processing, and
tool factory: when decodeToSharpCompat throws, try sharp(buffer).metadata()
before returning 422. If Sharp can read the buffer, processing continues
without the CLI decoder.
2026-05-11 18:00:59 +08:00
SnapOtter 50d1f532d1 fix: block PDF uploads, fix PBM/PGM/PPM batch failures, add tests
- Added isImageFile() filter to all drop handlers (dropzone, collage,
  file-upload-area) so PDFs and non-image files are rejected on drop.
  Previously only the file picker's accept attribute filtered; drag-and-
  drop accepted anything.

- Added ppm, pgm, pbm to CLI_DECODED_FORMATS in file-validation.ts.
  These formats were missing, causing Sharp metadata checks to fail for
  some files during batch validation, which silently dropped them from
  results ("File not found in batch results").

- Added integration tests for PBM, PGM, PPM, TIFF, QOI, JP2, SVGZ
  single-file processing, plus a test confirming PDF is rejected.
2026-05-11 17:33:51 +08:00
SnapOtter 172c0fa772 fix: update tool count to 51, refresh hero copy and login page
- Update stale tool counts (48/49/50) to 51 across all apps, docs, and tests
- Add Meme Generator to landing page bento grid (was missing)
- Add 12 SEO-friendly rotating phrases to hero typing cursor
- Change landing hero subtitle to "Every image tool you need."
- Replace outdated login page copy with branded hero + rotating phrases
2026-05-10 22:18:11 +08:00
SnapOtter 78ca9720e7 fix: sync all workspace package versions to 1.16.0 2026-05-10 20:19:02 +08:00
SnapOtter f0021a53d3 docs: sync API docs with codebase -- add meme-generator, remove phantom endpoints
- Add meme-generator tool and meme-templates API to OpenAPI spec, VitePress
  docs, and README
- Remove 4 phantom OpenAPI entries (brightness-contrast, saturation,
  color-channels, color-effects) that were consolidated into adjust-colors
- Bump OpenAPI version to 1.16.0, tool count to 51
- llms.txt and llms-full.txt auto-update from OpenAPI at runtime
2026-05-10 14:11:23 +08:00
SnapOtter a0556772e8 test: expand coverage across all layers -- 1,268 new tests, fix replace-color div-by-zero
14-agent parallel test expansion covering integration, unit, E2E, E2E-Docker,
cross-format matrix, adversarial, GUI navigation/tools/settings/visual/a11y/perf.

- Integration: expand 23 tool test files with HEIC, stress, batch, edge cases
- Unit: close coverage gaps in image-engine, stores, lib (metadata, auto-enhance,
  connection-store, lazy-with-retry, collage/file-store HEIC preview)
- AI bridge: 141 new tests for dispatcher buffering, crash recovery, OOM/segfault
- Cross-format: 794 parameterized tests (16 formats x 12 tools + no-crash matrix)
- Adversarial: memory stress (50x large file), zero-byte, corrupted headers, unicode
- E2E-Docker: expand 8 spec files with dimension verification, pipeline chains
- GUI E2E: tool UI settings/interactions for all 47 tools, remove all test.skip,
  RBAC per-role verification, visual screenshot naming, cross-browser smoke tests,
  a11y ARIA/focus/contrast, performance budgets, 15-tool stability test
- Fix: replace-color.ts tolerance=0 caused division-by-zero producing NaN pixels

Total: 8,958 tests passing across 202 files. Zero failures, zero skips.
2026-05-09 18:02:58 +08:00
SnapOtter 7b1f09f5d0 fix: CLAHE tile size and alpha channel corruption in image enhancement
CLAHE width/height is tile size in pixels, not tile count. A 3px tile on
a 992x1088 image created ~330x360 independent histogram regions, producing
crosshatch/etching artifacts. Now uses image_dimension/8 (clamped 8-256)
for ~8 tiles per axis. Also strips alpha before enhancement and re-joins
after to prevent CLAHE/normalise/linear from corrupting transparency.
2026-05-09 15:20:55 +08:00
SnapOtter 7f131d99a6 fix: QA sweep -- SSE crash, memory leaks, HEIC Docker decode, TGA detection, lint cleanup
- Fix SSE write-after-end crash in progress.ts (remove callback before ending stream)
- Fix blob URL memory leaks: revoke processedPreviewUrl and old HEIC preview URLs
- Add AbortController to batch fetch in use-tool-processor and use-pipeline-processor
- Fix TGA format misidentified as CUR (extension overrides magic bytes)
- Add libheif-plugin-libde265 to Docker for HEIC/HEIF decode support
- Remove unused imports and state (AppLayout, setSampledColor, useEffect)
- Fix non-null assertions in meme-text-renderer and meme-generator
- Fix confusing void type in meme-templates
- Remove unnecessary useEffect deps in adjustments-panel
- Fix Playwright strict mode violations in 5 E2E tests
2026-05-09 13:55:00 +08:00
SnapOtter 40522ebe1a feat: add Deep Enhance AI tier to image enhancement
When deepEnhance is true and the upscale-enhance bundle is installed,
runs SCUNet (quality tier) after the Sharp pipeline for noise/artifact
cleanup. Falls back gracefully to Sharp-only if sidecar is unavailable.
2026-05-09 11:29:27 +08:00
SnapOtter b61be9e438 fix: replace enhancement pipeline with CLAHE + normalise + gamma
CLAHE provides adaptive local contrast, normalise stretches the
histogram, and gamma adjusts exposure perceptually. Replaces the old
modulate/linear pipeline that compounded errors and darkened images.
Preset multipliers now include clahe and normalise entries.

Key fixes beyond the spec:
- maxSlope rounded to integer (Sharp requirement)
- White balance uses linear() instead of recomb() to avoid float-cast
  that breaks CLAHE in the libvips pipeline
- CLAHE tile size adapts to image dimensions (1x1 for tiny images)
- Gamma clamped to Sharp's valid range (1.0-3.0)
- Normalise lower/upper correctly mapped to percentile cutoffs
2026-05-09 11:24:00 +08:00
SnapOtter e22ffa4ec9 fix: editor native layout, UI polish, meme templates auth, pipeline export, install queuing
- Remove editor from AppLayout so it owns the full viewport with no sidebar/padding
- Add back-arrow in menu bar for navigation, restyle menu bar to match native app feel
- Slim left toolbar from 48px to 36px with smaller icons and subtler dividers
- Fix options bar overlapping canvas via shrink-0 and overflow-hidden
- Fix opacity/blend controls clipping in right panel with min-w-0 on flex children
- Add global range slider CSS for consistent thin-track + round-thumb styling
- Make meme template routes public so img tags can load without Bearer auth
- Show pipeline export buttons in default compact view, not just expanded hover
- Queue individual AI feature installs instead of erroring when one is active
2026-05-08 23:30:27 +08:00
SnapOtter e3e5fd5890 Merge branch 'testing/image-editor' into main
Merges all image editor work: RAW decode improvements, expanded format
export (AVIF/TIFF/GIF/JXL/PSD), Photoshop-style menu bar, custom Konva
filters, smart guides, clone stamp, dodge/burn, eyedropper, pixel brush,
selection and transform tool overlays, autosave blob URL persistence,
and 49+ bug fixes across editor canvas and E2E tests.

# Conflicts:
#	apps/api/src/routes/tool-factory.ts
#	apps/api/src/routes/tools/convert.ts
#	apps/web/src/components/editor/common/export-dialog.tsx
#	apps/web/src/components/editor/editor-canvas.tsx
2026-05-08 21:37:52 +08:00
SnapOtter 3a02affae3 feat: recover AVIF/TIFF/GIF/JXL/PSD export from orphaned commit
Recovers expanded export format support from orphaned commit 80961c01
and PSD export from b07ecd5. The editor export dialog now supports 7
formats (PNG, JPEG, WebP client-side; AVIF, TIFF, GIF, JXL via server
conversion). PSD export uses ImageMagick on the backend.
2026-05-08 21:06:29 +08:00
SnapOtter e7001df047 fix: add ImageData type assertion for barcode reader typecheck 2026-05-08 19:08:38 +08:00
SnapOtter aa773addb4 merge: resolve conflict with main branch in tool-registry.tsx 2026-05-08 18:55:28 +08:00
SnapOtter 4235510e5a fix(meme-generator): increase text box padding to prevent glyph overshoot clipping 2026-05-08 18:44:56 +08:00
SnapOtter f58c45138a fix(meme-generator): add padding to prevent stroke clipping at text box edges 2026-05-08 18:27:46 +08:00
SnapOtter d807a6ef45 fix(meme-generator): reduce auto font size cap to match preview proportions 2026-05-08 18:20:41 +08:00
SnapOtter dac30f14f0 fix(meme-generator): match preview and server render text sizing
- Preview font size now calculated from actual container width, not viewport
- Preview stroke scales proportionally with font size (4% ratio)
- Server stroke reduced from 6% to 4% to match preview
- Added ResizeObserver to track container width for accurate sizing
- Added paint-order: stroke fill to CSS preview for consistent rendering
2026-05-08 18:17:17 +08:00
SnapOtter a157af2ea9 fix(meme-generator): auto-sizer now checks line width, preventing text overflow 2026-05-08 17:44:48 +08:00
SnapOtter 0c1980c6db fix(meme-generator): cap auto font size, center text vertically, fix sidebar truncation
- Auto font size now capped at min(200, boxHeight/2, boxWidth/3) to prevent
  oversized text on server render
- Text vertically centered within each text box
- Sidebar color labels shortened (Text/Stroke) with min-w-0 to prevent overflow
2026-05-08 17:42:04 +08:00
SnapOtter e118717337 merge: resolve conflict with main branch in README.md 2026-05-08 17:32:16 +08:00
SnapOtter 1569cc26f2 fix(meme-generator): split into settings + preview panels, fix thumbnail URLs
- Created meme-store.ts Zustand store for shared state between panels
- Split monolithic component into meme-generator-preview.tsx (main area)
  and meme-generator-settings.tsx (sidebar)
- Added ResultsPanel to tool registry entry
- Fixed thumbnail URLs (.jpg -> .webp extension)
- Fixed text overlay sizing and positioning
2026-05-08 17:16:45 +08:00
SnapOtter 466ef1efb1 docs(beautify): add API docs, OpenAPI spec, LLM docs, update README
Add beautify tool endpoint to OpenAPI spec with full parameter
documentation. Add tool to REST API docs Layout & Composition table.
Update tool count from 49 to 50 across README, docs homepage,
architecture docs, VitePress config, OpenAPI spec, and LLM docs
generator.
2026-05-08 16:31:43 +08:00
SnapOtter 53b717243b fix(meme-generator): add opentype.js types, fix no-dropzone registry test 2026-05-08 16:29:44 +08:00
SnapOtter 136a4a0752 Merge branch 'feat/format-support-expansion'
# Conflicts:
#	README.md
#	apps/web/src/components/layout/app-layout.tsx
2026-05-08 16:21:11 +08:00
SnapOtter a90ba372df feat(beautify): add HTTP route, process pipeline, and pipeline registration 2026-05-08 16:17:17 +08:00
SnapOtter 6ec3a51fa4 feat(meme-generator): add meme generation API route with template and custom image modes
Custom route handler supporting template mode (JSON body with templateId)
and custom image mode (multipart upload). Registers process function for
pipeline compatibility. Includes 18 integration tests.
2026-05-08 16:13:34 +08:00
SnapOtter 69e107fbab feat(beautify): add device frame assets and PNG frame compositing 2026-05-08 16:12:46 +08:00
SnapOtter d8c1fdf5c2 feat(beautify): add SVG frame generators (macOS, Windows, browser) 2026-05-08 16:09:31 +08:00
SnapOtter 39358524cd feat(beautify): add shadow rendering (extracted from border.ts pattern) 2026-05-08 16:06:37 +08:00
SnapOtter b0cb17ff55 feat(meme-generator): add template listing and static serving endpoints 2026-05-08 16:05:17 +08:00
SnapOtter b13df56273 feat(beautify): add background generation (solid, gradient, image, transparent) 2026-05-08 16:04:34 +08:00
SnapOtter 2eef1f45f9 feat(beautify): add Zod schema, shadow presets, social dimensions 2026-05-08 16:01:55 +08:00
SnapOtter 9dff59c400 feat(meme-generator): add text renderer with opentype.js SVG path generation 2026-05-08 16:01:46 +08:00
SnapOtter 086a386d53 feat(meme-generator): add 100 meme templates with manifest and asset pipeline
Includes full-size images, WebP thumbnails, curated text box positions for
18 popular templates, and default top/bottom layout for the rest.
2026-05-08 15:57:36 +08:00
SnapOtter fc9e951e96 chore: bundle OFL/Apache-licensed fonts for meme generator 2026-05-08 15:42:02 +08:00
SnapOtter 180ec6edfb chore: add opentype.js dependency for meme text rendering 2026-05-08 15:39:34 +08:00
SnapOtter bcdc4bdf82 docs: add color-blindness tool to API docs and update tool counts 2026-05-08 15:23:22 +08:00
SnapOtter eedc2443d6 feat: add color-blindness API route and integration tests 2026-05-08 15:18:38 +08:00
SnapOtter 93a246ce23 test: add QOI codec unit tests and E2E GUI format support tests
- QOI codec: 16 tests covering encode/decode round-trips, error handling, fixture validation
- E2E: 28 tests for format upload/resize, convert new outputs, dropdown verification,
  HEIC-to-JPG flow, and exotic format upload acceptance
2026-05-08 15:16:06 +08:00
SnapOtter 44608733c6 feat: add PPM/PGM/PBM CLI decoder fallback, QOI fixture and format-matrix entry
- Add ppm/pgm/pbm to CLI_DECODED_FORMATS with Sharp-first, ImageMagick fallback
- Create sample.qoi test fixture (10x10 solid color)
- Add QOI to format-matrix test FORMAT_SAMPLES
- Mark PPM/PGM/PBM as needsCliDecoder in tests (Sharp doesn't support them natively)
2026-05-08 15:12:23 +08:00
SnapOtter 80961c0187 feat: add JXL to all tool format selectors, expand convert with BMP/ICO/JP2/QOI, add server-side editor export 2026-05-08 00:19:19 +08:00
SnapOtter 390b5adb8c feat: add QOI codec, format encoders (BMP/ICO/JP2/QOI), fix JXL output bug 2026-05-08 00:09:55 +08:00
SnapOtter 5c9fa2de49 feat: add decode pipelines for JP2, EPS, QOI, DDS, CUR, DPX, FITS, PPM, SVGZ, APNG
Add input decode support for 10 new image format families:

- JPEG 2000 (JP2/J2K): opj_decompress with ImageMagick fallback
- EPS: ImageMagick + Ghostscript delegate with 50MB size guard
- DDS: ImageMagick decode, first frame extraction
- CUR: reuses ICO decoder (structurally identical)
- DPX/Cineon: ImageMagick with sRGB colorspace conversion
- FITS: ImageMagick with normalize + sRGB conversion
- QOI: stub decoder (real codec deferred to Task 4)
- PPM/PGM/PBM/PFM: Sharp-native via libvips (no CLI decoder needed)
- SVGZ: gzip decompression with bomb protection before SVG sanitization
- APNG: accepted via extension, decoded as PNG first frame by Sharp

Updates magic bytes, MIME mappings, and frontend accept lists across
all file picker entry points (dropzone, tool page, file upload, editor).
2026-05-08 00:05:50 +08:00
SnapOtter 5205f4a215 feat: expand camera RAW support with exiftool-first decode strategy
- Add CR3 (Canon) brand detection in ftyp magic bytes, returning "raw"
  to route through the RAW decode pipeline
- Add magic bytes for Fujifilm RAF, Sigma X3F, and Minolta MRW formats
- Expand RAW_EXTENSIONS set from 6 to 24 formats (CR3, NRW, RAF, PEF,
  3FR, IIQ, SRW, X3F, RWL, GPR, FFF, MRW, MEF, KDC, DCR, ERF, PTX)
- Rewrite decodeRaw() with two-tier strategy: ExifTool embedded JPEG
  extraction (fast path) with ImageMagick+LibRaw fallback (full decode)
- Add ext parameter to decodeToSharpCompat/decodeRaw so temp files use
  the original extension for correct format identification
- Pass fileExt from tool-factory when calling decodeToSharpCompat
- Add JXL, ICO, PSD, EXR, HDR, TGA MIME entries to CONTENT_TYPE_TO_EXT
2026-05-07 23:59:47 +08:00