135 lines
5.6 KiB
C
135 lines
5.6 KiB
C
/* 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;
|
|
}
|