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 "b_APIEm/BFFaceFinder.h"
20 #include "b_APIEm/Functions.h"
21 #include "b_APIEm/DCR.h"
22 #include "b_BasicEm/Functions.h"
23 #include "b_BasicEm/Math.h"
24 
25 /* ------------------------------------------------------------------------- */
26 
27 /* ========================================================================= */
28 /*                                                                           */
29 /* ---- \ghd{ auxiliary functions } ---------------------------------------- */
30 /*                                                                           */
31 /* ========================================================================= */
32 
33 /* ------------------------------------------------------------------------- */
34 
35 /* ========================================================================= */
36 /*                                                                           */
37 /* ---- \ghd{ constructor / destructor } ----------------------------------- */
38 /*                                                                           */
39 /* ========================================================================= */
40 
41 /* ------------------------------------------------------------------------- */
42 
bpi_BFFaceFinder_init(struct bbs_Context * cpA,struct bpi_BFFaceFinder * ptrA)43 void bpi_BFFaceFinder_init( struct bbs_Context* cpA,
44 						    struct bpi_BFFaceFinder* ptrA )
45 {
46 	bpi_FaceFinder_init( cpA, &ptrA->baseE );
47 	ptrA->baseE.typeE = ( uint32 )bpi_FF_BF_FACE_FINDER;
48 	ptrA->baseE.vpSetParamsE = bpi_BFFaceFinder_setParams;
49 	ptrA->baseE.vpSetRangeE = bpi_BFFaceFinder_setRange;
50 	ptrA->baseE.vpProcessE = bpi_BFFaceFinder_processDcr;
51 	ptrA->baseE.vpPutDcrE = bpi_BFFaceFinder_putDcr;
52 	ptrA->baseE.vpGetDcrE = bpi_BFFaceFinder_getDcr;
53 
54 	ptrA->detectedFacesE = 0;
55 	ptrA->availableFacesE = 0;
56 	ptrA->faceDataBufferE = NULL;
57 	bbf_ScanDetector_init( cpA, &ptrA->detectorE );
58 }
59 
60 /* ------------------------------------------------------------------------- */
61 
bpi_BFFaceFinder_exit(struct bbs_Context * cpA,struct bpi_BFFaceFinder * ptrA)62 void bpi_BFFaceFinder_exit( struct bbs_Context* cpA,
63 						    struct bpi_BFFaceFinder* ptrA )
64 {
65 	ptrA->detectedFacesE = 0;
66 	ptrA->availableFacesE = 0;
67 	ptrA->faceDataBufferE = NULL;
68 	bbf_ScanDetector_exit( cpA, &ptrA->detectorE );
69 
70 	bpi_FaceFinder_exit( cpA, &ptrA->baseE );
71 }
72 
73 /* ------------------------------------------------------------------------- */
74 
75 /* ========================================================================= */
76 /*                                                                           */
77 /* ---- \ghd{ operators } -------------------------------------------------- */
78 /*                                                                           */
79 /* ========================================================================= */
80 
81 /* ------------------------------------------------------------------------- */
82 
bpi_BFFaceFinder_copy(struct bbs_Context * cpA,struct bpi_BFFaceFinder * ptrA,const struct bpi_BFFaceFinder * srcPtrA)83 void bpi_BFFaceFinder_copy( struct bbs_Context* cpA,
84 						    struct bpi_BFFaceFinder* ptrA,
85 							const struct bpi_BFFaceFinder* srcPtrA )
86 {
87 	bpi_FaceFinder_copy( cpA, &ptrA->baseE, &srcPtrA->baseE );
88 	bbf_ScanDetector_copy( cpA, &ptrA->detectorE, &srcPtrA->detectorE );
89 }
90 
91 /* ------------------------------------------------------------------------- */
92 
bpi_BFFaceFinder_equal(struct bbs_Context * cpA,const struct bpi_BFFaceFinder * ptrA,const struct bpi_BFFaceFinder * srcPtrA)93 flag bpi_BFFaceFinder_equal( struct bbs_Context* cpA,
94 							 const struct bpi_BFFaceFinder* ptrA,
95 							 const struct bpi_BFFaceFinder* srcPtrA )
96 {
97 	if( !bpi_FaceFinder_equal( cpA, &ptrA->baseE, &srcPtrA->baseE ) ) return FALSE;
98 	if( !bbf_ScanDetector_equal( cpA, &ptrA->detectorE, &srcPtrA->detectorE ) ) return FALSE;
99 	return TRUE;
100 }
101 
102 /* ------------------------------------------------------------------------- */
103 
104 /* ========================================================================= */
105 /*                                                                           */
106 /* ---- \ghd{ query functions } -------------------------------------------- */
107 /*                                                                           */
108 /* ========================================================================= */
109 
110 /* ------------------------------------------------------------------------- */
111 
bpi_BFFaceFinder_getMinEyeDistance(const struct bpi_BFFaceFinder * ptrA)112 uint32 bpi_BFFaceFinder_getMinEyeDistance( const struct bpi_BFFaceFinder* ptrA )
113 {
114 	return ( ( ptrA->detectorE.refDistanceE >> 8 ) * ( ptrA->detectorE.minScaleE >> 12 ) ) >> 16;
115 }
116 
117 /* ------------------------------------------------------------------------- */
118 
bpi_BFFaceFinder_getMaxEyeDistance(const struct bpi_BFFaceFinder * ptrA)119 uint32 bpi_BFFaceFinder_getMaxEyeDistance( const struct bpi_BFFaceFinder* ptrA )
120 {
121 	return ( ( ptrA->detectorE.refDistanceE >> 8 ) * ( ptrA->detectorE.maxScaleE >> 12 ) ) >> 16;
122 }
123 
124 /* ------------------------------------------------------------------------- */
125 
126 /* ========================================================================= */
127 /*                                                                           */
128 /* ---- \ghd{ modify functions } ------------------------------------------- */
129 /*                                                                           */
130 /* ========================================================================= */
131 
132 /* ------------------------------------------------------------------------- */
133 
bpi_BFFaceFinder_setMinEyeDistance(struct bbs_Context * cpA,struct bpi_BFFaceFinder * ptrA,uint32 distA)134 void bpi_BFFaceFinder_setMinEyeDistance( struct bbs_Context* cpA,
135 										 struct bpi_BFFaceFinder* ptrA,
136 										 uint32 distA )
137 {
138 	ptrA->detectorE.minScaleE = ( ( distA << 16 ) / ( ptrA->detectorE.refDistanceE >> 8 ) ) << 12;
139 	if( ptrA->detectorE.minScaleE < 0x100000 /* 1.0 */ ) ptrA->detectorE.minScaleE = 0x100000;
140 }
141 
142 /* ------------------------------------------------------------------------- */
143 
bpi_BFFaceFinder_setMaxEyeDistance(struct bbs_Context * cpA,struct bpi_BFFaceFinder * ptrA,uint32 distA)144 void bpi_BFFaceFinder_setMaxEyeDistance( struct bbs_Context* cpA,
145 										 struct bpi_BFFaceFinder* ptrA,
146 										 uint32 distA )
147 {
148 	if( distA > 0x0FFFF )
149 	{
150 		ptrA->detectorE.maxScaleE = 0; /* unlimited */
151 	}
152 	else
153 	{
154 		ptrA->detectorE.maxScaleE = ( ( distA << 16 ) / ( ptrA->detectorE.refDistanceE >> 8 ) ) << 12;
155 	}
156 }
157 
158 /* ------------------------------------------------------------------------- */
159 
160 /* ========================================================================= */
161 /*                                                                           */
162 /* ---- \ghd{ I/O } -------------------------------------------------------- */
163 /*                                                                           */
164 /* ========================================================================= */
165 
166 /* ------------------------------------------------------------------------- */
167 
bpi_BFFaceFinder_memSize(struct bbs_Context * cpA,const struct bpi_BFFaceFinder * ptrA)168 uint32 bpi_BFFaceFinder_memSize( struct bbs_Context* cpA,
169 								 const struct bpi_BFFaceFinder *ptrA )
170 {
171 	uint32 memSizeL = 0;
172 	memSizeL += bbs_SIZEOF16( uint32 );
173 	memSizeL += bbs_SIZEOF16( uint32 ); /* version */
174 	memSizeL += bpi_FaceFinder_memSize( cpA, &ptrA->baseE );
175 	memSizeL += bbf_ScanDetector_memSize( cpA, &ptrA->detectorE );
176 	memSizeL += bbs_SIZEOF16( uint16 ); /* csa */
177 	return memSizeL;
178 }
179 
180 /* ------------------------------------------------------------------------- */
181 
bpi_BFFaceFinder_memWrite(struct bbs_Context * cpA,const struct bpi_BFFaceFinder * ptrA,uint16 * memPtrA)182 uint32 bpi_BFFaceFinder_memWrite( struct bbs_Context* cpA,
183 								  const struct bpi_BFFaceFinder* ptrA,
184 								  uint16* memPtrA )
185 {
186 	uint32 memSizeL = bpi_BFFaceFinder_memSize( cpA, ptrA );
187 	memPtrA += bbs_memWrite32( &memSizeL, memPtrA );
188 	memPtrA += bbs_memWriteUInt32( bpi_BF_FACE_FINDER_VERSION, memPtrA );
189 	memPtrA += bpi_FaceFinder_memWrite( cpA, &ptrA->baseE, memPtrA );
190 	memPtrA += bbf_ScanDetector_memWrite( cpA, &ptrA->detectorE, memPtrA );
191 	memPtrA += bpi_memWriteCsa16( memPtrA, memSizeL, 0xFFFF );
192 	return memSizeL;
193 }
194 
195 /* ------------------------------------------------------------------------- */
196 
bpi_BFFaceFinder_memRead(struct bbs_Context * cpA,struct bpi_BFFaceFinder * ptrA,const uint16 * memPtrA,struct bbs_MemTbl * mtpA)197 uint32 bpi_BFFaceFinder_memRead( struct bbs_Context* cpA,
198 								 struct bpi_BFFaceFinder* ptrA,
199 								 const uint16* memPtrA,
200    								 struct bbs_MemTbl* mtpA )
201 {
202 	uint32 memSizeL, versionL;
203 	if( bbs_Context_error( cpA ) ) return 0;
204 	memPtrA += bbs_memRead32( &memSizeL, memPtrA );
205 	memPtrA += bbs_memReadVersion32( cpA, &versionL, bpi_BF_FACE_FINDER_VERSION, memPtrA );
206 	memPtrA += bpi_FaceFinder_memRead( cpA, &ptrA->baseE, memPtrA );
207 	if( bbs_Context_error( cpA ) ) return 0;
208 
209 	memPtrA += bbf_ScanDetector_memRead( cpA, &ptrA->detectorE, memPtrA, mtpA );
210 	if( bbs_Context_error( cpA ) ) return 0;
211 	memPtrA += bpi_memReadCsa16( memPtrA );
212 
213 /*	if( memSizeL != bpi_BFFaceFinder_memSize( cpA, ptrA ) )
214 	{
215 		bbs_ERROR0( "uint32 bpi_BFFaceFinder_memRead( .... ):\n"
216                     "Module file is corrupt or incorrect. Please check if the face finder module is still supported." );
217 		return 0;
218 	}
219 */
220 	return memSizeL;
221 }
222 
223 /* ------------------------------------------------------------------------- */
224 
225 /* ========================================================================= */
226 /*                                                                           */
227 /* ---- \ghd{ exec functions } --------------------------------------------- */
228 /*                                                                           */
229 /* ========================================================================= */
230 
231 /* ------------------------------------------------------------------------- */
232 
bpi_BFFaceFinder_process(struct bbs_Context * cpA,const struct bpi_BFFaceFinder * ptrA,void * imagePtrA,uint32 imageWidthA,uint32 imageHeightA,const struct bts_Int16Rect * roiPtrA,struct bts_Int16Vec2D * offsPtrA,struct bts_IdCluster2D * idClusterPtrA)233 int32 bpi_BFFaceFinder_process( struct bbs_Context* cpA,
234 							    const struct bpi_BFFaceFinder* ptrA,
235 								void* imagePtrA,
236 								uint32 imageWidthA,
237 								uint32 imageHeightA,
238 								const struct bts_Int16Rect* roiPtrA,
239 								struct bts_Int16Vec2D* offsPtrA,
240 								struct bts_IdCluster2D* idClusterPtrA )
241 {
242 	int32 xL = 0; /* 16.16 */
243 	int32 yL = 0; /* 16.16 */
244 	uint32 scaleL = 0;
245 	int32 actL = 0;
246 	int32* outArrL;
247 
248 	struct bts_Flt16Alt2D altL;
249 	struct bts_Flt16Vec2D centerL;
250 
251 	struct bpi_BFFaceFinder* ptrL = ( struct bpi_BFFaceFinder* )ptrA;
252 
253 	/* reset multi face imformation so they are not accidentally used */
254 	ptrL->detectedFacesE = 0;
255 	ptrL->availableFacesE = 0;
256 	ptrL->faceDataBufferE = NULL;
257 
258 	bbf_ScanDetector_process( cpA, ( struct bbf_ScanDetector* )&ptrA->detectorE, imagePtrA, imageWidthA, imageHeightA, roiPtrA, &outArrL );
259 
260 	xL      = outArrL[ 0 ]; /* 16.16 */
261 	yL      = outArrL[ 1 ]; /* 16.16 */
262 	scaleL  = outArrL[ 2 ]; /* 12.20 */
263 	actL    = outArrL[ 3 ]; /*  4.28 */
264 
265 	if( bbs_Context_error( cpA ) ) return 0;
266 
267 	offsPtrA->xE = xL >> 16;
268 	offsPtrA->yE = yL >> 16;
269 	xL -= ( ( int32 )offsPtrA->xE << 16 );
270 	yL -= ( ( int32 )offsPtrA->yE << 16 );
271 
272 	centerL = bts_Flt16Vec2D_create32( 0, 0, 0 );
273 	altL = bts_Flt16Alt2D_createScale( scaleL, 20, &centerL );
274 	altL.vecE = bts_Flt16Vec2D_create32( xL, yL, 16 );
275 
276 	/* compute cluster */
277 	{
278 		uint32 eyeDistL = ( ( ptrA->detectorE.refDistanceE >> 16 ) * scaleL ) >> 20;
279 		uint32 logEyeDistL = bbs_intLog2( eyeDistL );
280 		int32 bbpL = 11 - logEyeDistL;
281 		bbpL = bbpL < 0 ? 0 : bbpL;
282 		bbpL = bbpL > 6 ? 6 : bbpL;
283 		bts_IdCluster2D_copyTransform( cpA, idClusterPtrA, &ptrA->detectorE.refClusterE, altL, bbpL );
284 	}
285 
286 
287 	return ( actL + 0x10000000 ) >> 5; /*output range 0...1 in 8.24*/
288 }
289 
290 /* ------------------------------------------------------------------------- */
291 
bpi_BFFaceFinder_multiProcess(struct bbs_Context * cpA,const struct bpi_BFFaceFinder * ptrA,void * imagePtrA,uint32 imageWidthA,uint32 imageHeightA,const struct bts_Int16Rect * roiPtrA)292 uint32 bpi_BFFaceFinder_multiProcess( struct bbs_Context* cpA,
293 									  const struct bpi_BFFaceFinder* ptrA,
294 									  void* imagePtrA,
295 									  uint32 imageWidthA,
296 									  uint32 imageHeightA,
297 									  const struct bts_Int16Rect* roiPtrA )
298 {
299 	struct bpi_BFFaceFinder* ptrL = ( struct bpi_BFFaceFinder* )ptrA;
300 	ptrL->detectedFacesE = bbf_ScanDetector_process( cpA, ( struct bbf_ScanDetector* )&ptrA->detectorE, imagePtrA, imageWidthA, imageHeightA, roiPtrA, &ptrL->faceDataBufferE );
301 	ptrL->availableFacesE = ptrA->detectedFacesE > 0 ? ptrA->detectedFacesE : 1;
302 	if( bbs_Context_error( cpA ) ) return 0;
303 	return ptrL->detectedFacesE;
304 }
305 
306 /* ------------------------------------------------------------------------- */
307 
bpi_BFFaceFinder_getFace(struct bbs_Context * cpA,const struct bpi_BFFaceFinder * ptrA,uint32 indexA,struct bts_Int16Vec2D * offsPtrA,struct bts_IdCluster2D * idClusterPtrA)308 uint32 bpi_BFFaceFinder_getFace( struct bbs_Context* cpA,
309 								 const struct bpi_BFFaceFinder* ptrA,
310 								 uint32 indexA,
311 								 struct bts_Int16Vec2D* offsPtrA,
312 								 struct bts_IdCluster2D* idClusterPtrA )
313 {
314 	bbs_DEF_fNameL( "bpi_BFFaceFinder_getFace" )
315 	int32 xL = 0; /* 16.16 */
316 	int32 yL = 0; /* 16.16 */
317 	uint32 scaleL = 0;
318 	int32 actL = 0;
319 	struct bts_Flt16Alt2D altL;
320 	struct bts_Flt16Vec2D centerL;
321 
322 	if( bbs_Context_error( cpA ) ) return 0;
323 
324 	if( ptrA->availableFacesE == 0 || ptrA->faceDataBufferE == NULL )
325 	{
326 		bbs_ERROR1( "%s:\nNo faces are availabe. This function was called before the face finder could detect multiple faces in an image", fNameL );
327 		return 0;
328 	}
329 
330 	if( indexA >= ptrA->availableFacesE )
331 	{
332 		bbs_ERROR1( "%s:\nface index exceeds number of available faces", fNameL );
333 		return 0;
334 	}
335 
336 	xL      = ptrA->faceDataBufferE[ indexA * 4 + 0 ]; /* 16.16 */
337 	yL      = ptrA->faceDataBufferE[ indexA * 4 + 1 ]; /* 16.16 */
338 	scaleL  = ptrA->faceDataBufferE[ indexA * 4 + 2 ]; /* 12.20 */
339 	actL    = ptrA->faceDataBufferE[ indexA * 4 + 3 ]; /*  4.28 */
340 
341 	offsPtrA->xE = xL >> 16;
342 	offsPtrA->yE = yL >> 16;
343 
344 	xL -= ( ( int32 )offsPtrA->xE << 16 );
345 	yL -= ( ( int32 )offsPtrA->yE << 16 );
346 
347 	centerL = bts_Flt16Vec2D_create32( 0, 0, 0 );
348 	altL = bts_Flt16Alt2D_createScale( scaleL, 20, &centerL );
349 	altL.vecE = bts_Flt16Vec2D_create32( xL, yL, 16 );
350 
351 	/* compute cluster */
352 	{
353 		uint32 eyeDistL = ( ( ptrA->detectorE.refDistanceE >> 16 ) * scaleL ) >> 20;
354 		uint32 logEyeDistL = bbs_intLog2( eyeDistL );
355 		int32 bbpL = 11 - logEyeDistL;
356 		bbpL = bbpL < 0 ? 0 : bbpL;
357 		bbpL = bbpL > 6 ? 6 : bbpL;
358 		bts_IdCluster2D_copyTransform( cpA, idClusterPtrA, &ptrA->detectorE.refClusterE, altL, bbpL );
359 	}
360 
361 	return ( actL + 0x10000000 ) >> 5; /*output range 0...1 in 8.24*/
362 }
363 
364 /* ------------------------------------------------------------------------- */
365 
bpi_BFFaceFinder_getFaceDCR(struct bbs_Context * cpA,const struct bpi_BFFaceFinder * ptrA,uint32 indexA,struct bpi_DCR * dcrPtrA)366 void bpi_BFFaceFinder_getFaceDCR( struct bbs_Context* cpA,
367 								  const struct bpi_BFFaceFinder* ptrA,
368 								  uint32 indexA,
369 								  struct bpi_DCR* dcrPtrA )
370 {
371 	int32 confL = bpi_BFFaceFinder_getFace( cpA, ptrA, indexA, &dcrPtrA->offsE, &dcrPtrA->mainClusterE );
372 	bts_IdCluster2D_copy( cpA, &dcrPtrA->sdkClusterE, &dcrPtrA->mainClusterE );
373 	dcrPtrA->confidenceE = confL;
374 	dcrPtrA->approvedE = confL > ( ( int32 )1 << 23 );
375 }
376 
377 /* ------------------------------------------------------------------------- */
378 
bpi_BFFaceFinder_setMaxImageSize(struct bbs_Context * cpA,struct bpi_BFFaceFinder * ptrA,uint32 maxImageWidthA,uint32 maxImageHeightA)379 void bpi_BFFaceFinder_setMaxImageSize( struct bbs_Context* cpA,
380 									   struct bpi_BFFaceFinder* ptrA,
381 									   uint32 maxImageWidthA,
382 									   uint32 maxImageHeightA )
383 {
384 	ptrA->detectorE.maxImageWidthE = maxImageWidthA;
385 	ptrA->detectorE.maxImageHeightE = maxImageHeightA;
386 }
387 
388 /* ------------------------------------------------------------------------- */
389 
bpi_BFFaceFinder_setParams(struct bbs_Context * cpA,struct bpi_FaceFinder * ptrA,uint32 maxImageWidthA,uint32 maxImageHeightA)390 void bpi_BFFaceFinder_setParams( struct bbs_Context* cpA,
391 								 struct bpi_FaceFinder* ptrA,
392 								 uint32 maxImageWidthA,
393 								 uint32 maxImageHeightA )
394 {
395 	bbs_DEF_fNameL( "bpi_BFFaceFinder_setParams" );
396 
397 	if( bbs_Context_error( cpA ) ) return;
398 
399 	if( ptrA->typeE != bpi_FF_BF_FACE_FINDER )
400 	{
401 		bbs_ERROR1( "%s:\nObject type mismatch", fNameL );
402 		return;
403 	}
404 	bpi_BFFaceFinder_setMaxImageSize( cpA, ( struct bpi_BFFaceFinder* )ptrA, maxImageWidthA, maxImageHeightA );
405 }
406 
407 /* ------------------------------------------------------------------------- */
408 
bpi_BFFaceFinder_setRange(struct bbs_Context * cpA,struct bpi_FaceFinder * ptrA,uint32 minEyeDistanceA,uint32 maxEyeDistanceA)409 void bpi_BFFaceFinder_setRange( struct bbs_Context* cpA,
410 								struct bpi_FaceFinder* ptrA,
411 								uint32 minEyeDistanceA,
412 								uint32 maxEyeDistanceA )
413 {
414 	bbs_DEF_fNameL( "bpi_BFFaceFinder_setParams" );
415 
416 	if( bbs_Context_error( cpA ) ) return;
417 
418 	if( ptrA->typeE != bpi_FF_BF_FACE_FINDER )
419 	{
420 		bbs_ERROR1( "%s:\nObject type mismatch", fNameL );
421 		return;
422 	}
423 	bpi_BFFaceFinder_setMinEyeDistance( cpA, ( struct bpi_BFFaceFinder* )ptrA, minEyeDistanceA );
424 	bpi_BFFaceFinder_setMaxEyeDistance( cpA, ( struct bpi_BFFaceFinder* )ptrA, maxEyeDistanceA );
425 }
426 
427 /* ------------------------------------------------------------------------- */
428 
bpi_BFFaceFinder_processDcr(struct bbs_Context * cpA,const struct bpi_FaceFinder * ptrA,struct bpi_DCR * dcrPtrA)429 int32 bpi_BFFaceFinder_processDcr( struct bbs_Context* cpA,
430 								   const struct bpi_FaceFinder* ptrA,
431 						           struct bpi_DCR* dcrPtrA )
432 {
433 	bbs_DEF_fNameL( "bpi_BFFaceFinder_processDcr" );
434 
435 	if( bbs_Context_error( cpA ) ) return 0;
436 
437 	if( ptrA->typeE != bpi_FF_BF_FACE_FINDER )
438 	{
439 		bbs_ERROR1( "%s:\nObject type mismatch", fNameL );
440 		return 0;
441 	}
442 
443 	return bpi_BFFaceFinder_process( cpA,
444 									( const struct bpi_BFFaceFinder* )ptrA,
445 									dcrPtrA->imageDataPtrE,
446 									dcrPtrA->imageWidthE,
447 									dcrPtrA->imageHeightE,
448 									&dcrPtrA->roiRectE,
449 									&dcrPtrA->offsE,
450 									&dcrPtrA->mainClusterE );
451 }
452 
453 /* ------------------------------------------------------------------------- */
454 
bpi_BFFaceFinder_putDcr(struct bbs_Context * cpA,const struct bpi_FaceFinder * ptrA,struct bpi_DCR * dcrPtrA)455 int32 bpi_BFFaceFinder_putDcr( struct bbs_Context* cpA,
456 							   const struct bpi_FaceFinder* ptrA,
457 							   struct bpi_DCR* dcrPtrA )
458 {
459 	bbs_DEF_fNameL( "bpi_BFFaceFinder_putDcr" );
460 
461 	if( bbs_Context_error( cpA ) ) return 0;
462 
463 	if( ptrA->typeE != bpi_FF_BF_FACE_FINDER )
464 	{
465 		bbs_ERROR1( "%s:\nObject type mismatch", fNameL );
466 		return 0;
467 	}
468 
469 	return bpi_BFFaceFinder_multiProcess( cpA,
470 										 ( const struct bpi_BFFaceFinder* )ptrA,
471 										 dcrPtrA->imageDataPtrE,
472 										 dcrPtrA->imageWidthE,
473 										 dcrPtrA->imageHeightE,
474 										 &dcrPtrA->roiRectE );
475 }
476 
477 /* ------------------------------------------------------------------------- */
478 
bpi_BFFaceFinder_getDcr(struct bbs_Context * cpA,const struct bpi_FaceFinder * ptrA,uint32 indexA,struct bpi_DCR * dcrPtrA)479 void bpi_BFFaceFinder_getDcr( struct bbs_Context* cpA,
480 							  const struct bpi_FaceFinder* ptrA,
481 							  uint32 indexA,
482 							  struct bpi_DCR* dcrPtrA )
483 {
484 	bbs_DEF_fNameL( "bpi_BFFaceFinder_getDcr" );
485 
486 	if( bbs_Context_error( cpA ) ) return;
487 
488 	if( ptrA->typeE != bpi_FF_BF_FACE_FINDER )
489 	{
490 		bbs_ERROR1( "%s:\nObject type mismatch", fNameL );
491 		return;
492 	}
493 
494 	bpi_BFFaceFinder_getFaceDCR( cpA, ( const struct bpi_BFFaceFinder* )ptrA, indexA, dcrPtrA );
495 }
496 
497 /* ------------------------------------------------------------------------- */
498 
499 /* ========================================================================= */
500