android: revert image to locked orientation (user decision); keep official-style manual rotate/flip settings

This commit is contained in:
ZXCLI
2026-09-11 03:50:56 +08:00
parent 464cfcb5e8
commit f7bca894ba
13 changed files with 227 additions and 218 deletions
+20 -18
View File
@@ -67,7 +67,7 @@ android/app/src/main/kotlin/com/mag160c/thermal/
│ │ +底部快门区(相册/拍照/录像)+SurfaceView+PIP浮层
│ ├─ PipCameraView.kt 可见光PIP相机引擎(Camera2最小实现,异常只记日志)
│ ├─ ImageTransform.kt 方向/翻转/letterbox/缩放几何 + 传感器↔屏幕互逆映射(纯 Kotlin,单测覆盖)
│ └─ LiveRenderer.kt SurfaceView 软件渲染:图像按握持角补偿旋转(rot=90-φ)、
│ └─ LiveRenderer.kt SurfaceView 软件渲染:图像锁定竖屏框架(90°,可按设置手工旋转/翻转)、
│ letterbox+变倍、色标条/圆环标记/中心温OSD(标签按旋转包围盒定位)
├─ ui/gallery/ 相册页(MediaStore DCIM/MAG160C 扫描 + 内嵌JPEG缩略图 + 运行时媒体权限)
├─ ui/analyze/ MDT 离线分析(缩放/调色板重渲染/温度条+点击测温/备注回写/PDF报告)
@@ -130,28 +130,30 @@ res/drawable/*.xml 自绘矢量图标(双弧圆等可靠几何图形
- 旧 analysis/protocol_spec.md 的 66f/670 描述("prepare/version query")不准,
以 magcx_official_flow.md 为准。
### 4.3 实时画面渲染(2026-09-11 修订:图像内容随握持朝向补偿
### 4.3 实时画面渲染(2026-09-11 定稿:图像锁定 + 官方同款手工修正
- **Activity 锁定竖屏**manifest `screenOrientation="portrait"`):屏幕相对手机框架
永不旋转。顶栏、热像区域、底栏的**绝对位置**永远贴着手机竖屏的物理顶边(挖孔侧)、
中间、物理底边;手机怎么物理旋转,构图都不动。**不要改回 fullSensor。**
- **图像内容补偿旋转(本轮修订,勿回退)**:构图不动,但**画面内容**必须随握持朝向
反向补偿,否则转身后场景跟着转、与镜头实际指向脱节。规则:
`rot = 90 - φ`(φ = DeviceOrientation 握持角 0/90/180/270)。
依据官方实现:`MainActivity.windowOrientationListener` 把 Display.rotation
(0/1/2/3) 映射成图像 90/0/270/180,再经 `ImageViewer.drawImage` 的
`matrix.postRotate` 应用;官方**窗口会随传感器旋转**,故可见结果恒为 90
我们锁了窗口,图像就要承担全部差值 → `90 - φ`。
显示旋转索引→角度约定取自官方自家相机代码
`VisibleCameraHelper.setPreviewOrientation`case 0→0/1→90/2→180/3→270
即索引 N = 顺时针 N×90)。
- **手工修正项**(官方"旋转USB画面/水平翻转/竖直翻转"同款):设置页三项,
叠加在自动补偿之上,持久化于 `AppSettings.imageRotateDeg/imageFlipH/imageFlipV`
用于传感器安装方向特殊的机器。翻转在像素拷贝阶段完成,保证几何映射可测。
- **图像内容同样锁定**(用户 2026-09-11 明确)**,不随握持角旋转**:热像传感器
物理装在手机上、跟着手机一起转,所以锁定图像时场景与世界的相对方向自动保持
正确,**不需要**加速度计参与。这也正是官方 App 的屏上效果(官方窗口随传感器
转,其面板级图像旋转因此是恒定的 90°)。
- ⚠️ **曾经改错又改回**:2026-09-11 中途有一版把图像按握持角反向补偿
`rot = 90 - φ`),结果**双重补偿**,正是用户报的"右转画面往反方向转"
**不要再引入握持角参与图像旋转。**
- `ImageTransform.params()` **不接受握持角参数**——这是编译期保证。
- **手工修正项**(官方"旋转USB画面/水平翻转/竖直翻转"同款,设置页):
`imageRotateDeg`(0/90/180/270) 叠加在锁定基准 90° 之上;两个翻转作用在
**传感器帧**上(与官方一致:翻转交给 native,旋转在显示矩阵上)。
持久化于 `AppSettings`
- **数学等价关系(单测锁定)**:**"竖直翻转 + 旋转 90°" ≡ "水平翻转 + 旋转 270°"**
(逐像素比对验证)。用户实测"竖直翻转 + 旋转 90°"可把画面转到另一方向,
正是这条恒等式;两者只差一次水平镜像。
- **图标/文字按握持角补偿**`graphicsLayer rotationZ=-φ`Compose/
`canvas.rotate(-φ)`(Canvas)。**标签一律按旋转后包围盒定位**
`ImageTransform.rotatedBoxHalfExtents` + `drawGripText`),不要再拿基线锚点
摆位——色标条两端数字曾因此与色条错位。
`canvas.rotate(-φ)`Canvas,保证任何握持姿态下可读。**标签一律按旋转后
包围盒定位**`ImageTransform.rotatedBoxHalfExtents` + `drawGripText`),
不要再拿基线锚点摆位——色标条两端数字曾因此与色条错位。
- **几何单一来源**`ui/live/ImageTransform.kt`(纯 Kotlin,可单测)同时供
渲染器与点击/探针映射使用(`sensorToScreen` / `screenToSensor` 互为逆映射,
已对 0/90/180/270 × 翻转组合做往返测试)。渲染与取温映射**必须**用同一套参数,
+3 -2
View File
@@ -56,10 +56,11 @@
| # | 操作 | 预期 | 通过标准 |
|---|------|------|----------|
| 25 | 竖屏正持,观察画面 | (无日志) | 画面正常;中心温读数与手摸/环境常识一致(**不是 -161℃、不是 108℃ 这类离谱值**) |
| 26 | 手持手机**顺时针转 90°**(横过来),观察画面内容 | (无日志) | **场景方向不变**(画面内容跟着手反向补偿),顶栏/底栏文字仍可读;不是整个场景跟着转 |
| 26 | 手持手机转四个方向(0/90/180/270),观察画面内容 | (无日志) | **画面内容始终不动**(图像锁定在竖屏框架,与第四/五轮约定一致);顶栏/底栏文字仍随持机朝向保持可读 |
| 27 | 点"追踪"关闭 | (无日志) | **最高温和最低温两个标记同时消失**;再点开→两个都出现(此前最低温标记关不掉) |
| 28 | 点 FFC,紧盯最高/最低温读数 | `[cmd] FFC(0) write=8/8` | 读数**不出现 ~150℃ 的瞬时跳变**(可短暂保持不变,但不得跳到离谱值) |
| 29 | 设置页"旋转USB画面"依次选 0/90/180/270° | (无日志) | 画面按所选角度整体旋转,用于修正传感器安装方向 |
| 29 | 设置页"旋转USB画面"依次选 0/90/180/270° | (无日志) | 画面按所选角度整体旋转(在锁定基准 90° 之上叠加),用于修正传感器安装方向 |
| 29b | 设置页开"竖直翻转",同时"旋转USB画面"设为 90° | (无日志) | 这是用户实测能把画面转到另一方向的组合;**它等价于"水平翻转 + 旋转270°"**(只差一次水平镜像)——若 90°+竖直翻转 看着左右是反的,改用 270°+水平翻转 |
| 30 | 设置页"水平翻转"/"竖直翻转"开关 | (无日志) | 画面镜像;与官方 app 的同名设置表现一致 |
| 31 | 横屏持机时观察色标条 | (无日志) | 色标条**两端**的最高/最低温数字紧贴色条两端,**不与色条重叠**、不偏移 |
| 32 | 分析页打开一张 MDT,观察顶部温度条 | (无日志) | 温度条显示"中心/最低/最高",数值与拍照时实时页读数接近 |
+14 -12
View File
@@ -466,15 +466,16 @@
新增回归测试 `PipelineTemperatureStateTest`3 项)。
- [x] **追踪开关只关最高温**:最低温标记未受开关控制(`LiveRenderer.drawOsd`)。
现在开=最高+最低都画("高"/"低"),关=都不画。
- [x] **画面转向反了 / 横屏应翻 180°**先"图像恒 90°CW 不动"的约定在真机上
表现为转身后场景跟着转。改为**图像内容按握持角补偿**:`rot = 90 - φ`
依据官方实现(`MainActivity.windowOrientationListener` 把 Display.rotation
映射成图像 90/0/270/180,经 `ImageViewer.drawImage``matrix.postRotate`
应用;官方窗口随传感器转,可见结果恒 90);显示旋转索引→角度取官方自家
相机代码 `VisibleCameraHelper.setPreviewOrientation`N→N×90)。
构图(条栏/图像区绝对位置)仍钉死竖屏框架不变
- [x] **新增官方同款方向设置**:设置页"旋转USB画面"0/90/180/270)、
"水平翻转"、"竖直翻转",叠加在自动补偿之上并持久化。
- [x] **画面转向反了 / 横屏应翻 180°**:先"图像内容随握持角补偿(`rot = 90 - φ`"
改了一版,**用户实测后指正:图像应保持锁定**——传感器装在手机上跟着一起转,
锁定图像时场景相对世界方向自动正确,加速度计参与反而双重补偿(这正是
"右转画面往反方向转"的原因)。**已改回锁定**:`ImageTransform.params()`
不再接受握持角参数(编译期保证),只保留官方同款手工修正。
用户还实测发现"**竖直翻转 + 旋转 90°**"能把画面转到另一方向——已用单测
证明它等价于"水平翻转 + 旋转 270°"(逐像素比对),两者只差一次水平镜像
- [x] **新增官方同款方向设置**:设置页"旋转USB画面"0/90/180/270,叠加在锁定
基准 90° 上)、"水平翻转"、"竖直翻转"(作用在传感器帧上,与官方一致),
持久化于 `AppSettings`
- [x] **色标条两端最高/最低温与色条错位**:标签原先按未旋转的基线锚点定位。
改为**按旋转后包围盒**定位(`ImageTransform.rotatedBoxHalfExtents` +
`drawGripText`),任意握持角都贴着色条两端。
@@ -494,12 +495,13 @@
主机实现"后来者写 busy"accept 循环不再阻塞在 serve 上,第二客户端立即
收到 `{"type":"busy"}`;新增 `secondClientIsRejectedWithBusy`)。
另删除未使用的 `ACCESS_NETWORK_STATE` 权限。
- [x] 单测 44 → **61 项全绿**debug + release(R8) 双构建通过;APK 已更新
- [x] 单测 44 → **62 项全绿**debug + release(R8) 双构建通过;APK 已更新
12.66MB)。`screenOrientation=portrait` 复核保持、camera 系列仍
not-required、多余权限已消失。
⚠️ **规格偏离(已告知用户)**:本轮推翻了第四/五轮"图像恒 90°CW 不动"的约定
(用户实测该约定导致转向错误)。构图绝对位置不变,仅图像**内容**随握持角补偿。
⚠️ **规格说明(用户裁定)**:图像**锁定**在竖屏框架(第四/五轮约定维持不变);
新增的仅是官方同款三项手工方向修正。中途曾按握持角补偿图像,用户实测指正后
已改回,`ImageTransform.params()` 不再接受握持角参数以防回退。