Doc and build updates
[libfprint.git] / examples / img_capture_continuous.c
blob0f1644eb518be42e44c6225ee1cd6163f64d7b11
1 /*
2 * Example libfprint continuous image capture program
3 * Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
24 #include <libfprint/fprint.h>
25 #include <X11/Xlib.h>
26 #include <X11/keysym.h>
27 #include <X11/extensions/Xvlib.h>
29 #define FORMAT 0x32595559
31 static int adaptor = -1;
32 static unsigned char *framebuffer = NULL;
34 static Display *display = NULL;
35 static Window window=(Window)NULL;
36 static XvImage *xv_image = NULL;
37 static XvAdaptorInfo *info;
38 static GC gc;
39 static int connection = -1;
41 /* based on macro by Bart Nabbe */
42 #define GREY2YUV(grey, y, u, v)\
43 y = (9798*grey + 19235*grey + 3736*grey) / 32768;\
44 u = (-4784*grey - 9437*grey + 14221*grey) / 32768 + 128;\
45 v = (20218*grey - 16941*grey - 3277*grey) / 32768 + 128;\
46 y = y < 0 ? 0 : y;\
47 u = u < 0 ? 0 : u;\
48 v = v < 0 ? 0 : v;\
49 y = y > 255 ? 255 : y;\
50 u = u > 255 ? 255 : u;\
51 v = v > 255 ? 255 : v
53 static void grey2yuy2 (unsigned char *grey, unsigned char *YUV, int num) {
54 int i, j;
55 int y0, y1, u0, u1, v0, v1;
56 int gval;
58 for (i = 0, j = 0; i < num; i += 2, j += 4)
60 gval = grey[i];
61 GREY2YUV (gval, y0, u0 , v0);
62 gval = grey[i + 1];
63 GREY2YUV (gval, y1, u1 , v1);
64 YUV[j + 0] = y0;
65 YUV[j + 1] = (u0+u1)/2;
66 YUV[j + 2] = y1;
67 YUV[j + 3] = (v0+v1)/2;
71 static void display_frame(struct fp_img *img)
73 int width = fp_img_get_width(img);
74 int height = fp_img_get_height(img);
75 unsigned char *data = fp_img_get_data(img);
77 if (adaptor < 0)
78 return;
80 grey2yuy2(data, framebuffer, width * height);
81 xv_image = XvCreateImage(display, info[adaptor].base_id, FORMAT,
82 framebuffer, width, height);
83 XvPutImage(display, info[adaptor].base_id, window, gc, xv_image,
84 0, 0, width, height, 0, 0, width, height);
87 static void QueryXv()
89 int num_adaptors;
90 int num_formats;
91 XvImageFormatValues *formats = NULL;
92 int i,j;
93 char xv_name[5];
95 XvQueryAdaptors(display, DefaultRootWindow(display), &num_adaptors,
96 &info);
98 for(i = 0; i < num_adaptors; i++) {
99 formats = XvListImageFormats(display, info[i].base_id,
100 &num_formats);
101 for(j = 0; j < num_formats; j++) {
102 xv_name[4] = 0;
103 memcpy(xv_name, &formats[j].id, 4);
104 if(formats[j].id == FORMAT) {
105 printf("using Xv format 0x%x %s %s\n",
106 formats[j].id, xv_name,
107 (formats[j].format==XvPacked)
108 ? "packed" : "planar");
109 if (adaptor < 0)
110 adaptor = i;
114 XFree(formats);
115 if (adaptor < 0)
116 printf("No suitable Xv adaptor found\n");
119 static struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs)
121 struct fp_dscv_dev *ddev = NULL;
122 int i;
124 for (i = 0; ddev = discovered_devs[i]; i++) {
125 struct fp_driver *drv = fp_dscv_dev_get_driver(ddev);
126 printf("Found device claimed by %s driver\n",
127 fp_driver_get_full_name(drv));
128 return ddev;
131 return ddev;
134 int main(void)
136 int r = 1;
137 XEvent xev;
138 XGCValues xgcv;
139 long background=0x010203;
140 struct fp_dscv_dev *ddev;
141 struct fp_dscv_dev **discovered_devs;
142 struct fp_dev *dev;
143 int img_width;
144 int img_height;
145 int standardize = 0;
147 r = fp_init();
148 if (r < 0) {
149 fprintf(stderr, "Failed to initialize libfprint\n");
150 exit(1);
153 discovered_devs = fp_discover_devs();
154 if (!discovered_devs) {
155 fprintf(stderr, "Could not discover devices\n");
156 goto out;
159 ddev = discover_device(discovered_devs);
160 if (!ddev) {
161 fprintf(stderr, "No devices detected.\n");
162 goto out;
165 dev = fp_dev_open(ddev);
166 fp_dscv_devs_free(discovered_devs);
167 if (!dev) {
168 fprintf(stderr, "Could not open device.\n");
169 goto out;
172 if (!fp_dev_supports_imaging(dev)) {
173 fprintf(stderr, "this device does not have imaging capabilities.\n");
174 goto out_close;
177 img_width = fp_dev_get_img_width(dev);
178 img_height = fp_dev_get_img_height(dev);
179 if (img_width <= 0 || img_height <= 0) {
180 fprintf(stderr, "this device returns images with variable dimensions,"
181 " this example does not support that.\n");
182 goto out_close;
184 framebuffer = malloc(img_width * img_height * 2);
185 if (!framebuffer)
186 goto out_close;
188 /* make the window */
189 display = XOpenDisplay(getenv("DISPLAY"));
190 if(display == NULL) {
191 fprintf(stderr,"Could not open display \"%s\"\n",
192 getenv("DISPLAY"));
193 goto out_close;
196 QueryXv();
198 if (adaptor < 0)
199 goto out_close;
201 window = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0,
202 img_width, img_height, 0,
203 WhitePixel(display, DefaultScreen(display)), background);
205 XSelectInput(display, window, StructureNotifyMask | KeyPressMask);
206 XMapWindow(display, window);
207 connection = ConnectionNumber(display);
209 gc = XCreateGC(display, window, 0, &xgcv);
211 printf("Press S to toggle standardized mode, Q to quit\n");
213 while (1) { /* event loop */
214 struct fp_img *img;
216 r = fp_dev_img_capture(dev, 1, &img);
217 if (r) {
218 fprintf(stderr, "image capture failed, code %d\n", r);
219 goto out_close;
221 if (standardize)
222 fp_img_standardize(img);
224 display_frame(img);
225 fp_img_free(img);
226 XFlush(display);
228 while (XPending(display) > 0) {
229 XNextEvent(display, &xev);
230 if (xev.type != KeyPress)
231 continue;
233 switch (XKeycodeToKeysym(display, xev.xkey.keycode, 0)) {
234 case XK_q:
235 case XK_Q:
236 r = 0;
237 goto out_close;
238 break;
239 case XK_s:
240 case XK_S:
241 standardize = !standardize;
242 break;
244 } /* XPending */
247 r = 0;
248 out_close:
249 if (framebuffer)
250 free(framebuffer);
251 fp_dev_close(dev);
252 if ((void *) window != NULL)
253 XUnmapWindow(display, window);
254 if (display != NULL)
255 XFlush(display);
256 out:
257 fp_exit();
258 return r;