完成官方管线全量逆向与 demo3 v5 复刻,清理仓库
- 逆向:Ghidra/IDA 全量反编译 CoreSDKLib.dll/ThermalSDK.dll/libthermalSDK.so/ libcoresdk.so(ARM64)/libmagcore.so,导出 analysis/ida/export/ - 解码官方渲染管线:DDT 校准表加载->快门端点选择->Q12 插值->ref(4x type1 帧 均值)->NUC 查表->盲元补偿->窗口->LUT1024 重建->2x 升采样->调色板 - 逐像素验证:NUC+盲元 0/19200、插值 0 误差、2x 0/76800、窗口一致 - demo3 v5:完整复刻官方管线(含 DDT 解析、FFC 状态机、快门温度驱动), 修复 load_ddt 表错位导致的零像素问题 - 鬼影根因分析写入 analysis/reverse_20260813_full.md - 心跳/恢复机制:analysis/session_state.md + tools/resume_rev.ps1 - 新增 tsdk_pair3 增强采集工具;历史工具归档 csdk/tools/legacy/; 根目录抓帧残留删除,历史文档归档 analysis/history/ - csdk/README.md 完整使用文档;.gitignore/.gitattributes 补 LFS 规则
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
/* ThermalSDK.dll harness: use the OFFICIAL high-level SDK directly.
|
||||
* Start() runs the whole vendor pipeline; we capture the rendered IR frame
|
||||
* via SetNewIRFrameDelegate and read temperatures. This gives the exact
|
||||
* ground truth of what the official app displays on this hardware.
|
||||
*
|
||||
* The IR frame callback delivers a 160x120x3 RGB image (official render).
|
||||
*/
|
||||
#define _WIN32_WINNT 0x0601
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef void (CALLBACK *INewIRFrame)(const unsigned char *, int, int, int);
|
||||
typedef void (CALLBACK *INewDistance)(float);
|
||||
typedef void (CALLBACK *IDistanceError)();
|
||||
typedef void (CALLBACK *INewLimitEvent)(bool);
|
||||
typedef void (CALLBACK *UpdateCallback)(bool, int);
|
||||
|
||||
typedef bool (CALLBACK *fn_Start_t)(void);
|
||||
typedef void (CALLBACK *fn_Stop_t)(void);
|
||||
typedef bool (CALLBACK *fn_IsWorking_t)(void);
|
||||
typedef void (CALLBACK *fn_SetNewIRFrameDelegate_t)(INewIRFrame);
|
||||
typedef void (CALLBACK *fn_SetNewDistanceDelegate_t)(INewDistance);
|
||||
typedef void (CALLBACK *fn_SetDistanceError_t)(IDistanceError);
|
||||
typedef void (CALLBACK *fn_ReadTemperatureAtPoint_t)(int, int, unsigned char *);
|
||||
typedef void (CALLBACK *fn_SetTempBoundary_t)(double, double, double);
|
||||
typedef void (CALLBACK *fn_SetEmissivity_t)(double);
|
||||
typedef bool (CALLBACK *fn_Trigger_t)(void);
|
||||
typedef int (CALLBACK *fn_GetSDKVersion_t)(void);
|
||||
typedef void (CALLBACK *fn_SetUnitMode_t)(int);
|
||||
|
||||
static HMODULE g_tsdk;
|
||||
static fn_Start_t T_Start;
|
||||
static fn_Stop_t T_Stop;
|
||||
static fn_IsWorking_t T_IsWorking;
|
||||
static fn_SetNewIRFrameDelegate_t T_SetNewIRFrameDelegate;
|
||||
static fn_SetNewDistanceDelegate_t T_SetNewDistanceDelegate;
|
||||
static fn_SetDistanceError_t T_SetDistanceError;
|
||||
static fn_ReadTemperatureAtPoint_t T_ReadTemperatureAtPoint;
|
||||
static fn_SetTempBoundary_t T_SetTempBoundary;
|
||||
static fn_SetEmissivity_t T_SetEmissivity;
|
||||
static fn_Trigger_t T_Trigger;
|
||||
static fn_GetSDKVersion_t T_GetSDKVersion;
|
||||
static fn_SetUnitMode_t T_SetUnitMode;
|
||||
|
||||
static unsigned char g_rgb[160 * 120 * 3];
|
||||
static volatile int g_frame_count;
|
||||
|
||||
static void CALLBACK onIR(const unsigned char *buf, int w, int h, int ch) {
|
||||
if (buf && w == 160 && h == 120 && ch == 3 && g_frame_count < 10) {
|
||||
memcpy(g_rgb, buf, 160 * 120 * 3);
|
||||
g_frame_count++;
|
||||
printf(" IR frame %d: first px RGB=%d,%d,%d\n",
|
||||
g_frame_count, buf[0], buf[1], buf[2]);
|
||||
} else if (buf) {
|
||||
memcpy(g_rgb, buf, 160 * 120 * 3);
|
||||
g_frame_count++;
|
||||
}
|
||||
}
|
||||
static void CALLBACK onDist(float d) { (void)d; }
|
||||
static void CALLBACK onDistErr() {}
|
||||
|
||||
int main(void) {
|
||||
const char *dir = "C:\\Project\\MAG160C\\IR_Camera_SDK-1.0.1\\windows\\windows\\app";
|
||||
SetDllDirectoryA(dir);
|
||||
g_tsdk = LoadLibraryA("ThermalSDK.dll");
|
||||
if (!g_tsdk) { printf("ThermalSDK load failed %lu\n", GetLastError()); return 1; }
|
||||
T_Start = (fn_Start_t)GetProcAddress(g_tsdk, "Start");
|
||||
T_Stop = (fn_Stop_t)GetProcAddress(g_tsdk, "Stop");
|
||||
T_IsWorking = (fn_IsWorking_t)GetProcAddress(g_tsdk, "IsWorking");
|
||||
T_SetNewIRFrameDelegate = (fn_SetNewIRFrameDelegate_t)GetProcAddress(g_tsdk, "SetNewIRFrameDelegate");
|
||||
T_SetNewDistanceDelegate = (fn_SetNewDistanceDelegate_t)GetProcAddress(g_tsdk, "SetNewDistanceDelegate");
|
||||
T_SetDistanceError = (fn_SetDistanceError_t)GetProcAddress(g_tsdk, "SetDistanceError");
|
||||
T_ReadTemperatureAtPoint = (fn_ReadTemperatureAtPoint_t)GetProcAddress(g_tsdk, "ReadTemperatureAtPoint");
|
||||
T_SetTempBoundary = (fn_SetTempBoundary_t)GetProcAddress(g_tsdk, "SetTempBoundary");
|
||||
T_SetEmissivity = (fn_SetEmissivity_t)GetProcAddress(g_tsdk, "SetEmissivity");
|
||||
T_Trigger = (fn_Trigger_t)GetProcAddress(g_tsdk, "Trigger");
|
||||
T_GetSDKVersion = (fn_GetSDKVersion_t)GetProcAddress(g_tsdk, "GetSDKVersion");
|
||||
T_SetUnitMode = (fn_SetUnitMode_t)GetProcAddress(g_tsdk, "SetUnitMode");
|
||||
if (!T_Start || !T_SetNewIRFrameDelegate) { printf("missing exports\n"); return 2; }
|
||||
|
||||
printf("ThermalSDK version: %d\n", T_GetSDKVersion ? T_GetSDKVersion() : -1);
|
||||
T_SetUnitMode(0); /* metric */
|
||||
T_SetTempBoundary(30.0, 44.0, 37.0);
|
||||
T_SetEmissivity(0.98);
|
||||
T_SetNewDistanceDelegate(onDist);
|
||||
T_SetDistanceError(onDistErr);
|
||||
T_SetNewIRFrameDelegate(onIR);
|
||||
|
||||
printf("Start() ...\n");
|
||||
bool ok = T_Start();
|
||||
printf("Start -> %d\n", ok);
|
||||
|
||||
/* wait for frames */
|
||||
DWORD t0 = GetTickCount();
|
||||
while (g_frame_count < 30 && GetTickCount() - t0 < 20000) Sleep(100);
|
||||
printf("received %d IR frames in %.1fs\n", g_frame_count,
|
||||
(GetTickCount() - t0) / 1000.0);
|
||||
|
||||
/* temperature probe at center */
|
||||
unsigned char res[64] = {0};
|
||||
T_ReadTemperatureAtPoint(80, 60, res);
|
||||
printf("center temp result bytes: ");
|
||||
for (int i = 0; i < 32; ++i) printf("%02x ", res[i]);
|
||||
printf("\n");
|
||||
double *d = (double *)(res + 8);
|
||||
printf(" raw=%.4f arm=%.4f (guessed layout)\n", d[0], d[1]);
|
||||
|
||||
/* save official render */
|
||||
if (g_frame_count > 0) {
|
||||
unsigned sz = 54 + 160 * 120 * 3;
|
||||
unsigned char hdr[54] = {0};
|
||||
hdr[0] = 'B'; hdr[1] = 'M';
|
||||
hdr[2] = sz; hdr[3] = sz >> 8; hdr[4] = sz >> 16; hdr[5] = sz >> 24;
|
||||
hdr[10] = 54; hdr[14] = 40;
|
||||
hdr[18] = 160; hdr[22] = 120; hdr[26] = 1; hdr[28] = 24;
|
||||
FILE *f = fopen("official_render.bmp", "wb");
|
||||
if (f) {
|
||||
fwrite(hdr, 1, 54, f);
|
||||
fwrite(g_rgb, 1, 160 * 120 * 3, f);
|
||||
fclose(f);
|
||||
printf("saved official_render.bmp\n");
|
||||
}
|
||||
/* also save raw RGB dump */
|
||||
f = fopen("official_render.rgb", "wb");
|
||||
if (f) { fwrite(g_rgb, 1, 160 * 120 * 3, f); fclose(f); }
|
||||
}
|
||||
|
||||
T_Stop();
|
||||
printf("done\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user