Windows 上的本地图片 Cover Flow 浏览器。选一个文件夹,全屏翻看里面的图片。
StimFlow 用 Direct3D 11 画一条三维卡片带:中间一张正面显示,两侧按透视后退、绕 Y 轴旋转、缩小并淡出,带阴影和倒影。图片用 Windows Imaging Component 解码,按原始宽高比生成卡片,不裁切。
程序是一个静态链接的 exe。启动时选文件夹,之后只读这个文件夹;不建图库数据库,不联网,不写注册表。
版本 0.1.0 · Windows 10 1809+ / x64 · 约 0.5 MB
StimFlow 只做一件事:把一个本地文件夹里的图片以 Cover Flow 形式全屏展示。
启动后选一个文件夹,程序递归扫描支持的图片格式,按文件名自然排序。中间的卡片是当前图片,两侧是前后图片;点击中间卡片进入查看模式,可以旋转、缩放、平移。图片文件始终以只读方式打开。
适合照片文件夹、素材库、壁纸目录、截图收藏,也适合展会或展台循环播放。它不做图库整理、去重、人脸识别、云同步,也不播放视频。
持久化数据只有 exe 同目录的 StimFlow.ini 和可选的缩略图缓存。缓存默认放在非系统盘,用 DPAPI 加密,只保存缩略图;找不到可写盘时只用内存。
- Cover Flow 布局:透视、Y 轴旋转、缩放、透明度衰减、双层阴影、倒影、边缘淡出;没有深度缓冲,按
|delta|从远到近绘制。 - 统一视觉大小:按统一对角线缩放,所有卡片底边对齐;横图、竖图不会一个大一个小。
- 任意宽高比:卡片宽度 = 高度 × 图片宽高比,不裁切。
- 缩略图窗口:内存里保留中心 ±8 的纹理,滑出窗口即释放;中心 ±1 为 512×768,远景为 256×384。
- 排序与循环:按文件名自然排序;首尾相接;每次启动随机选中心。
- 翻页:弹簧过渡、连续输入排队、中心卡轻微 Y 轴翻转;鼠标拖拽带 fling,键盘/手柄按住连续翻页,松开后弹簧收敛。
- 自动轮播:5 秒间隔;鼠标进入卡片带暂停,空格/手柄 A 手动暂停。
- 标题:GDI 画到 DIB,以 RGB 最大值作为 alpha,中间卡片下方显示文件名(去扩展名)。
- 进入:点击中心卡片或手柄 X;保持原始宽高比,对角线不超过屏幕短边的 70%。
- 旋转:拖动或左摇杆;yaw 无限,pitch ±85°;双击/X 重置。
- 缩放/平移:滚轮或 LT/RT,1×–4×;放大后拖动或左摇杆平移,范围限制在图片边界内。
- 纹理分级:进入时解码 2048 上限的基础纹理;首次放大(滚轮或 RT)解码 8192 上限的原图;缩放时按 512×512 分块上传,只保留可见分块(可见集淘汰)。
- 释放:退回 1× 释放分块与原图 CPU 缓冲;退出查看模式释放基础/提示纹理,并调用 DXGI Trim。
- 分级退出:Esc/右键/手柄 B,先回 1×,再退回 Cover Flow。
- XInput:未连接时 500 ms 轮询,连接后 16 ms;D-pad/左摇杆翻页,A 暂停,B 退出,X 进入查看模式,Y 静音。
.scr模式:复用上次文件夹;任意键、鼠标移动 >20 px、点击、滚轮或手柄输入退出;不写缓存、不播放音效。
| 类别 | 使用 |
|---|---|
| 语言 | C++20 |
| 编译器 | MSVC(Visual Studio 2022/2026 Build Tools) |
| 图形 | Direct3D 11(feature level 11_0/10_1/10_0)、DXGI(flip-model 交换链、IDXGIDevice3::Trim)、HLSL Shader Model 5.0 |
| 着色器编译 | fxc 构建期编译成头文件 |
| 窗口/系统 | Win32、COM(STA)、WRL ComPtr、IFileOpenDialog、Shell、GDI |
| 图像 | Windows Imaging Component(WIC)、EXIF 方向、BGRA→RGBA |
| 输入 | XInput |
| 音频 | winmm PlaySound,WAV 以 RCDATA 嵌入 |
| 加密/哈希 | Windows DPAPI(CryptProtectData)、BCrypt SHA-256 |
| 构建 | CMake 3.25+、MSVC、Windows SDK 10.0.17763+、静态 CRT(/MT) |
| 生成器 | Visual Studio 或 Ninja |
| 调试 | D3D11 debug layer(Debug 构建) |
| 脚本 | PowerShell 5.1、vswhere(构建脚本) |
| 打包 | Compress-Archive |
| 线程 | 单线程 Win32 消息循环;WIC 解码和 D3D 纹理创建在 UI 线程同步执行 |
| 第三方依赖 | 无 |
| 版本控制 | Git |
实现细节和取舍见 docs/DESIGN.md。
- 只支持 WIC 内置格式:JPEG/PNG/BMP/GIF(首帧)/TIFF/ICO;HEIC/WebP/AVIF/RAW 会被跳过。
- 只使用主显示器,窗口是无边框全屏;多显示器扩展暂不支持。
- 不支持视频;GIF 只显示第一帧。
- 缩略图缓存没有容量上限,长期浏览大量图片会持续增长。
- 没有处理 D3D 设备丢失(TDR);设备重置后程序会报错退出。
| 项目 | 要求 |
|---|---|
| 操作系统 | Windows 10 1809(build 17763)或更新;64 位 |
| 图形 | 支持 Direct3D 11 的显卡(2012 年之后的集成显卡基本都支持) |
| 磁盘 | 程序本身约 0.5 MB;缓存视图片数量而定 |
| 运行库 | 无;exe 静态链接 |
| 手柄 | 可选;标准 XInput 手柄(Xbox 360 / Xbox One / Series 手柄等) |
目前只支持主显示器全屏;多显示器扩展模式暂不支持。
- 解压发布包到任意目录(不要放在需要管理员权限的
Program Files下,除非你确实要这样做)。 - 双击
StimFlow.exe。 - 第一次启动会弹出文件夹选择框;选中图片文件夹即可。
- 程序会在 exe 同目录写入
StimFlow.ini,记住上次文件夹和缓存设置。
没有安装程序,也没有卸载程序。删除 exe、StimFlow.ini 和缓存文件夹即可完全移除。
tools/install-hotkey.ps1 会在桌面创建一个 Ctrl+Alt+G 快捷方式,指向当前 exe。适合把 StimFlow 当成随时呼出的展示器。
把 StimFlow.exe 复制/改名为 StimFlow.scr,右键选择“安装”,或直接放进 C:\Windows\System32(需要管理员权限)。屏保启动时会使用上次选择的文件夹,不弹选择框;任意键盘、鼠标或手柄输入退出。
- 启动后选择文件夹。
- 程序递归扫描支持的图片;没有图片时会提示并退出。
- 中间卡片是当前图片,下方是文件名;左右两侧是前后图片。
- 等待 5 秒会自动翻页;也可以立即用键盘、鼠标或手柄操作。
图片很多时,第一次进入某个文件夹会边浏览边解码缩略图。开启磁盘缓存后,第二次打开同一文件夹会明显更快。
| 操作 | 功能 |
|---|---|
← / → |
上一张 / 下一张 |
| 鼠标滚轮 | 上一张 / 下一张 |
| 鼠标左键拖动 | 在任何位置(包括图片上)拖动卡片墙;松开后惯性滑动并吸附 |
| 鼠标左键单击 | 单击中心卡片进入查看模式;拖动不会误触发 |
空格 |
暂停 / 继续自动轮播 |
M |
静音 / 取消静音(仅本次运行) |
Esc / Alt+F4 |
退出 |
| 点击中间卡片 / 手柄 X | 进入查看模式 |
| 鼠标移到卡片带内 | 暂停自动轮播 |
| 鼠标移到上下空白区 | 恢复自动轮播 |
| 操作 | 功能 |
|---|---|
| D-pad 左 / 右、左摇杆 | 轻推 / 短按翻一张;按住连续翻页(与键盘重复速度一致) |
| A | 暂停 / 继续自动轮播 |
| X | 进入查看模式 |
| B | 退出(查看模式下先退回 Cover Flow) |
| Y | 静音 / 取消静音 |
手柄未连接时每 500 ms 轮询一次;连接后每 16 ms 轮询一次。
点击中间卡片进入查看模式。
- 图片按原始比例显示,对角线不超过屏幕短边的 70%;超大图片会等比缩小到 90% 屏幕以内。
- 按住鼠标左键拖动:水平方向旋转(无限),垂直方向俯仰(限制 ±85°)。
- 手柄:左摇杆旋转;X 重置旋转。
- 双击:旋转角度归零。
- 滚轮向上 / RT:进入缩放。
Esc/ 右键 / 手柄 B:退回 Cover Flow。- 进入后会显示 2 秒提示:
旋转 拖动/左摇杆 · 缩放 滚轮/LT·RT · 重置 双击/X · 返回 Esc/B;提示淡入淡出。 - 查看模式完全不显示标题,只保留图片和 2 秒操作提示。
- 滚轮继续放大 / 缩小,范围 1×–4×;手柄 RT 放大、LT 缩小;滚轮和扳机都走平滑插值,不会一卡一卡地跳。
- 按住左键拖动:平移;左摇杆同样可平移。平移被限制在图片边界内,不会拖出空白。
- 缩放状态下不旋转。
- 滚轮缩小到 1× / LT 缩到 1×:自动回到旋转状态。
Esc/ 右键 / 手柄 B:先回到 1× 旋转状态;再按一次退回 Cover Flow。
- 进入查看模式时先解码基础纹理(长边上限 2048);首次滚轮放大时再解码原图(长边上限 8192),保留在 CPU 内存。
- 缩放后只把当前可见区域切成 512×512 分块,按需上传为 D3D 纹理;离开视野的分块立即释放(可见集淘汰,不是 LRU)。
- 退回 1× 时释放分块纹理和原图 CPU 缓冲;退出查看模式或退出程序时再释放基础纹理和提示纹理。
- 查看模式不写任何磁盘文件;只有缩略图缓存会在用户选择“保留”时留在磁盘上。
StimFlow 使用 Windows Imaging Component(WIC)内置解码器,支持:
-
JPEG(
.jpg/.jpeg/.jpe/.jfif) -
PNG(
.png) -
BMP(
.bmp/.dib) -
GIF(
.gif,只取第一帧) -
TIFF(
.tif/.tiff,多页取第一页) -
ICO(
.ico) -
自动应用 EXIF 方向(手机竖拍照片不会横着显示)。
-
不支持 HEIC / HEIF、WebP、AVIF、RAW 等格式;这些文件会被静默跳过,不会报错。
-
扫描是递归的,按文件名自然排序(
2.jpg排在10.jpg前面)。 -
同一个文件夹里混排横图、竖图、方图、超宽图都可以。
| 层级 | 内容 | 生命周期 |
|---|---|---|
| 内存 | 当前窗口 ±8 张缩略图纹理;查看模式的基础纹理 / 分块纹理 / 原图缓冲 | 分块/原图缓冲在退回 1× 时释放;基础/提示纹理在退出查看模式时释放;缩略图纹理在退出程序时释放 |
| 磁盘 | 512 级别的缩略图 | 用户选择“保留”时跨启动保留 |
磁盘缓存只保存缩略图,不保存原图、查看模式的 4× 分块或旋转结果。
- 程序会选择一个非系统盘的固定磁盘中剩余空间最大的那个,创建
StimFlowCache文件夹,例如D:\StimFlowCache。 - 如果找不到可写的非系统固定磁盘,自动退回仅内存缓存,不写磁盘。
- 可以在
StimFlow.ini的cache_folder指定其他目录;留空则使用上面的自动选择。
- 每个缓存文件单独用 Windows DPAPI(当前用户)加密;换 Windows 用户或把文件拷到别的机器上都无法直接读取。
- 文件名 = 规范化完整路径(小写)的 SHA-256;缓存目录里不出现明文文件路径。
- 文件头包含 magic、版本、修改时间、文件大小、宽高和数据长度,且这些内容也在加密范围内。
- 原图修改时间或大小变化时,对应缓存自动失效并重新生成。
如果缓存启用,每次正常退出都会弹出缓存对话框,即使本次没有新写入:
| 按钮 | 行为 |
|---|---|
| A. 保留缓存并退出 | 保留所有缓存,下次启动更快 |
| B. 清除本次缓存 | 只删除本次运行新增的缓存文件 |
| C. 清除全部缓存 | 清空整个 StimFlowCache 文件夹里的 .sfc / .tmp 文件 |
- 关闭对话框或按
Esc等同于“保留并退出”,不会误删。 - 键盘直接按
A / B / C选择三个选项。 - 手柄:
A保留、B清除本次缓存、Y清除全部缓存(手柄没有 C 键,用 Y 代替 C 选项)。 - 缓存被禁用(
cache_enabled=0)时不弹窗。 .scr屏保模式不写缓存,也不弹窗。
编辑 StimFlow.ini:
[options]
cache_enabled=0程序将只使用内存缓存,不创建缓存目录,退出时也不会询问。
- 不联网、不上传、不分析图片内容。
- 不写注册表、不装服务、不创建后台进程。
- 不记录浏览历史;
StimFlow.ini只保存上次文件夹和缓存设置。 - 图片文件只读,不会被修改。
- 由
.scr扩展名或/s参数进入。 - 使用
StimFlow.ini里的last_folder,不弹文件夹选择框。 - 任意键盘按键、鼠标移动超过 20 px、鼠标点击、滚轮、手柄任意输入都会立即退出。
- 不播放音效、不阻止显示器休眠、不使用磁盘缓存。
/c和/p参数直接返回 0(没有配置界面,也不支持预览)。
StimFlow.ini 位于 exe 同目录,UTF-16 或 ANSI 均可:
[paths]
; 上次选择的文件夹;留空则默认“图片”库
last_folder=D:\Photos
; 缓存目录;留空则自动选择非系统盘
cache_folder=D:\StimFlowCache
[options]
; 1 = 内存 + 磁盘缓存;0 = 仅内存
cache_enabled=1
; 1 = 递归扫描子文件夹;0 = 只扫描当前文件夹
recursive=1程序启动时会读取;选择文件夹后会写回 last_folder。
只需要 Visual Studio Build Tools(含“使用 C++ 的桌面开发”)、Windows SDK 和 CMake 3.25+。完整步骤见 docs/BUILD.md。
最省事:
.\build.ps1产物:build\Release\StimFlow.exe。
不需要 Python、vcpkg 或任何第三方库;着色器在构建时由 fxc.exe 编译成头文件。
另有一个独立的 4KB intro 子项目:intro/。它不读取图片,用 D3D11 全屏着色器程序化生成扇形排列的 Cover Flow 卡片墙,用 Crinkler 压到 4KB 以内;目标平台是 Windows x86(64 位系统通过 WoW64 运行)。运行后用 ← / → 切换卡片,Esc 退出。
cd intro
.\get-crinkler.ps1
.\build.ps1产物:intro\build\intro.exe。
发布包:.\intro\package.ps1 → intro\dist\StimFlow-4KB-intro-win32.zip,解压后双击 intro.exe。
Q:为什么有些图片不显示? A:当前只支持 WIC 内置格式。HEIC / WebP / AVIF / RAW 会被跳过。
Q:图片会被裁切吗? A:不会。卡片按统一对角线缩放,宽度跟随图片比例;所有卡片底边对齐,只有极宽图片会略微缩小。
Q:为什么第一次打开很慢? A:缩略图需要从原图解码。开启磁盘缓存后,第二次打开同一文件夹会快很多。
Q:缓存文件可以被别人看到吗? A:缓存内容用 DPAPI 加密,其他 Windows 用户无法解密;文件名是路径的 SHA-256,不含明文路径。但当前登录用户可以解密自己账户下的缓存。
Q:怎么彻底清除缓存?
A:退出时选择“清除全部缓存”,或手动删除 StimFlowCache 文件夹。
Q:支持多显示器吗? A:目前只使用主显示器。窗口固定为无边框全屏。
Q:支持视频吗? A:不支持。GIF 只显示第一帧。
Q:为什么静止时还有少量 CPU? A:程序会每 500 ms 轮询一次手柄(连接后 16 ms),并每 5 秒自动翻页。没有操作时 GPU 只在需要时重绘;但手柄轮询和定时器仍会唤醒少量 CPU。
Q:查看模式为什么占内存? A:首次滚轮放大解码原图,最多保留一张原图 CPU 缓冲(长边上限 8192);缩放到 4× 时可见分块约 40–60 张。退回 1× 或退出查看模式会立即释放分块和 CPU 缓冲,并调用 DXGI Trim 让驱动归还显存分配。以 5000×3500 测试图为例:Cover Flow 约 65 MB,4× 峰值约 240 MB,回到 Cover Flow 后约 65–85 MB。
MIT。见 LICENSE。
翻页音效来自项目内 assets/audio/ 的采样,构建时以 RCDATA 嵌入 exe;运行时不读取外部音频文件。