Skip to content

Releases: L0stInFades/Afterglow

Afterglow v2.0.0

Choose a tag to compare

@L0stInFades L0stInFades released this 12 Feb 11:18

Afterglow v2.0.0 — Stability & Smoothness Hardening

长期运行稳定性大版本,消除崩溃/OOM 风险,改善动画精度。

Changes

  • D2D 设备丢失自动恢复 — GPU 驱动重置/显示模式切换后自动重建渲染链,不再黑屏
  • 全尺寸图片缓存 LRU 淘汰 — 256MB 上限,浏览大量高分辨率图片不再 OOM
  • 抖动动画精度保护editModeTime_ fmod 包装,长时间编辑模式不再抖动异常
  • 缩略图请求失败清理 — 解码失败的路径可被重试,不再永久卡住
  • 删除 4 个渲染器死代码方法 — 减少无用 GPU 开销
  • 快速滚动检测灵敏度提升 — 平滑系数 0.6/0.4,~2-3 帧响应
  • 窗口图标修复 — 标题栏现在正确显示应用图标

Download

下载 afterglow.exe 即可运行,无需安装。

v1.5.2 — Scan Pipeline Jank Fix

Choose a tag to compare

@L0stInFades L0stInFades released this 11 Feb 14:28

What's Changed

Eliminates the visible stutter/jank during startup scan (blue progress bar phase).

Performance Fixes

  • Freeze gallery during scan — no more O(n) full rebuilds every 200 images; gallery data is rebuilt once when scan completes
  • Remove intermediate flush — eliminates ~25 O(n log n) sorts on the scan thread
  • Scan thread priority lowered to BELOW_NORMAL so rendering thread gets CPU priority
  • 60fps throttle replaces 100% CPU spin during scan (~5% CPU usage now)
  • Async LoadPersistentThumbs — first frame renders 5-50ms earlier

UX Polish

  • Smooth sinusoidal progress bar — silky ease-in-out sweep replaces the old jumpy bar

v1.5.1-tuning

Choose a tag to compare

@L0stInFades L0stInFades released this 11 Feb 10:17

v1.5.1-tuning — Robustness Polish

v1.5.0 性能优化的健壮性打磨,不加新功能,只修复异常安全、线程安全、资源泄漏等隐患。

Fixes

  1. ThreadPool 异常安全task.fn() 用 try-catch 包裹,memory order 从 relaxed 升级为 acq_rel
  2. BackgroundModeGuard RAII — THREAD_MODE_BACKGROUND BEGIN/END 配对用 RAII 替代手动调用
  3. Tier 2 解压移到锁外 — ~0.3ms 解压不再持有 cacheMutex_;CompressorGuard/DecompressorGuard 防句柄泄漏
  4. Tier 2 LRU 驱逐 — 满时驱逐最旧条目,不再直接拒绝新条目
  5. SetViewSize 布局缓存失效 — 窗口 resize 后强制下帧重算,修复 HitTest 点击错位
  6. QPF 移到 Initialize — QueryPerformanceFrequency 从每帧调用改为初始化一次
  7. 滚动指示器 NaN 防护 — 3 处除零位置加 > 0.01f 守卫
  8. RecordFolderVisit 线程安全 — folderProfiles_ 读写加 scanMutex_ 保护
  9. LoadFolderProfiles 防御解析 — count 上限 100k + fread 返回值检查

Afterglow v1.5.0 — Unfair Scheduling & Tiered Cache

Choose a tag to compare

@L0stInFades L0stInFades released this 11 Feb 09:49

What's New

借鉴 vivo OriginOS 三大核心技术(不公平调度、双渲染架构、Ledger 内存账本),为 Afterglow 引入 5 项性能优化:

1. 不公平线程调度

Worker 线程根据任务优先级动态设置 OS 线程优先级:可见缩略图解码获得 ABOVE_NORMAL,预取任务降为 BELOW_NORMAL。CPU 繁忙时,可见内容优先调度。

2. 帧预算管理(双渲染架构启发)

内容渲染(缩略图网格)受 12ms 预算约束,Glass 动画覆盖层永远不会被跳过。极端滚动场景下,Tab Bar 等动画始终丝滑。

3. Tier 2 压缩缓存(Ledger 启发)

GPU 缓存驱逐的缩略图不再丢弃,而是压缩到 CPU RAM(XPRESS+Huffman)。再次需要时解压恢复 ~0.3ms,远快于重新磁盘解码 ~5ms。快速来回滚动体验大幅提升。

4. I/O 优先级分层

预取任务进入 THREAD_MODE_BACKGROUND,降低 I/O 和内存优先级,不与可见缩略图争抢磁盘带宽。HDD 用户受益明显。

5. 持久化文件夹访问画像

跨会话记录文件夹访问频率,冷启动时高频相册优先扫描加载。


Full Changelog: v1.4.0...v1.5.0

Afterglow v1.4.0 — ThreadPool & Architecture Cleanup

Choose a tag to compare

@L0stInFades L0stInFades released this 11 Feb 05:40

What's New

High-Performance ThreadPool

替换所有散装线程管理,统一为自研高性能线程池。

  • 3 优先级车道: High / Normal / Low,visible 缩略图走 High 优先解码
  • Spin-Yield-Wait 空闲策略: spin 64 次 → _mm_pause yield 256 次 → CV wait,减少 ~90% syscall 开销
  • Cache-line 对齐: alignas(64) 防止 false sharing
  • 批量提交: SubmitBatch 一次加锁 + notify_all,减少唤醒开销
  • 自动线程数: hardware_concurrency() - 1(保留一个核给渲染线程)

ImagePipeline 重构

  • 5 个散装线程(1 load + 4 thumbnail workers)→ 1 个统一线程池
  • 3 个 mutex(requestMutex_ / visibleMutex_ / queueMutex_)→ 1 个 cacheMutex_
  • readyQueue: vector::erase(begin, begin+n) O(n) → deque::pop_front() O(1)
  • 消除嵌套锁(requestMutex_ → visibleMutex_)死锁风险

Architecture Cleanup

删除 19 个从未使用的空壳文件(-905 行):

  • D3D12Renderer(D2D 底层已走 D3D11 硬件加速,D3D12 对 2D 查看器无收益)
  • TextureManager / MipMapGenerator.cpp / Viewport.cpp(真实代码在 Direct2DRenderer.cpp)
  • image_processing 全模块(FilterPipeline, ColorCorrection, SharpenEngine, BatchProcessor, RAWDecoder)
  • MainWindow / MetadataPanel(孤儿 UI 空壳)
  • CacheManager::TextureCache 类声明
  • 去掉 d3d12 链接依赖

Glass Folder Header

文件夹详情页标题从不透明覆盖改为 Liquid Glass 毛玻璃渲染。


Full Changelog: v1.3.0...v1.4.0

Afterglow v1.3.0 — Album Management & Transition Perf

Choose a tag to compare

@L0stInFades L0stInFades released this 10 Feb 16:34

Album Edit Mode (iOS Jiggle Management)

  • Glass 编辑/完成 toggle at top-right of Albums tab
  • Per-card sin-wave jiggle: sin(2π × 5Hz × t + φᵢ) × 1.5° with random phase offset, zero spring overhead
  • Red delete badge on every album — spring pop-in (stiffness=600, damping=25)
  • Delete flow: badge tap → spring shrink 1→0 (400/30) → RemoveAlbumFolder in-memory surgery → no rescan
  • + add card at grid end → folder dialog → StartFullScan
  • Escape / tab switch auto-exits edit mode

Zero-Rescan Delete Architecture

hiddenAlbumPaths_.push_back(path) → SaveHiddenAlbums()
lock(scanMutex_) { scannedResults_.erase(remove_if(parent == path)) }  // O(n) single-pass
SetImagesGrouped(results)  // rebuilds Photos + Albums in one call
SaveScanCache(results)     // binary persist, single fwrite
  • FilterHiddenAlbums: unordered_set<wstring> construction O(k), per-image lookup O(1), total O(n+k)
  • Hidden albums survive rescans and restarts via %LocalAppData%/UltraImageViewer/hidden_albums.txt

Folder Transition Stutter Fix

Root cause: RequestThumbnail performs synchronous ID2D1DeviceContext::CreateBitmap (GPU upload) from persistent cache — up to 200 per frame. During folder-enter transition, RenderFolderDetail hits this path for every visible + prefetch cell on the first frame, causing 30-50ms frame spikes.

Solution — three-part pipeline deconfliction:

  1. Fast-scroll override during transition: isFastScrolling_ = true while folderTransitionActive_ — both RenderAlbumsTab and RenderFolderDetailRenderImageGrid use GetCachedThumbnail only (hash lookup, no GPU work)
  2. Album cover fast-path: RenderAlbumsTab now gates RequestThumbnail vs GetCachedThumbnail on isFastScrolling_ — covers are already in memory cache so display is unaffected
  3. Decode pre-warming: EnterFolderDetail submits first 40 thumbnail requests before the spring animation starts — worker threads decode in parallel during the ~300ms slide, thumbnails land in readyQueue_ and get flushed on the first steady-state frame

Result: transition frames drop from ~40ms to <4ms. Thumbnails appear instantly when the slide animation completes.

Text Overflow Fix

  • albumTitleFormat_ configured with DWRITE_WORD_WRAPPING_NO_WRAP + DWRITE_TRIMMING_GRANULARITY_CHARACTER
  • Long album names truncated with ellipsis glyph at card boundary — photo count always visible

Build

  • Executable: afterglow.exe (x64, Release, /O2 /GL /LTCG)

Afterglow v1.1.0 — Albums & Smart Filter

Choose a tag to compare

@L0stInFades L0stInFades released this 09 Feb 10:36

What's New

Smart Image Filtering

  • Images smaller than 100KB are automatically filtered out (icons, favicons, UI assets)
  • Common asset directories are skipped during scanning (icons, thumbnails, sprites, etc.)

iOS-Style Tab Navigation

  • Bottom tab bar with Photos and Albums tabs
  • Independent scroll state per tab

Albums View

  • Folder-based album cards with cover images
  • Responsive grid layout — adapts columns to screen width
  • Click any album to enter its folder gallery

UI Improvements

  • Rounded corner thumbnails and album cards
  • Modern spacing and typography
  • Fixed header overlay (content scrolls behind headers)
  • Pill-shaped back button in folder detail view

Bug Fixes

  • Fixed album card click opening viewer instead of folder detail
  • Fixed scrolling content overlapping header elements

Full Changelog: v1.0.0...v1.1.0

Afterglow v1.0.0

Choose a tag to compare

@L0stInFades L0stInFades released this 09 Feb 07:30

Afterglow v1.0.0

The light that lingers after the moment has passed.

Features

  • Gallery view with automatic year/month grouping
  • Ctrl+D to curate album folders — multiple folders merged into one timeline
  • Ctrl+O to open image files
  • Drag & drop support
  • Direct2D hardware-accelerated rendering with spring animations
  • Background async scanning, lazy thumbnail loading
  • Album folder list persisted across sessions

Formats

JPG / PNG / BMP / GIF / TIFF / WebP / HEIC / AVIF / ICO / JXR

Download

Grab Afterglow.exe below. Portable — no installation needed.