diff --git a/ChangeLog.md b/ChangeLog.md index 90ab421..55af114 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -2,45 +2,14 @@ Todo: More testing Linux / Mac. Create Windows .exe. Write better documentation / help. Add splash screen / icon. Fix raw image support. -## Unreleased - -- Auto-levels and auto white balance produce noticeably better output: - - Auto-levels no longer gives up on an end of the histogram just because a tiny number of pixels is already clipped there (e.g. one small specular highlight used to disable the entire white-point stretch). The clip threshold now acts as a true budget: the stretch is chosen so the total clipped fraction — pre-existing plus new — stays within the threshold. - - Auto-levels endpoints are now luminance-driven with a per-channel clip budget (new "Channel Clip Budget" setting, default 3x the threshold), so a single saturated channel (blue sky, red flowers) no longer vetoes the whole stretch. Analysis histograms use 1024 bins instead of 256 for finer, more stable endpoint placement. - - New midtone correction (new "Midtone Correction" + "Midtone Target" settings, on by default, target 0.38): auto-levels also nudges brightness when a full-range image is under- or over-exposed. Images already within a dead band of the target are left alone, and corrected images recover only partway toward the band edge — so well-exposed photos and intentional low-key/high-key shots are preserved rather than normalized to one brightness. Full-range but underexposed images, which previously got "no change (already full range)", are now corrected. The nudge is conservative (-15%/+30% max) and is only auto-set when the brightness slider is untouched. - - The blacks/whites levels ramp rolls off smoothly near pure white and black instead of hard-clipping each channel independently (new "Highlight Soft Rolloff" setting, on by default). Stretched highlights keep tonal separation and hue — sunset clouds no longer color-shift when one channel clips before the others — and crushed shadows keep a hint of separation. - - Strong level stretches no longer band smooth gradients (skies) on export: a deterministic, imperceptible triangular-noise dither is applied during 8-bit quantization when the stretch gain reaches 1.2x (new "Export Dithering" setting, on by default). The levels uint8 fast-path save defers to the float pipeline in that case so the dither can be applied. - - Auto white balance now analyzes only the cropped area, so borders and backgrounds you have cropped away can no longer skew the color estimate (auto-levels already worked this way). - - Auto white balance scales its correction by confidence: few usable neutral pixels, or disagreement between its two estimators, fades the correction toward neutral instead of over-correcting scenes that lack true grays. - - Auto white balance blends a second, independent estimator (Shades-of-Gray, Minkowski p=6) with the neutral-pixel estimate; agreement between the two raises confidence and blending tempers each one's biases. - - Magenta/green (tint) corrections are damped relative to blue/yellow (new "Tint Correction" setting, default 60%): real light sources vary mostly along the blue/yellow axis, so a large tint component is usually subject color (foliage) rather than a cast — this prevents the classic "green forest turns magenta" failure. - - White-balance gains are now normalized to preserve luminance, so warming or cooling an image no longer slightly brightens or darkens it (applies to slider WB and AWB alike, including the uint8 fast-path save). - - Auto vibrance is now hue-aware: it backs off when a small subject is already vivid (90th-percentile saturation guard) and halves the boost when a meaningful share of pixels falls in the skin-tone envelope. - - The compact editor's Light section now includes a Brightness slider (the full editor already had one), so the midtone correction applied by auto-levels is visible and adjustable there. The soft highlight rolloff and luminance-preserving white balance apply to manual Blacks/Whites and Temp/Tint slider edits in both editors too, since they live in the shared render pipeline. -- Applying a crop (and full-resolution renders generally) no longer copies the entire full-resolution float master before slicing out the crop — at 20MP that was a ~240MB copy on the UI thread per crop apply. The render now shares the master and copies only the cropped region, and skips even that when the display downscale already produced fresh memory. Preview-sized renders during crop drags get the same treatment. Output is bit-identical. -- Rotate mode (crop straightening) now overlays a grid of horizontal and vertical reference lines. The lines stay screen-aligned while the image rotates underneath, so horizons and verticals can be lined up without guessing; the center lines are drawn brighter. The grid is only visible while rotate mode is active. -- Image editing is much faster. Quick auto-adjust keys (`l`, `L`, `-`, `=`, `+`, `_`) and editor sliders now show results several times sooner: - - sRGB↔linear conversions in the edit pipeline use lookup tables (~3x faster, error under 0.03 of one 8-bit step). - - Preview renders skip the linear round-trip entirely when only sRGB-space edits (levels, brightness, contrast, saturation, vibrance, vignette) are active; the live clipping indicators are still computed from a downsampled view. - - Final display conversion uses a fused OpenCV pass (~5x faster). - - Quick auto-adjust loads the image preview-only, removing a ~400ms UI freeze on the first keypress; the full-resolution master is materialized in the background. - - Full-resolution live previews (after crop/rotate) now publish a fast preview-sized frame immediately, then replace it with the high-resolution frame, and the high-resolution render is capped at display size when not zoomed (it was processing 20MP for pixels the screen cannot show). Crop apply/cancel renders are capped the same way. - - The editor now decodes JPEG pixels with TurboJPEG (Pillow fallback) instead of Pillow, roughly halving image-load time on the first edit keypress; EXIF/ICC metadata is preserved via a lazy header read. Full editor loads of JPEGs also no longer decode the file a second time through OpenCV's 16-bit probe. - - More debug timing logs: `[RENDER_DECODED]` breaks down apply/u8/color time per preview render. -- The batch-clear shortcut now uses `|` instead of plain `\`, so Shift must be held down. -- Fixed re-editing a previously cropped (or otherwise edited) image showing a double-applied edit (e.g. crop-on-crop) in preview-sized renders: the editor seeded its preview buffer from the already-saved pixels while also replaying the saved edits on top. The preview is now rebuilt from the backup source pixels whenever edits are replayed. -- EXIF orientation is now applied with OpenCV rotate/flip (bit-identical, ~5x faster): rotated camera images (orientation 3/6/8) were paying a ~244ms numpy transpose copy at 20MP on every editor load and prefetch decode. -- A save no longer invalidates and re-decodes the displayed image two or three times: the save-completion handler and the watcher events it triggers now recognize (via an mtime+size fingerprint) that the file state was already invalidated. Single-file metadata changes (timestamp/backup flag after a save) also no longer cancel the whole prefetch generation, which was silently re-decoding the ±8 window in the background after every save. -- Editor preview buffers are built with cv2.resize instead of a PIL thumbnail round-trip when the JPEG fast path is active (~4x faster at 20MP). -- Fixed display-only oversaturation when editing a previously saved image in ICC color mode: editor preview buffers built from source pixels (backup re-edit loads, restored in-flight sessions, compare previews) were sRGB but displayed as monitor-space. They are now color-corrected to display space at build time, exactly like the prefetcher's cached previews. Saved files were never affected. -- Navigating away from a just-edited image and back no longer flashes the original pixels while the background save is in flight: the last live preview is seeded into the decode cache when the session save is queued, then replaced by the real decode when the save completes (and dropped if the save fails). -- Fixed a duplicate watcher-debounce fire (with an already-drained change set) falling back to a global cache invalidation, which re-decoded the whole prefetch window once after some saves. -- Saving is much cheaper end to end: - - Adding an image to a batch (including the automatic add-on-first-edit) no longer rebuilds the entire grid model — batch badges are computed live, so the grid is just told to repaint them. This removes a ~1 second UI-thread stall after every save. - - Sidecar metadata lookups from grid refreshes no longer run the legacy-key migration scan (O(entries) filesystem checks per missing entry); measured 1184ms → 28ms for a 341-image folder with 300 sidecar entries. Migration still runs on user-action lookups, so old entries are still upgraded when an image is viewed or modified. - - The vibrance pipeline (active on every quick auto-adjust save and preview) avoids a hidden float64 promotion in the gray-blend math and uses OpenCV for channel max/min and luma (~3x faster at full resolution), and the save path's float→uint8 conversion is a fused OpenCV pass. -- Navigation metadata lookups (filename/uploaded/stack/batch status shown per image) no longer run the sidecar legacy-key migration scan, which was doing hundreds of filesystem checks per navigated image on the GUI thread during fast arrow-key scrolling. -- Saving an image no longer invalidates the entire decode cache. Saves, watcher-detected file changes, and edit-revert now invalidate only the files that actually changed, so navigation right after a save no longer hits a blocking re-decode and the prefetch window stays warm (previously every save re-decoded ~9 neighboring images and bumped the global cache generation several times). A per-path invalidation epoch makes this safe: decode results that started reading a file before it was replaced are discarded instead of re-inserting stale pixels. The global invalidation still applies for resize/zoom/color-mode changes and unattributable directory events. +## 1.6.5 (2026-06-20) + +- Better automatic photo adjustments. Auto-levels, auto white balance, brightness, highlights, shadows, and vibrance now produce more natural results. +- Faster editing and previews. Sliders, quick-adjust keys, crop/rotate previews, JPEG loading, and full-resolution renders are much faster, so editing should feel noticeably more responsive. +- Improved crop and rotate workflow. Cropping is faster and more reliable, and rotate/straighten mode now shows a helpful grid so horizons and vertical lines are easier to align. +- More reliable color display. Several preview/color-management issues were fixed so edited images display more consistently, especially when working with ICC color profiles. +- Safer batch clearing shortcut. The batch-clear shortcut is now `|` instead of plain `\`, making it harder to trigger accidentally. +- Easier external editor setup. The app now automatically searches for Photoshop and Helicon Focus paths across supported systems, including macOS, Linux, and Windows, so external editor setup should require less manual configuration. ## 1.6.4 (2026-06-06) diff --git a/README.md b/README.md index 9be19ad..e00c78b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # FastStack -# Version 1.6.4 - June 7, 2026 +# Version 1.6.5 - June 20, 2026 # By Alan Rockefeller @@ -16,13 +16,12 @@ This tool is optimized for speed, using `libjpeg-turbo` for decoding, aggressive - **Spark Line**: In grid view, a spark line is visible on each folder, so you can see how far you have gotten in uploading photos in each directory. - **Helicon Focus Integration:** Launch Helicon Focus with your selected RAW files with a single keypress (`Enter`). - **Instant Navigation:** Sub-10ms next/previous image switching, high performance decoding via `PyTurboJPEG`. +- **Drag & Drop:** Drag images to external applications. Press { and } to batch files to drag & drop multiple images. - **Image Editor:** Built-in editor with exposure, contrast, white balance, sharpness, and more (E key) - **Background Darkening:** Mask-based background darkening tool (K key) with smart edge detection, subject protection, and multiple modes. Paint rough background hints and the tool refines them into natural-looking dark backgrounds. - **Quick Auto Adjust:** Press `l` for quick auto-levels, `L` for auto white balance + auto-levels together, `A` for auto white balance, `-`/`_` to keep adjusting the highlight/white side in 14-point steps, and `=`/`+` to adjust the shadow/black side in 7-point steps. These update the live in-memory edit session immediately and save once when you navigate away, start a drag, or explicitly save. Auto-levels treats its clip threshold as a budget (a few already-clipped specular pixels won't disable the stretch), brightens underexposed midtones toward a configurable target, and rolls off stretched highlights smoothly instead of hard-clipping them. Auto white balance analyzes only the cropped area, fades its correction when the scene lacks reliable neutrals, and damps magenta/green corrections so foliage isn't mistaken for a color cast. The midtone target, channel clip budget, highlight rolloff, export dithering, and tint correction strength are all adjustable in Settings. - **Photoshop / Gimp Integration:** Edit current image in Photoshop or Gimp (P key) - always uses RAW files when available. -- **Clipboard Support:** Copy image path to clipboard (Ctrl+C) - **Image Filtering:** Filter images by filename -- **Drag & Drop:** Drag images to external applications. Press { and } to batch files to drag & drop multiple images. - **Theme Support:** Toggle between light and dark themes - **Delete & Undo:** Move images to recycle bin (Delete/Backspace) with undo support (Ctrl+Z) - **Has Memory:** Starts where you left off, tells you which images have been edited, stacked and uploaded. @@ -34,9 +33,26 @@ This tool is optimized for speed, using `libjpeg-turbo` for decoding, aggressive ## Installation -### macOS (Recommended) +### Download a build (Recommended) + +Most users should grab a prebuilt **Windows** or **macOS** build — no Python +setup required. Download the latest release for your platform from the +[GitHub Releases](https://github.com/AlanRockefeller/faststack/releases) page: + +- **Windows:** Download the Windows build, unzip it, and run + `FastStack.exe`. +- **macOS:** Download the macOS build, open the `.dmg`, and drag FastStack to + your Applications folder. On first launch you need to right-click the app + and choose **Open** to bypass Gatekeeper. + +FastStack checks GitHub Releases for newer versions when update checks are enabled in Settings. + +### Install from source + +Power users and Linux users can install from source. FastStack performs best on +Python 3.12 due to PySide6 compatibility. -FastStack performs best on Python 3.12 due to PySide6 compatibility. +#### macOS 1. **Install Python 3.12 (via Homebrew):** @@ -67,7 +83,7 @@ FastStack performs best on Python 3.12 due to PySide6 compatibility. faststack --loupe /path/to/photos # start in loupe view, skip initial thumbnails ``` -### Windows / Linux +#### Windows / Linux ```bash python -m venv venv @@ -105,19 +121,6 @@ Automatic installation is intentionally disabled for source/virtualenv installs because a running Python app cannot reliably replace its own environment across Windows, Linux, and macOS. -### Maintainer Release Builds - -Windows and macOS binaries are built by GitHub Actions from `v*` tags. From a -clean checkout after the intended changes are merged to `main`, run: - -```bash -./build-release.sh -``` - -The script creates the next `v-buildN` tag on `origin/main`, pushes it, -and the workflow publishes the Windows and macOS ZIP files to the GitHub Release -for that tag. - ### Command Line Options ```text @@ -159,29 +162,6 @@ set FASTSTACK_TURBOJPEG_LIB=C:\path\to\turbojpeg.dll faststack "C:\path\to\photos" ``` -### Troubleshooting on Windows - -If startup logs mention: - -```text -TurboJPEG initialization failed (N location(s) tried). Falling back to Pillow for JPEG decoding. -``` - -that means the Python package is installed but FastStack could not initialize TurboJPEG from any discovered location and is using Pillow instead. - -Fastest fixes: - -1. Install `libjpeg-turbo` for Windows x64 so that this file exists: - `C:\libjpeg-turbo64\bin\turbojpeg.dll` -2. Or point FastStack to the dll explicitly: - -```cmd -set FASTSTACK_TURBOJPEG_LIB=C:\path\to\turbojpeg.dll -faststack "C:\path\to\photos" -``` - -If you do nothing, FastStack will still run, but JPEG decoding and thumbnail generation will use Pillow instead of `libjpeg-turbo`, which is slower. - ## Keyboard Shortcuts - `Right Arrow`: Next Image diff --git a/pyproject.toml b/pyproject.toml index 76d2b54..f37c9c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "faststack" -version = "1.6.4" +version = "1.6.5" authors = [ { name = "Alan Rockefeller" }, ]