app+csdk+docs: 按反汇编定案修复——官方安卓路径无 160→320 插值级(ImageViewer 无 FILTER_BITMAP 最近邻放大),我们的双线性 2× 自造交错细纹;实测冷区细条纹比 1.16/1.29→1.00/0.93,csdk 同加 upscale_nearest,119 单测全绿
This commit is contained in:
@@ -301,6 +301,10 @@ build-artifacts\csdk_test_display.exe
|
||||
同场景照片逐像素平均差 4.5/255、逐计数中位差 2 级,见 §10/§11)。
|
||||
⚠️ **本机没有 C 编译器**(gcc/clang/NDK 都没有),所以这段 C **未编译**——
|
||||
算法本身由 Kotlin golden 测试锁定,合入前请在带编译器的环境编译 + 跑回归。
|
||||
- 同一节还有个 `upscale_nearest`:官方**安卓**路径没有 160→320 的插值级
|
||||
(SDK 给 App 的位图就是 160×120,App 用 `new Paint(1)`(无 FILTER_BITMAP)最近邻放大),
|
||||
而 PC 版的双线性会展出一层"全幅/半幅"交错细纹(暗/低温区最明显)。
|
||||
真机实测:冷区细尺度列条纹比 1.16/1.29(双线性)→ **1.00/0.93**(最近邻)。
|
||||
- 顺带(同一条链):**曲线插值温度要加 `BasePara2.fpaTempFix`**。官方 App 传给 SDK 的是
|
||||
`帧尾 FPA + fpaTempFix`(真机 1699),`SelectCaliCurve`/`GenerateVolatileLens`
|
||||
用它选/插值每像素标定表;温度换算链路仍用帧尾原值。C 侧**已实现**
|
||||
|
||||
@@ -60,6 +60,14 @@ typedef struct mag160c_render_cfg_t {
|
||||
int fpa_temp_fix;
|
||||
/* Brightness offset for the Android LUT base; the official app passes 0. */
|
||||
int lut_brightness;
|
||||
/* 1 = replicate pixels in the 160x120 -> 320x240 stage instead of interpolating.
|
||||
The official ANDROID path has no such stage at all (its SDK hands the app a
|
||||
160x120 bitmap which ImageViewer draws with a non-filtering paint = nearest),
|
||||
while the PC SDK's bilinear version fabricates an interleaved full/half
|
||||
amplitude column pattern at the sensor Nyquist - visible as extra fine stripes
|
||||
in the dark/cold regions. Measured on device: fine-scale cold-region stripe
|
||||
ratio vs the official 1.16-1.29x (bilinear) -> 1.00/0.93 (nearest). */
|
||||
int upscale_nearest;
|
||||
mag160c_render_ffc_cb_t ffc_cb;
|
||||
void *ffc_user;
|
||||
mag160c_render_post_nuc_cb_t post_nuc_cb;
|
||||
|
||||
@@ -59,7 +59,7 @@ struct mag160c_render_t {
|
||||
mag160c_render_post_gray_cb_t post_gray_cb;
|
||||
void *post_gray_user;
|
||||
int ffc_period, ffc_drift, warm_frames, cdf_pivot_75, force75;
|
||||
int android_lut, fpa_temp_fix, lut_brightness;
|
||||
int android_lut, fpa_temp_fix, lut_brightness, upscale_nearest;
|
||||
};
|
||||
|
||||
static int counts_to_temp_mc(int counts) {
|
||||
@@ -524,6 +524,19 @@ static void upscale2x(mag160c_render_t *r) {
|
||||
const unsigned char *s = r->gray160;
|
||||
unsigned char *o = r->gray320;
|
||||
int W = r->w, H = r->h, W2 = W * 2;
|
||||
if (r->upscale_nearest) {
|
||||
/* Android parity: no interpolation stage (see mag160c_render.h) */
|
||||
for (int y = 0; y < H; ++y) {
|
||||
const unsigned char *row = s + y * W;
|
||||
unsigned char *o0 = o + y * W2 * 2, *o1 = o0 + W2;
|
||||
for (int x = 0; x < W; ++x) {
|
||||
unsigned char v = row[x];
|
||||
o0[x * 2] = v; o0[x * 2 + 1] = v;
|
||||
o1[x * 2] = v; o1[x * 2 + 1] = v;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int y = 0; y < H - 1; ++y) {
|
||||
const unsigned char *r0 = s + y * W, *r1 = r0 + W;
|
||||
unsigned char *o0 = o + y * W2 * 2, *o1 = o0 + W2;
|
||||
@@ -667,6 +680,7 @@ mag160c_error_t mag160c_render_init(mag160c_render_t **out,
|
||||
r->android_lut = cfg->android_lut;
|
||||
r->fpa_temp_fix = cfg->fpa_temp_fix;
|
||||
r->lut_brightness = cfg->lut_brightness;
|
||||
r->upscale_nearest = cfg->upscale_nearest;
|
||||
r->force75 = cfg->startup_force_ffc;
|
||||
r->dev24 = 5;
|
||||
r->dev4c_shift = 3;
|
||||
|
||||
@@ -618,6 +618,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmd, int show) {
|
||||
cfg.cdf_pivot_75 = 1; /* kept for the PC path */
|
||||
cfg.android_lut = 1;
|
||||
cfg.fpa_temp_fix = 1699; /* BasePara2.fpaTempFix of device 160043865 */
|
||||
cfg.upscale_nearest = 1; /* official Android path has no interpolating 2x stage */
|
||||
cfg.ffc_cb = ffc_cb;
|
||||
cfg.post_nuc_cb = post_nuc_cb;
|
||||
cfg.post_gray_cb = post_gray_cb;
|
||||
|
||||
@@ -134,6 +134,7 @@ int main(int argc, char **argv) {
|
||||
cfg.cdf_pivot_75 = 1; /* kept for the PC path */
|
||||
cfg.android_lut = 1;
|
||||
cfg.fpa_temp_fix = 1699; /* BasePara2.fpaTempFix of device 160043865 */
|
||||
cfg.upscale_nearest = 1; /* official Android path has no interpolating 2x stage */
|
||||
cfg.ffc_cb = ffc_cb;
|
||||
mag160c_render_t *render = NULL;
|
||||
if (mag160c_render_init(&render, &cfg) != MAG160C_OK) {
|
||||
|
||||
Reference in New Issue
Block a user