Source file: /~heha/mb-iwp/Infrarot-Kamera/Lügendetektor.zip/src/Lügendetektor.cpp

#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
Wrong umlauts? - Assume file is ANSI (CP1252) encoded