Release Notes

RawCull version release notes and changelogs.

Version 2.1.8

RawCull Changelog β€” v2.0.5 β†’ 2.1.8

Submitted for update on Apple App Store.


πŸ” Actual-Pixels Inspection

  • Added Z as a fast inspection shortcut from grid, loupe, and comparison views.
  • Opens the zoom overlay directly on the embedded JPEG at an actual-pixels zoom level.
  • Centers the view around the AF focus point when one is available.
  • Shows the focus-point marker on open for faster sharpness checking.

⭐ Faster Culling Flow

  • Rating, reject, keep, and tag actions now advance automatically to the next image.
  • The same advance behavior is available in thumbnail navigation, zoom overlay, and comparison grid workflows.
  • Catalog loading now preselects the first visible file by name, so keyboard culling can begin immediately.

🧭 Orientation-Correct Previews

  • Normalized source orientation for thumbnails, embedded previews, sharpened previews, comparison images, and zoom previews.
  • Improved handling for Sony embedded previews that do not carry their own orientation metadata.
  • Added corrected transform handling for EXIF orientation values, including rotated and mirrored images.

🧠 Adaptive Memory Handling

  • Added adaptive preview and grid cache recommendations based on installed memory, current system memory use, and macOS memory pressure.
  • Reduced cache budgets automatically when memory pressure is warning or critical.
  • Updated default cache settings for different memory tiers.
  • Simplified the memory warning banner and added a close button.

πŸͺŸ About Window

  • Added a native About RawCull window.
  • Replaced the standard app info command with RawCull’s custom About window.
  • Included app version/build information and a compact keystroke reference.

πŸ—‚οΈ Saved Files View Cleanup

  • Split saved-files UI into smaller focused components for catalog rows, file rows, detail rows, section headers, and star ratings.
  • Kept the saved-file detail presentation while making the view easier to maintain.
  • Added a FileRecord convenience initializer for previews and tests.

πŸ§ͺ Tests

  • Added and expanded Swift Testing coverage for culling auto-advance, thumbnail/cache admission, zoom overlay key actions, comparison navigation, and thumbnail provider behavior.
  • Added coverage for Z actual-pixels inspection in comparison navigation.

πŸ› οΈ Maintenance

  • Aligned project versioning across build settings and release branches.
  • Added a test-performance Makefile target.
  • Performed cleanup in scoring parameter UI and cache-related code.

Version 2.0.5

RawCull Changelog β€” v2.0.2 β†’ 2.0.5

Submitted for update on Apple App Store.


  • πŸ–ΌοΈ Fixed orientation handling for embedded JPEG previews, sidecar JPEGs, cached previews, comparison view, and zoom previews.
  • 🎯 Improved sharpness scoring and burst analysis so they can run on selected files or active star-rating filters instead of always processing the full catalog.
  • ⚑ Refreshed full-size JPEG cache keys to avoid reusing older non-orientation-normalized previews.
  • 🧹 Fixed empty catalog handling so loading state and security-scoped access are cleaned up correctly.
  • ✨ Added an β€œAdd Catalog” action when a selected folder contains no RAW files.
  • πŸ§ͺ Added regression tests for orientation decoding, scoped sharpness/burst analysis, cache behavior, and empty catalog cleanup.

Version 2.0.2

RawCull Changelog β€” v1.9.6 β†’ 2.0.2

Updated on Apple App Store.


✨ New β€” Image source toggle in zoom / loupe view

Switch between the embedded JPEG preview and a full-size JPEG created from the RAW file while inspecting an image:

  • New ImageSourceToggleView with keyboard shortcut support
  • ZoomPreviewHandler significantly expanded to manage source switching
  • ZoomOverlayView updated with key-action routing
  • FullSizeJPGDiskCache extended to support the toggle flow
  • New DiskCacheAndScanAdmissionTests covering the cache admission logic

✨ New β€” Burst Review Queue

A structured review-queue workflow for burst groups:

  • New BurstReviewQueueFilter (.all, .needsReview, .deferred, .reviewed) β€” filter the culling grid to a specific review state
  • New BurstReviewQueuePolicy β€” stateless logic that derives each group’s effective state (high-confidence, no cautions β†’ auto-reviewed; low confidence or open cautions β†’ needs review)
  • New BurstReviewQueueCounts value type exposed on RawCullViewModel
  • Review-state action buttons in BurstGroupHeaderView: Reviewed, Needs Review, Defer β€” rendered contextually per current state
  • State badge overlay on burst group headers (purple = Needs Review, blue = Reviewed, gray = Deferred)
  • Filter buttons added to SimilarityGridSelectionView toolbar β€” live counts shown inline; filter resets to .all on Exit Groups
  • Auto-sharpness scoring toggle removed from toolbar; scoring now triggered automatically via runWithAutoScoring before burst analysis runs
  • Review states persisted to the burst analysis disk cache on every state change

πŸ—οΈ Refactored β€” CullingGridView decomposed

The monolithic CullingGridView split into focused, independently testable objects:

  • CullingGridSelectionCoordinator β€” selection state & keyboard navigation
  • CullingGridRenderCache β€” per-cell image caching (keyed by CullingGridRenderCacheKey)
  • CullingGridProgressOverlay β€” loading progress overlay
  • Cell data flow cleaned up: isSelected, ratingValue, ratingDisplay, ratingColor now passed directly to ImageItemView, removing ViewModel look-ups inside the cell

πŸ—οΈ Refactored β€” ComparisonGridView decomposed and redesigned

  • ComparisonGridDisplayState β€” display/layout state extracted from the view
  • ComparisonGridImageCoordinator β€” per-pane image loading coordination extracted from the view
  • Background changed to near-black (Color.black.opacity(0.97)) for a cinema-style comparison experience
  • BurstComparisonEvidenceView promoted to a floating overlay (ZStack + .zIndex(2)) so it no longer pushes image panes down
  • Image panes fill the full viewport height instead of being constrained to a fixed 3:2 ratio
  • Scroll indicators hidden; viewport transform resets automatically when the comparison group or active burst group changes

πŸ“¦ New β€” RawParserKit SPM package (rsyncOSX/RawParserKit v1.1.0)

All raw-file parsing logic extracted from RawCull into a standalone, reusable Swift package:

  • Sony: SonyMakerNoteParser, SonyThumbnailExtractor, SonyRawFormat, JPGSonyARWExtractor
  • Nikon: NikonMakerNoteParser, NikonThumbnailExtractor, NikonRawFormat, JPGNikonNEFExtractor
  • Shared: RawFormat, RawFormatRegistry, RawParserDiagnostics, CancellableImageIOWork, ThumbnailSharpener
  • ✨ New in package: SonyRAWJPEGCreator β€” Sony-specific embedded JPEG creator; ThumbnailError typed errors

πŸ“¦ New β€” RawCullCore SPM package (rsyncOSX/RawCullCore v1.0.0)

Core data models and domain logic extracted into a standalone package:

  • Burst: BurstGroupingEngine, BurstRankingEngine, BurstAnalysisModels
  • File model: RawCullFileItem (replaces the internal FileItem)
  • Histogram: HistogramCalculator (replaces the internal CalculateHistogram)
  • ✨ New in package: ExifMetadata, FocusPointParser, RawCullSourceCatalog, SaliencyInfo β€” new shared data types

πŸ—οΈ Refactored β€” ScanStatsSheetView expanded

  • Layout widened from 460 β†’ 800 pt; content reorganised into a two-column HStack
  • Left column: Culling Status, Catalog Summary, Sharpness Summary, and a new Burst Review section (total groups, needs-review / deferred / reviewed counts)
  • Right column: new Burst Label Guide β€” caption-sized reference grid explaining every confidence and state badge

🧹 Cleanup & dead-code removal

  • FocusPeakingControlsView and related BurstAnalysisModels display-only properties removed (moved to package / no longer needed)
  • CacheSettingsTab simplified β€” removed stale showResetConfirmation, showSaveSettingsConfirmation, and cacheConfig state variables
  • SharedMemoryCache β€” 34 lines of redundant code removed
  • SettingsViewModel β€” dead state and unused helpers pruned
  • ImageItemView β€” substantial simplification following the cell data-flow refactor
  • SharedMainToolbarContent β€” stale toolbar items removed

πŸ§ͺ Tests β€” Cleaned up & extended

Tests for code that moved to SPM packages removed from the main test target; new and expanded tests added:

  • βž• CullingGridCoordinatorTests β€” coordinator selection and keyboard-navigation logic
  • βž• ZoomOverlayKeyActionTests (expanded) β€” image-source toggle key actions
  • βž• DiskCacheAndScanAdmissionTests β€” full-size JPG disk-cache admission coverage
  • βž• CullingModelTests (expanded) β€” BurstWinnerOverride exact-membership matching; upsert with differing member sets
  • βž• RawCullVerifyTestsConcurrencyTests (expanded) β€” burst review-state concurrency coverage
  • βž– Removed (now tested inside their respective SPM packages): BurstAnalysisTests, NikonMakerNoteParserTests, SonyMakerNoteParserTests, SimilarityScoringTests, CancellableImageIOWorkTests, ComparisonCandidateInspectorTests, LoupeImageKeyActionTests

Version 1.9.6

RawCull Changelog β€” v1.9.4 β†’ 1.9.6

Released on Apple App Store.

πŸ”„ Comparison view is now a horizontal filmstrip

The burst comparison layout was completely redesigned.

  • Candidates are now presented in a side-by-side horizontal scroll, one full-width pane per candidate, instead of a vertical grid stack.
  • Navigation is left/right only β€” up/down arrow keys are removed. The view snaps one candidate at a time using SwiftUI scrollTargetBehavior(.viewAligned).
  • Selecting a file in the filmstrip updates the main selection and vice-versa, keeping both views in sync automatically.
  • The burst header bar is more compact: decision text and action buttons share a single line with tooltips replacing verbose inline descriptions.

πŸ” Loupe view can now toggle the extracted JPG

The loupe (single-image zoom) view gains a built-in extracted-JPG mode so you can compare the embedded thumbnail against the full-size sidecar or extracted JPEG without opening a separate window.

  • Press J (or j) to toggle between the embedded thumbnail and the extracted JPG. Zoom (+/-) continues to work in both modes.
  • A LoupeImageKeyAction enum centralises key resolution (+, -, j/J), replacing the inline switch on key characters and making key handling unit-testable.
  • When the extracted JPG is active, a ProgressView is shown while loading and a “No extracted JPG” placeholder appears if no sidecar or embedded preview is available. The task is cancelled and cleaned up when the image changes or the view disappears.
  • ZoomPreviewHandler.loadExtractedJPGPreview is extracted as a reusable static method (sidecar JPG β†’ RAM cache β†’ raw extraction pipeline), shared between the loupe toggle and the existing zoom-window open path.
  • The focus overlay and focus mask both track currentImageSize / currentDisplayedImage, so they remain correctly anchored whether the thumbnail or the extracted JPG is displayed.
  • The image-source toggle in ImageOverlayControlsView is now wired to showExtractedJPG, replacing the previously constant .constant(false) binding.

🏷 Rating badge now visible on every thumbnail view

CurrentRatingBadgeView is now shown as an overlay on ImageItemView, RatedImageItemView, and the loupe MainThumbnailImageView.

  • A new density parameter (.regular / .compact) shrinks the badge’s font, icon, and padding for use inside small thumbnails where screen space is limited.
  • In ImageItemView the rating badge and the burst-recommendation badge are stacked vertically in the top-left corner.
  • RatedImageItemView extracts its rating lookup into a shared ratingValue computed property, eliminating duplicated savedFiles traversal.

🎯 Scoring signatures now version-stamp every result

Sharpness scores are now stamped with a SharpnessScoringSignature that captures the exact algorithm version, ISO scaling policy, aperture hint policy, and all scoring parameters used to produce the score.

  • Saved file records (savedfiles.json) store the scoring signature, file size, and modification date alongside the score, so RawCull can detect when a cached score is stale.
  • A SharpnessScoringSignature carries explicit algorithm version, ISO policy version, and aperture hint policy version fields, making it straightforward to invalidate old scores when the pipeline changes.
  • The burst cache schema advances to version 2 to match the new signature layout.
  • BurstSharpnessSignature is now a typealias for SharpnessScoringSignature (no migration needed for existing burst caches).

🩺 Candidate inspector shows richer scoring evidence

The inspector panel shown when reviewing burst candidates now surfaces much more of the internal scoring data.

  • New fields: Source, Blur Gate sigma, Subject Label, Subject Confidence, Focus Flag, Mask Region, and Mask Threshold in the Scoring section.
  • New evidence fields: Scoring Local Detail, AF Center Detail, AF Neighborhood Detail, Scoring AF Patch, Scoring Subject Patch, Saliency Candidates, Saliency Selection reason, Evidence Threshold, Evidence Coverage, and Visibility Relaxed.

🧩 Saliency selection is now multi-candidate with AF-point guidance

Vision saliency results are no longer collapsed into a single union rectangle.

  • Each detected object is now a SaliencyCandidate with its own rect and confidence.
  • A dedicated selectSaliencyCandidate function picks the winning region by weighing AF-point overlap, distance to AF point, local detail score, and area β€” preferring the subject the camera actually focused on.
  • The selection reason and candidate count are recorded in the breakdown and shown in the inspector.

πŸ–Ό Focus mask gains visibility relaxation

The focus mask overlay now actively checks whether the selected threshold would produce a nearly invisible mask.

  • When coverage falls below a configurable minimum, the threshold is automatically relaxed until the overlay is visible, and relaxedForVisibility = true is recorded in the breakdown.
  • Overlay styles are renamed from subjectHeat/globalDetail to subjectEdges/globalEdges to better reflect what they show.

⚑ Cancellation guards throughout the scoring pipeline

All heavy per-frame work checks Task.isCancelled at every major stage, so switching images quickly no longer queues up stale work.

  • A shared runCancellableWorker helper on FocusMaskEngine wraps detached tasks with a proper withTaskCancellationHandler so cancellation propagates immediately.
  • Calibration, saliency, Laplacian sampling, mask generation, and scoring all return early when cancelled.

πŸ“ Calibration now samples pixel energies, not scores

The auto-calibration pass that sets the visual edge threshold was redesigned.

  • Instead of scoring every file end-to-end, calibration now decodes a small 512-px thumbnail, runs only the Laplacian, and collects raw pixel energy samples.
  • This makes calibration faster and ensures the core sharpness score no longer depends on catalog contents β€” only the visual threshold changes per catalog.

πŸŽ› Compact overlay controls in comparison panes

All image overlay control capsules (focus mask, focus points, ratings, image source) now accept a density parameter.

  • .compact density shrinks button sizes, padding, and font sizes for use inside the comparison pane where screen space is limited.
  • Focus peaking (FocusPeakingControlsView and the G keyboard shortcut) has been removed from the zoom overlay.

πŸ§ͺ New tests

  • resolution scaling uses longest side regardless of orientation
  • scoring size normalization clamps legacy and oversized values
  • conservative subject score keeps broad score dominant
  • conservative subject score preserves broad fallback without patches
  • saliency selection prefers AF overlap over confidence
  • saliency selection is deterministic without AF
  • saliency selection reports empty fallback
  • cancellable worker forwards cancellation (thread-safety, 1 min limit)
  • visibility relaxation lowers threshold and reports coverage
  • generic decode normalization produces sRGB eight bit RGBA
  • scoring signature ignores visual controls and tracks score controls
  • scoring signature invalidates for every score-affecting field and policy version
  • applying visual calibration does not change scoring signature
  • zoom shortcuts resolve from characters
  • jpg source shortcuts resolve from lowercase and uppercase j
  • unmapped keys are ignored

Version 1.9.4

RawCull Changelog β€” v1.8.5 β†’ 1.9.4

Updated on Apple App Store.

v1.9.1 β†’ v1.9.4

🎯 Sharpness scoring now has intent presets and precision modes

Sharpness scoring is now much more configurable and better tuned for different kinds of photography.

  • Added photo-type presets: Auto, Birds/Wildlife, Portrait, Landscape, and Action.
  • Added quality modes: Fast, Balanced, and High Precision. Balanced and High Precision decode larger previews and blend more fine detail for better small-subject ranking.
  • Added a scoring source picker: Embedded Preview for normal culling speed, or RAW Demosaic for slow, final-precision checks.
  • These scoring choices are now persisted in settings and restored when a catalog is reopened.

πŸ” Focus mask evolved into focus evidence

The focus mask is now much closer to an explanation overlay for the sharpness score, instead of a generic edge mask.

  • Focus evidence now chooses between AF center, AF neighborhood, saliency/subject region, or global detail, depending on which region best supports the score.
  • Sharp images can now relax the visual threshold when needed, so the overlay stays visible when RawCull says the image is sharp.
  • Aperture-aware blur gating and revised high-ISO handling make wildlife, portrait, and deep-DoF scenes behave more consistently.
  • The system now records richer diagnostics such as winning region, rendered region, overlay style, patch rankings, AF distance, spatial alignment, and confidence reason.

πŸ“Š Better burst ranking and comparison evidence

Burst ranking is now more nuanced when multiple images in a burst are very close.

  • Burst ranking now blends absolute sharpness with burst-relative sharpness when there is a meaningful spread inside the group.
  • Very small sharpness spreads no longer create artificial separation between near-identical frames.
  • High-confidence Keep Best decisions still require strong absolute sharpness evidence.
  • Comparison view now surfaces subject-sharpness rank and subject/global deltas against the burst winner.
  • Candidate Inspector now shows burst-relative sharpness alongside subject, global, and AF-detail breakdowns.

πŸ› οΈ Stability and persistence improvements

  • Burst analysis cache now invalidates when scoring intent, quality, source, thumbnail size, or related scoring parameters change.
  • Settings loading/saving was tightened so persisted scoring settings are not overwritten during initial load.
  • Shared memory cache diagnostics and counters were improved and covered by new tests.
  • Version metadata advanced to 1.9.4 / build 94.

πŸ§ͺ Tests

  • SharpnessScoringTests expanded heavily around RAW demosaic selection, focus-evidence region choice, visibility relaxation, patch ranking heuristics, focus-failure classification, aperture hints, ISO ramps, and concurrent scoring.
  • BurstAnalysisTests added coverage for burst-relative sharpness and comparison summaries.
  • New concurrency tests cover cache counters and settings persistence.

v1.9.0 β†’ v1.9.1

🏷️ Burst grid label legend

A legend panel now appears above the grouped burst grid so the burst badges are explained in-place.

  • The legend currently documents: Best frame found, Compare first, Needs manual review, Manual, Applied, Suggested best, and Check frame.
  • The legend is only shown while burst groups are visible in Similarity Grid, so it does not clutter the normal grid.

βœ… Batch selection and rating by visible badge

The standard culling grid can now batch-select visible thumbnails by their current badge labels.

  • Badge buttons show the visible count for each currently present burst/subject badge.
  • Clicking a badge button selects all matching thumbnails; holding ⌘ Command adds or removes them from the current selection.
  • A compact rating picker plus Apply button lets you rate the whole selection in one action.
  • These controls are hidden while burst groups are displayed.

πŸ”„ Burst mode now survives view changes

Burst analysis and burst mode are no longer discarded when moving between the main view modes.

  • Burst state is preserved when switching between Loupe, Grid, and Similarity Grid.
  • Burst-group rendering is now gated by showsBurstGroups, so grouped bursts are only shown where they belong: Similarity Grid.
  • This prevents grouped-burst UI from leaking into unrelated views while still preserving the active burst-analysis state.

🧹 Cleanup

  • Marketing version updated to 1.9.1.
  • Burst display logic was centralized through showsBurstGroups.
  • Stale internal markdown documents were removed from documents/.

πŸ§ͺ Tests

  • BurstAnalysisTests now verify the legend label set and ensure grouped-burst visibility survives view switching correctly.

v1.8.5 β†’ v1.9.0

βœ‹ Manual burst winner override

You can now override the algorithm’s automatic burst winner and pick the keeper yourself.

  • Set Manual Winner appears in burst comparison.
  • Manual winners are clearly labeled in both comparison and grid views.
  • Manual overrides are persisted in savedfiles.json, survive reloads, and are reattached when bursts regroup.
  • Keep Best respects the manual winner when one is active.

🧠 Safer burst culling decisions

Burst culling is now more conservative about when automatic actions are allowed.

  • Keep Best and Keep Top 2 are only available when the burst is safe for one-click culling and sharpness scores are present.
  • Medium-confidence bursts now push you toward comparing finalists first.
  • Low-confidence bursts ask for manual review instead of presenting an unsafe automatic choice.
  • Burst keyboard shortcuts now respect the same safety rules.

πŸ”Ž Better burst comparison workflow

Burst comparison gained a much richer inspection flow.

  • Added a Candidate Inspector side panel with ranking evidence, EXIF summary, candidate reasons/cautions, and rank tables.
  • Comparison view can focus on finalists, return to the active burst group, and clearly shows when a manual winner is active.
  • Comparison navigation and image-loading behavior were refined to make burst review smoother.

🧾 Clearer burst presentation in the grid

Burst headers and recommendation copy were rewritten to be easier to understand at a glance.

  • Burst headers now use clearer decision text such as Best frame found, Compare before deleting, Needs manual review, and Manual winner: frame X.
  • Human-readable explanations replace raw internal reasoning.
  • Thumbnail badges more clearly distinguish suggested frames, manual winners, and applied actions.

πŸ”„ Burst reanalysis

A new Reanalyze Bursts action lets you throw away stale cached analysis and recompute from scratch for the current catalog.

  • The action deletes the saved burst-analysis cache for the catalog before rerunning analysis.
  • It is disabled while grouping or analysis is already in progress.

🎭 Focus mask on demand

Focus mask generation is now done only when you actually ask for it.

  • Focus masks are generated when the overlay is toggled on, instead of being precomputed for every image.
  • In-flight mask work is cancelled if you toggle the overlay off.
  • Mask state resets cleanly when switching images.

πŸ” Zoom and inspection improvements

  • Zoom now preserves scale while navigating between images and recenters the pan offset.
  • RAW diagnostics presentation is now driven through RawCullViewModel.presentRawDiagnostics().
  • The main window now starts in detail-only mode.

πŸ› Fixes & internal improvements

  • Version metadata advanced through 1.8.6, 1.8.7, 1.8.8, 1.8.9, and 1.9.0, with build 90 at v1.9.0.
  • BurstAnalysisCache gained explicit deletion support for reanalysis.
  • Burst review states were expanded to track manual overrides and applied actions.
  • Logger identifiers were corrected in RequestThumbnail.
  • Burst presentation helpers were cleaned up for Swift 6.

πŸ§ͺ Tests

  • BurstAnalysisTests expanded for grouping, confidence handling, manual winners, reanalysis, and safe one-click culling.
  • New ComparisonCandidateInspectorTests cover ranking evidence and EXIF presentation.
  • CullingModelTests cover manual-winner persistence and pruning.
  • ComparisonGridNavigationTests, SharpnessScoringTests, and ZoomOverlayKeyActionTests gained regression coverage.

Version 1.8.5

RawCull Changelog β€” v1.8.1 β†’ 1.8.5

✨ Smarter Burst Culling

RawCull now includes an intelligent burst analysis workflow to help identify the best frames in fast sequences.

  • Groups visually similar burst shots automatically.
  • Recommends the best frame using sharpness, subject/saliency, AF evidence, and metadata stability.
  • Shows confidence levels: High, Medium, or Low.
  • Adds burst evidence and caution notes so you can understand why a frame was recommended.
  • Adds quick actions to Keep Best, Keep Top 2, Compare, or Undo.

πŸ” Improved Burst Comparison

The comparison view now supports burst-specific review.

  • Compare top burst candidates directly.
  • See analysis evidence while reviewing.
  • Use keyboard shortcuts for faster decisions.
  • Escape returns from burst comparison back to the active burst group.
  • Added keyboard controls for zoom, ratings, thumbnail source, focus mask, and focus points.

πŸ›  RAW Diagnostics

A new RAW diagnostics view helps troubleshoot camera-file parsing issues.

  • Opens diagnostics for the selected RAW file with Command-I.
  • Shows file identity, scan metadata, ImageIO details, parser traces, and embedded JPEG offsets.
  • Reports Sony and Nikon AF focus parser stages with explicit error messages.
  • Helps diagnose unsupported RAW layouts without relying on external tools.

πŸ“· Better Support for Newer Sony RAW Files

RAW preview and JPEG extraction are more reliable for newer Sony ARW files.

  • Improved support for ARW 6.0 / RA16-backed files such as A7V and A7R VI / ILCE-7RM6.
  • Reads embedded JPEGs directly before ImageIO attempts unsupported RAW decoding.
  • Detects full-size JpgFromRaw images stored in Sony SubIFD layouts.
  • Uses the largest embedded JPEG for zoom/extraction when available.
  • Bumped the full-size JPEG cache key to avoid stale cached results from older extraction logic.

πŸ”Ž Improved Nikon and Sony Parser Tracing

RAW parser internals are now easier to inspect and verify.

  • Added diagnostic parser paths for Sony embedded JPEG locations and AF focus location.
  • Added diagnostic parser paths for Nikon NEF embedded JPEG locations and AF focus location.
  • Nikon AFInfo parsing now reports accepted/unsupported AFInfo versions and failed parsing stages.
  • Parser location models are now Sendable-friendly for Swift 6 concurrency.

🏷 Better Thumbnail Labels

Sharpness badges are now easier to read.

  • Replaced numeric-only sharpness scores with friendly labels: Sharp, Good, Check, Soft.
  • Added burst recommendation badges such as BEST, BEST?, 2ND, Keeper, Top 2, and Rejected.
  • Added accessibility labels and clearer help text.

⚑ Faster Repeat Analysis

Burst analysis results are now cached.

  • Reopening the same catalog can reuse valid burst analysis data.
  • Cached results include similarity data, sharpness scores, saliency info, burst groups, and recommendations.
  • Cache validation checks catalog path, file count, file size, modification date, and analysis settings.

🧭 Zoom Overlay Improvements

The zoom overlay now better matches the current browsing mode.

  • Shows sharpness and saliency badges inside the zoom overlay.
  • Adds an in-overlay rating action bar.
  • Adds keyboard shortcuts for ratings, zoom, JPEG/RAW source toggle, focus mask, and focus points.
  • Uses horizontal navigation in grid-style views.
  • Uses vertical navigation in loupe-style viewing.
  • Navigation icons and help text now reflect the active direction.

πŸ“ Safer Saved State Location

RawCull now stores saved culling state in Application Support instead of the user’s Documents folder.

  • savedfiles.json now lives under ~/Library/Application Support/RawCull/.
  • This keeps app state out of the user’s document workspace and avoids unnecessary document/iCloud clutter.

πŸ“€ More Reliable Copy Operations

Copy/export handling is more robust.

  • Security-scoped folder access is now cleaned up reliably.
  • Copy cancellation and sheet dismissal now close active rsync work properly.
  • Progress callbacks now hop safely back to the main actor.
  • Removed an invalid empty environment entry from rsync process setup.

πŸ§ͺ Test Suite Cleanup and Coverage

The test suite was reorganized and expanded around current app behavior.

  • Added tests for burst analysis.
  • Added tests for culling model behavior.
  • Added tests for disk cache and scan admission.
  • Added tests for file sorting and EXIF formatting.
  • Added more Sony MakerNote parser coverage.
  • Added Nikon MakerNote parser diagnostics coverage.
  • Added RAW diagnostics tests.
  • Added A7R VI-style Sony embedded JPEG extraction tests.
  • Added zoom overlay and comparison grid keyboard shortcut tests.
  • Added thumbnail cancellation coverage.
  • Removed older duplicated or obsolete verification/test documents.

Version 1.8.1

RawCull Changelog β€” v1.8.0 β†’ 1.8.1

A stability and resource-hygiene release. Focus is on eliminating main-thread hangs in the zoom preview, tightening security-scoped resource lifecycles, and fixing actor-isolation gaps in the rsync copy path.


πŸ”’ Security-Scoped Resource Lifecycle

  • Catalog access is now scoped to the active catalog, not every catalog ever opened in the sidebar. Long sessions no longer accumulate stale security-scoped accesses.
  • Added explicit startSecurityScopedAccess(for:), stopSecurityScopedAccess(for:), and stopActiveSecurityScopedAccess() on RawCullViewModel.
  • Catalog cancellation and app shutdown both route through the same cleanup path; deinit is now a last-resort fallback rather than the primary stop point.
  • Picker flow simplified β€” view no longer manually pairs start/stop calls.

⚑ Zoom Preview β€” No More Main-Thread Hangs

  • ZoomPreviewHandler sidecar JPG decode moved off the MainActor into a Task.detached(priority: .userInitiated).
  • Opening the zoom overlay on a large Sony JPEG no longer blocks the UI while ImageIO opens and decodes the file.
  • Cancellation is now checked between every async step, so dismissing the overlay early stops in-flight work cleanly.
  • loadCGImage(from:) and the disk-cache accessor are marked nonisolated to make the off-main path explicit.

πŸ› οΈ Rsync Copy Path (ExecuteCopyFiles)

  • Security-scoped URLs for source and destination are now paired with a single, idempotent cleanup() call covering: rsync success, launch failure, user close/cancel, sheet dismissal, and deinit.
  • Progress streaming callback hops to @MainActor before touching progressContinuation, removing a latent actor-isolation race that strict concurrency would flag.
  • Progress continuations and streaming handler state are finished/cleared exactly once.

🧡 Catalog Loading & Cancellation

  • startCatalogLoad(for:) short-circuits cleanly when the active catalog already has live security-scoped access β€” no redundant cancel/restart cycles.
  • cancelCatalogLoad() now also clears currentselectedSource and stops active security-scoped access, preventing a new load from racing previous cleanup.

πŸ§ͺ Tests

  • New RawCullViewModelSecurityScopeTests covering start/stop pairing, re-selection no-op behavior, and cancellation cleanup.
  • ThumbnailProvider* tests updated for the refreshed memory and cancellation surface.

🧹 Cleanup

  • Removed legacy documents/ver176.md; added documents/ver181.md capturing the v1.8.0 review findings actually shipped in this release.
  • Minor follow-ups in RawCullViewModel+Catalog, SharpnessScoringModel, and project settings.

Version 1.8.0

RawCull Changelog β€” v1.7.4 β†’ 1.8.0

RawCull has received improvements to image comparison, zoom review, rating workflow, thumbnail responsiveness, cache reliability, sharpness/similarity behavior, and release/test tooling. Version 1.8.0 is submitted for update on Apple App Store.

πŸš€ v1.8.0

πŸ–ΌοΈ New Comparison View

  • Added a dedicated comparison view for reviewing selected images side by side.
  • Supports comparing up to four selected thumbnails.
  • Added keyboard navigation inside the comparison view.
  • Added zoom and pan controls for closer inspection.
  • Added focus mask and focus point overlays while comparing images.
  • Added support for switching between thumbnail preview and extracted JPEG source.
  • Added rating controls directly inside comparison mode.

πŸ” Improved Zoom Review

  • Improved the full-window zoom overlay experience.
  • Added previous/next image navigation in zoom view.
  • Added visible rating badge for the current image.
  • Added keyboard shortcuts for zooming and switching image source.
  • Added tests for zoom overlay navigation and behavior.

⚑ Faster and More Responsive Thumbnail Handling

  • Improved cancellation of thumbnail and JPEG extraction work.
  • Switching or cancelling catalogs should now feel more responsive because old ImageIO work is cancelled earlier.
  • Sony and Nikon thumbnail/JPEG extraction now check for cancellation before expensive decode work.
  • Improved thumbnail loader slot accounting so cancelled requests do not consume concurrency capacity.
  • Added regression tests for thumbnail loader cancellation and concurrency behavior.

🎯 Sharpness and Similarity Reliability

  • Similarity and burst actions now wait for in-progress sharpness scoring when needed.
  • Prevents similarity/burst workflows from running before required sharpness scores are ready.
  • Added test coverage for concurrent sharpness scoring behavior.

🧠 Cache and Memory Improvements

  • Improved cache replacement accounting for memory and grid thumbnail caches.
  • Improved test isolation around shared cache state.
  • Added memory diagnostics checklist for validating large-catalog behavior.
  • Improved cache-related concurrency tests.

⭐ Rating Workflow Improvements

  • Added reusable rating controls and rating badge UI.
  • Rating actions are now available in more review contexts, including comparison and zoom workflows.
  • Ratings support reject, keeper, and 2-5 star values.

πŸ› οΈ Build and Test Tooling

  • Added shared Xcode scheme.
  • Added dedicated test plans:
    • Smoke
    • Full test suite
    • Performance
  • Updated Makefile test commands.
  • Improved documentation for test architecture and release validation.
  • Pinned Swift Package dependencies to exact versions for more predictable builds.

πŸ“· Camera and Image Extraction Notes

  • Continued improvements to Sony ARW thumbnail extraction.
  • Added cancellation-aware extraction paths for Sony and Nikon raw/JPEG preview handling.
  • Nikon support remains experimental.

πŸ“ Latest Commit After v1.8.0

πŸ“š Documentation

  • Updated README release information and project description.

Version 1.7.4

RawCull Changelog β€” v1.7.0 β†’ 1.7.4

Version 1.7.4 is submitted for update on Apple App Store. RawCull 1.7.0 focuses on faster zoom previews, better cache management, and more reliable culling-data saving.

✨New

  • Full-size JPG disk cache. The zoom view now caches the full-resolution embedded JPEG to disk (~/Library/Caches/no.blogspot.RawCull/FullsizeJPGs/), so re-opening a previously zoomed photo is instant instead of re-extracting from the ARW.
  • “Cache JPGs” button in the catalog sidebar lets you pre-warm the full-size JPG cache for an entire catalog in one go (uses a new ScanAndExtractJPGs actor with progress + ETA).
  • JPG cache controls in Settings β†’ Cache. A new section shows the on-disk size of the full-size JPG cache and adds a Prune action (with confirmation).

πŸ”„ Changed

  • Unified culling grid. The standard grid and the Similarity/Burst grid now share one CullingGridView. Selection, scroll-to-selection, rating filter, the “N selected” status, and the three progress overlays now behave identically in both views.
  • Redesigned Scan Stats sheet β€” clearer layout for the per-catalog statistics.
  • Smoother progress ETA. The “Estimated time to completion” label is now “Estimated time left”, and the countdown no longer jitters upward when a slow file briefly inflates the average.
  • Cleaner toolbar mode switching. Loupe / Grid / Similarity / Rated buttons go through a single selectMainViewMode(...) helper for consistent state reset.
  • Saved-files persistence moved out of the main view model into a dedicated CullingModel, with debounced JSON writes (350 ms) to avoid hammering disk on rapid rating changes.

πŸ“¦ Under the hood

  • New concurrency tests for SharedMemoryCache and FocusMaskModel; revisions to thumbnail-cache eviction (CacheDelegate, CachedThumbnail) for safer cross-actor access.
  • Catalog load/cancel path reworked β€” switching catalogs now reliably cancels in-flight scan, thumbnail, JPG-extract, and sharpness/similarity work.
  • Image extractors (SaveJPGImage, JPGSonyARWExtractor, JPGNikonNEFExtractor) tightened.

Version 1.7.0

RawCull Changelog β€” v1.6.9 β†’ 1.7.0

Version 1.7.0 is submitted for update on Apple App Store. RawCull 1.7.0 focuses on faster zoom previews, better cache management, and more reliable culling-data saving.

✨ Highlights

  • Faster zoom preview loading with a new full-size JPG disk cache.
  • Better cache controls in Settings, including cache size visibility and manual JPG cache pruning.
  • More reliable culling persistence when rating, batch-rating, and saving sharpness results.
  • Improved diagnostics for understanding memory pressure and cache evictions.

✨ What’s new

Full-size JPG disk cache for zoom previews

RawCull now caches extracted full-size JPEG previews on disk. Reopening zoomed images is faster, and the app avoids repeating the same extraction work for files you have already inspected.

JPG cache controls in Settings

The Cache settings screen now shows the size of the full-size JPG cache and adds a dedicated Prune JPG Cache action, making it easier to reclaim disk space when needed.

πŸ”„ Improvements

More accurate cache estimates

Cache estimates in Settings are now based on live cache usage when available, giving a more realistic idea of how many images fit in memory and in the grid cache.

More consistent culling grid behavior

The standard grid and similarity grid now share the same core grid implementation. This improves consistency across:

  • multi-selection
  • keyboard-driven rating
  • burst-group display
  • progress overlays
  • scroll-to-selection behavior

More reliable rating and scoring saves

Rating updates, batch rating changes, threshold-based culling, and persisted sharpness/saliency results now go through a centralized culling model with coalesced saves. This reduces the risk of stale or out-of-order writes during fast culling sessions.

Safer persistence pipeline

Saved-file models are now concurrency-safe, and JSON writes are serialized through a shared writer to improve stability.

⚑ Diagnostics and Cache Monitoring

Richer memory diagnostics

Memory diagnostics now break out evictions by cache type, making it easier to see whether pressure is coming from the main memory cache or the grid cache.

Better cache visibility

RawCull now exposes more current cache usage details in Settings, including memory cache and grid cache counts and sizes.

πŸ“¦ Under the Hood

  • Internal cache-management cleanup to support the new zoom-preview cache.
  • Concurrency and isolation fixes in supporting code paths.
  • Documentation and internal review notes updated during the 1.7.0 cycle.