diff options
Diffstat (limited to 'circuitpython/lib/quirc/demo/demo.c')
-rw-r--r-- | circuitpython/lib/quirc/demo/demo.c | 333 |
1 files changed, 333 insertions, 0 deletions
diff --git a/circuitpython/lib/quirc/demo/demo.c b/circuitpython/lib/quirc/demo/demo.c new file mode 100644 index 0000000..178fde8 --- /dev/null +++ b/circuitpython/lib/quirc/demo/demo.c @@ -0,0 +1,333 @@ +/* quirc -- QR-code recognition library + * Copyright (C) 2010-2012 Daniel Beer <dlbeer@gmail.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <unistd.h> +#include <SDL.h> +#include <SDL_gfxPrimitives.h> +#include <quirc.h> +#include <time.h> +#include <getopt.h> + +#include "camera.h" +#include "mjpeg.h" +#include "convert.h" +#include "dthash.h" +#include "demoutil.h" + +/* Collected command-line arguments */ +static const char *camera_path = "/dev/video0"; +static int video_width = 640; +static int video_height = 480; +static int want_frame_rate = 0; +static int want_verbose = 0; +static int printer_timeout = 2; + +static void fat_text(SDL_Surface *screen, int x, int y, const char *text) +{ + int i, j; + + for (i = -1; i <= 1; i++) + for (j = -1; j <= 1; j++) + stringColor(screen, x + i, y + j, text, 0xffffffff); + stringColor(screen, x, y, text, 0x008000ff); +} + +static void fat_text_cent(SDL_Surface *screen, int x, int y, const char *text) +{ + x -= strlen(text) * 4; + + fat_text(screen, x, y, text); +} + +static void draw_qr(SDL_Surface *screen, struct quirc *q, struct dthash *dt) +{ + int count = quirc_count(q); + int i; + + for (i = 0; i < count; i++) { + struct quirc_code code; + struct quirc_data data; + quirc_decode_error_t err; + int j; + int xc = 0; + int yc = 0; + char buf[128]; + + quirc_extract(q, i, &code); + + for (j = 0; j < 4; j++) { + struct quirc_point *a = &code.corners[j]; + struct quirc_point *b = &code.corners[(j + 1) % 4]; + + xc += a->x; + yc += a->y; + lineColor(screen, a->x, a->y, b->x, b->y, 0x008000ff); + } + + xc /= 4; + yc /= 4; + + if (want_verbose) { + snprintf(buf, sizeof(buf), "Code size: %d cells", + code.size); + fat_text_cent(screen, xc, yc - 20, buf); + } + + err = quirc_decode(&code, &data); + + if (err) { + if (want_verbose) + fat_text_cent(screen, xc, yc, + quirc_strerror(err)); + } else { + fat_text_cent(screen, xc, yc, (char *)data.payload); + print_data(&data, dt, want_verbose); + + if (want_verbose) { + snprintf(buf, sizeof(buf), + "Ver: %d, ECC: %c, Mask: %d, Type: %d", + data.version, "MLHQ"[data.ecc_level], + data.mask, data.data_type); + fat_text_cent(screen, xc, yc + 20, buf); + } + } + } +} + +static int main_loop(struct camera *cam, SDL_Surface *screen, + struct quirc *q, struct mjpeg_decoder *mj) +{ + SDL_Event ev; + time_t last_rate = 0; + int frame_count = 0; + char rate_text[64]; + struct dthash dt; + + rate_text[0] = 0; + dthash_init(&dt, printer_timeout); + + for (;;) { + time_t now = time(NULL); + const struct camera_buffer *head; + const struct camera_parms *parms = camera_get_parms(cam); + + if (camera_dequeue_one(cam) < 0) { + perror("camera_dequeue_one"); + return -1; + } + + head = camera_get_head(cam); + + SDL_LockSurface(screen); + switch (parms->format) { + case CAMERA_FORMAT_MJPEG: + mjpeg_decode_rgb32(mj, head->addr, head->size, + screen->pixels, screen->pitch, + screen->w, screen->h); + break; + + case CAMERA_FORMAT_YUYV: + yuyv_to_rgb32(head->addr, parms->width * 2, + parms->width, parms->height, + screen->pixels, screen->pitch); + break; + + default: + fprintf(stderr, "Unknown frame format\n"); + return -1; + } + + if (camera_enqueue_all(cam) < 0) { + perror("camera_enqueue_all"); + return -1; + } + + rgb32_to_luma(screen->pixels, screen->pitch, + screen->w, screen->h, + quirc_begin(q, NULL, NULL), + screen->w); + quirc_end(q); + SDL_UnlockSurface(screen); + + draw_qr(screen, q, &dt); + if (want_frame_rate) + fat_text(screen, 5, 5, rate_text); + SDL_Flip(screen); + + while (SDL_PollEvent(&ev) > 0) { + if (ev.type == SDL_QUIT) + return 0; + + if (ev.type == SDL_KEYDOWN && ev.key.keysym.sym == 'q') + return 0; + } + + if (now != last_rate) { + snprintf(rate_text, sizeof(rate_text), + "Frame rate: %d fps", frame_count); + frame_count = 0; + last_rate = now; + } + + frame_count++; + } +} + +static int run_demo(void) +{ + struct quirc *qr; + struct camera cam; + struct mjpeg_decoder mj; + const struct camera_parms *parms; + SDL_Surface *screen; + + camera_init(&cam); + if (camera_open(&cam, camera_path, video_width, video_height, + 25, 1) < 0) { + perror("camera_open"); + goto fail_qr; + } + + if (camera_map(&cam, 8) < 0) { + perror("camera_map"); + goto fail_qr; + } + + if (camera_on(&cam) < 0) { + perror("camera_on"); + goto fail_qr; + } + + if (camera_enqueue_all(&cam) < 0) { + perror("camera_enqueue_all"); + goto fail_qr; + } + + parms = camera_get_parms(&cam); + + qr = quirc_new(); + if (!qr) { + perror("couldn't allocate QR decoder"); + goto fail_qr; + } + + if (quirc_resize(qr, parms->width, parms->height) < 0) { + perror("couldn't allocate QR buffer"); + goto fail_qr_resize; + } + + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + perror("couldn't init SDL"); + goto fail_sdl_init; + } + + screen = SDL_SetVideoMode(parms->width, parms->height, 32, + SDL_SWSURFACE | SDL_DOUBLEBUF); + if (!screen) { + perror("couldn't init video mode"); + goto fail_video_mode; + } + + mjpeg_init(&mj); + if (main_loop(&cam, screen, qr, &mj) < 0) + goto fail_main_loop; + mjpeg_free(&mj); + + SDL_Quit(); + quirc_destroy(qr); + camera_destroy(&cam); + + return 0; + +fail_main_loop: + mjpeg_free(&mj); +fail_video_mode: + SDL_Quit(); +fail_qr_resize: +fail_sdl_init: + quirc_destroy(qr); +fail_qr: + camera_destroy(&cam); + + return -1; +} + +static void usage(const char *progname) +{ + printf("Usage: %s [options]\n\n" +"Valid options are:\n\n" +" -f Show frame rate on screen.\n" +" -v Show extra data for detected codes.\n" +" -d <device> Specify camera device path.\n" +" -s <WxH> Specify video dimensions.\n" +" -p <timeout> Set printer timeout (seconds).\n" +" --help Show this information.\n" +" --version Show library version information.\n", + progname); +} + +int main(int argc, char **argv) +{ + static const struct option longopts[] = { + {"help", 0, 0, 'H'}, + {"version", 0, 0, 'V'}, + {NULL, 0, 0, 0} + }; + int opt; + + printf("quirc demo\n"); + printf("Copyright (C) 2010-2014 Daniel Beer <dlbeer@gmail.com>\n"); + printf("\n"); + + while ((opt = getopt_long(argc, argv, "d:s:fvg:p:", + longopts, NULL)) >= 0) + switch (opt) { + case 'V': + printf("Library version: %s\n", quirc_version()); + return 0; + + case 'H': + usage(argv[0]); + return 0; + + case 'v': + want_verbose = 1; + break; + + case 'f': + want_frame_rate = 1; + break; + + case 's': + if (parse_size(optarg, &video_width, &video_height) < 0) + return -1; + break; + + case 'p': + printer_timeout = atoi(optarg); + break; + + case 'd': + camera_path = optarg; + break; + + case '?': + fprintf(stderr, "Try --help for usage information\n"); + return -1; + } + + return run_demo(); +} |