#define _WIN32_WINNT 0x0400
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <shlwapi.h>
#include "GrabDll/irbgrab.h"
#define elemof(x) (sizeof(x)/sizeof(*(x)))
#define T TEXT
HINSTANCE hInst;
HANDLE hGrabber;
BOOL CALLBACK AboutDlgProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
switch (Msg) {
case WM_INITDIALOG: {
}return TRUE;
case WM_COMMAND: switch (LOWORD(wParam)) {
case IDOK:
case IDCANCEL: EndDialog(Wnd,wParam); break;
}
}
return FALSE;
}
int iitrafo(int i,int a,int b,int A,int B) {
return A+MulDiv(i-a,B-A,b-a);
}
extern "C" int _fltused=0;
extern "C" long _declspec(naked) _cdecl _ftol(void){ _asm{
push eax
fistp dword ptr [esp]
fwait
pop eax
ret
}}
int fitrafo(float i,float a,float b,int A,int B) {
return A+(int)((i-a)/(b-a)*(B-A));
}
// Der Optimierer darf hier nichts wegoptimieren!!
void _stdcall Line(HDC dc, int x1, int, int, int) {
Polyline(dc,(POINT*)&x1,2);
}
int (_cdecl*_stprintf)(PTSTR,int,PTSTR,...);
int (_cdecl*_stscanf)(PTSTR,PTSTR,...);
#ifdef UNICODE
# define __IMP__STPRINTF "_snwprintf"
# define __IMP__STSCANF "swscanf"
#else
# define __IMP__STPRINTF "_snprintf"
# define __IMP__STSCANF "sscanf"
#endif
/************************
* unauffällige Objekte *
************************/
struct palette_t{
struct entry{
int index;
BYTE r,g,b;
};
struct entry data[50];
bool Load(void) {
HANDLE f=CreateFile("c:/Programme/IRBIS_professional_2.2/col/ThvVario.col",
GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,0);
if (f==INVALID_HANDLE_VALUE) return false;
DWORD len=1000;
char *buf=(char*)LocalAlloc(LMEM_FIXED,len);
ReadFile(f,buf,len-1,&len,NULL);
buf[len]=0;
CloseHandle(f);
// Zeilen auswerten
char*p=buf;
struct entry *dest=data;
int pos=0;
_stscanf(p,"color\r\n%n",&pos);
if (!pos) return false;
p+=pos;
int i,r,g,b;
for (;;) {
if (_stscanf(p,"%d,%d,%d,%d\r\n%n",&i,&r,&g,&b,&pos)!=4) break;
dest->index=i;
dest->r=r;
dest->g=g;
dest->b=b;
dest++;
p+=pos;
}
return true;
}
// RGB-Wert durch lineare Approximation ermitteln
bool CalcRgb(int idx, BYTE*r, BYTE*g, BYTE*b) {
int i;
// 1. Suchen von <idx> im "Index-Wertebereich" (monoton wachsend)
for (i=1;idx>data[i].index;i++) {
if (!data[i].index) return false;
}
// 2. Gerade als Verbindung zweier Punkte annehmen, Wert ermitteln
if (r) *r=iitrafo(idx,data[i-1].index,data[i].index,data[i-1].r,data[i].r)<<2;
if (g) *g=iitrafo(idx,data[i-1].index,data[i].index,data[i-1].g,data[i].g)<<2;
if (b) *b=iitrafo(idx,data[i-1].index,data[i].index,data[i-1].b,data[i].b)<<2;
return true;
}
COLORREF CalcRgb(int idx) {
BYTE ret[4];
CalcRgb(idx,ret,ret+1,ret+2);
return *(COLORREF*)ret;
}
}Palette;
struct lug_t{ // Lug und Trug!
float add; // Addier- oder Subtrahierwert für Gesichtstemperaturen, in K
float from; // Schwelle für Gesichtstemperatur, in K
float w; // Breite der Schwelle (lineare Approximation zwischen from und from+w), in K
float limit; // maximale Temperaturänderung (+/-; sonst wird's lächerlich), in K
void init(void) {
from=273.15F+30;
w=4;
limit=2;
}
float modify(float t) {
float ramp=(t-from)/w;
if (ramp<0) return t; // unverändert für Raumtemperatur
if (ramp>=1) return t+add; // verfälscht für Gesicht
return t+add*ramp; // linearer Übergangsbereich
}
void HandleMouseWheel(int i) {
add+=i*0.2F;
if (add>limit) add=limit;
if (add<-limit) add=-limit;
}
}lug;
struct camdata_t{ // Kameradaten
int cx, cy; // Bitmap-Ausdehnungen
PBYTE data; // Bitmap-Daten (Bytes)
size_t xy; // Anzahl Bytes der Bitmap
float *buf; // Float-Puffer
size_t buflen; // Puffer-Größe, in floats
float min;
float max;
int zoom;
void init(void) {
cx = getimgwidth(hGrabber);
cy = getimgheight(hGrabber);
xy = ((cx+3)&~3)*cy; // Zeilen auf DWORD-Grenzen ausrichten
data=(PBYTE)LocalAlloc(LPTR,xy);
buflen=cx*cy;
buf=(float*)LocalAlloc(LPTR,buflen*sizeof(float));
min=273.15F+20;
max=273.15F+40;
zoom=2;
}
void done(void) {
LocalFree(data);
LocalFree(buf);
}
float getvalue(int x, int y) {
if (!buf) return 0;
return gCamData.buf[y*cx+x];
}
void transfer(void) { // transferiert <buf> nach <data>
float *s=buf;
BYTE *d=data;
for (int yy=0; yy<cy; yy++) {
for (int xx=0; xx<cx; xx++) {
int z=fitrafo(lug.modify(*s++),min,max,0,255);
if (z<0) z=0;
if (z>255) z=255;
*d++=(BYTE)z;
}
xx&=3;
if (xx) d+=4-xx; // ggf. neu ausrichten
}
}
}gCamData;
struct bmi_t:BITMAPINFOHEADER{
RGBQUAD bmiColors[256];
void init(void) {
biSize=sizeof(BITMAPINFOHEADER);
biWidth=gCamData.cx;
biHeight=gCamData.cy;
biPlanes=1;
biBitCount=8;
biCompression=BI_RGB;
biSizeImage=0;
biXPelsPerMeter=0;
biYPelsPerMeter=0;
biClrUsed=256; // alle
biClrImportant=0; // alle
for (int i=0; i<256; i++) {
Palette.CalcRgb(i,
&bmiColors[i].rgbRed,
&bmiColors[i].rgbGreen,
&bmiColors[i].rgbBlue);
bmiColors[i].rgbReserved=0;
}
}
}bmi;
struct poi_t:POINT{
bool InUse;
TCHAR name[4];
void init(int idx) {
wsprintf(name,T("P%d"),idx+1);
}
void draw(HDC dc) { // Einzeichnen in Thermografiebild
POINT p={x*gCamData.zoom,y*gCamData.zoom};
Line(dc,p.x-4,p.y,p.x+4,p.y);
Line(dc,p.x,p.y-4,p.x,p.y+4);
TextOut(dc,p.x+2,p.y+1,name,lstrlen(name));
}
}poi[10];
void DrawPois(HDC dc) {
HPEN open=SelectPen(dc,GetStockPen(WHITE_PEN));
COLORREF ocolor=SetTextColor(dc,0xFFFFFF);
UINT obkmode=SetBkMode(dc,TRANSPARENT);
for (int i=0; i<elemof(poi); i++) {
if (poi[i].InUse) {
poi[i].draw(dc);
}
}
SetBkMode(dc,obkmode);
SetTextColor(dc,ocolor);
SelectPen(dc,open);
}
HWND hStatus,hList;
int ListCreateColumn(int Spalte, LPCTSTR s, int Breite) {
LVCOLUMN lvc;
lvc.mask=LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
lvc.fmt=LVCFMT_LEFT;
lvc.cx=Breite;
lvc.pszText=(LPSTR)s;
lvc.iSubItem=Spalte;
return ListView_InsertColumn(hList,Spalte,&lvc);
}
// Neues Element bei Index einfügen (Rest rutscht nach hinten)
int ListInsertItem(int idx, LPCTSTR s) {
LVITEM lvi;
lvi.mask=LVIF_TEXT;
lvi.iItem=idx;
lvi.iSubItem=0; //??notwendig??
lvi.pszText=(LPSTR)s;
return ListView_InsertItem(hList,&lvi);
}
// Koordinaten der dargestellten Bitmap, in Client-Koordinaten des Dialogfensters, für Maus-Treffertest
void GetBitmapRect(HWND Wnd, LPRECT r) {
GetWindowRect(GetDlgItem(Wnd,10),r);
ScreenToClient(Wnd,(LPPOINT)r);
r->right=r->left+gCamData.cx*gCamData.zoom;
r->bottom=r->top+gCamData.cy*gCamData.zoom;
}
// Maus-Treffertest; liefert Bitmap-Koordinaten (ungezoomt)
bool GetBitmapPosFromMouse(HWND Wnd, LPARAM lParam, LPPOINT pt) {
RECT r;
GetBitmapRect(Wnd,&r);
POINT p={GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam)};
if (!PtInRect(&r,p)) return false;
if (pt) {
pt->x=(p.x-r.left)/gCamData.zoom; // Bildkoordinaten
pt->y=(p.y-r.top) /gCamData.zoom;
}
return true;
}
BOOL EnableDlgItem(HWND Wnd, UINT id, BOOL enable) {
return EnableWindow(GetDlgItem(Wnd,id),enable);
}
BOOL CALLBACK MainDlgProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
switch (Msg) {
case WM_INITDIALOG: {
SetClassLong(Wnd,GCL_HICON,(LONG)LoadIcon(hInst,MAKEINTRESOURCE(10)));
SetClassLong(Wnd,GCL_HICONSM,(LONG)LoadImage(hInst,MAKEINTRESOURCE(10),IMAGE_ICON,16,16,0));
hStatus=GetDlgItem(Wnd,20);
static const int widths[]={200,300,-1};
SendMessage(hStatus,SB_SETPARTS,elemof(widths),(LPARAM)widths);
SendMessage(hStatus,SB_SETTEXT,1,(LPARAM)"50,0 Hz");
SendMessage(hStatus,SB_SETTEXT,2,(LPARAM)"*Kamera kalibriert/42");
hList=GetDlgItem(Wnd,21);
ListCreateColumn(0,T("# POI"),40);
ListCreateColumn(1,T("Temperatur"),68);
for (int i=0; i<elemof(poi); i++) {
poi[i].init(i);
TCHAR buf[10];
wsprintf(buf,T("%d"),i+1);
ListInsertItem(i,buf);
}
Palette.Load(); // Palette aus Datei laden
lug.init();
PostMessage(Wnd,WM_COMMAND,17,(LPARAM)GetDlgItem(Wnd,17));
}return TRUE;
case WM_DRAWITEM: switch (wParam) {
case 10: {
PDRAWITEMSTRUCT dis = (PDRAWITEMSTRUCT)lParam;
SetWindowOrgEx(dis->hDC,dis->rcItem.left,dis->rcItem.top,NULL);
if (gCamData.data)
StretchDIBits(dis->hDC,
0,gCamData.cy*gCamData.zoom,gCamData.cx*gCamData.zoom,-gCamData.cy*gCamData.zoom,
0,0,gCamData.cx,gCamData.cy,
gCamData.data,
(PBITMAPINFO)&bmi,DIB_RGB_COLORS,SRCCOPY);
DrawPois(dis->hDC);
}break;
case 11: {
PDRAWITEMSTRUCT dis = (PDRAWITEMSTRUCT)lParam;
RECT R;
CopyRect(&R,&dis->rcItem);
R.bottom=R.top+2;
for (int i=255; i>=0; i--) {
HBRUSH br=CreateSolidBrush(Palette.CalcRgb(i));
FillRect(dis->hDC,&R,br);
DeleteBrush(br);
OffsetRect(&R,0,2);
}
// Ellipse(dis->hDC,dis->rcItem.top,dis->rcItem.top,dis->rcItem.right,dis->rcItem.bottom);
}break;
}break;
case WM_SIZE: {
SendMessage(hStatus,Msg,wParam,lParam); // an Statuszeile weiterreichen, damit diese sich repositioniert
}break;
case WM_MOUSEWHEEL: {
lug.HandleMouseWheel((short)HIWORD(wParam)/WHEEL_DELTA);
}break;
case WM_MOUSEMOVE: if (gCamData.buf) {
POINT p;
if (GetBitmapPosFromMouse(Wnd,lParam,&p)) {
float temp=lug.modify(gCamData.getvalue(p.x,p.y)); // Temperaturwert des Pixels in Kelvin
TCHAR buf[64], *sp;
_stprintf(buf,elemof(buf),T("(%d,%d): %.2f °C"),p.x,p.y,temp-273.15);
sp=StrChr(buf,'.');
if (sp) *sp=',';
SendMessage(hStatus,SB_SETTEXT,0,(LPARAM)buf);
}
}break;
case WM_RBUTTONDOWN: {
POINT p;
if (GetBitmapPosFromMouse(Wnd,lParam,&p)) {
HMENU m=LoadMenu(hInst,MAKEINTRESOURCE(11));
for (int i=0; i<elemof(poi); i++) {
if (poi[i].InUse) EnableMenuItem(m,211+i,MF_ENABLED);
}
POINT pt={GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam)};
ClientToScreen(Wnd,&pt);
UINT id=TrackPopupMenu(GetSubMenu(m,0),
TPM_LEFTALIGN|TPM_TOPALIGN|TPM_RETURNCMD|TPM_RIGHTBUTTON,
pt.x,pt.y,0,Wnd,NULL);
DestroyMenu(m);
switch (id) {
case 201: { // Punkt erstellen
for (int i=0; i<elemof(poi); i++) {
if (poi[i].InUse) continue;
poi[i].x=p.x;
poi[i].y=p.y;
poi[i].InUse=true;
break;
}
}break;
case 211:
case 212:
case 213:
case 214:
case 215:
case 216:
case 217:
case 218:
case 219:
case 220: {
poi[id-211].InUse=false;
LVITEM lvi={LVIF_TEXT,id-211,1,0,0,T("")};
ListView_SetItem(hList,&lvi); // Listenelement löschen
}break;
}
}
}break;
case WM_TIMER: switch (wParam) {
case 10: {
if (grabvalues(hGrabber,gCamData.buf,-2)) {
gCamData.transfer();
InvalidateRect(GetDlgItem(Wnd,10),NULL,FALSE);
for (int i=0; i<elemof(poi); i++) {
if (poi[i].InUse) { // Listenzeile aktualisieren
TCHAR buf[16];
LVITEM lvi={LVIF_TEXT,i,1,0,0,buf};
_stprintf(buf,elemof(buf),"%.2f °C",lug.modify(gCamData.getvalue(poi[i].x,poi[i].y))-273.15);
ListView_SetItem(hList,&lvi);
}
}
}
}break;
}break;
case WM_COMMAND: switch (LOWORD(wParam)) {
case 112: { // Menüpunkt "Start/Stop"
lug.add=0; // Lügen beenden (vorläufig:-)
}break;
case 18: if (hGrabber) { // Knopf "Autofokus"
char buf[100];
sendcommand(hGrabber,":autofocus 1\r\n",buf,200);
}break;
case 17: {
if (hGrabber) {
stopgrabber(hGrabber);
KillTimer(Wnd,10);
gCamData.done();
closegrabber(hGrabber);
releasegrabber(hGrabber);
hGrabber = 0;
EnableDlgItem(Wnd,18,FALSE) ;
SetWindowText((HWND)lParam,"Verbinden") ;
}else{
char dir[MAX_PATH], *p;
GetModuleFileNameA(0,dir,elemof(dir));
p=PathFindFileNameA(dir);
lstrcpyA(p,"IrbGrab.ini");
HANDLE f=CreateFileA(dir,0,0,NULL,OPEN_EXISTING,0,0);
if (f==INVALID_HANDLE_VALUE) {
TCHAR buf[1024];
wsprintf(buf,T("The initialization file %s was not found!"),dir);
MessageBox(Wnd,buf,NULL,MB_OK);
break;
}
CloseHandle(f);
hGrabber = initgrabber(Wnd,dir,"GrabSect");
if (!hGrabber) break;
EnableDlgItem(Wnd,18,TRUE) ;
SetWindowText((HWND)lParam,T("Trennen"));
gCamData.init();
bmi.init(); // Bitmapinfoheader füllen (ungefälscht)
SetTimer(Wnd,10,50,NULL);
startgrabber(hGrabber);
}
Sleep(100) ;
}break;
case IDCANCEL: {
if (hGrabber) {
stopgrabber(hGrabber);
closegrabber(hGrabber);
releasegrabber(hGrabber);
hGrabber=0;
}
EndDialog(Wnd,wParam);
}break;
}break;
}
return FALSE;
}
void WINAPI WinMainCRTStartup(void) {
hInst=GetModuleHandle(NULL);
// irgendwo in der Programminitialisierung:
HINSTANCE hLibMSVCRT=LoadLibraryA("MSVCRT.DLL");
*(FARPROC*)&_stprintf=GetProcAddress(hLibMSVCRT,__IMP__STPRINTF);
*(FARPROC*)&_stscanf=GetProcAddress(hLibMSVCRT,__IMP__STSCANF);
InitCommonControls();
ExitProcess(DialogBox(0,MAKEINTRESOURCE(10),0,MainDlgProc));
}
| Detected encoding: ANSI (CP1252) | 4
|
|
|