#include "image.hpp" #include "state.hpp" #ifdef __APPLE__ #include #include #include #else #include #include #endif #include #include #include #include #include #include #include #include #include using namespace std; const uint16_t PORT = 8081; const uint16_t BUFFER_SIZE = 2048; GLuint imageTexture; GLuint blankTexture; GLint screenWidth = 0; GLint screenHeight = 0; Image img; State state; void actionDisplay () { } void actionLoad () { string imagePath = state.getImage(); vector position = state.getPosition(); Mat image = img.loadImage(imagePath, position[0], position[1], position[2], position[3]); glGenTextures(2, &imageTexture); glBindTexture(GL_TEXTURE_2D, imageTexture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexImage2D(GL_TEXTURE_2D, // Type of texture 0, // Pyramid level (for mip-mapping) - 0 is the top level GL_RGB, // Internal colour format to convert to image.cols, // Image width i.e. 640 for Kinect in standard mode image.rows, // Image height i.e. 480 for Kinect in standard mode 0, // Border width in pixels (can either be 1 or 0) GL_RGB, // Input image format (i.e. GL_RGB, GL_RGBA, GL_BGR etc.) GL_UNSIGNED_BYTE, // Image data type image.ptr()); // The actual image data itself } void actionStop () { } void loadBlank () { Mat blank = img.getBlank(); glGenTextures(1, &blankTexture); glBindTexture(GL_TEXTURE_2D, blankTexture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexImage2D(GL_TEXTURE_2D, // Type of texture 0, // Pyramid level (for mip-mapping) - 0 is the top level GL_RGB, // Internal colour format to convert to blank.cols, // Image width i.e. 640 for Kinect in standard mode blank.rows, // Image height i.e. 480 for Kinect in standard mode 0, // Border width in pixels (can either be 1 or 0) GL_RGB, // Input image format (i.e. GL_RGB, GL_RGBA, GL_BGR etc.) GL_UNSIGNED_BYTE, // Image data type blank.ptr()); // The actual image data itself } void display () { glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_TEXTURE_2D); glViewport(0, 0, screenWidth, screenHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); glBindTexture(GL_TEXTURE_2D, imageTexture); glBegin(GL_QUADS); // front face glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 0.0f); //bottom right glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f); //top right glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f); //top left glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 0.0f); //bottom left glEnd(); glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); glutSwapBuffers(); //glFlush(); } /** * State Message Variables **/ bool receivedMessage = false; bool sendMessage = false; string incomingMessage; string outgoingMessage; mutex receivedMutex; condition_variable receivedCondVar; mutex sendMutex; condition_variable sendCondVar; /** * **/ void processMessage () { if (receivedMessage) { cout << "RECEIVED" << endl; state.receiveMessage(incomingMessage); receivedMessage = false; while (state.isActive()) { if (state.getAction() == LOAD) { actionLoad(); } else if (state.getAction() == DISPLAY) { actionDisplay(); } else if (state.getAction() == STOP) { actionStop(); } } if (state.isError()) { outgoingMessage = state.createMessage(false); } else { outgoingMessage = state.createMessage(true); } sendMessage = true; } } void handleTCPConnection(int clientSocket) { char buffer[BUFFER_SIZE]; memset(buffer, 0, BUFFER_SIZE); while (true) { int bytesRead = recv(clientSocket, buffer, BUFFER_SIZE - 1, 0); if (bytesRead <= 0) { cerr << "Client disconnected or errored out" << endl; break; } string localIncomingMessage(buffer, bytesRead); { lock_guard lock(receivedMutex); receivedMessage = true; sendMessage = false; incomingMessage = localIncomingMessage; receivedCondVar.notify_all(); } processMessage(); bool localSendMessage; string localOutgoingMessage; { unique_lock lock(sendMutex); sendCondVar.wait(lock, [&] { return sendMessage; }); localSendMessage = sendMessage; localOutgoingMessage = outgoingMessage; } if (localSendMessage) { const char* msg = localOutgoingMessage.c_str(); int bytesSent = send(clientSocket, msg, strlen(msg), 0); if (bytesSent < 0) { cerr << "Error sending ACK to client" << endl; break; } } memset(buffer, 0, BUFFER_SIZE); } } void runTCPServer (int serverSocket) { while (true) { struct sockaddr_in clientAddr; socklen_t clientAddrLen = sizeof(clientAddr); int clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddr, &clientAddrLen); if (clientSocket < 0) { cerr << "Error accepting client connection" << endl; continue; } cout << "New client connected" << endl; handleTCPConnection(clientSocket); } } uint8_t handleArgs (int argc, char** argv) { if (argc > 1) { screenWidth = atoi(argv[1]); cout << "Set width: " << screenWidth << endl; } else { cerr << "Please provide screen width as first argument" << endl; return 1; } if (argc > 2) { screenHeight = atoi(argv[2]); cout << "Set height: " << screenHeight << endl; } else { cerr << "Please provide screen height as second argument" << endl; return 2; } return 0; } int main (int argc, char** argv) { uint8_t argsRet = handleArgs(argc, argv); if (argsRet > 0) { return argsRet; } img.setDimensions( (uint16_t) screenWidth, (uint16_t) screenHeight); loadBlank(); glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE); glutCreateWindow("opengl_opencv_example"); glutSetCursor(GLUT_CURSOR_NONE); glutFullScreen(); glutDisplayFunc(display); glutMainLoop(); int serverSocket = socket(AF_INET, SOCK_STREAM, 0); if (serverSocket < 0) { cerr << "Error creating socket" << endl; return 1; } struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = INADDR_ANY; serverAddr.sin_port = htons(PORT); int bindResult = ::bind(serverSocket, reinterpret_cast(&serverAddr), sizeof(serverAddr)); if (bindResult < 0) { cerr << "Error binding socket" << endl; close(serverSocket); return 1; } if (listen(serverSocket, 5) < 0) { cerr << "Error listening on socket" << endl; return 1; } cout << "TCP server listening on port " << PORT << endl; thread serverThread(runTCPServer, serverSocket); serverThread.join(); close(serverSocket); return 0; }