Skip to content

Conversation

@shipurjan
Copy link

@shipurjan shipurjan commented Dec 14, 2025

Add RAW File Support + Unified Image Preview Caching

I used Claude Code to implement this feature. This PR adds RAW image format support and fixes a major performance bottleneck with how image previews were being loaded.

Motivation

I work with RAW files and had to manually extract JPEG previews before using Cullergrader. Additionally, the app was re-reading every JPEG from disk whenever I changed grouping thresholds, which made working with large folders (1000+ photos) painfully slow.

Implementation

RAW File Support

Added support for common RAW formats (ARW, CR2, NEF, DNG, ORF, RAF, RW2, etc.) by extracting embedded JPEG previews using the metadata-extractor library. Uses ExifThumbnailDirectory.getAdjustedThumbnailOffset() to read thumbnail bytes directly from RAW files.

Upgraded metadata-extractor from 2.18.0 to 2.19.0 to get access to getAdjustedThumbnailOffset() which properly calculates the absolute offset of thumbnails in RAW files. See the 2.18.0 to 2.19.0 comparison for details.

RAW files without embedded previews are gracefully skipped with a log message.

Unified Image Preview Cache

The big performance fix: all image formats now use a unified fill-until-full memory cache instead of re-reading from disk constantly. The cache stores previews at display resolution (240×160) and serves them directly for thumbnails. When hashing needs 8×8, it scales down from the cached preview.

Cache size is configurable via IMAGE_PREVIEW_CACHE_SIZE_MB in config.json (default 2048 MB). The cache fills until reaching the configured limit, then stops caching new entries. No eviction policy means stable memory usage and predictable behavior.

Cache operations log to console only, not the GUI info panel, so "load completed" stays visible.

Performance Impact

With the cache, changing thresholds and reloading groups no longer re-reads files from disk, making these operations significantly faster. This is especially noticeable with large folders (1000+ files).

Changes

  • Added RAW file detection and embedded preview extraction in PhotoUtils.java
  • Implemented unified image preview cache with simple fill-until-full strategy (no eviction)
  • Added IMAGE_PREVIEW_CACHE_SIZE_MB configuration option (default 2048 MB)
  • Added console-only logging method in Logger.java
  • Fixed NPE crash when RAW files without previews created null hashes in GroupingEngine.java
  • Cache clears automatically when loading a new directory in GroupGridFrame.java
  • Upgraded metadata-extractor from 2.18.0 to 2.19.0
  • Updated README with RAW support and Performance Tuning section

Testing

Tested extensively with 1700 Sony ARW files (6192×4128). Other RAW formats (CR2, NEF, etc.) are untested but should work since they use standard EXIF metadata. If you encounter issues with other formats, please report them.

Limitations

RAW support is experimental. Only Sony ARW was tested. RAW files must contain embedded JPEG previews (most modern cameras do). Cache is in-memory only and cleared when loading a new directory or restarting the app.

Backward Compatibility

No breaking changes. This is purely additive. Existing JPEG/PNG functionality is enhanced, not changed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant