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, ¢erL );
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, ¢erL );
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