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
24 #include <libfprint/fprint.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
;
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;\
49 y = y > 255 ? 255 : y;\
50 u = u > 255 ? 255 : u;\
53 static void grey2yuy2 (unsigned char *grey
, unsigned char *YUV
, int num
) {
55 int y0
, y1
, u0
, u1
, v0
, v1
;
58 for (i
= 0, j
= 0; i
< num
; i
+= 2, j
+= 4)
61 GREY2YUV (gval
, y0
, u0
, v0
);
63 GREY2YUV (gval
, y1
, u1
, v1
);
65 YUV
[j
+ 1] = (u0
+u1
)/2;
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
);
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
);
91 XvImageFormatValues
*formats
= NULL
;
95 XvQueryAdaptors(display
, DefaultRootWindow(display
), &num_adaptors
,
98 for(i
= 0; i
< num_adaptors
; i
++) {
99 formats
= XvListImageFormats(display
, info
[i
].base_id
,
101 for(j
= 0; j
< num_formats
; j
++) {
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");
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
;
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
));
139 long background
=0x010203;
140 struct fp_dscv_dev
*ddev
;
141 struct fp_dscv_dev
**discovered_devs
;
149 fprintf(stderr
, "Failed to initialize libfprint\n");
153 discovered_devs
= fp_discover_devs();
154 if (!discovered_devs
) {
155 fprintf(stderr
, "Could not discover devices\n");
159 ddev
= discover_device(discovered_devs
);
161 fprintf(stderr
, "No devices detected.\n");
165 dev
= fp_dev_open(ddev
);
166 fp_dscv_devs_free(discovered_devs
);
168 fprintf(stderr
, "Could not open device.\n");
172 if (!fp_dev_supports_imaging(dev
)) {
173 fprintf(stderr
, "this device does not have imaging capabilities.\n");
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");
184 framebuffer
= malloc(img_width
* img_height
* 2);
188 /* make the window */
189 display
= XOpenDisplay(getenv("DISPLAY"));
190 if(display
== NULL
) {
191 fprintf(stderr
,"Could not open display \"%s\"\n",
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 */
216 r
= fp_dev_img_capture(dev
, 1, &img
);
218 fprintf(stderr
, "image capture failed, code %d\n", r
);
222 fp_img_standardize(img
);
228 while (XPending(display
) > 0) {
229 XNextEvent(display
, &xev
);
230 if (xev
.type
!= KeyPress
)
233 switch (XKeycodeToKeysym(display
, xev
.xkey
.keycode
, 0)) {
241 standardize
= !standardize
;
252 if ((void *) window
!= NULL
)
253 XUnmapWindow(display
, window
);