Updates, release notes, and technical write-ups about RsyncUI.
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
Zas 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
FileRecordconvenience 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
Zactual-pixels inspection in comparison navigation.
π οΈ Maintenance
- Aligned project versioning across build settings and release branches.
- Added a
test-performanceMakefile 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
ImageSourceToggleViewwith keyboard shortcut support ZoomPreviewHandlersignificantly expanded to manage source switchingZoomOverlayViewupdated with key-action routingFullSizeJPGDiskCacheextended to support the toggle flow- New
DiskCacheAndScanAdmissionTestscovering 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
BurstReviewQueueCountsvalue type exposed onRawCullViewModel - 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
SimilarityGridSelectionViewtoolbar β live counts shown inline; filter resets to.allon Exit Groups - Auto-sharpness scoring toggle removed from toolbar; scoring now triggered automatically via
runWithAutoScoringbefore 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 navigationCullingGridRenderCacheβ per-cell image caching (keyed byCullingGridRenderCacheKey)CullingGridProgressOverlayβ loading progress overlay- Cell data flow cleaned up:
isSelected,ratingValue,ratingDisplay,ratingColornow passed directly toImageItemView, removing ViewModel look-ups inside the cell
ποΈ Refactored β ComparisonGridView decomposed and redesigned
ComparisonGridDisplayStateβ display/layout state extracted from the viewComparisonGridImageCoordinatorβ 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 BurstComparisonEvidenceViewpromoted 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;ThumbnailErrortyped 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 internalFileItem) - Histogram:
HistogramCalculator(replaces the internalCalculateHistogram) - β¨ 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
FocusPeakingControlsViewand relatedBurstAnalysisModelsdisplay-only properties removed (moved to package / no longer needed)CacheSettingsTabsimplified β removed staleshowResetConfirmation,showSaveSettingsConfirmation, andcacheConfigstate variablesSharedMemoryCacheβ 34 lines of redundant code removedSettingsViewModelβ dead state and unused helpers prunedImageItemViewβ substantial simplification following the cell data-flow refactorSharedMainToolbarContentβ 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) βBurstWinnerOverrideexact-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
SharpnessScoringTestsexpanded heavily around RAW demosaic selection, focus-evidence region choice, visibility relaxation, patch ranking heuristics, focus-failure classification, aperture hints, ISO ramps, and concurrent scoring.BurstAnalysisTestsadded 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
BurstAnalysisTestsnow 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.
BurstAnalysisCachegained 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
BurstAnalysisTestsexpanded for grouping, confidence handling, manual winners, reanalysis, and safe one-click culling.- New
ComparisonCandidateInspectorTestscover ranking evidence and EXIF presentation. CullingModelTestscover manual-winner persistence and pruning.ComparisonGridNavigationTests,SharpnessScoringTests, andZoomOverlayKeyActionTestsgained 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.jsonnow 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:), andstopActiveSecurityScopedAccess()onRawCullViewModel. - Catalog cancellation and app shutdown both route through the same cleanup path;
deinitis 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
ZoomPreviewHandlersidecar JPG decode moved off the MainActor into aTask.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 markednonisolatedto 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, anddeinit. - Progress streaming callback hops to
@MainActorbefore touchingprogressContinuation, 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 clearscurrentselectedSourceand stops active security-scoped access, preventing a new load from racing previous cleanup.
π§ͺ Tests
- New
RawCullViewModelSecurityScopeTestscovering 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; addeddocuments/ver181.mdcapturing 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
ScanAndExtractJPGsactor 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
SharedMemoryCacheandFocusMaskModel; 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.