/* openpnp test application Niels Moseley */ #include #include #include #include #include #include #include "openpnp-capture.h" #include "../common/context.h" #include "../common/logging.h" typedef struct { GtkImage *image; int32_t rows, cols, stride; CapContext ctx; int32_t streamID; bool takeSnapshot; uint32_t snapshotCounter; int32_t zoom,gain,exposure,wbalance,focus; int32_t exposure_step; int32_t gstep,wbstep; int32_t fps; } CallbackInfo; void free_pixels(guchar *pixels, gpointer data) { free(pixels); } static void activate(GtkApplication* app, gpointer user_data) { GtkWidget *window; window = gtk_application_window_new (app); gtk_window_set_title (GTK_WINDOW (window), "OpenPnP Capture"); gtk_window_set_default_size (GTK_WINDOW (window), 640, 480); gtk_widget_show_all (window); } static void triggerSnapshot(GtkWidget *widget, gpointer data) { CallbackInfo *id = (CallbackInfo*)data; id->takeSnapshot = true; printf("Snapshot triggered!\n"); } void showAutoProperty(CapContext ctx, int32_t streamID, uint32_t propertyID) { uint32_t bValue; if (Cap_getAutoProperty(ctx, streamID, propertyID, &bValue)==CAPRESULT_OK) { if (bValue) { printf("Auto\n"); } else { printf("Manual\n"); } } else { printf("Unsupported\n"); } } void showAutoProperties(CapContext ctx, int32_t streamID) { printf("--= Automatic =--\n"); printf("White balance: "); showAutoProperty(ctx, streamID, CAPPROPID_WHITEBALANCE); printf("Exposure : "); showAutoProperty(ctx, streamID, CAPPROPID_EXPOSURE); printf("Focus : "); showAutoProperty(ctx, streamID, CAPPROPID_FOCUS); printf("Gain : "); showAutoProperty(ctx, streamID, CAPPROPID_GAIN); } void showProperty(CapContext ctx, int32_t streamID, uint32_t propertyID) { int32_t value; if (Cap_getProperty(ctx, streamID, propertyID, &value)==CAPRESULT_OK) { printf("%d\n", value); } else { printf("Unsupported\n"); } } void showProperties(CapContext ctx, int32_t streamID) { printf("White balance: "); showProperty(ctx, streamID, CAPPROPID_WHITEBALANCE); printf("Exposure : "); showProperty(ctx, streamID, CAPPROPID_EXPOSURE); printf("Focus : "); showProperty(ctx, streamID, CAPPROPID_FOCUS); printf("Zoom : "); showProperty(ctx, streamID, CAPPROPID_ZOOM); printf("Gain : "); showProperty(ctx, streamID, CAPPROPID_GAIN); } bool writeBufferAsPPM(uint32_t frameNum, uint32_t width, uint32_t height, const uint8_t *bufferPtr, size_t bytes) { char fname[100]; sprintf(fname, "frame_%d.ppm",frameNum); FILE *fout = fopen(fname, "wb"); if (fout == 0) { fprintf(stderr, "Cannot open %s for writing\n", fname); return false; } fprintf(fout, "P6 %d %d 255\n", width, height); // PGM header fwrite(bufferPtr, 1, bytes, fout); fclose(fout); return true; } int updatePicture(gpointer data) { //static int N = 0; //if (N > 100) return FALSE; // stop timer CallbackInfo *id = (CallbackInfo*)data; GdkPixbuf *pb = gtk_image_get_pixbuf(id->image); gdk_pixbuf_fill(pb, 0); // clear to black guchar *g = gdk_pixbuf_get_pixels(pb); if (Cap_hasNewFrame(id->ctx, id->streamID)==1) { if (Cap_captureFrame(id->ctx, id->streamID, g, id->cols * id->rows * 3) == CAPRESULT_OK) { LOG(LOG_VERBOSE, "Cap ACK\n"); gtk_image_set_from_pixbuf(GTK_IMAGE(id->image), pb); if (id->takeSnapshot) { id->takeSnapshot = false; writeBufferAsPPM(id->snapshotCounter++, id->cols, id->rows, g, id->cols * id->rows * 3); } } else { LOG(LOG_VERBOSE, "Cap NACK\n"); } } return TRUE; // continue timer } void estimateFrameRate(CapContext ctx, int32_t streamID) { std::chrono::time_point tstart, tend; tstart = std::chrono::system_clock::now(); uint32_t fstart = Cap_getStreamFrameCount(ctx, streamID); usleep(2000000); // 2-second wait uint32_t fend = Cap_getStreamFrameCount(ctx, streamID); tend = std::chrono::system_clock::now(); std::chrono::duration fsec = tend-tstart; uint32_t frames = fend - fstart; printf("Frames = %d\n", frames); std::chrono::milliseconds d = std::chrono::duration_cast(fsec); printf("Measured fps=%5.2f\n", 1000.0f*frames/static_cast(d.count())); fflush(stdout); } gboolean on_key_press (GtkWidget *widget, GdkEventKey *event, gpointer data) { if (data == nullptr) { return FALSE; } if (event == nullptr) { return FALSE; } CallbackInfo *ptr = (CallbackInfo*)data; CapContext ctx = ptr->ctx; int32_t streamID = ptr->streamID; switch(event->keyval) { case 'q': gtk_main_quit(); return TRUE; case '+': ptr->exposure += ptr->exposure_step; Cap_setProperty(ctx, streamID, CAPPROPID_EXPOSURE, ptr->exposure); printf("exposure: %d\r", ptr->exposure); fflush(stdout); return TRUE; case '-': ptr->exposure -= ptr->exposure_step; Cap_setProperty(ctx, streamID, CAPPROPID_EXPOSURE, ptr->exposure); printf("exposure: %d\r", ptr->exposure); fflush(stdout); return TRUE; case '0': printf("0"); fflush(stdout); ptr->exposure = 0; Cap_setProperty(ctx, streamID, CAPPROPID_EXPOSURE, ptr->exposure); return TRUE; case '1': printf("manual exposure\n"); fflush(stdout); Cap_setAutoProperty(ctx, streamID, CAPPROPID_EXPOSURE, 0); return TRUE; case '2': printf("auto exposure\n"); fflush(stdout); Cap_setAutoProperty(ctx, streamID, CAPPROPID_EXPOSURE, 1); return TRUE; #if 0 case '3': ptr->fps--; Cap_setFrameRate(ctx, streamID, ptr->fps); printf("framerate = %d\n", ptr->fps); fflush(stdout); return TRUE; case '4': ptr->fps++; Cap_setFrameRate(ctx, streamID, ptr->fps); printf("framerate = %d\n", ptr->fps); fflush(stdout); return TRUE; #endif case 'f': Cap_setProperty(ctx, streamID, CAPPROPID_FOCUS, ++ptr->focus); printf("focus = %d \r", ptr->focus); fflush(stdout); return TRUE; case 'g': Cap_setProperty(ctx, streamID, CAPPROPID_FOCUS, --ptr->focus); printf("focus = %d \r", ptr->focus); fflush(stdout); return TRUE; case 'z': Cap_setProperty(ctx, streamID, CAPPROPID_ZOOM, ++ptr->zoom); printf("zoom = %d \r", ptr->zoom); fflush(stdout); return TRUE; case 'x': Cap_setProperty(ctx, streamID, CAPPROPID_ZOOM, --ptr->zoom); printf("zoom = %d \r", ptr->zoom); fflush(stdout); return TRUE; case '[': ptr->wbalance -= ptr->wbstep; Cap_setProperty(ctx, streamID, CAPPROPID_WHITEBALANCE, ptr->wbalance); printf("wbal = %d \r", ptr->wbalance); fflush(stdout); return TRUE; case ']': ptr->wbalance += ptr->wbstep; Cap_setProperty(ctx, streamID, CAPPROPID_WHITEBALANCE, ptr->wbalance); printf("wbal = %d \r", ptr->wbalance); fflush(stdout); return TRUE; case 'a': ptr->gain -= ptr->gstep; Cap_setProperty(ctx, streamID, CAPPROPID_GAIN, ptr->gain); printf("gain = %d \r", ptr->gain); fflush(stdout); return TRUE; case 's': ptr->gain += ptr->gstep; Cap_setProperty(ctx, streamID, CAPPROPID_GAIN, ptr->gain); printf("gain = %d \r", ptr->gain); fflush(stdout); return TRUE; case 'd': printf("Camera configuration:\n"); showProperties(ctx, streamID); showAutoProperties(ctx, streamID); printf("\n"); fflush(stdout); return TRUE; case 'p': printf("Estimating frame rate..\n"); estimateFrameRate(ctx, streamID); fflush(stdout); return TRUE; case 'w': printf("Writing frame to disk..\n"); ptr->takeSnapshot = true; return TRUE; default: return FALSE; } return FALSE; } std::string FourCCToString(uint32_t fourcc) { std::string v; for(uint32_t i=0; i<4; i++) { v += static_cast(fourcc & 0xFF); fourcc >>= 8; } return v; } int main (int argc, char *argv[]) { // https://cboard.cprogramming.com/c-programming/172801-how-display-2d-array-image-using-gtk3plus.html GtkApplication *app; GtkWidget *button; GtkWidget *button_box; int status; uint32_t deviceFormatID = 0; uint32_t deviceID = 0; gtk_init(&argc, &argv); printf("==============================\n"); printf(" OpenPNP Capture Test Program\n"); printf(" %s\n", Cap_getLibraryVersion()); printf("==============================\n"); Cap_setLogLevel(7); if (argc == 1) { printf("Usage: openpnp-capture-test \n"); printf("\n..continuing with default camera parameters.\n\n"); } if (argc >= 2) { deviceID = atoi(argv[1]); } if (argc >= 3) { deviceFormatID = atoi(argv[2]); } CapContext ctx = Cap_createContext(); uint32_t deviceCount = Cap_getDeviceCount(ctx); printf("Number of devices: %d\n", deviceCount); for(uint32_t i=0; i %s\n", i, Cap_getDeviceName(ctx,i)); printf("Unique: %s\n", Cap_getDeviceUniqueID(ctx,i)); // show all supported frame buffer formats int32_t nFormats = Cap_getNumFormats(ctx, i); printf(" Number of formats: %d\n", nFormats); std::string fourccString; for(int32_t j=0; j m_buffer; m_buffer.resize(finfo.width*finfo.height*3); #if 0 if (Cap_captureFrame(ctx, streamID, &m_buffer[0], m_buffer.size()) == CAPRESULT_OK) { printf("Buffer captured!\n"); FILE *fout = fopen("image.ppm", "wb"); fprintf(fout, "P6 %d %d 255\n", finfo.width, finfo.height); // PGM header // exchange BGR to RGB uint32_t idx = 0; for(uint32_t i=0; i