Main Page   Compound List   File List   Compound Members   File Members  

modules.c

00001 /*
00002 GOCR Copyright (C) 2000  Joerg Schulenburg Joerg.Schulenburg@physik.uni-magdeburg.de 
00003 GOCR API Copyright (C) 2001 Bruno Barberi Gnecco <brunobg@sourceforge.net>
00004 
00005 This program is free software; you can redistribute it and/or
00006 modify it under the terms of the GNU General Public License
00007 as published by the Free Software Foundation; either version 2
00008 of the License, or (at your option) any later version.
00009 
00010 This program is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 GNU General Public License for more details.
00014 
00015 You should have received a copy of the GNU General Public License
00016 along with this program; if not, write to the Free Software
00017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018 
00019 */
00020 
00021 /* NOTE: this was the first piece of code I wrote for GOCR API, and it really
00022 seems so. Apart from a review I'm doing, some functions may be completely
00023 rewritten.
00024 One of the things that may happen is using hash tables instead of linked lists,
00025 for liblist. Module functions need to be linked lists, since order matters. */
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  * Internal functions
00063  */
00064 
00065 int _gocr_initModule ( void ) {
00066   gocr_moduleType i;
00067   struct _gocr_modulefunction *m;
00068   int r;
00069 
00070   /* init lists */
00071   list_init(&liblist);
00072   for ( i = 0; i < allModules; i++ ) {
00073     list_init(&modulefunclist[i]);
00074   }
00075 
00076   /* init libltdl */
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  * External Functions
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(&currentimage->blocklist) {
00533     currentblock  = (gocrBlock *)list_get_current(&currentimage->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(&currentimage->blocklist), 
00538           m->data) == 0 ) /* function took care */
00539           break;
00540     } end_for_each(&modulefunclist[charFinder]);
00541   } end_for_each(&currentimage->blocklist);
00542 
00543 #if 0
00544   /* recognize each character */
00545   for_each_data(&currentimage->blocklist) {
00546     currentblock  = (gocrBlock *)list_get_current(&currentimage->blocklist);
00547     for_each_data(&currentblock->boxlist) {
00548       int i;
00549 
00550       currentbox = (gocrBox *)list_get_current(&currentblock->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(&currentblock->boxlist);
00568   } end_for_each(&currentimage->blocklist);
00569 #endif
00570 
00571 #if 0
00572   /* do something with unrecognized characters */
00573   for_each_data(&currentimage->blocklist) {
00574     currentblock  = (gocrBlock *)list_get_current(&currentimage->blocklist);
00575     for_each_data(&currentblock->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(&currentblock->boxlist), m->data))
00580           break;
00581       } end_for_each(&modulefunclist[contextCorrection]);
00582     } end_for_each(&currentblock->boxlist);
00583   } end_for_each(&currentimage->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 }

Generated at Thu Mar 1 10:05:32 2001 for GOCR API by doxygen1.2.2 written by Dimitri van Heesch, © 1997-2000