00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 00011 00012 00013 00014 00015 00016 00017 00018 00019
00020
00021 00022 00023 00024 00025
00026
00027 #include <string.h>
00028 #include <ltdl.h>
00029 #include "_gocr.h"
00030 #include "gocr.h"
00031
00032 List liblist;
00033 List modulefunclist[allModules];
00034
00035 static currentid = 0, currentlibid = 0;
00036
00037 struct _gocr_lib {
00038 void *handle;
00039 int id;
00040 int (*setAttrib) (void *, void *);
00041 };
00042
00043 struct _gocr_modulefunction {
00044 int id;
00045 struct _gocr_lib *l;
00046 char *name;
00047 void *data;
00048
00049 union {
00050 void (*grayImageFilter) ( int x, int y, unsigned char **data, void *v );
00051 int (*grayToBW) ( gocrImage *img, void *v );
00052 void (*bwImageFilter) ( gocrImage *img, void *v );
00053 void (*blockFinder) ( gocrImage *img, void *v );
00054 int (*charFinder) ( gocrBlock *b, void *v );
00055 int (*charRecognizer) ( gocrImage *pix, gocrBox *b, void *v );
00056 void (*contextCorrection) ( gocrImage *pix, gocrBox *b, void *v );
00057 void (*outputFormatter) ( void *v );
00058 } func;
00059 };
00060
00061 00062 00063
00064
00065 int _gocr_initModule ( void ) {
00066 gocr_moduleType i;
00067 struct _gocr_modulefunction *m;
00068 int r;
00069
00070
00071 list_init(&liblist);
00072 for ( i = 0; i < allModules; i++ ) {
00073 list_init(&modulefunclist[i]);
00074 }
00075
00076
00077 r = lt_dlinit();
00078 if ( r )
00079 return r;
00080 #if 0
00081 lt_dladdsearchdir(GOCR_PATH);
00082 #endif
00083 return 0;
00084 }
00085
00086 void _gocr_endModule ( void ) {
00087 gocr_moduleType i;
00088 struct _gocr_modulefunction *m;
00089
00090 for ( i = 0; i < allModules; i++ ) {
00091 for_each_data(&modulefunclist[i]) {
00092 m = (struct _gocr_modulefunction *)list_get_current(&modulefunclist[i]);
00093 if (m) {
00094 if (m->name)
00095 free(m->name);
00096 free(m);
00097 }
00098 } end_for_each(&modulefunclist[i]);
00099 list_free(&modulefunclist[i]);
00100 }
00101
00102 for_each_data(&liblist) {
00103 struct _gocr_lib *t = (struct _gocr_lib *)list_get_current(&liblist);
00104 lt_dlclose(t->handle);
00105 } end_for_each(&liblist);
00106 list_free(&liblist);
00107
00108 lt_dlexit();
00109 }
00110
00111 00112 00113
00114
00124 int gocr_moduleLoad ( char *filename ) {
00125 struct _gocr_lib *l;
00126 int (*init_func)(void);
00127
00128 _gocr_debug(3, fprintf(_data.error, "gocr_loadModule(%s)\n", filename);)
00129 l = (struct _gocr_lib *)malloc(sizeof(struct _gocr_lib));
00130 if ( !l ) {
00131 _gocr_debug(1, fprintf(_data.error, "Not enough memory\n");)
00132 return -1;
00133 }
00134
00135 l->handle = lt_dlopen( filename );
00136 if ( !l->handle ) {
00137 _gocr_debug(1, fprintf(_data.error, "Could not open module %s: %s\n", filename, dlerror());)
00138 return -1;
00139 }
00140
00141 /* try to open an init function */
00142 init_func = lt_dlsym( l->handle, "initModule" );
00143 if ( init_func ) {
00144 int r;
00145
00146 _gocr_debug(3, fprintf(_data.error, "Running init_func\n");)
00147 r = init_func();
00148 if ( r != 0 ) {
00149 lt_dlclose(l->handle);
00150 free(l);
00151 _gocr_debug(1, fprintf(_data.error, "%s init function returned %d\n", filename, r );)
00152 return -1;
00153 }
00154 }
00155
00156 /* try to open the setAttrib function */
00157 l->setAttrib = lt_dlsym( l->handle, "setAttribute" );
00158 l->id = currentlibid++;
00159
00160 list_app(&liblist, l);
00161 return l->id;
00162 }
00163
00173 void gocr_moduleClose ( int id ) {
00174 void (*close)(void);
00175 struct _gocr_lib *l;
00176 struct _gocr_modulefunction *m;
00177 gocr_moduleType t;
00178
00179 _gocr_debug(3, fprintf(_data.error, "gocr_closeModule(%d)\n", id);)
00180 /* search module */
00181 for_each_data(&liblist) {
00182 l = (struct _gocr_lib *)list_get_current(&liblist);
00183 if ( l->id == id )
00184 break;
00185 } end_for_each(&liblist);
00186
00187 if ( l->id != id ) {/* module not found */
00188 _gocr_debug(1, fprintf(_data.error, "Module not found\n", id);)
00189 return;
00190 }
00191
00192 close = lt_dlsym( l->handle, "closeModule" );
00193 if ( close )
00194 close();
00195
00196 for ( t = 0; t < allModules; t++ ) {
00197 for_each_data(&modulefunclist[t]) {
00198 m = (struct _gocr_modulefunction *)list_get_current(&modulefunclist[t]);
00199 if ( m->l == l ) {
00200 if ( m->name )
00201 free(m->name);
00202 list_del(&modulefunclist[t], m);
00203 free(m);
00204 }
00205 } end_for_each(&modulefunclist[t]);
00206 }
00207
00208 lt_dlclose(l->handle);
00209 list_del(&liblist, l);
00210 free(l);
00211 }
00212
00225 int gocr_moduleSetAttribute ( int id, void *a, void *b ) {
00226 struct _gocr_lib *l;
00227
00228 _gocr_debug(3, fprintf(_data.error, "gocr_setModuleAttribute(%d, %p, %p)\n", id, a, b);)
00229 for_each_data(&liblist) {
00230 l = (struct _gocr_lib *)list_get_current(&liblist);
00231 if ( l->id == id )
00232 break;
00233 } end_for_each(&liblist);
00234
00235 if ( l->id == id ) { /* module not found */
00236 _gocr_debug(1, fprintf(_data.error, "Module library not found, setModuleAttrib\n");)
00237 return -1;
00238 }
00239
00240 if ( l->setAttrib == NULL ) { /* no such function */
00241 _gocr_debug(1, fprintf(_data.error, "Module library doesn't contain setAttrib, setModuleAttrib\n");)
00242 return -1;
00243 }
00244
00245 return l->setAttrib( a, b );
00246 }
00247
00261 int gocr_functionInsertBefore ( gocr_moduleType t, char *functionname,
00262 void *data, int id ) {
00263 struct _gocr_modulefunction *m;
00264 int i = 0;
00265
00266 _gocr_debug(3, fprintf(_data.error, "gocr_insertModuleBefore(%d, %s, %p, %d)",
00267 (int)t, functionname, data, id);)
00268 m = (struct _gocr_modulefunction *)malloc(sizeof(struct _gocr_modulefunction));
00269 if (!m) {
00270 _gocr_debug(1, fprintf(_data.error, "Not enough memory\n");)
00271 return -1;
00272 }
00273
00274 /* open module function; search the opened modules. */
00275 for_each_data(&liblist) {
00276 switch (t) {
00277 case grayImageFilter:
00278 m->func.grayImageFilter = lt_dlsym(list_get_current(&liblist), functionname);
00279 i++;
00280 break;
00281 case grayToBW:
00282 m->func.grayToBW = lt_dlsym(list_get_current(&liblist), functionname);
00283 i++;
00284 break;
00285 case bwImageFilter:
00286 m->func.grayImageFilter = lt_dlsym(list_get_current(&liblist), functionname);
00287 i++;
00288 break;
00289 case blockFinder:
00290 m->func.blockFinder = lt_dlsym(list_get_current(&liblist), functionname);
00291 i++;
00292 break;
00293 case charFinder:
00294 m->func.charFinder = lt_dlsym(list_get_current(&liblist), functionname);
00295 i++;
00296 break;
00297 case charRecognizer:
00298 m->func.charRecognizer = lt_dlsym(list_get_current(&liblist), functionname);
00299 i++;
00300 break;
00301 case contextCorrection:
00302 m->func.contextCorrection = lt_dlsym(list_get_current(&liblist), functionname);
00303 i++;
00304 break;
00305 case outputFormatter:
00306 m->func.outputFormatter = lt_dlsym(list_get_current(&liblist), functionname);
00307 i++;
00308 break;
00309 }
00310 m->l = list_get_current(&liblist);
00311 if ( i ) /* found the module */
00312 break;
00313 } end_for_each(&liblist);
00314
00315 if ( !i ) { /* module not found */
00316 _gocr_debug(1, fprintf(_data.error, "Module function %s not found\n", functionname);)
00317 return -1;
00318 }
00319
00320 m->id = currentid++;
00321 m->name = strdup(functionname);
00322 m->data = data;
00323
00324 /* there can be only one Highlander. I mean, grayToBW. */
00325 if ( t == grayToBW ) {
00326 struct _gocr_modulefunction *n =
00327 (struct _gocr_modulefunction *)list_get_header(&modulefunclist[t]);
00328 gocr_functionDeleteById(n->id);
00329 id = -1;
00330 }
00331
00332 /* and add to the list! */
00333 if ( id == -1 )
00334 list_app(&modulefunclist[t], m);
00335 else {
00336 struct _gocr_modulefunction *n;
00337
00338 for_each_data(&modulefunclist[t]) {
00339 n = (struct _gocr_modulefunction *)list_get_current(&modulefunclist[t]);
00340 if ( n->id == id )
00341 break;
00342 } end_for_each(&modulefunclist[t]);
00343 if ( n == NULL )
00344 list_app(&modulefunclist[t], m);
00345 else
00346 list_ins(&modulefunclist[t], n, m);
00347 }
00348
00349 return m->id;
00350 }
00351
00364 int gocr_functionAppend ( gocr_moduleType t, char *functionname,
00365 void *data ) {
00366 return gocr_functionInsertBefore(t, functionname, data, -1);
00367 }
00368
00379 void *gocr_functionDeleteById ( int id ) {
00380 gocr_moduleType t;
00381 struct _gocr_modulefunction *m;
00382 void *data;
00383
00384 _gocr_debug(3, fprintf(_data.error, "gocr_functionDeleteById(%d)", id);)
00385 for ( t = 0; t < allModules; t++ ) {
00386 for_each_data(&modulefunclist[t]) {
00387 m = (struct _gocr_modulefunction *)list_get_current(&modulefunclist[t]);
00388 if ( m->id == id ) {
00389 list_del(&modulefunclist[t], m);
00390 if ( m->name )
00391 free(m->name);
00392 data = m->data;
00393 free(m);
00394 return data;
00395 }
00396 } end_for_each(&modulefunclist[t]);
00397 }
00398
00399 _gocr_debug(1, fprintf(_data.error, "functionDelete: Module function with id %d not found.\n", id );)
00400 return NULL;
00401 }
00402
00403 #if 0
00404 int gocr_runModuleFunction ( int id ) {
00405 struct _gocr_modulefunction *m;
00406 gocr_moduleType i;
00407 int done = 0;
00408
00409 _gocr_debug(3, fprintf(_data.error, "gocr_runModuleFunction(%d)", id);)
00410 for ( i = 0; i < allModules; i++ ) {
00411 for_each_data(&modulefunclist[i]) {
00412 m = (struct _gocr_modulefunction *)list_get_current(&modulefunclist[i]);
00413 if ( m->id == id ) {
00414 switch (i) {
00415 case grayImageFilter:
00416 m->func.grayImageFilter(currentimage->x, currentimage->y,
00417 (unsigned char **)currentimage->data, m->data);
00418 done++;
00419 break;
00420 case grayToBW:
00421 m->func.grayToBW(currentimage, m->data);
00422 done++;
00423 break;
00424 case bwImageFilter:
00425 m->func.bwImageFilter(currentimage, m->data);
00426 done++;
00427 break;
00428 case blockFinder:
00429 m->func.blockFinder(currentimage, m->data);
00430 done++;
00431 break;
00432 case charFinder:
00433 m->func.charFinder(block, m->data);
00434 done++;
00435 break;
00436 case charRecognizer:
00437 m->func.charRecognizer(pix, box, m->data);
00438 done++;
00439 break;
00440 case contextCorrection:
00441 m->func.contextCorrection(pix, box, m->data);
00442 done++;
00443 break;
00444 case outputFormatter:
00445 m->func.outputFormatter(m->data);
00446 done++;
00447 break;
00448 }
00449 }
00450 if ( done ) break;
00451 } end_for_each(&modulefunclist[i]);
00452 if ( done ) return 0;
00453 }
00454
00455 _gocr_debug(1, fprintf(_data.error, "runModuleFunction: no such id\n");)
00456 return -1;
00457 }
00458
00459 int gocr_runModuleType ( gocr_moduleType t ) {
00460 struct _gocr_modulefunction *m;
00461
00462 _gocr_debug(3, fprintf(_data.error, "gocr_runModuleType(%d)\n", t);)
00463 for_each_data(&modulefunclist[t]) {
00464 m = (struct _gocr_modulefunction *)list_get_current(&modulefunclist[t]);
00465 // m->func(m->data);
00466 } end_for_each(&modulefunclist[t]);
00467 }
00468 #endif
00469
00470 int gocr_runAllModules ( void ) {
00471 struct _gocr_modulefunction *m;
00472 gocrImage *image;
00473
00474 _gocr_debug(3, fprintf(_data.error, "gocr_runAllModules\n");)
00475
00476 /* if the image is gray, apply the gray* modules */
00477 if ( currentimage->type == GRAY ) {
00478 for_each_data(&modulefunclist[grayImageFilter]) {
00479 m = (struct _gocr_modulefunction *)list_get_current(&modulefunclist[grayImageFilter]);
00480 _gocr_debug(3, fprintf(_data.error, "module grayImageFilter:%s\n", m->name);)
00481 m->func.grayImageFilter(currentimage->x, currentimage->y,
00482 (unsigned char **)currentimage->data, m->data);
00483 } end_for_each(&modulefunclist[grayImageFilter]);
00484
00485 m = (struct _gocr_modulefunction *)list_get_header(&modulefunclist[grayToBW]);
00486 if ( m == NULL ) {
00487 _gocr_debug(3, fprintf(_data.error, "module grayToBW: internal\n");)
00488 if ( otsu(currentimage, NULL) != 0 ) {
00489 _gocr_debug(1, fprintf(_data.error, "grayToBW returned -1\n");)
00490 return -1;
00491 }
00492 }
00493 else { /* user supplied one */
00494 _gocr_debug(3, fprintf(_data.error, "module grayToBW: %s\n", m->name);)
00495 if ( m->func.grayToBW(currentimage, m->data) != 0 ) {
00496 _gocr_debug(1, fprintf(_data.error, "grayToBW returned -1\n");)
00497 return -1;
00498 }
00499 /* and clean the gocrPixel structure, except the value field */
00500 {
00501 int i, j;
00502 gocrPixel p;
00503 unsigned char **data = (unsigned char **)currentimage->data, *c;
00504
00505 memset(&p, 0, sizeof(gocrPixel));
00506 p.value = 1;
00507 c = (unsigned char *)&p;
00508
00509 for ( i = 0; i < currentimage->x; i++ )
00510 for ( j = 0; j < currentimage->y; j++ )
00511 data[i][j] &= *c;
00512 }
00513 }
00514 currentimage->type = BLACK_AND_WHITE;
00515 }
00516
00517 /* b&w filters */
00518 for_each_data(&modulefunclist[bwImageFilter]) {
00519 m = (struct _gocr_modulefunction *)list_get_current(&modulefunclist[bwImageFilter]);
00520 _gocr_debug(3, fprintf(_data.error, "module bwImageFilter:%s\n", m->name);)
00521 m->func.bwImageFilter(currentimage, m->data);
00522 } end_for_each(&modulefunclist[bwImageFilter]);
00523
00524 /* find blocks */
00525 for_each_data(&modulefunclist[blockFinder]) {
00526 m = (struct _gocr_modulefunction *)list_get_current(&modulefunclist[blockFinder]);
00527 _gocr_debug(3, fprintf(_data.error, "module blockFinder:%s\n", m->name);)
00528 m->func.blockFinder(currentimage, m->data);
00529 } end_for_each(&modulefunclist[blockFinder]);
00530
00531 /* frame characters in each block */
00532 for_each_data(¤timage->blocklist) {
00533 currentblock = (gocrBlock *)list_get_current(¤timage->blocklist);
00534 for_each_data(&modulefunclist[charFinder]) {
00535 m = (struct _gocr_modulefunction *)list_get_current(&modulefunclist[charFinder]);
00536 _gocr_debug(3, fprintf(_data.error, "module charFinder:%s\n", m->name);)
00537 if ( m->func.charFinder((gocrBlock *)list_get_current(¤timage->blocklist),
00538 m->data) == 0 ) /* function took care */
00539 break;
00540 } end_for_each(&modulefunclist[charFinder]);
00541 } end_for_each(¤timage->blocklist);
00542
00543 #if 0
00544 /* recognize each character */
00545 for_each_data(¤timage->blocklist) {
00546 currentblock = (gocrBlock *)list_get_current(¤timage->blocklist);
00547 for_each_data(¤tblock->boxlist) {
00548 int i;
00549
00550 currentbox = (gocrBox *)list_get_current(¤tblock->boxlist);
00551
00552 /* these is a simple but bad solution. The best thing to do is to use
00553 realloc or something; very little waste, much more speed. */
00554 _gocr_imageCopy(currentimage, currentbox->x0, currentbox->y0,
00555 currentbox->x1, currentbox->y1, image);
00556
00557 for_each_data(&modulefunclist[charRecognizer]) {
00558 m = (struct _gocr_modulefunction *)list_get_current(&modulefunclist[charRecognizer]);
00559 _gocr_debug(3, fprintf(_data.error, "module charRecognizer:%s\n", m->name);)
00560 _gocr_debug(3, gocr_printBox(currentbox);)
00561 if (m->func.charRecognizer(image, currentbox, m->data))
00562 break;
00563 } end_for_each(&modulefunclist[charRecognizer]);
00564
00565 gocr_imageFree(image);
00566
00567 } end_for_each(¤tblock->boxlist);
00568 } end_for_each(¤timage->blocklist);
00569 #endif
00570
00571 #if 0
00572 /* do something with unrecognized characters */
00573 for_each_data(¤timage->blocklist) {
00574 currentblock = (gocrBlock *)list_get_current(¤timage->blocklist);
00575 for_each_data(¤tblock->boxlist) {
00576 for_each_data(&modulefunclist[contextCorrection]) {
00577 m = (struct _gocr_modulefunction *)list_get_current(&modulefunclist[contextCorrection]);
00578 _gocr_debug(3, fprintf(_data.error, "module contextCorrection:%s\n", m->name);)
00579 if (m->func((gocrBox *)list_get_current(¤tblock->boxlist), m->data))
00580 break;
00581 } end_for_each(&modulefunclist[contextCorrection]);
00582 } end_for_each(¤tblock->boxlist);
00583 } end_for_each(¤timage->blocklist);
00584
00585 /* output */
00586 for_each_data(&modulefunclist[outputFormatter]) {
00587 _gocr_debug(3, fprintf(_data.error, "module outputFormatter:%s\n", m->name);)
00588 m = (struct _gocr_modulefunction *)list_get_current(&modulefunclist[outputFormatter]);
00589 m->func(block?);
00590 } end_for_each(&modulefunclist[outputFormatter]);
00591 #endif
00592 }