1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/* ---- includes ----------------------------------------------------------- */
18
19#include "FaceFinder_Internal.h"
20
21/* ---- related objects  --------------------------------------------------- */
22
23/* ---- typedefs ----------------------------------------------------------- */
24
25/* ---- constants ---------------------------------------------------------- */
26
27/* ------------------------------------------------------------------------- */
28
29/* ========================================================================= */
30/*                                                                           */
31/* ---- functions ---------------------------------------------------------- */
32/*                                                                           */
33/* ========================================================================= */
34
35/* ------------------------------------------------------------------------- */
36
37void btk_FaceFinder_init( struct bbs_Context* cpA, struct btk_FaceFinder* ptrA )
38{
39	ptrA->hsdkE = NULL;
40	ptrA->hidE = btk_HID_FF;
41
42	bpi_FaceFinderRef_init( cpA, &ptrA->ffE );
43
44	ptrA->facesE = 0;
45	ptrA->faceIndexE = 0;
46}
47
48/* ------------------------------------------------------------------------- */
49
50void btk_FaceFinder_exit( struct bbs_Context* cpA, struct btk_FaceFinder* ptrA )
51{
52	ptrA->hsdkE = NULL;
53	ptrA->hidE = btk_HID_FF;
54
55	bpi_FaceFinderRef_exit( cpA, &ptrA->ffE );
56
57	ptrA->facesE = 0;
58	ptrA->faceIndexE = 0;
59}
60
61/* ------------------------------------------------------------------------- */
62
63btk_FaceFinderCreateParam btk_FaceFinder_defaultParam()
64{
65	btk_FaceFinderCreateParam paramL;
66	paramL.reserved = 0;
67	paramL.pModuleParam = NULL;
68	paramL.moduleParamSize = 0;
69	paramL.maxDetectableFaces = 0;
70	return paramL;
71}
72
73/* ------------------------------------------------------------------------- */
74
75btk_Status btk_FaceFinder_create( btk_HSDK hsdkA,     /* sdk handle */
76								  const btk_FaceFinderCreateParam* pCreateParamA,
77								  btk_HFaceFinder* hpFaceFinderA )
78{
79	const char* fNameL = "btk_FaceFinder_create";
80
81	btk_HFaceFinder hFaceFinderL = NULL;
82
83	if( hpFaceFinderA == NULL )					return btk_STATUS_INVALID_HANDLE;
84	if( *hpFaceFinderA != NULL )				return btk_STATUS_INVALID_HANDLE;
85	if( hsdkA == NULL )							return btk_STATUS_INVALID_HANDLE;
86	if( hsdkA->hidE != btk_HID_SDK )			return btk_STATUS_INVALID_HANDLE;
87	if( pCreateParamA == NULL )					return btk_STATUS_INVALID_HANDLE;
88	if( bbs_Context_error( &hsdkA->contextE ) ) return btk_STATUS_PREEXISTING_ERROR;
89
90	hFaceFinderL = ( btk_HFaceFinder )bbs_MemSeg_alloc( &hsdkA->contextE, hsdkA->contextE.memTblE.espArrE[ 0 ], bbs_SIZEOF16( struct btk_FaceFinder ) );
91	if( bbs_Context_error( &hsdkA->contextE ) ) return btk_STATUS_ERROR;
92
93	btk_FaceFinder_init( &hsdkA->contextE, hFaceFinderL );
94	if( bbs_Context_error( &hsdkA->contextE ) ) return btk_STATUS_ERROR;
95
96	hFaceFinderL->hsdkE = hsdkA;
97
98	if( btk_SDK_paramConsistencyTest( hsdkA, pCreateParamA->pModuleParam, pCreateParamA->moduleParamSize, fNameL ) == btk_STATUS_ERROR ) return btk_STATUS_ERROR;
99
100	if( hsdkA->maxImageWidthE * hsdkA->maxImageHeightE == 0 )
101	{
102		bbs_Context_pushError( &hsdkA->contextE,
103			                   bbs_Error_create( bbs_ERR_ERROR, 0, NULL, "%s:\nSDK parameter maxImageWidth or maxImageWidth is 0!\n"
104							                                             "Since SDK version 1.3.0 the maximum image size must be specified when creating the SDK handle.\n"
105																		 "Set the values in *pCreateParamA when you call function btk_SDK_create.", fNameL ) );
106		return btk_STATUS_ERROR;
107	}
108
109	bpi_FaceFinderRef_memRead( &hsdkA->contextE,
110							   &hFaceFinderL->ffE,
111							   hsdkA->maxImageWidthE,
112							   hsdkA->maxImageHeightE,
113							   pCreateParamA->pModuleParam,
114							   &hsdkA->contextE.memTblE );
115
116	if( bbs_Context_error( &hsdkA->contextE ) ) return btk_STATUS_ERROR;
117
118	*hpFaceFinderA = hFaceFinderL;
119	hsdkA->refCtrE++;
120
121	return btk_STATUS_OK;
122}
123
124/* ------------------------------------------------------------------------- */
125
126btk_Status btk_FaceFinder_close( btk_HFaceFinder hFaceFinderA )
127{
128	btk_HSDK hsdkL = NULL;
129	if( hFaceFinderA == NULL )				return btk_STATUS_INVALID_HANDLE;
130	if( hFaceFinderA->hidE != btk_HID_FF )	return btk_STATUS_INVALID_HANDLE;
131	if( hFaceFinderA->hsdkE == NULL )		return btk_STATUS_INVALID_HANDLE;
132	hsdkL = hFaceFinderA->hsdkE;
133	if( bbs_Context_error( &hsdkL->contextE ) ) return btk_STATUS_PREEXISTING_ERROR;
134
135	hsdkL->refCtrE--;
136
137	btk_FaceFinder_exit( &hsdkL->contextE, hFaceFinderA );
138	if( bbs_Context_error( &hsdkL->contextE ) ) return btk_STATUS_ERROR;
139
140	bbs_MemSeg_free( &hsdkL->contextE, hsdkL->contextE.memTblE.espArrE[ 0 ], hFaceFinderA );
141	if( bbs_Context_error( &hsdkL->contextE ) ) return btk_STATUS_ERROR;
142
143	return btk_STATUS_OK;
144}
145
146/* ------------------------------------------------------------------------- */
147
148btk_Status btk_FaceFinder_setRange( btk_HFaceFinder hFaceFinderA,
149								    u32 minDistA,
150									u32 maxDistA )
151{
152	btk_HSDK hsdkL = NULL;
153	if( hFaceFinderA == NULL )				return btk_STATUS_INVALID_HANDLE;
154	if( hFaceFinderA->hidE != btk_HID_FF )	return btk_STATUS_INVALID_HANDLE;
155	hsdkL = hFaceFinderA->hsdkE;
156	if( bbs_Context_error( &hsdkL->contextE ) ) return btk_STATUS_PREEXISTING_ERROR;
157
158	bpi_FaceFinderRef_setRange( &hsdkL->contextE, &hFaceFinderA->ffE, minDistA, maxDistA );
159	if( bbs_Context_error( &hsdkL->contextE ) ) return btk_STATUS_ERROR;
160
161	return btk_STATUS_OK;
162}
163
164/* ------------------------------------------------------------------------- */
165
166btk_Status btk_FaceFinder_putDCR( btk_HFaceFinder hFaceFinderA,
167								  btk_HDCR hdcrA )
168{
169	const char* fNameL = "btk_FaceFinder_putDCR";
170
171	btk_HSDK hsdkL = NULL;
172	if( hFaceFinderA == NULL )				return btk_STATUS_INVALID_HANDLE;
173	if( hFaceFinderA->hidE != btk_HID_FF )	return btk_STATUS_INVALID_HANDLE;
174	if( hdcrA == NULL )			return btk_STATUS_INVALID_HANDLE;
175	hsdkL = hFaceFinderA->hsdkE;
176	if( bbs_Context_error( &hsdkL->contextE ) ) return btk_STATUS_PREEXISTING_ERROR;
177
178	if( hdcrA->dcrE.imageDataPtrE == NULL )
179	{
180		bbs_Context_pushError( &hsdkL->contextE,
181			                   bbs_Error_create( bbs_ERR_ERROR, 0, NULL,
182							       "%s:\nNo image was assigned to data carrier", fNameL ) );
183	}
184
185	hFaceFinderA->facesE = bpi_FaceFinderRef_putDcr( &hsdkL->contextE,
186												     &hFaceFinderA->ffE,
187													 &hdcrA->dcrE );
188
189	hFaceFinderA->faceIndexE = 0;
190	if( bbs_Context_error( &hsdkL->contextE ) ) return btk_STATUS_ERROR;
191
192	return btk_STATUS_OK;
193}
194
195/* ------------------------------------------------------------------------- */
196
197u32 btk_FaceFinder_faces( btk_HFaceFinder hFaceFinderA )
198{
199	if( hFaceFinderA == NULL )				return 0;
200	if( hFaceFinderA->hidE != btk_HID_FF )	return 0;
201	return hFaceFinderA->facesE - hFaceFinderA->faceIndexE;
202}
203
204/* ------------------------------------------------------------------------- */
205
206btk_Status btk_FaceFinder_getDCR( btk_HFaceFinder hFaceFinderA,
207								  btk_HDCR hdcrA )
208{
209	btk_HSDK hsdkL = NULL;
210	if( hFaceFinderA == NULL )				return btk_STATUS_INVALID_HANDLE;
211	if( hFaceFinderA->hidE != btk_HID_FF )	return btk_STATUS_INVALID_HANDLE;
212	if( hdcrA == NULL )			return btk_STATUS_INVALID_HANDLE;
213	hsdkL = hFaceFinderA->hsdkE;
214	if( bbs_Context_error( &hsdkL->contextE ) ) return btk_STATUS_PREEXISTING_ERROR;
215
216	if( hFaceFinderA->faceIndexE < hFaceFinderA->facesE )
217	{
218		bpi_FaceFinderRef_getDcr( &hsdkL->contextE,
219								  &hFaceFinderA->ffE,
220								   hFaceFinderA->faceIndexE,
221								  &hdcrA->dcrE );
222
223		if( bbs_Context_error( &hsdkL->contextE ) ) return btk_STATUS_ERROR;
224
225		hdcrA->dcrE.approvedE = TRUE;
226		hFaceFinderA->faceIndexE++;
227	}
228	else
229	{
230		bpi_FaceFinderRef_getDcr( &hsdkL->contextE,
231								  &hFaceFinderA->ffE,
232								  0,
233								  &hdcrA->dcrE );
234		hdcrA->dcrE.approvedE = FALSE;
235	}
236
237	return btk_STATUS_OK;
238}
239
240/* ------------------------------------------------------------------------- */
241
242btk_Status btk_FaceFinder_process( btk_HFaceFinder hFaceFinderA,
243								   btk_HDCR hdcrA )
244{
245	const char* fNameL = "btk_FaceFinder_process";
246	int32 confL;
247
248	btk_HSDK hsdkL = NULL;
249	if( hFaceFinderA == NULL )				return btk_STATUS_INVALID_HANDLE;
250	if( hFaceFinderA->hidE != btk_HID_FF )	return btk_STATUS_INVALID_HANDLE;
251	if( hdcrA == NULL )						return btk_STATUS_INVALID_HANDLE;
252	hsdkL = hFaceFinderA->hsdkE;
253	if( bbs_Context_error( &hsdkL->contextE ) ) return btk_STATUS_PREEXISTING_ERROR;
254
255	if( hdcrA->dcrE.imageDataPtrE == NULL )
256	{
257		bbs_Context_pushError( &hsdkL->contextE,
258			                   bbs_Error_create( bbs_ERR_ERROR, 0, NULL,
259							       "%s:\nNo image was assigned to data carrier", fNameL ) );
260	}
261
262	confL = bpi_FaceFinderRef_process( &hsdkL->contextE,
263									   &hFaceFinderA->ffE,
264									   &hdcrA->dcrE );
265
266	if( bbs_Context_error( &hsdkL->contextE ) ) return btk_STATUS_ERROR;
267
268	hdcrA->dcrE.confidenceE = confL;
269	hdcrA->dcrE.approvedE = confL > ( ( int32 )1 << 23 );
270
271	hFaceFinderA->faceIndexE = 0;
272	hFaceFinderA->facesE = 0;
273
274	bts_IdCluster2D_copy( &hsdkL->contextE,
275		                  &hdcrA->dcrE.sdkClusterE,
276						  &hdcrA->dcrE.mainClusterE );
277
278	if( bbs_Context_error( &hsdkL->contextE ) ) return btk_STATUS_ERROR;
279
280	return btk_STATUS_OK;
281}
282
283/* ------------------------------------------------------------------------- */
284
285/* ========================================================================= */
286