// Code by gynvael.coldwind//vx // Consider this code to be on a BSD-style licence // And belive me - this code SUCK big time, has lots of bugs, etc. #include #include #include #include // Video stuff: // Needs option -lavicap3 -lgdi32 // Be sure to have the newset version of Windows API headers+libs. #include // Some global buffer #pragma pack(push,1) struct BGR { unsigned char b,g,r; }; #pragma pop BGR *ImgData; int ImgW, ImgH; HWND ImgWin; static BITMAPINFOHEADER bmhdr = { sizeof(BITMAPINFOHEADER), 640, -480, 1, 24, BI_RGB, 0, 0, 0, 0, 0 }; struct InputInfo { int x, y; }; InputInfo input[10]; struct InputMaxMin { int max, min; }; InputMaxMin input_maxmin[10]; HWND input_desc[10]; LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); void SaveInputInfo(void) { FILE *f; f = fopen("inputinfo.dat", "wb"); if(f) { fwrite(input, 1, sizeof(input), f); fclose(f); } else { puts("Could not save inputinfo.dat"); } } void LoadInputInfo(void) { FILE *f; int i; f = fopen("inputinfo.dat", "rb"); if(f) { fread(input, 1, sizeof(input), f); fclose(f); printf("Read inputinfo.dat:\n"); for(i = 0; i < sizeof(input) / sizeof(input[0]); i++) printf("[%i]: %i %i\n", i, input[i].x,input[i].y); } } void DriverList() { char DevName[256]; char DevVersion[256]; puts("Found video capture devices:"); int i; for(i = 0; i < 10; i++) // MSDN quote: "The index can range from 0 through 9." { BOOL Status; Status = capGetDriverDescription(i, DevName, sizeof(DevName), DevVersion, sizeof(DevVersion)); if(Status) printf("%i: %s (%s)\n", i, DevName, DevVersion); } } void Usage() { puts("usage: datatrans \n" "Run without arguments to display driver list."); } HWND CreateMainWindow(int width, int height) { WNDCLASSEX wc; HWND hwnd; HINSTANCE hInstance = GetModuleHandle(0); wc.cbSize = sizeof(WNDCLASSEX); wc.style = 0; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW-1); wc.lpszMenuName = NULL; wc.lpszClassName = "DataTransClass"; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); if(!RegisterClassEx(&wc)) { puts("Failed to register window class"); return NULL; } hwnd = CreateWindowEx( 0, "DataTransClass", "Video data receiver", WS_OVERLAPPEDWINDOW, 150, 150, width, height, NULL, NULL, hInstance, NULL); if(!hwnd) { puts("Failed to create main window"); return NULL; } return hwnd; } LRESULT CALLBACK CamCallback( HWND hWnd, LPVIDEOHDR lpVHdr ) { //printf("[%i] lpData = %.8x, dwBytesUsed: %.8x\n", lpVHdr->dwTimeCaptured, lpVHdr->lpData, lpVHdr->dwBytesUsed); bool Cfirst, Clast; unsigned char Cdata = 0; static bool LastData = true; static unsigned char StoredData[1024]; static int StoredDataEnd = 0; if(lpVHdr->dwBytesUsed) { memcpy(ImgData, lpVHdr->lpData, lpVHdr->dwBytesUsed); // OK, let's get some info int i; for(i = 0; i < 10; i++) { int sum = ImgData[input[i].x + input[i].y * ImgW].r + ImgData[input[i].x + input[i].y * ImgW].g +ImgData[input[i].x + input[i].y * ImgW].b; // Auto calibrating if(input_maxmin[i].max == 0) input_maxmin[i].max = sum; if(input_maxmin[i].min == 0) input_maxmin[i].min = sum; if(input_maxmin[i].max < sum) input_maxmin[i].max = sum; if(input_maxmin[i].min > sum) input_maxmin[i].min = sum; int what = 0; int diff_max, diff_min; input_maxmin[i].max = 756; // hardcoded ;D // What is closer ? diff_max = input_maxmin[i].max - sum; diff_min = sum - input_maxmin[i].min; if(diff_max < 60) what = 1; char buf[256]; sprintf(buf, "%i -- max:%i > curr:%i > min:%i", what, input_maxmin[i].max, sum, input_maxmin[i].min); SetWindowText(input_desc[i], buf); if(i == 0) Cfirst = (bool)what; else if(i == 9) Clast = (bool)what; else Cdata |= what << (8-i); // Select color unsigned char r,g,b; r = 0; g = 0; b = 0xff; if(what) { r = 0xff; g = 0; b = 0; } int j; int from, to; from = input[i].x - 5 >= 0 ? input[i].x - 5 : 0; to = input[i].x + 5 < ImgW ? input[i].x + 5 : ImgW; for(j = from; j <= to; j++) { ImgData[input[i].y * ImgW + j].r = r; ImgData[input[i].y * ImgW + j].g = g; ImgData[input[i].y * ImgW + j].b = b; } from = input[i].y - 5 >= 0 ? input[i].y - 5 : 0; to = input[i].y + 5 < ImgH ? input[i].y + 5 : ImgH; for(j = from; j <= to; j++) { ImgData[input[i].x + j * ImgW].r = r; ImgData[input[i].x + j * ImgW].g = g; ImgData[input[i].x + j * ImgW].b = b; } } if(Clast == Cfirst) // checksum { if(LastData != Clast) // New Data { LastData = Clast; printf("Data: %.2x\n", StoredData[StoredDataEnd/2]); FILE *f = fopen("recvdata.bin", "ab"); if(f) { fwrite(&StoredData[StoredDataEnd/2], 1, 1, f); fclose(f); } StoredDataEnd = 0; StoredData[StoredDataEnd++] = Cdata; } else // Still showing old data { StoredData[StoredDataEnd++] = Cdata; } } RECT r = { 0, ImgH+10, ImgW, ImgH*2 + 10 }; InvalidateRect(ImgWin, &r, false); UpdateWindow(ImgWin); } return 0; } /* funkcja glowna */ int main(int argc, char **argv) { int DriverId = -1; // Args if(argc != 2) { Usage(); DriverList(); return 1; } if(sscanf(argv[1], "%i", &DriverId) != 1) { Usage(); return 2; } LoadInputInfo(); // Window stuff MSG Msg; HWND hwnd; hwnd = CreateMainWindow(1024, 768); if(!hwnd) return 3; ImgWin = hwnd; // Camera window stuff HWND chwnd; chwnd = capCreateCaptureWindow( "Something", WS_CHILD | WS_VISIBLE, 0, 0, 352, 288, hwnd, (int) 1); if(!chwnd) { puts("Failed to create camera window"); return 4; } int status; status = capDriverConnect(chwnd, 0); if(status == FALSE) { puts("Failed to connect driver"); return 5; } // Display some options CAPDRIVERCAPS DrvCaps; capDriverGetCaps(chwnd, &DrvCaps, sizeof(DrvCaps)); if(DrvCaps.fHasDlgVideoSource) capDlgVideoSource(chwnd); if(DrvCaps.fHasDlgVideoFormat) capDlgVideoFormat(chwnd); if(DrvCaps.fHasDlgVideoDisplay) capDlgVideoDisplay(chwnd); // Allocate buffer CAPSTATUS CapStatus; capGetStatus(chwnd, &CapStatus, sizeof(CapStatus)); printf("Img dim: %i %i\n", CapStatus.uiImageWidth, CapStatus.uiImageHeight); ImgData = new BGR[CapStatus.uiImageWidth * CapStatus.uiImageHeight]; bmhdr.biWidth = CapStatus.uiImageWidth; bmhdr.biHeight = -CapStatus.uiImageHeight; ImgW = CapStatus.uiImageWidth; ImgH = CapStatus.uiImageHeight; // Add buttons int i; for(i=0;i<10;i++) { char name[256]; sprintf(name, "Select input %i", i); CreateWindowEx(0, "button", name, WS_CHILD | WS_VISIBLE, ImgW + 10, 30 * i, 100, 25, hwnd, (HMENU)(0x1000 +i), GetModuleHandle(0), NULL); input_desc[i] = CreateWindowEx(0, "static", name, WS_CHILD | WS_VISIBLE, ImgW + 10 + 100, 30 * i, 300, 25, hwnd, (HMENU)(0), GetModuleHandle(0), NULL); } // Setup callback capSetCallbackOnFrame(chwnd, CamCallback); // Start preview capPreviewRate(chwnd, 30); capPreview(chwnd, TRUE); //capOverlay(chwnd, TRUE); // Show main window and enter the loop ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); while(GetMessage( &Msg, NULL, 0, 0)) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return Msg.wParam; } /* callback WndProc */ LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { PAINTSTRUCT ps; HDC hdc; int status; static WORD CurrentInputSelection; switch( msg ) { case WM_CLOSE: DestroyWindow( hwnd ); break; case WM_DESTROY: PostQuitMessage( 0 ); break; case WM_COMMAND: { WORD code = (WORD)wParam; if(code >= 0x1000 && code <= 0x1009) { printf("Select (click on the lower preview) input coordinates for input source %i\n", code - 0x1000); CurrentInputSelection = code; } } break; case WM_LBUTTONDOWN: { if(CurrentInputSelection) { int xPos, yPos; xPos = LOWORD(lParam); yPos = HIWORD(lParam) - ImgH - 10; printf("%i %i\n", xPos, yPos); input[CurrentInputSelection - 0x1000].x = xPos; input[CurrentInputSelection - 0x1000].y = yPos; SaveInputInfo(); CurrentInputSelection = 0; } } break; case WM_PAINT: if(ImgData) { hdc = BeginPaint(hwnd, &ps); status = StretchDIBits(hdc, 0, ImgH+10, ImgW, ImgH, 0, 0, ImgW, ImgH, ImgData, (BITMAPINFO*)&bmhdr, DIB_RGB_COLORS, SRCCOPY); EndPaint(hwnd, &ps); } break; default: return DefWindowProc( hwnd, msg, wParam, lParam ); } return 0; }