fingerprint-ruby 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MjA4YmM3MWJkODZiYzU4NzQ2MjMxOWU0MzhjNGFkNDIyYmNmMTJiNw==
5
+ data.tar.gz: !binary |-
6
+ NDkyZGQzZTdkZDI0YTU2NzlhNzAwYTRiMDk4NTU1Njg1N2VjY2IzNg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MWJiODhiOTE2ZDA5Y2ZhNGFiYTdjMjg4MjZjNmUzZmFmMWRlMGNiYjhiNTU5
10
+ NmM2M2E2NGQzNzk5MDM2YTZlZGJkMTAwNjljYWJmZjExODM0MGI1YTFjYmQ2
11
+ ODViMDEwYzUxNTRhOTRiY2I2ZTczYzc1MjI0MDVhODU1ZTlmZDA=
12
+ data.tar.gz: !binary |-
13
+ ZDE4ODY3OGFhOGFhNzgzNTg2NWJjOTgwOGY5MWExNTY2ODE5YTBmY2I0ZDM4
14
+ ZTgzYWFlMWVmMjQyYTg3MDMxZGEyYzRjMzEyODI0MzQxMDFhMzE1M2EyYWM3
15
+ ODlkZDM1ZDNjZWZmYWJiYThmOGM2MTZkNmIwMjg5NDEwZDQzMjE=
@@ -0,0 +1,58 @@
1
+ #include <iostream>
2
+ #include <fstream>
3
+ #include <unistd.h>
4
+ #include "compare.h"
5
+
6
+ using namespace std;
7
+
8
+ bool VerifyUser( std::string db_file,
9
+ std::string print_file) {
10
+ unsigned char *dbFmd = NULL, *printFmd = NULL;
11
+ unsigned int dbFmdSize = 0, printFmdSize = 0;
12
+
13
+ LoadPrint(db_file, &dbFmd, &dbFmdSize);
14
+ LoadPrint(print_file, &printFmd, &printFmdSize);
15
+
16
+ return VerifyUser(dbFmd, dbFmdSize, printFmd, printFmdSize);
17
+ }
18
+
19
+ bool VerifyUser( unsigned char* dbPrint,
20
+ unsigned int dbPrintSize,
21
+ unsigned char* print,
22
+ unsigned int printSize) {
23
+
24
+ // Only compare if both fingerprints have data
25
+ if(dbPrintSize > 0 && printSize > 0) {
26
+ unsigned int falsematch_rate;
27
+ int result = dpfj_compare(DPFJ_FMD_ANSI_378_2004, dbPrint, dbPrintSize, 0,
28
+ DPFJ_FMD_ANSI_378_2004, print, printSize, 0, &falsematch_rate);
29
+
30
+ // If the comparison was successful and the prints matched
31
+ if(result == DPFJ_SUCCESS && falsematch_rate < TARGET_FALSEMATCH_RATE) {
32
+ return true;
33
+ }
34
+ }
35
+
36
+ return false;
37
+ }
38
+
39
+ void LoadPrint( std::string file,
40
+ unsigned char** print,
41
+ unsigned int* printSize) {
42
+
43
+ // Open the file in binary mode
44
+ ifstream input(file.c_str(), ios::in | ios::binary | ios::ate);
45
+
46
+ // Only try if the file exists
47
+ if(input.is_open()) {
48
+ // Figure out the file size and allocate memory
49
+ // for the data
50
+ *printSize = (unsigned int) input.tellg();
51
+ *print = new unsigned char[*printSize];
52
+
53
+ // Read the file data from the beginning
54
+ input.seekg(0, ios::beg);
55
+ input.read((char*) (*print), *printSize);
56
+ input.close();
57
+ }
58
+ }
@@ -0,0 +1,31 @@
1
+ /*
2
+ * Provides methods needed to compare fingerprints.
3
+ */
4
+
5
+ #ifndef COMPARE_H_
6
+ #define COMPARE_H_
7
+
8
+ #include <string>
9
+ #include <dpfj.h>
10
+ #include <dpfpdd.h>
11
+
12
+ // Target accuracy of fingerprint comparison
13
+ #define TARGET_FALSEMATCH_RATE (DPFJ_PROBABILITY_ONE / 100000)
14
+
15
+ // Compares the fingerprints in the two provided files
16
+ bool VerifyUser( std::string db_file,
17
+ std::string print_file);
18
+
19
+ // Compares the fingerprints in the two provided buffers
20
+ bool VerifyUser( unsigned char* dbPrint,
21
+ unsigned int dbPrintSize,
22
+ unsigned char* print,
23
+ unsigned int printSize);
24
+
25
+ // Loads a fingerprint from the specified file into the
26
+ // supplied buffer
27
+ void LoadPrint( std::string file,
28
+ unsigned char** print,
29
+ unsigned int* printSize);
30
+
31
+ #endif /*COMPARE_H_*/
@@ -0,0 +1,19 @@
1
+ require 'mkmf'
2
+
3
+ def bits
4
+ ['bits'].pack('p').size * 8
5
+ end
6
+
7
+ library_dir = File.realpath(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'u_are_u', "lib#{bits}"))
8
+
9
+ dir_config('', 'compare', 'compare')
10
+ dir_config('', 'u_are_u', 'u_are_u')
11
+ dir_config('', library_dir, library_dir)
12
+
13
+ have_library('dpfj') or raise
14
+ have_library('dpfpdd') or raise
15
+ have_library('stdc++') or raise
16
+
17
+ $objs = ['fingerprint.o', 'compare/compare.o']
18
+
19
+ create_makefile('keyme/fingerprint')
@@ -0,0 +1,77 @@
1
+ #include <stdio.h>
2
+
3
+ #include "ruby.h"
4
+ #include "compare/compare.h"
5
+
6
+ VALUE verify_user_wrapper(VALUE self, VALUE db_print, VALUE check_print) {
7
+ bool result;
8
+ unsigned char *db, *check;
9
+ unsigned int db_len, check_len;
10
+
11
+ Check_Type(db_print, T_ARRAY);
12
+ Check_Type(check_print, T_ARRAY);
13
+
14
+ db_len = RARRAY_LEN(db_print);
15
+ check_len = RARRAY_LEN(check_print);
16
+
17
+ db = (unsigned char*) malloc(db_len);
18
+ check = (unsigned char*) malloc(check_len);
19
+
20
+ for(unsigned int i = 0; i < db_len; i++) {
21
+ db[i] = NUM2UINT(rb_ary_entry(db_print, i));
22
+ }
23
+ for(unsigned int i = 0; i < check_len; i++) {
24
+ check[i] = NUM2UINT(rb_ary_entry(check_print, i));
25
+ }
26
+
27
+ result = VerifyUser(db, db_len, check, check_len);
28
+
29
+ free(db);
30
+ free(check);
31
+
32
+ return result ? Qtrue : Qfalse;
33
+ }
34
+
35
+ VALUE load_print_wrapper(VALUE self, VALUE path) {
36
+ VALUE result;
37
+ unsigned char *print;
38
+ unsigned int printSize;
39
+
40
+ Check_Type(path, T_STRING);
41
+ LoadPrint(RSTRING_PTR(path), &print, &printSize);
42
+
43
+ result = rb_ary_new();
44
+ for(unsigned int i = 0; i < printSize; i++) {
45
+ rb_ary_push(result, UINT2NUM(print[i]));
46
+ }
47
+
48
+ free(print);
49
+
50
+ return result;
51
+ }
52
+
53
+ VALUE rb_mKeyMe;
54
+ VALUE rb_mFingerprint;
55
+
56
+ extern "C" {
57
+ void Init_fingerprint() {
58
+ rb_mKeyMe = rb_define_module("KeyMe");
59
+ rb_mFingerprint = rb_define_module_under(
60
+ rb_mKeyMe,
61
+ "Fingerprint"
62
+ );
63
+
64
+ rb_define_singleton_method(
65
+ rb_mFingerprint,
66
+ "verify_user",
67
+ RUBY_METHOD_FUNC(verify_user_wrapper),
68
+ 2
69
+ );
70
+ rb_define_singleton_method(
71
+ rb_mFingerprint,
72
+ "load_print",
73
+ RUBY_METHOD_FUNC(load_print_wrapper),
74
+ 1
75
+ );
76
+ }
77
+ }
@@ -0,0 +1,963 @@
1
+ /**
2
+ \file dpfj.h
3
+
4
+ \copyright (c) 2011 DigitalPersona, Inc
5
+
6
+ \brief U.are.U SDK FingerJet Engine API
7
+
8
+ Data types and functions for feature extraction, matching and conversion.
9
+
10
+ \version 2.0.0
11
+ */
12
+
13
+ #ifndef __DPFJ_H__
14
+ #define __DPFJ_H__
15
+
16
+
17
+ /** \cond NEVER */
18
+ #ifndef NULL
19
+ # define NULL 0
20
+ #endif
21
+
22
+ #ifndef DPERROR
23
+ # define _DP_FACILITY 0x05BA
24
+ # define DPERROR(err) ((int)err | (_DP_FACILITY << 16))
25
+ #endif /* DPERROR */
26
+
27
+ #define DPFJ_API_VERSION_MAJOR 1
28
+ #define DPFJ_API_VERSION_MINOR 0
29
+ /** \endcond */
30
+
31
+
32
+ /****************************************************************************************************
33
+ Error codes
34
+ ****************************************************************************************************/
35
+
36
+ /**
37
+ \brief API call succeeded.
38
+ */
39
+ #define DPFJ_SUCCESS 0
40
+
41
+ /**
42
+ \brief API call is not implemented.
43
+ */
44
+ #define DPFJ_E_NOT_IMPLEMENTED DPERROR(10)
45
+
46
+ /**
47
+ \brief Unspecified failure.
48
+
49
+ "Catch-all" generic failure code. Can be returned by all API calls in case of failure, when the reason for the failure is unknown or cannot be specified.
50
+ */
51
+ #define DPFJ_E_FAILURE DPERROR(11)
52
+
53
+ /**
54
+ \brief No data is available.
55
+ */
56
+ #define DPFJ_E_NO_DATA DPERROR(12)
57
+
58
+ /**
59
+ \brief Memory allocated by application is not enough to contain data which is expected.
60
+ */
61
+ #define DPFJ_E_MORE_DATA DPERROR(13)
62
+
63
+ /**
64
+ \brief One or more parameters passed to the API call are invalid.
65
+ */
66
+ #define DPFJ_E_INVALID_PARAMETER DPERROR(20)
67
+
68
+ /**
69
+ \brief FID is invalid.
70
+ */
71
+ #define DPFJ_E_INVALID_FID DPERROR(101)
72
+
73
+ /**
74
+ \brief Image is too small.
75
+ */
76
+ #define DPFJ_E_TOO_SMALL_AREA DPERROR(102)
77
+
78
+ /**
79
+ \brief FMD is invalid.
80
+ */
81
+ #define DPFJ_E_INVALID_FMD DPERROR(201)
82
+
83
+ /**
84
+ \brief Enrollment operation is in progress.
85
+ */
86
+ #define DPFJ_E_ENROLLMENT_IN_PROGRESS DPERROR(301)
87
+
88
+ /**
89
+ \brief Enrollment operation has not begun.
90
+ */
91
+ #define DPFJ_E_ENROLLMENT_NOT_STARTED DPERROR(302)
92
+
93
+ /**
94
+ \brief Not enough in the pool of FMDs to create enrollment FMD.
95
+ */
96
+ #define DPFJ_E_ENROLLMENT_NOT_READY DPERROR(303)
97
+
98
+ /****************************************************************************************************
99
+ Data types and definitions
100
+ ****************************************************************************************************/
101
+
102
+ /**
103
+ \brief Normalized value when probability = 1.
104
+ */
105
+ #define DPFJ_PROBABILITY_ONE 0x7fffffff
106
+
107
+ /**
108
+ \brief Fingerprint Image Data (FID) Format.
109
+ */
110
+ typedef int DPFJ_FID_FORMAT;
111
+
112
+ #define DPFJ_FID_ANSI_381_2004 0x001B0401 /**< ANSI INSITS 381-2004 format */
113
+ #define DPFJ_FID_ISO_19794_4_2005 0x01010007 /**< ISO IEC 19794-4-2005 format */
114
+
115
+ /**
116
+ \brief Fingerptint Minutiae Data (FMD) Format.
117
+ */
118
+ typedef int DPFJ_FMD_FORMAT;
119
+
120
+ #define DPFJ_FMD_ANSI_378_2004 0x001B0001 /**< ANSI INSITS 378-2004 Fingerprint Minutiae Data format */
121
+ #define DPFJ_FMD_ISO_19794_2_2005 0x01010001 /**< ISO IEC 19794-2-2005 Fingerprint Minutiae Data format */
122
+ #define DPFJ_FMD_DP_PRE_REG_FEATURES 0 /**< deprecated DigitalPersona pre-registration feature set format */
123
+ #define DPFJ_FMD_DP_REG_FEATURES 1 /**< deprecated DigitalPersona registration template format */
124
+ #define DPFJ_FMD_DP_VER_FEATURES 2 /**< deprecated DigitalPersona verification feature set format */
125
+
126
+ /** \brief Defines finger position.
127
+
128
+ Finger position according to ANSI 378-2004 and ISO 19794-2-2005 standards.
129
+ */
130
+ typedef int DPFJ_FINGER_POSITION;
131
+
132
+ #define DPFJ_POSITION_UNKNOWN 0 /**< position unknown */
133
+ #define DPFJ_POSITION_RTHUMB 1 /**< right thumb */
134
+ #define DPFJ_POSITION_RINDEX 2 /**< right index finger */
135
+ #define DPFJ_POSITION_RMIDDLE 3 /**< right middle finger */
136
+ #define DPFJ_POSITION_RRING 4 /**< right ring finger */
137
+ #define DPFJ_POSITION_RLITTLE 5 /**< right little finger */
138
+ #define DPFJ_POSITION_LTHUMB 6 /**< left thumb */
139
+ #define DPFJ_POSITION_LINDEX 7 /**< left index finger */
140
+ #define DPFJ_POSITION_LMIDDLE 8 /**< left middle finger */
141
+ #define DPFJ_POSITION_LRING 9 /**< left ring finger */
142
+ #define DPFJ_POSITION_LLITTLE 10 /**< left little finger */
143
+
144
+ /**
145
+ \brief Defines impression type.
146
+
147
+ Impression type according to ANSI 378-2004 and ISO 19794-2-2005 standards
148
+ */
149
+ typedef int DPFJ_SCAN_TYPE;
150
+
151
+ #define DPFJ_SCAN_LIVE_PLAIN 0
152
+ #define DPFJ_SCAN_LIVE_ROLLED 1
153
+ #define DPFJ_SCAN_NONLIVE_PLAIN 2
154
+ #define DPFJ_SCAN_NONLIVE_ROLLED 3
155
+ #define DPFJ_SCAN_SWIPE 8
156
+
157
+
158
+ /** \cond NEVER */
159
+ #define DPFJ_FID_ANSI_381_2004_RECORD_HEADER_LENGTH 36
160
+ #define DPFJ_FID_ISO_19794_4_2005_RECORD_HEADER_LENGTH 32
161
+ #define DPFJ_FID_ANSI_ISO_VIEW_HEADER_LENGTH 14
162
+
163
+ #define DPFJ_FMD_ANSI_378_2004_RECORD_HEADER_LENGTH 26
164
+ #define DPFJ_FMD_ISO_19794_2_2005_RECORD_HEADER_LENGTH 24
165
+ #define DPFJ_FMD_ANSI_ISO_VIEW_HEADER_LENGTH 4
166
+ #define DPFJ_FMD_ANSI_ISO_MINITIA_LENGTH 6
167
+ /** \endcond */
168
+
169
+ /**
170
+ \brief Maximum size of a single-view FMD with no extended data block.
171
+ */
172
+ #define MAX_FMD_SIZE (DPFJ_FMD_ANSI_378_2004_RECORD_HEADER_LENGTH + DPFJ_FMD_ANSI_ISO_VIEW_HEADER_LENGTH + 255 * DPFJ_FMD_ANSI_ISO_MINITIA_LENGTH + 2)
173
+
174
+ /**
175
+ \brief API Version information.
176
+ */
177
+ typedef struct dpfj_ver_info {
178
+ int major; /**< major version number */
179
+ int minor; /**< minor version number */
180
+ int maintanance; /**< maintanance or revision number */
181
+ } DPFJ_VER_INFO;
182
+
183
+ /**
184
+ \brief Complete information about library/SDK.
185
+ */
186
+ typedef struct dpfj_version {
187
+ unsigned int size; /**< Size of the structure, in bytes */
188
+ DPFJ_VER_INFO lib_ver; /**< file version of the library/SDK */
189
+ DPFJ_VER_INFO api_ver; /**< version of the API */
190
+ } DPFJ_VERSION;
191
+
192
+ /**
193
+ \brief Candidate, result of identification.
194
+ */
195
+ typedef struct dpfj_candidate{
196
+ unsigned int size; /**< size of the structure, in bytes */
197
+ unsigned int fmd_idx; /**< index of the FMD in the input array */
198
+ unsigned int view_idx; /**< index of the view in the FMD */
199
+ } DPFJ_CANDIDATE;
200
+
201
+
202
+ /****************************************************************************************************
203
+ API calls
204
+ ****************************************************************************************************/
205
+
206
+ #ifdef __cplusplus
207
+ extern "C" {
208
+ #endif /* __cplusplus */
209
+
210
+ /**
211
+ \brief Query the library and API version information.
212
+
213
+ \param ver [in] Pointer to the empty structure (per DPFJ_VERSION); [out] Pointer to structure containing version information
214
+ \return DPFJ_SUCCESS: Version information was acquired;
215
+ \return DPFJ_E_FAILURE: Failed to acquire version information.
216
+ */
217
+ int dpfj_version(
218
+ DPFJ_VERSION* ver
219
+ );
220
+
221
+
222
+ /**
223
+ \brief Extracts features and creates an FMD from a raw image.
224
+
225
+ When you do a fingerprint capture, you can receive a raw image or a FID. If you specify a raw image, you can then extract features into an FMD using this function.
226
+ The raw image is just a buffer of pixels. This function works with raw images that have
227
+ - 8 bits per pixel
228
+ - no padding
229
+ - square pixels (dpi is the same for horizontal and vertical)
230
+
231
+ The size of the resulting FMD will vary depending on the minutiae in a specific fingerprint. The maximum possible size of a single-view FMD is MAX_FMD_SIZE.
232
+ If the value pointed to by fmd_size is zero, the function will return with the error code DPFJ_E_MORE_DATA and the required size will be stored in the
233
+ value pointed to by fmd_size. In order to determine the size, this function processes the image, extracts features and discards the FMD, so it takes significant
234
+ processing time. However if memory shortages are a key issue, this allows you to allocate memory more efficiently at the expense of processing time.
235
+ If memory is available, you will get the best performance if you always allocate MAX_FMD_SIZE for the FMD.
236
+ The value pointed to by fmd_size will always be returned as the actual size of the FMD that was extracted.
237
+
238
+ \param image_data pointer to the image data
239
+ \param image_size size of the image data
240
+ \param image_width width of the image
241
+ \param image_height height of the image
242
+ \param image_dpi resolution of the image
243
+ \param finger_pos position of the finger
244
+ \param cbeff_id CBEFF product ID, from IBIA registry
245
+ \param fmd_type type of the FMD
246
+ \param fmd pointer to recieve FMD
247
+ \param fmd_size pointer to allocated size for the FMD, pointer to receive the actual size of the FMD
248
+ \return DPFJ_SUCCESS: FMD was created;
249
+ \return DPFJ_E_MORE_DATA: Features extracted, but allocated memory is not sufficient for FMD. The required memory size is in the fmd_size.
250
+ \return DPFJ_E_INVALID_PARAMETER: One or more parameters passed are invalid.
251
+ \return DPFJ_E_FAILURE: Failed to create FMD.
252
+ */
253
+ int dpfj_create_fmd_from_raw (
254
+ const unsigned char* image_data,
255
+ unsigned int image_size,
256
+ unsigned int image_width,
257
+ unsigned int image_height,
258
+ unsigned int image_dpi,
259
+ DPFJ_FINGER_POSITION finger_pos,
260
+ unsigned int cbeff_id,
261
+ DPFJ_FMD_FORMAT fmd_type,
262
+ unsigned char* fmd,
263
+ unsigned int* fmd_size
264
+ );
265
+
266
+ /**
267
+ \brief Extracts features and creates an FMD from an ANSI or ISO image.
268
+
269
+ This function works with FIDs that have
270
+ - 8 bits per pixel
271
+ - no padding
272
+ - square pixels (dpi is the same for horizontal and vertical)
273
+ The size of the resulting FMD will vary depending on the minutiae in a specific fingerprint. The maximum possible size of a single-view FMD is MAX_FMD_SIZE.
274
+ If the value pointed to by fmd_size is zero, the function will return with the error code DPFJ_E_MORE_DATA and the required size will be stored in the value
275
+ pointed to by fmd_size. In order to determine the size, this function processes the image, extracts the FMD and discards the FMD, so it takes significant processing time.
276
+ However if memory shortages are a key issue, this allows you to allocate memory more efficiently at the expense of processing time.
277
+ If memory is available, you will get the best performance if you always allocate MAX_FMD_SIZE for the FMD.
278
+ The value pointed to by fmd_size will always be returned as the actual size of the FMD that was extracted.
279
+
280
+ \param fid_type type of the FID
281
+ \param fid pointer to the FID data
282
+ \param fid_size size of the FID data
283
+ \param fmd_type type of the FMD
284
+ \param fmd pointer to recieve FMD data
285
+ \param fmd_size pointer to allocated size for the FMD, pointer to receive the actual size of the FMD
286
+ \return DPFJ_SUCCESS: FMD was created;
287
+ \return DPFJ_E_MORE_DATA: Features extracted, but allocated memory is not sufficient for FMD. The required memory size is in the fmd_size.
288
+ \return DPFJ_E_INVALID_PARAMETER: One or more parameters passed are invalid.
289
+ \return DPFJ_E_FAILURE: Failed to create FMD.
290
+ */
291
+ int dpfj_create_fmd_from_fid (
292
+ DPFJ_FID_FORMAT fid_type,
293
+ const unsigned char* fid,
294
+ unsigned int fid_size,
295
+ DPFJ_FMD_FORMAT fmd_type,
296
+ unsigned char* fmd,
297
+ unsigned int* fmd_size
298
+ );
299
+
300
+ /**
301
+ \brief Compares two fingerprints.
302
+
303
+ Given two single views from two FMDs, this function returns a <b>dissimilarity score</b> indicating the quality of the match.
304
+ The dissimilarity scores returned values are between:
305
+ 0=match
306
+ maxint=no match
307
+ Values close to 0 indicate very close matches, values closer to maxint indicate very poor matches.
308
+ For a discussion of how to evaluate dissimilarity scores, as well as the statistical validity of the dissimilarity score and error rates, consult the Developer Guide.
309
+ The dpfj_compare function returns DPFJ_SUCCESS if it is able to compare the fingerprints successfully (i.e., the FMDs are valid and correctly formed).
310
+ However that does not mean that the fingerprints matched. To check whether they matched, you must look at the dissimilarity score.
311
+
312
+ \param fmd1_type type of the first FMD
313
+ \param fmd1 pointer to the first FMD
314
+ \param fmd1_size size of the first FMD
315
+ \param fmd1_view_idx index of the view
316
+ \param fmd2_type type of the second FMD
317
+ \param fmd2 pointer to the second FMD
318
+ \param fmd2_size size of the second FMD
319
+ \param fmd2_view_idx index of the view
320
+ \param score pointer to receive dissimilarity score
321
+ \return DPFJ_SUCCESS: Comparison finished;
322
+ \return DPFJ_E_FAILURE: Unknown error.
323
+ */
324
+ int dpfj_compare(
325
+ DPFJ_FMD_FORMAT fmd1_type,
326
+ unsigned char* fmd1,
327
+ unsigned int fmd1_size,
328
+ unsigned int fmd1_view_idx,
329
+ DPFJ_FMD_FORMAT fmd2_type,
330
+ unsigned char* fmd2,
331
+ unsigned int fmd2_size,
332
+ unsigned int fmd2_view_idx,
333
+ unsigned int* score
334
+ );
335
+
336
+ /**
337
+ \brief Compares a single fingerprint to an array of fingerprints.
338
+
339
+ This function takes as inputs:
340
+ - a single view in an FMD
341
+ - an array of FMDs (each FMD can contain up to 16 views) to compare
342
+ - the desired number of candidates to return
343
+ - the threshold for False Positive Identification Rate that is permitted
344
+ This function compares a single view against an array of FMDs. Each time view has a score lower than the threshold, that view is marked as a possible candidate.
345
+ Then when all possible candidates are identified (i.e., they meet the threshold), they are ranked by their score. Finally, the function returns as many
346
+ candidates as requested, based on the candidates with the lowest dissimilarity score.
347
+ For a discussion of setting the threshold as well as the statistical validity of the dissimilarity score and error rates, consult the Developer Guide.
348
+
349
+ \param fmd1_type type of the FMDs
350
+ \param fmd1 pointer to the first FMD data
351
+ \param fmd1_size size of the first FMD data
352
+ \param fmd1_view_idx index of the view
353
+ \param fmds_type type of the FMDs in the fmds array
354
+ \param fmds_cnt number of FMDs in the fmds array
355
+ \param fmds array of FMDs
356
+ \param fmds_size array of sizes of the FMDs data
357
+ \param threshold_score target threshold on degree of dissimilarity
358
+ \param candidate_cnt [in] number of allocated entries in the candidates array; [out] receives the actual number of candidates filled in the array as a result of identification
359
+ \param candidates array of candidates
360
+ \return DPFJ_SUCESS: Identification finished;
361
+ \return DPFJ_E_FAILURE: Unknown error.
362
+ */
363
+ int dpfj_identify(
364
+ DPFJ_FMD_FORMAT fmd1_type,
365
+ unsigned char* fmd1,
366
+ unsigned int fmd1_size,
367
+ unsigned int fmd1_view_idx,
368
+ DPFJ_FMD_FORMAT fmds_type,
369
+ unsigned int fmds_cnt,
370
+ unsigned char** fmds,
371
+ unsigned int* fmds_size,
372
+ unsigned int threshold_score,
373
+ unsigned int* candidate_cnt,
374
+ DPFJ_CANDIDATE* candidates
375
+ );
376
+
377
+ /**
378
+ \brief Starts enrollment operation.
379
+
380
+ \param fmd_type type of FMD to produce as a result of enrollment operation
381
+ \return DPFJ_SUCCESS: Enrollment started.
382
+ \return DPFJ_E_INVALID_PARAMETER: Requested FMD type is invalid.
383
+ \return DPFJ_E_ENROLLMENT_IN_PROGRESS: Another enrollment operation is in prgress.
384
+ \return DPFJ_E_FAILURE: Unknown error.
385
+ */
386
+ int dpfj_start_enrollment(
387
+ DPFJ_FMD_FORMAT fmd_type
388
+ );
389
+
390
+ /**
391
+ \brief Adds FMD to enrollment operation.
392
+
393
+ Add an FMD to the pool of FMDs for enrollment and return a flag indicating when the enrollment is ready.
394
+ This function must be called before dpfj_create_enrollment_fmd.
395
+
396
+ \param fmd_type type of the FMD.
397
+ \param fmd pointer to the FMD data.
398
+ \param fmd_size size of the FMD data.
399
+ \param fmd_view_idx index of the view
400
+ \return DPFJ_SUCCESS: FMD added, enrollment is ready.
401
+ \return DPFJ_E_MORE_DATA: FMD added, more FMDs for enrollment required.
402
+ \return DPFJ_E_INVALID_PARAMETER: One or more parameters passed are invalid.
403
+ \return DPFJ_E_ENROLLMENT_NOT_STARTED: Enrollment is not started.
404
+ \return DPFJ_E_FAILURE: Unknown error.
405
+ */
406
+ int dpfj_add_to_enrollment(
407
+ DPFJ_FMD_FORMAT fmd_type,
408
+ unsigned char* fmd,
409
+ unsigned int fmd_size,
410
+ unsigned int fmd_view_idx
411
+ );
412
+
413
+ /**
414
+ \brief Creates and returns enrollment FMD.
415
+
416
+ Create an FMD for an enrolled finger. The output FMD is suitable for storing in a database of enrolled users.
417
+ Some applications like voting, banking and law enforcement require that you check for duplicate fingerprints before storing a new fingerprint in the database.
418
+ For ANSI/ISO formats, the enrollment FMD is a standard FMD (the same as an FMD generated by the extraction function). For the DigitalPersona data format,
419
+ the enrollment FMD uses the "fingerprint template" format as used by legacy DigitalPersona applications.
420
+ This function must be called after dpfj_add_to_enrollment.
421
+ The size of the resulting FMD will vary depending on the minutiae in the fingerprint(s) that were enrolled. The maximum possible size of an FMD is MAX_FMD_SIZE.
422
+ If the value pointed to by fmd_size is zero, the function will return with the error code DPFJ_E_MORE_DATA and the required size will be stored in the value pointed to by fmd_size.
423
+ In order to determine the size, this function processes the image, extracts features and discards the FMD, so it takes significant processing time.
424
+ However if memory shortages are a key issue, this allows you to allocate memory more efficiently at the expense of processing time.
425
+ If memory is available, you will get the best performance if you always allocate MAX_FMD_SIZE for the FMD.
426
+ The value pointed to by fmd_size will always be returned as the actual size of the FMD that was extracted.
427
+
428
+ \param fmd pointer to recieve FMD data
429
+ \param fmd_size pointer to allocated size for the FMD data, pointer to receive the actual size of the FMD data
430
+ \return DPFJ_SUCCESS: FMD created.
431
+ \return DPFJ_E_MORE_DATA: FMD created, but allocated memory is not sufficient. The required memory size is in the fmd_size.
432
+ \return DPFJ_E_INVALID_PARAMETER: One or more parameters passed are invalid.
433
+ \return DPFJ_E_ENROLLMENT_NOT_STARTED: Enrollment is not started.
434
+ \return DPFJ_E_FAILURE: Unknown error.
435
+ */
436
+ int dpfj_create_enrollment_fmd(
437
+ unsigned char* fmd,
438
+ unsigned int* fmd_size
439
+ );
440
+
441
+ /**
442
+ \brief Ends enrollment operation, releases memory.
443
+
444
+ This function releases resources used during the enrollment process. Call after enrollment is complete.
445
+ \return DPFJ_SUCCESS: Enrollment ended.
446
+ \return DPFJ_E_FAILURE: Unknown error.
447
+ */
448
+ int dpfj_finish_enrollment();
449
+
450
+ /**
451
+ \brief Converts an FMD from any supported format to any other supported format.
452
+
453
+ \param fmd1_type type of the input FMD
454
+ \param fmd1 pointer to the input FMD data
455
+ \param fmd1_size size of the input FMD data
456
+ \param fmd2_type type of the target FMD
457
+ \param fmd2 pointer to receive target FMD data
458
+ \param fmd2_size pointer to allocated size for the FMD data, pointer to receive the actual size of the FMD data
459
+ \return DPFJ_SUCCESS: FMD was converted;
460
+ \return DPFJ_E_INVALID_PARAMETER: One or more parameters passed are invalid.
461
+ \return DPFJ_E_FAILURE: Failed to convert FMD.
462
+ */
463
+ int dpfj_fmd_convert(
464
+ DPFJ_FMD_FORMAT fmd1_type,
465
+ unsigned char* fmd1,
466
+ unsigned int fmd1_size,
467
+ DPFJ_FMD_FORMAT fmd2_type,
468
+ unsigned char* fmd2,
469
+ unsigned int* fmd2_size
470
+ );
471
+
472
+ /****************************************************************************************************
473
+ legacy DigitalPersona image format conversion
474
+ ****************************************************************************************************/
475
+
476
+ /**
477
+ \brief Converts legacy DigitalPersona image to the image in ANSI or ISO format.
478
+
479
+ \param dp_image pointer to the DP image data
480
+ \param dp_image_size size of the DP image data
481
+ \param fid_type type of the FID
482
+ \param fid_dpi resolution of the FID, valid values are 500 and 1000
483
+ \param rotate180 flag: rotate image, 0 - do not rotate, 1 - rotate
484
+ \param fid pointer to receive FID data
485
+ \param fid_size pointer to receive the size of the FID
486
+ \return DPFJ_SUCCESS: FID was created
487
+ \return DPFJ_E_FAILURE: Failed to create FID
488
+ */
489
+ int dpfj_dp_fid_convert(
490
+ unsigned char* dp_image,
491
+ unsigned int dp_image_size,
492
+ DPFJ_FID_FORMAT fid_type,
493
+ unsigned int fid_dpi,
494
+ unsigned int rotate180,
495
+ unsigned char* fid,
496
+ unsigned int* fid_size
497
+ );
498
+
499
+ /****************************************************************************************************
500
+ FID and FMD manipulation: types and definitions
501
+ ****************************************************************************************************/
502
+
503
+ #ifndef DPFJ_NO_IM_MANIPULATION
504
+
505
+ /**
506
+ \brief Define image properties.
507
+
508
+ Structure defines image properties for FIDs in ANSI 381-2004
509
+ and ISO 19794-4-2005 formats.
510
+ */
511
+ typedef struct dpfj_fid_record_params{
512
+ unsigned int record_length; /**< total length of the image, including headers and all views */
513
+ unsigned int cbeff_id; /**< CBEFF product identifier */
514
+ unsigned int capture_device_id; /**< vendor specified */
515
+ unsigned int acquisition_level; /**< from Table 1 in "ANSI INSITS 381-2004" */
516
+ unsigned int finger_cnt; /**< total number of fingerprints in the record, must be greater or equal to 1 */
517
+ unsigned int scale_units; /**< pixels/cm (2) or pixels/inch (1) */
518
+ unsigned int scan_res; /**< scan resolution */
519
+ unsigned int image_res; /**< image resolution */
520
+ unsigned int bpp; /**< pixel depth, 1 - 16 bits */
521
+ unsigned int compression; /**< from Table 3 in "ANSI INSITS 381-2004" */
522
+ } DPFJ_FID_RECORD_PARAMS;
523
+
524
+ /**
525
+ \brief Define fingerprint image view (FIV) properties.
526
+
527
+ Structure defines image view properties for FIVs in ANSI 381-2004
528
+ and ISO 19794-4-2005 formats.
529
+ */
530
+ typedef struct dpfj_fid_view_params{
531
+ unsigned int data_length; /**< total length of the finger data including headers and all views */
532
+ DPFJ_FINGER_POSITION finger_position; /**< finger position */
533
+ unsigned int view_cnt; /**< number of views associated with this finger, must be greater or equal to 1 */
534
+ unsigned int view_number; /**< 1 - 256 */
535
+ unsigned int quality; /**< 1 - 100 for ISO; 1 - 100, 254 for ANSI */
536
+ DPFJ_SCAN_TYPE impression_type; /**< impression type */
537
+ unsigned int width; /**< width of the fingerprint view, in pixels */
538
+ unsigned int height; /**< height of the fingerprint view, in pixels */
539
+ unsigned char* view_data; /**< pointer to the view data */
540
+ } DPFJ_FID_VIEW_PARAMS;
541
+
542
+ /**
543
+ \brief Define FMD properties.
544
+
545
+ Structure defines minutiae data properties for FMDs in ANSI 378-2004
546
+ and ISO 19794-2-2005 formats.
547
+ */
548
+ typedef struct dpfj_fmd_record_params{
549
+ unsigned int record_length; /**< total length of the image, including headers and all views */
550
+ unsigned int cbeff_id; /**< CBEFF product identifier */
551
+ unsigned int capture_equipment_comp; /**< 4 bits: compliance; */
552
+ unsigned int capture_equipment_id; /**< 12 bits: capture device id, vendor specified */
553
+ unsigned int width; /**< width of the fingerprint image, in pixels */
554
+ unsigned int height; /**< height of the fingerprint image, in pixels */
555
+ unsigned int resolution; /**< resolution of the fingerprint image */
556
+ unsigned int view_cnt; /**< number of views */
557
+ } DPFJ_FMD_RECORD_PARAMS;
558
+
559
+ /**
560
+ \brief Define fingerprint minutiae view (FMV) properties.
561
+
562
+ Structure defines minutiae view properties for FMVs in ANSI 378-2004
563
+ and ISO 19794-2-2005 formats.
564
+ */
565
+ typedef struct dpfj_fmd_view_params{
566
+ DPFJ_FINGER_POSITION finger_position; /**< 0 - 10, from Table 5 in "ANSI INSITS 381-2004" */
567
+ unsigned int view_number; /**< 0 - 15 */
568
+ DPFJ_SCAN_TYPE impression_type; /**< Table 2 in "ANSI INSITS 378-2004" */
569
+ unsigned int quality; /**< 1 - 100 */
570
+ unsigned int minutia_cnt; /**< number of minutiae */
571
+ unsigned int ext_block_length; /**< length of the extended data block, in bytes */
572
+ unsigned char* ext_block; /**< pointer to the extended data block */
573
+ } DPFJ_FMD_VIEW_PARAMS;
574
+
575
+ /****************************************************************************************************
576
+ FID manipulation
577
+ ****************************************************************************************************/
578
+
579
+ /**
580
+ \brief Read image properties from FID.
581
+
582
+ \param image_type type of the FID (per DPFJ_FID_FORMAT)
583
+ \param image pointer to the FID
584
+ \param params pointer to the structure to receive image properties
585
+ \return void
586
+ */
587
+ static inline void dpfj_get_fid_record_params(
588
+ DPFJ_FID_FORMAT image_type,
589
+ const unsigned char* image,
590
+ DPFJ_FID_RECORD_PARAMS* params
591
+ );
592
+
593
+ /**
594
+ \brief Writes image properties to FID.
595
+
596
+ \param params pointer to the structure containing image properties
597
+ \param image_type format of the FID (per DPFJ_FID_FORMAT)
598
+ \param image pointer to the FID
599
+ \return void
600
+ */
601
+ static inline void dpfj_set_fid_record_params(
602
+ const DPFJ_FID_RECORD_PARAMS* params,
603
+ DPFJ_FID_FORMAT image_type,
604
+ unsigned char* image
605
+ );
606
+
607
+ /**
608
+ \brief Returns pointer to the specified view from FID.
609
+
610
+ \param image_type type of the FID (per DPFJ_FID_FORMAT)
611
+ \param image pointer to the FID
612
+ \param view_idx view index
613
+ \return offset to the specified view
614
+ */
615
+ static inline unsigned int dpfj_get_fid_view_offset(
616
+ DPFJ_FID_FORMAT image_type,
617
+ const unsigned char* image,
618
+ const unsigned int view_idx
619
+ );
620
+
621
+ /**
622
+ \brief Read image view properties from FID.
623
+
624
+ \param view pointer to the view from the FID
625
+ \param params pointer to the structure to receive view properties
626
+ \return void
627
+ */
628
+ static inline void dpfj_get_fid_view_params(
629
+ const unsigned char* view,
630
+ DPFJ_FID_VIEW_PARAMS* params
631
+ );
632
+
633
+ /**
634
+ \brief Write image view properties to FID.
635
+
636
+ \param params pointer to the structure containing view properties
637
+ \param view pointer to the view from the FID
638
+ \return void
639
+ */
640
+ static inline void dpfj_set_fid_view_params(
641
+ const DPFJ_FID_VIEW_PARAMS* params,
642
+ unsigned char* view
643
+ );
644
+
645
+ /****************************************************************************************************
646
+ FMD manipulation
647
+ ****************************************************************************************************/
648
+
649
+ /**
650
+ \brief Read minutiae record properties from FMD.
651
+
652
+ \param fmd_type format of the FMD (per DPFJ_FMD_FORMAT)
653
+ \param fmd pointer to the FMD
654
+ \param params pointer to the structure to receive FMD properties
655
+ \return void
656
+ */
657
+ static inline void dpfj_get_fmd_record_params(
658
+ DPFJ_FMD_FORMAT fmd_type,
659
+ const unsigned char* fmd,
660
+ DPFJ_FMD_RECORD_PARAMS* params
661
+ );
662
+
663
+ /** \brief Write minutiae record properties to FMD.
664
+
665
+ \param params pointer to the structure containing FMD properties
666
+ \param fmd_type format of the FMD (per DPFJ_FMD_FORMAT)
667
+ \param fmd pointer to the FMD
668
+ \return void
669
+ */
670
+ static inline void dpfj_set_fmd_record_params(
671
+ const DPFJ_FMD_RECORD_PARAMS* params,
672
+ DPFJ_FMD_FORMAT fmd_type,
673
+ unsigned char* fmd
674
+ );
675
+
676
+ /**
677
+ \brief Return pointer to the specified view from FMD.
678
+
679
+ \param fmd_type format of the FMD (per DPFJ_FMD_FORMAT)
680
+ \param fmd pointer to the FMD
681
+ \param view_idx view index
682
+ \return offset to the specified view
683
+ */
684
+ static inline unsigned int dpfj_get_fmd_view_offset(
685
+ DPFJ_FMD_FORMAT fmd_type,
686
+ const unsigned char* fmd,
687
+ const unsigned int view_idx
688
+ );
689
+
690
+ /**
691
+ \brief Read view properties from FMD.
692
+
693
+ \param view pointer to the view from the FMD
694
+ \param params pointer to the structure to receive view properties
695
+ \return void
696
+ */
697
+ static inline void dpfj_get_fmd_view_params(
698
+ const unsigned char* view,
699
+ DPFJ_FMD_VIEW_PARAMS* params
700
+ );
701
+
702
+ /**
703
+ \brief Write view properties to FMD.
704
+
705
+ \param params pointer to the structure containing view properties
706
+ \param view pointer to the view from the FMD
707
+ \return void
708
+ */
709
+ static inline void dpfj_set_fmd_view_params(
710
+ const DPFJ_FMD_VIEW_PARAMS* params,
711
+ unsigned char* view
712
+ );
713
+
714
+
715
+ /****************************************************************************************************
716
+ FID and FMD manipulation: implementation
717
+ ****************************************************************************************************/
718
+
719
+ /** \cond NEVER */
720
+
721
+ static inline unsigned int read_be16(const unsigned char* addr) {
722
+ unsigned int var = *addr;
723
+ var <<= 8;
724
+ var |= *(addr + 1);
725
+ return var;
726
+ };
727
+
728
+ static inline void write_be16(unsigned int var, unsigned char* addr) {
729
+ *(addr) = (unsigned char)(var >> 8);
730
+ *(addr + 1) = (unsigned char)var;
731
+ };
732
+
733
+ static inline unsigned int read_be32(const unsigned char* addr) {
734
+ unsigned int var = *(addr);
735
+ var <<= 8;
736
+ var |= *(addr + 1);
737
+ var <<= 8;
738
+ var |= *(addr + 2);
739
+ var <<= 8;
740
+ var |= *(addr + 3);
741
+ return var;
742
+ };
743
+
744
+ static inline void write_be32(unsigned int var, unsigned char* addr) {
745
+ *(addr) = (unsigned char)(var >> 24);
746
+ *(addr + 1) = (unsigned char)(var >> 16);
747
+ *(addr + 2) = (unsigned char)(var >> 8);
748
+ *(addr + 3) = (unsigned char)var;
749
+ };
750
+
751
+ /****************************************************************************************************/
752
+ /* FID functions */
753
+
754
+ static inline void dpfj_get_fid_record_params(DPFJ_FID_FORMAT image_type, const unsigned char* image, DPFJ_FID_RECORD_PARAMS* params){
755
+ if(NULL == image) return;
756
+
757
+ params->record_length = read_be32(image + 10);
758
+ int off = (DPFJ_FID_ANSI_381_2004 == image_type) ? DPFJ_FID_ANSI_381_2004_RECORD_HEADER_LENGTH - DPFJ_FID_ISO_19794_4_2005_RECORD_HEADER_LENGTH : 0;
759
+ params->cbeff_id = (DPFJ_FID_ANSI_381_2004 == image_type) ? read_be32(image + 14) : 0;
760
+ params->capture_device_id = read_be16(image + 14 + off);
761
+ params->acquisition_level = read_be16(image + 16 + off);
762
+ params->finger_cnt = *(image + 18 + off);
763
+ params->scale_units = *(image + 19 + off);
764
+ params->scan_res = read_be16(image + 20 + off);
765
+ params->image_res = read_be16(image + 24 + off);
766
+ params->bpp = *(image + 28 + off);
767
+ params->compression = *(image + 29 + off);
768
+ }
769
+
770
+ static inline void dpfj_set_fid_record_params(const DPFJ_FID_RECORD_PARAMS* params, DPFJ_FID_FORMAT image_type, unsigned char* image){
771
+ if(NULL == image) return;
772
+
773
+ image[0] = 'F'; image[1] = 'I'; image[2] = 'R'; image[3] = 0;
774
+ image[4] = '0'; image[5] = '1'; image[6] = '0'; image[7] = 0;
775
+ write_be16(0, image + 8);
776
+ write_be32(params->record_length, image + 10);
777
+ int off = (DPFJ_FID_ANSI_381_2004 == image_type) ? 4 : 0;
778
+ if(DPFJ_FID_ANSI_381_2004 == image_type) write_be32(params->cbeff_id, image + 14);
779
+ write_be16(params->capture_device_id, image + 14 + off);
780
+ write_be16(params->acquisition_level, image + 16 + off);
781
+ *(image + 18 + off) = (unsigned char)params->finger_cnt;
782
+ *(image + 19 + off) = (unsigned char)params->scale_units;
783
+ write_be16(params->scan_res, image + 20 + off);
784
+ write_be16(params->scan_res, image + 22 + off);
785
+ write_be16(params->image_res, image + 24 + off);
786
+ write_be16(params->image_res, image + 26 + off);
787
+ *(image + 28 + off) = (unsigned char)params->bpp;
788
+ *(image + 29 + off) = (unsigned char)params->compression;
789
+ write_be16(0, image + 30 + off);
790
+ }
791
+
792
+ static inline unsigned int dpfj_get_fid_view_offset(DPFJ_FID_FORMAT image_type, const unsigned char* image, unsigned int view_idx){
793
+ if(NULL == image) return 0;
794
+
795
+ unsigned int record_length = read_be32(image + 10);
796
+ unsigned int pos = (DPFJ_FID_ANSI_381_2004 == image_type) ? DPFJ_FID_ANSI_381_2004_RECORD_HEADER_LENGTH : DPFJ_FID_ISO_19794_4_2005_RECORD_HEADER_LENGTH;
797
+ unsigned int i = 0;
798
+ for(i = 0; i < view_idx && pos < record_length; i++){
799
+ //go to next
800
+ pos += read_be32(image + pos);
801
+ }
802
+
803
+ //check if offset is valid
804
+ if(pos >= record_length) return 0;
805
+ return pos;
806
+ }
807
+
808
+ static inline void dpfj_get_fid_view_params(const unsigned char* view, DPFJ_FID_VIEW_PARAMS* params){
809
+ if(NULL == view) return;
810
+
811
+ params->data_length = read_be32(view);
812
+ params->finger_position = (DPFJ_FINGER_POSITION)*(view + 4);
813
+ params->view_cnt = (unsigned int)*(view + 5);
814
+ params->view_number = (unsigned int)*(view + 6);
815
+ params->quality = (unsigned int)*(view + 7);
816
+ params->impression_type = (DPFJ_SCAN_TYPE)*(view + 8);
817
+ params->width = read_be16(view + 9);
818
+ params->height = read_be16(view + 11);
819
+ params->view_data = (unsigned char*)(view + DPFJ_FID_ANSI_ISO_VIEW_HEADER_LENGTH);
820
+ }
821
+
822
+ static inline void dpfj_set_fid_view_params(const DPFJ_FID_VIEW_PARAMS* params, unsigned char* view){
823
+ if(NULL == view) return;
824
+
825
+ unsigned int view_size = params->width * params->height + DPFJ_FID_ANSI_ISO_VIEW_HEADER_LENGTH;
826
+ write_be32(view_size, view);
827
+ *(view + 4) = (unsigned char)params->finger_position;
828
+ *(view + 5) = (unsigned char)params->view_cnt;
829
+ *(view + 6) = (unsigned char)params->view_number;
830
+ *(view + 7) = (unsigned char)params->quality;
831
+ *(view + 8) = (unsigned char)params->impression_type;
832
+ write_be16(params->width, view + 9);
833
+ write_be16(params->height, view + 11);
834
+ *(view + 13) = 0;
835
+ }
836
+
837
+ /****************************************************************************************************/
838
+ /* FMD functions */
839
+
840
+ static inline void dpfj_get_fmd_record_params(DPFJ_FMD_FORMAT fmd_type, const unsigned char* fmd, DPFJ_FMD_RECORD_PARAMS* params){
841
+ if(NULL == fmd) return;
842
+
843
+ int off = 0;
844
+ if(DPFJ_FMD_ANSI_378_2004 == fmd_type){
845
+ params->record_length = read_be16(fmd + 8);
846
+ params->cbeff_id = read_be32(fmd + 10);
847
+ off = 2;
848
+ if(0 == params->record_length){
849
+ params->record_length = read_be32(fmd + 10);
850
+ params->cbeff_id = read_be32(fmd + 14);
851
+ off = 6;
852
+ }
853
+ }
854
+ else if(DPFJ_FMD_ISO_19794_2_2005 == fmd_type){
855
+ params->record_length = read_be32(fmd + 8);
856
+ params->cbeff_id = 0;
857
+ }
858
+ else return;
859
+
860
+ params->capture_equipment_comp = *(fmd + 12 + off) & 0xf0;
861
+ params->capture_equipment_id = read_be16(fmd + 12 + off) & 0x0fff;
862
+ params->width = read_be16(fmd + 14 + off);
863
+ params->height = read_be16(fmd + 16 + off);
864
+ params->resolution = read_be16(fmd + 18 + off);
865
+ params->view_cnt = *(fmd + 22 + off);
866
+ }
867
+
868
+ static inline void dpfj_set_fmd_record_params(const DPFJ_FMD_RECORD_PARAMS* params, DPFJ_FMD_FORMAT fmd_type, unsigned char* fmd){
869
+ if(NULL == fmd) return;
870
+
871
+ fmd[0] = 'F'; fmd[1] = 'M'; fmd[2] = 'R'; fmd[3] = 0;
872
+ fmd[4] = ' '; fmd[5] = '2'; fmd[6] = '0'; fmd[7] = 0;
873
+
874
+ int off = 0;
875
+ if(DPFJ_FMD_ANSI_378_2004 == fmd_type){
876
+ if(0xffff < params->record_length){
877
+ off = 6;
878
+ write_be32(params->record_length, fmd + 10);
879
+ write_be32(params->cbeff_id, fmd + 14);
880
+ }
881
+ else{
882
+ off = 2;
883
+ write_be16(params->record_length, fmd + 8);
884
+ write_be32(params->cbeff_id, fmd + 10);
885
+ }
886
+ }
887
+ else if(DPFJ_FMD_ISO_19794_2_2005 == fmd_type){
888
+ write_be32(params->record_length, fmd + 8);
889
+ }
890
+ else return;
891
+
892
+ *(fmd + 12 + off) = (unsigned char)(((params->capture_equipment_comp & 0x0f) << 4) || ((params->capture_equipment_id >> 16) & 0x0f));
893
+ *(fmd + 13 + off) = (unsigned char)(params->capture_equipment_id & 0xff);
894
+ write_be16(params->width, fmd + 14 + off);
895
+ write_be16(params->height, fmd + 16 + off);
896
+ write_be16(params->resolution, fmd + 18 + off);
897
+ write_be16(params->resolution, fmd + 20 + off);
898
+ *(fmd + 22 + off) = (unsigned char)params->view_cnt;
899
+ *(fmd + 23 + off) = 0;
900
+ }
901
+
902
+ static inline unsigned int dpfj_get_fmd_view_offset(DPFJ_FMD_FORMAT fmd_type, const unsigned char* fmd, unsigned int view_idx){
903
+ if(NULL == fmd) return 0;
904
+
905
+ DPFJ_FMD_RECORD_PARAMS rp = {0};
906
+ dpfj_get_fmd_record_params(fmd_type, fmd, &rp);
907
+
908
+ //check index
909
+ if(view_idx >= rp.view_cnt) return 0; //invalid view index
910
+
911
+ unsigned int pos = DPFJ_FMD_ISO_19794_2_2005_RECORD_HEADER_LENGTH;
912
+ if(DPFJ_FMD_ANSI_378_2004 == fmd_type){
913
+ pos = DPFJ_FMD_ANSI_378_2004_RECORD_HEADER_LENGTH;
914
+ if(0xffff < rp.record_length) pos += 4;
915
+ }
916
+ unsigned int i = 0;
917
+ for(i = 0; i < view_idx && pos < rp.record_length; i++){
918
+ pos += (unsigned int)*(fmd + pos + 3) * DPFJ_FMD_ANSI_ISO_MINITIA_LENGTH + DPFJ_FMD_ANSI_ISO_VIEW_HEADER_LENGTH;
919
+ pos += read_be16(fmd + pos) + 2;
920
+ }
921
+
922
+ //check if offset is valid
923
+ if(pos >= rp.record_length) return 0;
924
+ return pos;
925
+ }
926
+
927
+ static inline void dpfj_get_fmd_view_params(const unsigned char* view, DPFJ_FMD_VIEW_PARAMS* params){
928
+ if(NULL == view) return;
929
+
930
+ params->finger_position = (DPFJ_FINGER_POSITION)*view;
931
+ params->view_number = (unsigned int)(*(view + 1) >> 4) & 0x0f;
932
+ params->impression_type = (DPFJ_SCAN_TYPE)(*(view + 1) & 0x0f);
933
+ params->quality = (unsigned int)*(view + 2);
934
+ params->minutia_cnt = (unsigned int)*(view + 3);
935
+ params->ext_block_length = read_be16(view + 4 + params->minutia_cnt * DPFJ_FMD_ANSI_ISO_MINITIA_LENGTH);
936
+ params->ext_block = (unsigned char*)(view + 4 + params->minutia_cnt * DPFJ_FMD_ANSI_ISO_MINITIA_LENGTH + 2);
937
+ }
938
+
939
+ static inline void dpfj_set_fmd_view_params(const DPFJ_FMD_VIEW_PARAMS* params, unsigned char* view){
940
+ if(NULL == view) return;
941
+
942
+ *view = (unsigned char)params->finger_position;
943
+ *(view + 1) = (unsigned char)((params->view_number << 4) | (params->impression_type & 0x0f));
944
+ *(view + 2) = (unsigned char)params->quality;
945
+ *(view + 3) = (unsigned char)params->minutia_cnt;
946
+ unsigned char* ext_block = view + 4 + params->minutia_cnt * DPFJ_FMD_ANSI_ISO_MINITIA_LENGTH;
947
+ write_be16(params->ext_block_length, ext_block);
948
+ ext_block += 2;
949
+ if(ext_block != params->ext_block){
950
+ unsigned int i = 0;
951
+ for(i = 0; i < params->ext_block_length; i++) ext_block[i] = params->ext_block[i];
952
+ }
953
+ }
954
+
955
+ /** \endcond */
956
+
957
+ #endif /* DPFJ_NO_IM_MANIPULATION */
958
+
959
+ #ifdef __cplusplus
960
+ }
961
+ #endif /* __cplusplus */
962
+
963
+ #endif /* __DPFJ_H__ */