android: fix real-device defects (temp double-conversion, FFC temp jump, image orientation per grip, remote raw+metadata stream)
This commit is contained in:
@@ -66,8 +66,9 @@ android/app/src/main/kotlin/com/mag160c/thermal/
|
||||
│ ├─ LiveScreen.kt 稳定单分支相机布局:顶栏5控制项(FFC/变倍/追踪/调色板/画中画)
|
||||
│ │ +底部快门区(相册/拍照/录像)+SurfaceView+PIP浮层
|
||||
│ ├─ PipCameraView.kt 可见光PIP相机引擎(Camera2最小实现,异常只记日志)
|
||||
│ └─ LiveRenderer.kt SurfaceView 软件渲染:图像恒90°旋转(3:4竖)钉在竖屏框架固定区域,
|
||||
│ 文字恒屏幕水平;色标条/圆圈标记/中心温OSD
|
||||
│ ├─ ImageTransform.kt 方向/翻转/letterbox/缩放几何 + 传感器↔屏幕互逆映射(纯 Kotlin,单测覆盖)
|
||||
│ └─ LiveRenderer.kt SurfaceView 软件渲染:图像按握持角补偿旋转(rot=90-φ)、
|
||||
│ letterbox+变倍、色标条/圆环标记/中心温OSD(标签按旋转包围盒定位)
|
||||
├─ ui/gallery/ 相册页(MediaStore DCIM/MAG160C 扫描 + 内嵌JPEG缩略图 + 运行时媒体权限)
|
||||
├─ ui/analyze/ MDT 离线分析(缩放/调色板重渲染/温度条+点击测温/备注回写/PDF报告)
|
||||
├─ ui/settings/ 设置页(默认调色板/发射率/报警温度/语言/云同步/远程预览两行/关于)
|
||||
@@ -129,25 +130,39 @@ res/drawable/*.xml 自绘矢量图标(双弧圆等可靠几何图形
|
||||
- 旧 analysis/protocol_spec.md 的 66f/670 描述("prepare/version query")不准,
|
||||
以 magcx_official_flow.md 为准。
|
||||
|
||||
### 4.3 实时画面渲染(最终约定:构图钉死竖屏框架)
|
||||
### 4.3 实时画面渲染(2026-09-11 修订:图像内容随握持朝向补偿)
|
||||
|
||||
- **Activity 锁定竖屏**(manifest `screenOrientation="portrait"`):屏幕相对手机框架
|
||||
永不旋转。顶栏、热像区域、底栏的**绝对位置**永远贴着手机竖屏的物理顶边(挖孔侧)、
|
||||
中间、物理底边;手机怎么物理旋转,构图都不动(用户明确要求:屏显方向必须始终
|
||||
与热像镜头实际方向对应,横屏后显示区域跟着屏幕转是错的)。**不要改回 fullSensor。**
|
||||
- **图标/文字按物理持机朝向补偿旋转**(第六轮定稿):`ui/DeviceOrientation.kt` 用
|
||||
加速度计得出手机相对竖屏的顺时针物理转角 φ(0/90/180/270,带滞回;竖屏锁定下
|
||||
Display.rotation 恒 0 不可用)。顶栏/底部导航条目 `graphicsLayer rotationZ=-φ`
|
||||
原位预旋转;渲染器 OSD 文字 `canvas.rotate(-φ)` 绕锚点旋转(标记圆点、色标条
|
||||
几何仍钉死在图像上)。对话框与其他页签暂不补偿。
|
||||
中间、物理底边;手机怎么物理旋转,构图都不动。**不要改回 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`,
|
||||
用于传感器安装方向特殊的机器。翻转在像素拷贝阶段完成,保证几何映射可测。
|
||||
- **图标/文字按握持角补偿**:`graphicsLayer rotationZ=-φ`(Compose)/
|
||||
`canvas.rotate(-φ)`(Canvas)。**标签一律按旋转后包围盒定位**(
|
||||
`ImageTransform.rotatedBoxHalfExtents` + `drawGripText`),不要再拿基线锚点
|
||||
摆位——色标条两端数字曾因此与色条错位。
|
||||
- **几何单一来源**:`ui/live/ImageTransform.kt`(纯 Kotlin,可单测)同时供
|
||||
渲染器与点击/探针映射使用(`sensorToScreen` / `screenToSensor` 互为逆映射,
|
||||
已对 0/90/180/270 × 翻转组合做往返测试)。渲染与取温映射**必须**用同一套参数,
|
||||
否则标记会落到错误像素上。
|
||||
- **加速度计符号约定(第七轮教训,勿改回)**:真机 TYPE_ACCELEROMETER 静止读数
|
||||
指向世界上方(竖屏正持 y=+9.81);模拟器虚拟传感器是反的重力约定(y=-9.81)。
|
||||
DeviceOrientation 映射按**真机约定**写,模拟器测试须用反号值驱动
|
||||
(φ=0→`adb emu sensor set acceleration 0:9.81:0`)。
|
||||
- **图像恒 90°CW 绘制为 3:4 竖向**,填满可用区域(顶栏下~底导航上)。
|
||||
- **文字/图标恒屏幕水平**(可读);标记文字位置自动跟随(probeToScreen 固定 90° 映射:
|
||||
`fx=1-sy/120, fy=sx/160`)。
|
||||
- 顶栏=4 个相机控制项(FFC / 变倍×N / 追踪·开 / 调色板+名称),恒在顶部并带小字
|
||||
标签,`safeDrawing` 顶部inset 适配挖孔屏。
|
||||
- **追踪开关控制最高+最低两个标记**(此前只关最高,最低永远画着)。
|
||||
- 顶栏=5 个控制项(FFC / 变倍×N / 追踪·开 / 调色板+名称 / 画中画),恒在顶部并带
|
||||
小字标签,`safeDrawing` 顶部 inset 适配挖孔屏。
|
||||
- 底部(仅实时页)导航栏上方为**相机快门区**:相册快捷入口 / 大快门拍照 /
|
||||
录像-停止;快门区高度并入 `vm.uiBottomPx`(= 导航高+快门区高)。
|
||||
- 顶栏高度经 `onSizeChanged`→`vm.uiTopPx`(**必须挂在 safeDrawing inset 之前**,
|
||||
@@ -158,6 +173,18 @@ res/drawable/*.xml 自绘矢量图标(双弧圆等可靠几何图形
|
||||
`connect()` 置 `status="no_device"`,LiveScreen 显示占位文案"未检测到热像仪,
|
||||
请插入MAG160C",渲染器无帧黑底;startDemo/合成帧代码已删除。
|
||||
|
||||
### 4.3.1 温度显示(2026-09-11 修复三个真机缺陷)
|
||||
|
||||
- **中心温度**:`probeTemp()` 返回的**已经是毫度**,界面只许除以 1000 一次。
|
||||
旧代码又调了一次 `countsToTempMc()`,真机显示 108.7℃(实际约 24℃)。
|
||||
- **FFC 期间的温度跳变**:FFC 参考帧过去被解码进 `nuc`(OSD 采样的同一缓冲区),
|
||||
未补偿的原始 counts 直接参与显示 → 最高/最低短暂跳到 ~150℃。
|
||||
现在参考帧走独立 `refScratch` 缓冲。
|
||||
- **上电/未就绪**:首帧渲染前 `nuc` 全 0,而 `countsToTempMc(0) = -161.0℃`
|
||||
(看着像合法读数)。`RenderPipeline.tempsReady()` / `IrSession.tempsReady()`
|
||||
门控 UI 取温;远程页同样门控。
|
||||
- 回归测试:`core/PipelineTemperatureStateTest.kt`。
|
||||
|
||||
### 4.4 温度
|
||||
- 温度 = 毫度 int(÷1000 = ℃)。`counts_to_temp_mc`(NUC域→T2E逆映射)用于探针/OSD,
|
||||
在真机上需按 DDT 标定核对绝对值(待办)。
|
||||
|
||||
Reference in New Issue
Block a user