/******************************************************* *** Bildverarbeitungs- und OCR-Routinen *** *** *** *******************************************************/ /** includes **/ #include #include #include #include #include #include #include #include "ocr.h" #include "baum.h" #include "semantik.h" #include "main.h" /** defines **/ #define MAXDIFFERENZ 64 #define Segment_X 128 #define Segment_Y 180 #define Segment_Bytes 16 #define MAXSTACK 30000 #define MAXWINKEL 0.2094395102 #define MAXANZAHL 60 /************ Globale Variablen *****************/ extern short int Wsa[]; extern long Quadrat[]; extern struct Parameter ParaAktuell; struct LearndListe *ZeichenListeStart[35][16][16]; unsigned char Bits[8] = {128, 64, 32, 16, 8, 4, 2, 1}; unsigned char RandRechts[8] = { 1, 3, 7, 15, 31, 63,127,254}; unsigned char RandLinks[8] = {128,192,224,240,248,252,254,255}; struct BitBlockListe *BitBlockListeStartPtr = NULL; struct BitBlockListe *SegmentBitBlockListeStartPtr = NULL; struct BitBlockListe *KopierePtr = NULL; long Page_x,Page_y,Page_Bytes_pro_Zeile; long Max_x,Min_x,Min_y,Max_y; long maxcount,rek_x,rek_y,xx,yy,offset_x,offset_y; unsigned char *OrginalBildPuffer,*ArbeitsPuffer,*HilfsPtr; unsigned char Value,Value1; unsigned char *rek_y_zeile; unsigned short int PunkteInByte[256]; unsigned short int ByteIstGespiegelt[256]; float faktorx,faktory; long durch_dx, durch_dy; /******** Sonstiges/Deklarationen *************/ void SucheBitBloecke(); void SucheSegmenteBitBloecke(); /*************************************************************** Procedure : void Spiegle() Uebergabe : short int Rueckgabe : short int Zugriffe/Global : Keine Autor : Martin Bauer Letzte Aenderung : 1.6.1995 Getestet : JA , Resultat: fehlerfrei (1.6.1995) Aufgabe: Es soll der Eingabeparameter (8-Bit) einfach gespiegelt werden. Die muss nicht effizient geloest sein ! **************************************************************** Arithmetic is being able to count up to twenty without taking off your shoes. ****************************************************************/ unsigned short int Spiegle(wert) unsigned long wert; { long l,r,t; unsigned short int wert_1; l=128; r=1; wert_1=0; for (t=0;t<4;t++) { if (l & wert) wert_1 = wert_1 | r; if (r & wert) wert_1 = wert_1 | l; l=l>>1; r=r<<1; } return(wert_1); } /*************************************************************** Procedure : void ZaehlePunkte() Uebergabe : short int Rueckgabe : short int Zugriffe/Global : Keine Autor : Martin Bauer Letzte Aenderung : 1.6.1995 Getestet : JA , Resultat: fehlerfrei (1.6.1995) Aufgabe: Es sollen alle im Eingabeparameter (8-Bit) gesetzten Bits gezaehlt werden. Die muss nicht effizient geloest sein ! *****************************************************************/ /* Remember: Silly is a state of Mind, Stupid is a way of Life.*/ /****************************************************************/ unsigned short int ZaehlePunkte(wert) unsigned long wert; { unsigned long l,t; unsigned char wert_1; l=1; wert_1=0; for (t=0;t<8;t++) { if (l & wert) wert_1++; l=l<<1; } return(wert_1); } /*************************************************************** Procedure : MemoryError() Uebergabe : Nichts Rueckgabe : Nichts Autor : Martin Bauer Letzte Aenderung : 3.6.1995 Getestet : JA , Resultat: fehlerfrei Aufgabe: Bei zuwenig Speicher soll ein Fehler ausgegeben werden. ****************************************************************/ void MemoryError() { /* "Heisenberg may have slept here" */ fprintf(stderr," -------> FEHLER <------- \n"); fprintf(stderr," \n"); fprintf(stderr,"- Das System hat den angefordeten Speicher \n"); fprintf(stderr," nicht zur verfuegung gestellt ! \n"); fprintf(stderr," \n"); fprintf(stderr,"- Behebung des Fehlers: \n"); fprintf(stderr," \n"); fprintf(stderr," 1. Swapspace erhoehen \n"); fprintf(stderr," 2. Mehr Arbeitsspeicher kaufen \n"); fprintf(stderr," 3. Andere Applikationen schliessen \n"); fprintf(stderr," \n"); fflush(stderr); exit(-1); } /*************************************************************** Procedure : OcrInit() Uebergabe : Nichts Rueckgabe : Nichts Autor : Martin Bauer Letzte Aenderung : 3.6.1995 Getestet : JA , Resultat: fehlerfrei Aufgabe: Es werden diverse Initialisierungen und Berechnungen vorgenommen . ****************************************************************/ void LadeGelernteZeichen(); void OcrInit() { unsigned long t,t1,t2; for (t=0;t<256;t++) { PunkteInByte[t]=ZaehlePunkte(t); ByteIstGespiegelt[t]=Spiegle(t); } /* init der Zeichenliste */ for (t=0;t<35;t++) for (t1=0;t1<16;t1++) for (t2=0;t2<16;t2++) ZeichenListeStart[t][t1][t2]=NULL; LadeGelernteZeichen(); } /*************************************************************** Procedure : void LoescheBildFeld(x,y,dx,dy) Uebergabe : Kordinaten x,y,dx,dy Rueckgabe : Nichts Zugriffe/Global : OrginalBildPuffer,Page_Bytes_Pro_Zeile Autor : Martin Bauer Letzte Aenderung : 1.6.1995 Getestet : JA , Resultat: fehlerfrei Aufgabe: Es soll in dem Bild ein Bereich beginnend bei x,y mit der Groesse dx,dy geloescht werden. ****************************************************************/ void LoescheBildFeld(x,y,dx,dy) long x,y,dx,dy; { char *P; long xx,yy,x1,y1,beginx,endex; x--; dx++; xx=x+dx; yy=y+dy+1; if (xx>=Page_x) xx=Page_x-1; if (yy>=Page_y) yy=Page_y-1; endex=(xx>>3); beginx=(x>>3); for (y1=y;y1=Page_x) xx=Page_x-1; if (yy>=Page_y) yy=Page_y-1; endex=(xx>>3); beginx=(x>>3); x &= 7; xx &= 7; for (y1=y;y1Bilddaten. Das Ur-Bild (y_zeile zeigt darauf) wird dabei VERNICHTET ! ****************************************************************/ void KopiereRekursiv() { maxcount++; if (maxcount>MAXSTACK) { maxcount--; return; } /* notfall-rek. abbruch */ if ((rek_x<0) || (Page_x> 3)); Value=*HilfsPtr; Value1=Value & (~(128>>(rek_x&7))); if ( Value!=Value1 ) { *HilfsPtr=Value1; { long x,y; x=((rek_x-KopierePtr->x)*faktory) ; y=((rek_y-KopierePtr->y)*faktory) ; x=x+offset_x; y=y+offset_y; if (y>15) y=15; if (x>15) x=15; HilfsPtr=(KopierePtr->BildDaten+y+y+(x>>3)); *HilfsPtr=*HilfsPtr | (128>>(x&7)); } if (Min_x>rek_x) Min_x=rek_x; if (Min_y>rek_y) Min_y=rek_y; if (Max_x>3)))) { /* Pixel im ArbeitsBild gesetzt ! */ Min_x=x; Max_x=x; Min_y=y; Max_y=y; maxcount=0; rek_x=x; rek_y=y; rek_y_zeile=y_zeile+ArbeitsPuffer; /* suche nun den groessten Block */ SucheBitBloecke(); dx=Max_x-Min_x; dy=Max_y-Min_y; if ((dx>0) && (dy>0)) { /* erstelle Datenelement */ anzahl++; n_dx+=dx; n_dy+=dy; Ptr=calloc(1,sizeof(struct BitBlockListe)); if (Ptr==NULL) { MemoryError(); } Ptr->Bytes_pro_Zeile=t; Ptr->x=Min_x; Ptr->y=Min_y; Ptr->Startx=x; Ptr->Starty=y; Ptr->Geloescht=0; Ptr->SpaltenNummer=0; Ptr->SegmentNummer=0; Ptr->XSpiegel=0; Ptr->YSpiegel=0; Ptr->Untere_Zeile=-1; Ptr->Obere_Zeile=-1; Ptr->Bild=0; Ptr->dx=dx; Ptr->Elemente=1; Ptr->dy=dy; Ptr->xx=Min_x+dx; Ptr->yy=Min_y+dy; Ptr->NextPtrInZeile=NULL; Ptr->NextSegmentBlockPtr=NULL; Ptr->NextPtrInSegment=NULL; Ptr->NextPtr=BitBlockListeStartPtr; BitBlockListeStartPtr=Ptr; } x=x+dx-1; } /* punkt gesetzt */ } /* x loop */ } /* y loop */ if (anzahl!=0) { /* es gab also Bitbloecke */ long schnittx,schnitty; schnittx=(n_dx / (anzahl+0.0))*15; schnitty=(n_dy / (anzahl+0.0))*15; for (Ptr=BitBlockListeStartPtr;Ptr!=NULL;Ptr=Ptr->NextPtr) { if (Ptr->dx>schnittx) { Ptr->Bild=1; } if (Ptr->dy>schnitty) { Ptr->Bild=1; } } /* suche nach bilder die sich ueberschneiden */ for (Ptr=BitBlockListeStartPtr;Ptr!=NULL;Ptr=Ptr->NextPtr) { if ((Ptr->Geloescht==0) && (Ptr->Bild==1)) { for (Ptr1=BitBlockListeStartPtr;Ptr1!=NULL;Ptr1=Ptr1->NextPtr) { if ((Ptr1!=Ptr) && (Ptr1->Geloescht==0)) { if (Ptr->x>Ptr1->x) { x=Ptr->x; } else { x=Ptr1->x; } if (Ptr->y>Ptr1->y) { y=Ptr->y; } else { y=Ptr1->y; } if (Ptr->xxxx) { xx=Ptr->xx; } else { xx=Ptr1->xx; } if (Ptr->yyyy) { yy=Ptr->yy; } else { yy=Ptr1->yy; } if (((xx-x)>=0) && ((yy-y)>=0)) { /* verschmelzen ! */ if (Ptr->x>Ptr1->x) { x=Ptr1->x; } else { x=Ptr->x; } if (Ptr->y>Ptr1->y) { y=Ptr1->y; } else { y=Ptr->y; } if (Ptr->xxxx) { xx=Ptr1->xx; } else { xx=Ptr->xx; } if (Ptr->yyyy) { yy=Ptr1->yy; } else { yy=Ptr->yy; } Ptr1->Geloescht=0; Ptr1->Bild=1; Ptr->x=x; Ptr->Bild=1; Ptr->Geloescht=0; Ptr->y=y; Ptr->xx=xx; Ptr->yy=yy; Ptr->dx=xx-x; Ptr->dy=yy-y; } /* diff x,y */ } } } } /* und loesche alle Bilder aus dem Orginal-Bild ! */ for (Ptr=BitBlockListeStartPtr;Ptr!=NULL;Ptr=Ptr->NextPtr) { if (Ptr->Bild==1) { Ptr->Geloescht=1; LoescheBildFeld(Ptr->x,Ptr->y,Ptr->dx,Ptr->dy); } } } /* Jetzt werden alle erkannten Bloecke aus dem Bild kopiert */ /* resturiere ArbeitsBild */ x=Page_y*Page_Bytes_pro_Zeile; P1=ArbeitsPtr; P2=OrginalBildPuffer; for (t=0;tNextPtr) { if ((Ptr->Bild==0) && (Ptr->Geloescht==0)) { for (t=0;t<32;t++) Ptr->BildDaten[t]=0; offset_x=0; offset_y=0; if (Ptr->dx>Ptr->dy) { faktory=16/(Ptr->dx+0.0); offset_y=(16-(faktory*Ptr->dy))/2; } else { faktory=16/(Ptr->dy+0.0); offset_x=(16-(faktory*Ptr->dx))/2; } if ((Ptr->dx<16) && (Ptr->dy<16)) { faktory=1.0; offset_y=(16-Ptr->dy)>>1; offset_x=(16-Ptr->dx)>>1; } KopierePtr=Ptr; rek_x=Ptr->Startx; rek_y=Ptr->Starty; maxcount=0; rek_y_zeile=ArbeitsPtr+rek_y*Page_Bytes_pro_Zeile; KopiereRekursiv(); } } free(ArbeitsPtr); } /*************************************************************** Procedure : void Finde_SegmentBloecke() Uebergabe : Nichts Rueckgabe : Nichts Autor : Martin Bauer Letzte Aenderung : 1.6.1995 Getestet : JA , Resultat: fehlerfrei (1.6.1995) Aufgabe: Es sollen in einem Bild (*OrginalBildPuffer) der Groesse Page_x,Page_y (Page_Bytes_pro_Zeile) alle "Segmente", d.h. alle rechteckigen Bloecke zusammengefasst werden die nach einem Verkleinerungszoom des Orginalbildes sich gebildet haben. Dadurch kann man einzelne Text-Bloecke gut herausfinden. Diese gefundenen Bloecke werden in eine Liste eingetragen. Der StartPointer der Liste ist: SegmentBitBlockListeStartPtr Die Elemente der Liste haben den Typ: BitBlockListe. Der Zeiger auf das naechste Segment ist: NextPtrInSegment Es sollen weiterhin alle Segmente in Spalten sortiert werden. Dabei gilt: Spalten von links nach rechts, Segmente in den Spalten vun oben nach unten. ****************************************************************/ void Finde_SegmentBloecke() { long t,x,y,dx,dy,y1,xx,yy,y_zeile; struct BitBlockListe *Ptr,*P1,*P2,*P3,*P4,*P0; unsigned char *HilfsPuffer,*P,*Pc1; long SegmentNummer,x11,y11,k,min,max,Anzahl,Summe; float deltax,deltay; /* Init der lokalen Variablen */ t=0; x=0; y=0; dx=0; dy=0; xx=0; yy=0; y_zeile=0; SegmentNummer=0; x11=0; y11=0; k=0; min=0; max=0; Summe=0; Anzahl=0; y1=0; P1=NULL; P2=NULL; P3=NULL; P4=NULL; P0=NULL; P=NULL; HilfsPuffer=NULL; deltax=0.0; deltay=0.0; /* lege platz fuer segment-kopie an ! */ k=Page_Bytes_pro_Zeile*Page_y; HilfsPuffer=calloc(1,k); if (HilfsPuffer==NULL) { MemoryError(); } Pc1=HilfsPuffer; for (t=0;tNextPtr) { if ((Ptr->Bild==0) && (Ptr->Geloescht==0)) { dx=dx+Ptr->dx; dy=dy+Ptr->dy; Anzahl++; } } x11=0; y11=0; if (Anzahl!=0) { x11=((dx+0.0)/Anzahl)*2; y11=((dy+0.0)/Anzahl)*3; } for (Ptr=BitBlockListeStartPtr;Ptr!=NULL;Ptr=Ptr->NextPtr) { if ((Ptr->Bild==0) && (Ptr->Geloescht==0)) { if (x11>Ptr->dx) { x=x11; } else { x=Ptr->dx*1.5; } if (y11>Ptr->dy) { y=y11; } else { y=Ptr->dy*1.5; } SetzeBildFeld(HilfsPuffer,Page_Bytes_pro_Zeile,Ptr->x,Ptr->y,x,y); } } /* Jetzt wird nach den Bloecken im schwarzen bloecke Bild gesucht */ y_zeile=0-Page_Bytes_pro_Zeile; for (y=0;y> 3)))) { /* Pixel im ArbeitsBild gesetzt ! */ Min_x=x; Max_x=x; Min_y=y; Max_y=y; maxcount=0; ArbeitsPuffer=HilfsPuffer; rek_x=x; rek_y=y; rek_y_zeile=y_zeile+ArbeitsPuffer; SucheBitBloecke(); dx=Max_x-Min_x+1; dy=Max_y-Min_y+1; if ((dx>3) && (dy>3)) { /* erstelle Datenelement */ Ptr=calloc(1,sizeof(struct BitBlockListe)); if (Ptr==NULL) { MemoryError(); } Ptr->Bytes_pro_Zeile=0; Ptr->x=Min_x; Ptr->y=Min_y; Ptr->Startx=x; Ptr->Starty=y; Ptr->Bild=0; Ptr->SegmentNummer=-1; Ptr->SpaltenNummer=-1; Ptr->XSpiegel=0; Ptr->YSpiegel=0; Ptr->Untere_Zeile=-1; Ptr->Obere_Zeile=-1; Ptr->Geloescht=0; Ptr->dx=dx; Ptr->dy=dy; Ptr->xx=Min_x+dx; Ptr->yy=Min_y+dy; Ptr->NextPtrInZeile=NULL; Ptr->NextSegmentBlockPtr=NULL; Ptr->NextPtrInSegment=NULL; Ptr->NextPtr=SegmentBitBlockListeStartPtr; SegmentBitBlockListeStartPtr=Ptr; } /* min. 2 pixel */ x=x+dx-1; } /* punkt gesetzt */ } /* x loop */ } /* y loop */ free(HilfsPuffer); /* Wenn nun wegen max-rekursion abgebrochen wurde, muessen */ /* wir noch zusammenhaengende Segmente zusammenfuegen ! */ for (P1=SegmentBitBlockListeStartPtr;P1!=NULL;P1=P1->NextPtr) { if (P1->Geloescht==0) { for (P2=SegmentBitBlockListeStartPtr;P2!=NULL;P2=P2->NextPtr) { if ((P2->Geloescht==0) && (P1!=P2)) { if (P1->x>P2->x) { x=P1->x; } else { x=P2->x; } if (P1->y>P2->y) { y=P1->y; } else { y=P2->y; } if (P1->xxxx) { xx=P1->xx; } else { xx=P2->xx; } if (P1->yyyy) { yy=P1->yy; } else { yy=P2->yy; } if (((xx-x)>=0) && ((yy-y)>=0)) { /* verschmelzen ! */ if (P1->x>P2->x) { x=P2->x; } else { x=P1->x; } if (P1->y>P2->y) { y=P2->y; } else { y=P1->y; } if (P1->xxxx) { xx=P2->xx; } else { xx=P1->xx; } if (P1->yyyy) { yy=P2->yy; } else { yy=P1->yy; } P2->Geloescht=1; P1->x=x; P1->y=y; P1->xx=xx; P1->yy=yy; P1->dx=xx-x; P1->dy=yy-y; } /* diff x,y */ } /* p1!=p2 */ } /* for P2 */ } /* if */ if (((P1->xx-P1->x)<2) && ((P1->yy-P1->y)<3)) P1->Geloescht=1; } /* for P1 */ /* Berechne nun die Spalten / Segmentreihenfolge */ min=9999999; max=0; Summe=0; Anzahl=0; P2=NULL; for (P1=SegmentBitBlockListeStartPtr;P1!=NULL;P1=P1->NextPtr) { if (P1->Geloescht==0) { if (P1->xx; P2=P1; } if (P1->xx>max) { max=P1->xx; } Anzahl++; Summe=Summe+P1->xx-P1->x; } /* if not killed */ } /* for */ if(Anzahl!=0) { float Schnitt,aha; long SpaltenAnzahl,x1,SpaltenNummer; Schnitt=Summe/(Anzahl+0.0); SpaltenNummer=0; SpaltenAnzahl=(0.5+((max-min) / Schnitt)); aha=((max-min) / SpaltenAnzahl)*0.7 ; for (P1=SegmentBitBlockListeStartPtr;P1!=NULL;P1=P1->NextPtr) { if ((P1->dxdx+x11; xx=dx+P1->x; P1->dx=dx; P1->xx=xx; } } min=9999999; max=0; Summe=0; Anzahl=0; P2=NULL; for (P1=SegmentBitBlockListeStartPtr;P1!=NULL;P1=P1->NextPtr) { if (P1->Geloescht==0) { if (P1->xx; P2=P1; } if (P1->xx>max) { max=P1->xx; } Anzahl++; Summe=Summe+P1->xx-P1->x; } /* if not killed */ } /* for */ Schnitt=Summe/(Anzahl+0.0); SpaltenNummer=0; SpaltenAnzahl=(0.5+((max-min) / Schnitt)); /* */ for (SpaltenNummer=0;SpaltenNummer<=SpaltenAnzahl;) { x1=min+Schnitt; for (P1=SegmentBitBlockListeStartPtr;P1!=NULL;P1=P1->NextPtr) { if ((P1->Geloescht==0) && (P1->SpaltenNummer==-1) && (P1->xSpaltenNummer=SpaltenNummer; } /* if not killed */ } /* for */ SpaltenNummer++; min=max+1; for (P1=SegmentBitBlockListeStartPtr;P1!=NULL;P1=P1->NextPtr) { if ((P1->Geloescht==0) && (P1->SpaltenNummer==-1) && (P1->xx; } /* if */ } /* for */ } /* for spaltennummer */ P3=NULL; P4=NULL; SegmentNummer=0; min=9999999; for (SpaltenNummer=0;SpaltenNummer<=SpaltenAnzahl;SpaltenNummer++) { P2=SegmentBitBlockListeStartPtr; for (;P2!=NULL;) { P2=NULL; min=88888888; for (P1=SegmentBitBlockListeStartPtr;P1!=NULL;P1=P1->NextPtr) { if ((P1->Geloescht==0) && (P1->SpaltenNummer==SpaltenNummer) && (P1->SegmentNummer==-1)) { if (P1->yy; P2=P1; } } /* if */ } /* for */ if (P2!=NULL) { if (P3==NULL) P4=P2; /* start */ if (P3!=NULL) P3->NextSegmentBlockPtr=P2; P3=P2; P2->SegmentNummer=SegmentNummer; SegmentNummer++; } } /* P2!=NULL */ } /* for spaltennummer */ P0=NULL; if (P4!=NULL) { for (P1=P4;P1!=NULL;P1=P1->NextSegmentBlockPtr) { if (P1->NextSegmentBlockPtr!=NULL) { P2=P1->NextSegmentBlockPtr; if (P1->y>P2->y) { y=P1->y; } else { y=P2->y; } if (P1->yyyy) { yy=P1->yy; } else { yy=P2->yy; } if ((yy-y)>=0) { /* aha, auf der gleichen ebene ! */ if (P1->x>P2->x) { /* falsch, es muss zuerst P1 kommen ! */ P3=P2->NextSegmentBlockPtr; if (P0!=NULL) { P0->NextSegmentBlockPtr=P2; } else { P4=P2; } P2->NextSegmentBlockPtr=P1; P1->NextSegmentBlockPtr=P3; P1=P4; } } } /* if */ P0=P1; } /* for */ } /* if NULL */ /* Korrigiere die Kordinaten, da diese gezoomt sind ! */ SegmentBitBlockListeStartPtr=P4; /* for (P1=P4;P1!=NULL;P1=P1->NextSegmentBlockPtr) { P1->NextPtrInSegment=NULL; P1->x=P1->x/deltax; P1->y=P1->y/deltay; P1->dx=P1->dx/deltax; P1->dy=P1->dy/deltay; } */ } /* Wenn der Groessenanpassung muessen */ /* wir noch zusammenhaengende Segmente zusammenfuegen ! */ if (1) for (P1=SegmentBitBlockListeStartPtr;P1!=NULL;P1=P1->NextSegmentBlockPtr) { if (P1->Geloescht==0) { for (P2=P1->NextSegmentBlockPtr;P2!=NULL;P2=P2->NextSegmentBlockPtr) { if ((P2->Geloescht==0) && (P1!=P2)) { if (P1->x>P2->x) { x=P1->x; } else { x=P2->x; } if (P1->y>P2->y) { y=P1->y; } else { y=P2->y; } if (P1->xxxx) { xx=P1->xx; } else { xx=P2->xx; } if (P1->yyyy) { yy=P1->yy; } else { yy=P2->yy; } if (((xx-x)>=0) && ((yy-y)>=0) && (P1->xx)) { /* verschmelzen ! */ if (P1->x>P2->x) { x=P2->x; } else { x=P1->x; } if (P1->y>P2->y) { y=P2->y; } else { y=P1->y; } if (P1->xxxx) { xx=P2->xx; } else { xx=P1->xx; } if (P1->yyyy) { yy=P2->yy; } else { yy=P1->yy; } P2->Geloescht=1; P1->x=x; P1->y=y; P1->xx=xx; P1->yy=yy; P1->dx=xx-x; P1->dy=yy-y; break; } /* diff x,y */ } /* p1!=p2 */ } /* for P2 */ } /* if */ if (((P1->xx-P1->x)<2) && ((P1->yy-P1->y)<3)) P1->Geloescht=1; } /* for P1 */ } /*************************************************************** Procedure : void Bloecke_in_Segmente() Uebergabe : Nichts Rueckgabe : Nichts Zugriffe/Global : SegmentBitBlockListeStartPtr sollte auf die Segment-liste zeigen Autor : Martin Bauer Letzte Aenderung : 1.6.1995 Getestet : JA , Resultat: fehlerfrei (1.6.1995) Aufgabe: Es sollen alle BitBloecke in einem Segment dem Segment als verkette Liste zugeordnet werden ! ****************************************************************/ void Bloecke_in_Segmente() { long x,y,xx,yy,Summe,Anzahl; struct BitBlockListe *P1,*P2; /* init der lokalen Variabeln */ x=0; y=0; xx=0; yy=0; P1=NULL; P2=NULL; /* gehe alle Segmente durch */ for (P1=SegmentBitBlockListeStartPtr;P1!=NULL;P1=P1->NextSegmentBlockPtr) { Summe=0; Anzahl=0; /* lebt dieses Segment noch ? */ if (P1->Geloescht==0) { P1->NextPtrInSegment=NULL; x=P1->x; y=P1->y; xx=x+P1->dx; yy=y+P1->dy; /* gehe alle BitBloecke durch */ for (P2=BitBlockListeStartPtr;P2!=NULL;P2=P2->NextPtr) { /* lebt dieser Bitblock noch ? */ if ((P2->Geloescht==0) && (P2->Bild==0)) { if ((P2->x>=x) && (P2->x<=xx) && (P2->y>=y) && (P2->y<=yy)) { /* element ist in diesem Segment ! */ Anzahl++; Summe=Summe+P2->dx; P2->NextPtrInSegment=P1->NextPtrInSegment; P1->NextPtrInSegment=P2; } } } if (Anzahl!=0) P1->ddx=(Summe+0.0)/Anzahl; } } } /*************************************************************** Procedure : void FindeZeilen() Uebergabe : Nichts Rueckgabe : Nichts Zugriffe/Global : SegmentBitBlockListeStartPtr sollte auf die Segment-liste zeigen Autor : Martin Bauer Letzte Aenderung : 1.6.1995 Getestet : JA , Resultat: fehlerfrei (1.6.1995) Aufgabe: Es sollen in Segmenten Zeilen erkannt werden und in diesen Zeilen sollen alle zugehoerigen Bitbloecke in eine Liste der x-Position nach eingetragen werden. (kleines x steht am weitesten links ! (wie im Bild) ) In den Zeilen kann es eine UNTERE und OBERE Linie geben. Diese UNTERE-Linie existiert genau dann, wenn z.b. ein p,q,g,y unter den normalen Zeichen nach unten stehen. Eine OBERE Linie existiert dann, wenn ausser denn Kleinbuchstaben a,c,e,o,u,m,n... auch noch ein Grossbuchstabe oder ein "langer" Kleinbuchstabe wie z.b. h,b,t,... vorkommt. ****************************************************************/ void FindeZeilen() { long t,y,yy,x,xx,Zeile,flag,flag1,Starty,Endey,Schnitt,Anzahl,Summe,i; long uu,Starty1,aha,frau,merkey,merkey1,y1,y11,min,max,max1,min1; double Winkel,Winkel1,toll; struct BitBlockListe *P1,*P2,*P3,*P4,*P5,*P6,*P7,*P8,*LastPtr; /* init der lokalen variablen */ i=0; t=0; x=0; y=0; xx=0; yy=0; flag=0; flag1=0; Starty=0; Endey=0; min=0; min1=0; max=0; max1=0; Winkel=0.0; Winkel1=0.0; toll=0.0; Anzahl=0; Summe=0; frau=0; uu=0; aha=0; Starty1=0; merkey1=-1; merkey=-1; P1=NULL; P2=NULL; P3=NULL; P4=NULL; P5=NULL; P6=NULL; P7=NULL; P8=NULL; /* gehe alle Segmente durch */ for (P1=SegmentBitBlockListeStartPtr;P1!=NULL;P1=P1->NextSegmentBlockPtr) { /* berechne durchschnittsgroesse eines Zeichens in einem Segment */ Anzahl=0; aha=0; frau=1; Summe=0; Schnitt=0; P1->NextZeileInSegment=NULL; for (P2=P1->NextPtrInSegment;P2!=NULL;P2=P2->NextPtrInSegment) { Summe=Summe+P2->dy; Anzahl++; } /* Wenn es BitBloecke gab , dann berechne durchschnittl. Groesse. */ if (Anzahl!=0) { Schnitt=(Summe/Anzahl)*2; Summe=Schnitt; Anzahl=Schnitt*0.3; } /* durchlaufe jetzt jede y-zeile im Segment durch */ Zeile=0; flag=1; flag1=1; yy=P1->y+P1->dy+2; Starty1=P1->y; LastPtr=NULL; for (y=(P1->y-1);y<=yy;y++) { flag=1; /* durchlaufe alle Elemente eines Segments */ for (P2=P1->NextPtrInSegment;P2!=NULL;P2=P2->NextPtrInSegment) { /* ist Element in der Zeile ? */ if (P2->dyy<=y) && ((P2->y+P2->dy))>=y) { flag=0; break;} if (P2->dy>=Schnitt) { Schnitt=Schnitt*2; } } /* erkenne Zeilenstart/Ende --> ist etwas kryptisch geraten :-() */ if ((frau==1) && (flag==0)) { frau=0; Starty1=y; } Schnitt=Summe; if ((aha==1) && (flag==0) && (flag1==0)) { aha=0; Starty1=Starty; } if ((flag==0) && (flag1==1)) { uu=0; Starty=y; if (Anzahl>=P2->dy) { y=y+Anzahl; } aha=1; } /* Zeilenende gefunden -> erstelle Zeilenelement */ if ((flag==1) && (flag1==0)) { Endey=y; P4=(struct BitBlockListe *)calloc(1,sizeof(struct BitBlockListe)); if (P4==NULL) { MemoryError(); } P4->NextZeileInSegment=NULL; P4->NextSegmentBlockPtr=NULL; P4->NextPtr=NULL; P4->NextPtrInZeile=NULL; P4->y=Starty1; P4->dy=Endey-Starty1; P4->Geloescht=0; P4->Bild=0; P4->Untere_Zeile=-1; P4->Obere_Zeile=-1; P4->x=P1->x; P4->dx=P1->dx; P4->xx=P4->dx+P4->x; P4->yy=P4->dy+P4->y; if (LastPtr==NULL) { P4->NextZeileInSegment=NULL; P1->NextZeileInSegment=P4; LastPtr=P4; } else { P4->NextZeileInSegment=NULL; LastPtr->NextZeileInSegment=P4; LastPtr=P4; } /* Durchlaufe alle Elemnte in dem Segment */ for (P3=P1->NextPtrInSegment;P3!=NULL;P3=P3->NextPtrInSegment) { P6=NULL; /* Element in der Zeile ? */ if ((P4->y<=P3->y) && ((P4->yy)>=P3->y)) { /* Wenn dies das ALLERERSTE Elment in der Liste ist -> eintragen */ if (P4->NextPtrInZeile==NULL) { P4->NextPtrInZeile=P3; P3->NextPtrInZeile=NULL; } else { /* es gibt also schon mid. 1 Element in der Liste ! */ i=0; P6=NULL; /* durchlaufe alle schon einsortierten Elemente */ for (P5=P4->NextPtrInZeile;P5!=NULL;P5=P5->NextPtrInZeile) { /* schon vorbei ? (zu grosser x-Wert ?)*/ if ((P5->x) > (P3->x)) { /* und beim vorigem Element einsortieren */ if (P6!=NULL) { P3->NextPtrInZeile=P6->NextPtrInZeile; P6->NextPtrInZeile=P3; } else { P3->NextPtrInZeile=P4->NextPtrInZeile; P4->NextPtrInZeile=P3; } i=1; break; } /* if groesser */ /* vorheriges Element merken */ P6=P5; } /* for ... */ if (i==0) { /* dies muss also letztes element sein ! */ P6->NextPtrInZeile=P3; P3->NextPtrInZeile=NULL; P6=NULL; } } /* if erster */ } /* if in zeile */ } /* for zeilen */ merkey1=-1; merkey=-1; /* Hier berechnen wir nun die UNTERE und OBERE Linie einer Zeile */ /* alle Elemente einer Zeile eines Segmentes durchlaufen */ for (P6=P4->NextPtrInZeile;P6!=NULL;P6=P6->NextPtrInZeile) { P7=P6->NextPtrInZeile; if (P7!=NULL) { /* es existiert ein Nachbar ! */ if ((P6->x!=P7->x)) { toll=MAXWINKEL; max =(0.5*P4->dy )+P4->y; min =(0.15*P4->dy)+P4->y; min1=(0.5*P4->dy )+P4->y; max1=(0.85*P4->dy)+P4->y; Winkel =atan((double) ((P6->y-P7->y ) / (0.0+P6->x-P7->x))) ; Winkel1=atan((double) (((P6->y+P6->dy) - (P7->y+P7->dy)) / (0.0+P6->x-P7->x))) ; if (Winkel<0) Winkel =-Winkel; if (Winkel1<0) Winkel1=-Winkel1; if ((toll>Winkel) && (miny) && (max>P6->y)) { /* gleiche hoehe ! */ y1=P6->y; if (y1>P7->y) { y1=P7->y; } if (merkeyObere_Zeile =merkey; } /* grad ok */ if ((toll>Winkel1) && (min1<(P6->y+P6->dy)) && (max1>(P6->y+P6->dy))) { /* gleiche hoehe ! */ y11=P6->y+P6->dy; if (y11>(P7->y+P7->dy)) { y11=P7->y+P7->dy; } if (merkey1Untere_Zeile=merkey1; } /* grad ok */ } /* hoehe */ P8=P7->NextPtrInZeile; if (P8!=NULL) { /* es existiert ein Nachbar ! */ if ((P6->x!=P8->x)) { toll=MAXWINKEL; max=(0.5*P4->dy)+P4->y; min=(0.15*P4->dy)+P4->y; Winkel=atan((double) ((P6->y-P8->y) / (0.0+P6->x-P8->x))) ; if (Winkel<0) Winkel=-Winkel; if ((toll>Winkel) && (miny) && (max>P6->y)) { /* gleiche hoehe ! */ y1=P6->y; if (y1>P8->y) { y1=P8->y; } if (merkeyObere_Zeile =merkey; } /* grad ok */ } /* hoehe */ } /* exist */ } /* exist */ } } flag1=flag; } /* for alle y-zeilen */ } /* for segmente */ } /* proc */ /*************************************************************** Procedure : void VerschmelzeBitBloeckeInZeile() Uebergabe : Nichts Rueckgabe : Nichts Zugriffe/Global : SegmentBitBlockListeStartPtr sollte auf den Anfang der Segment-liste stehen ! Autor : Martin Bauer Letzte Aenderung : 1.6.1995 Getestet : JA , Resultat: fehlerfrei (1.6.1995) Aufgabe: Es soll in allen Zeilen ueberprueft werden, ob maximal 99 BitBloecke uebereinander liegen (-> Schnittflache mit x , keine Schnittflaeche mit y). Wenn ja, dann sollen alle uebereinanderliegenden Bloecke geloescht werden (indem ein Flag gesetzt wird) und diese Bloecke zu einem neuen Block zusammengesetzt werden. Dazu werden in allen gefundenen Bloecken die jeweiligen start(x,y)-sequenzen verwendet und ein neues bereits auf 16x16 Bild transformiert. Wichtig: Es duerfen nicht einfach die rechteckigen Bloecke kopiert werden, da kursive Zeichen sonst mitkopiert werden ! ****************************************************************/ void VerschmelzeBitBloeckeInZeile() { struct BitBlockListe *P1,*P2,*P3,*P4; struct BitBlockListe *Pcat[100]; long dx,dy,x,y,xx,yy,min_x,max_x,max_y,min_y; long t,i,Flag; char *Pc1,*Pc2,*ArbeitsPtr; /* setze alle Variablen auf def. Werte */ t=0; i=0; P1=NULL; P2=NULL; P3=NULL; P4=NULL; dx=0;dy=0;Flag=0;x=0;y=0;xx=0;yy=0;min_x=0;min_y=0;max_y=0;max_x=0; Pc1=NULL; Pc2=NULL; ArbeitsPtr=NULL; for (i=0;i<99;i++) Pcat[i]=NULL; /* kopiere Arbeitspuffer , da dieser bei rekursivem kopieren spaeter zerstoert wird */ i=Page_y*Page_Bytes_pro_Zeile; ArbeitsPtr=malloc(i); if (ArbeitsPtr==NULL) { MemoryError(); } Pc1=ArbeitsPtr; Pc2=OrginalBildPuffer; for (t=0;tNextSegmentBlockPtr) { /* gehe jetzt alle Zeilen eines Segments durch */ for (P2=P1->NextZeileInSegment;P2!=NULL;P2=P2->NextZeileInSegment) { Flag=0; min_x=99999; min_y=99999; max_x=-99999; max_y=-99999; /* gehe jetzt alle Bitbloecke einer Zeile durch */ for (P3=P2->NextPtrInZeile;P3!=NULL;P3=P3->NextPtrInZeile) { /* lebt dieses Bitblock noch ? */ if (P3->Geloescht==0) { min_x=P3->x; min_y=P3->y; max_x=P3->x+P3->dx; max_y=P3->y+P3->dy; /* ok , schaue die naechsten Bitbloecke an (die weiter rechts) */ for (P4=P3->NextPtrInZeile;P4!=NULL;P4=P4->NextPtrInZeile) { if ((P4->x)>(P3->x+P3->dx)) break; /* schon zu weit rechts ? (keine x-Schnittflaeche moeglich !) */ if ((P4->Geloescht==0) && (P4!=P3)) { /* Berechne eventuelle x,y-ueberschneidungen */ if (P4->x>P3->x) { x=P4->x; } else { x=P3->x; } if (P4->y>P3->y) { y=P4->y; } else { y=P3->y; } if (P4->xxxx) { xx=P4->xx; } else { xx=P3->xx; } if (P4->yyyy) { yy=P4->yy; } else { yy=P3->yy; } /* X-ueberschneidung und keine y-ueberschneidung ?*/ if (((xx-x)>0) && ((yy-y)<0)) { /* ja, also block loeschen und min/max platzbedarf des neuen Blocks berechnen */ if ((P4->x+P4->dx)>max_x) max_x=P4->x+P4->dx; if ((P4->y+P4->dy)>max_y) max_y=P4->y+P4->dy; if (P4->xx; if (P4->yy; Pcat[Flag+1]=P4; /* merke den geloeschten Block !*/ Flag++; /* merke die Anzahl der geloschten Bloecke ! */ P4->Geloescht=1; } } /* if killed */ } /* for elemente */ /* gab es den Fall , dass Bloecke uebereinander lagen ?*/ if (Flag!=0) { Pcat[0]=P3; /* Merke "untersten" Block !*/ dx=max_x-min_x; /* Groesse des Blocks berechnen */ dy=max_y-min_y; P3->x=min_x; P3->y=min_y; P3->xx=max_x; P3->yy=max_y; P3->dx=max_x-min_x; P3->dy=max_y-min_y; /* berechne den Zoom-faktor fuer die 16x16 zoom. */ offset_x=0; offset_y=0; if (dx>dy) { faktory=16/(dx+0.0); offset_y=(16-(faktory*dy))/2; } else { faktory=16/(dy+0.0); offset_x=(16-(faktory*dx))/2; } if ((dx<16) && (dy<16)) { faktory=1.0; offset_y=(16-dy)>>1; } /* leere das 16x16 Bild */ for (t=0;t<32;t++) P3->BildDaten[t]=0; /* loesche bild */ if (Flag>99) Flag=99; KopierePtr=P3; /* gehe alle geloschten Bloecke durch und zoome sie in das 16x16 Feld */ for (i=0;i<=Flag;i++) { /* Cat alle diese Elemente */ rek_x=Pcat[i]->Startx; rek_y=Pcat[i]->Starty; P3->Elemente++; Pcat[i]->Geloescht=1; maxcount=0; rek_y_zeile=ArbeitsPtr+rek_y*Page_Bytes_pro_Zeile; KopiereRekursiv(); } P3->Geloescht=0; Flag=0; } } /* if killed */ } /* for elemente */ } /* for zeilen */ } /* for segmente */ free(ArbeitsPtr); } /*************************************************************** Procedure : void SucheBitBloecke() Uebergabe : Nichts Rueckgabe : Nichts (-> Global: Min_x,Max_x,Min_y,Max_y) Zugriffe/Global : maxcount , Value1 , Value, rek_y, rek_x, rek_y_zeile, HilfsPtr Page_x , Page_y Autor : Martin Bauer Letzte Aenderung : 1.6.1995 Getestet : JA , Resultat: fehlerfrei (1.6.1995) Aufgabe: Aus Performance-Gruenden und Stacksize minimierung wurden absichtlich auf alle lokalen Variablen/Parameter verzichtet ! Diese Routine soll in einem Bild mit der Groesse: Page_x,Page_y nach zusammenhaengenden Punkten suchen. Dabei wird diese Funktion rekursiv aufgerufen. Damit es zu keinem Stack-overflow kommt (bei einem sehr grossen, total schwarzen Block wird mit der Variable maxcount die aktuelle Stacktiefe gezaehlt, bei maxcount > MAXSTACK wird die Rekursion abgebrochen -> Dies ergibt zwar spaeter kein zusammenhaengendes Bild, wird aber (speziell deswegen) spaeter wieder "repariert !". Die Variable rek_y_Zeile zeigt auf das Ur-Bild. Dieses Ur-Bild wird VERNICHTET ! ****************************************************************/ void SucheBitBloecke() { maxcount++; if (maxcount>MAXSTACK) { maxcount--; return; } /* notfall-rek. abbruch */ /* sind wir am Bild-Rand ? */ if ((rek_x<0) || (Page_x> 3)); /* hole Byte aus dem Bild */ Value=*HilfsPtr; /* ist dieser x-Punkt gesetzt ? */ Value1=Value & (~(128>>(rek_x&7))); if ( Value!=Value1 ) { /* Punkt war gesetzt, loesche diesen um Endlos-Rekursion zu vermeiden */ *HilfsPtr=Value1; /* suche nach maximalen umrandung */ if (Min_x>rek_x) Min_x=rek_x; if (Min_y>rek_y) Min_y=rek_y; if (Max_x Global: Min_x,Max_x,Min_y,Max_y) Zugriffe/Global : maxcount , Value1 , Value, rek_y, rek_x, rek_y_zeile, HilfsPtr Page_x , Page_y Autor : Martin Bauer Letzte Aenderung : 1.6.1995 Getestet : JA , Resultat: fehlerfrei (1.6.1995) Aufgabe: Aus Performance-Gruenden und Stacksize minimierung wurden absichtlich auf alle lokalen Variablen/Parameter verzichtet ! Es sollen alle zusammenhaengende Punkte in einem Bild der Groesse: Segment_x,Segment_Y gefunden werden. Die Variable rek_y_Zeile zeigt auf das Ur-Bild. Dieses Ur-Bild wird VERNICHTET ! ****************************************************************/ void SucheSegmenteBitBloecke() { maxcount++; /* schon maximaler Stacktiefe angelangt ? */ if (maxcount>MAXSTACK) { maxcount--; return; } /* notfall-rek. abbruch */ /* am Bildrand ? */ if ((rek_x<0) || (Segment_X> 3)); /* hole dieses Byte */ Value=*HilfsPtr; Value1=Value & (~(128>>(rek_x&7))); /* Punkt gesetzt ? */ if ( Value!=Value1 ) { /* loesche diesen Punkt */ *HilfsPtr=Value1; /* berechne Ausdehung des Blockes */ if (Min_x>rek_x) Min_x=rek_x; if (Min_y>rek_y) Min_y=rek_y; if (Max_xBildDaten+(x>>3)); if (A & (128>>(x&7))) { B++; } } /* for Punkt */ Ptr->WsaAchsenWerte[Achse]=B; c=c+Quadrat[B+100]; t+=48; } /* for Achse */ c=sqrt(c); Ptr->Klasse=c/6; } /* proc */ /*************************************************************** Procedure : void VergleicheAufSymetrieUndWsa() Uebergabe : Nichts Rueckgabe : Nichts Autor : Martin Bauer Letzte Aenderung : 1.6.1995 Getestet : JA , Resultat: fehlerfrei (1.6.1995) Aufgabe: Es sollen alle BitBloecke auf (X/Y)-Achsensymetrie uberprueft werden. Die Achsen beginnen hierbai in der Mitte des Bildes (-> gezoomtes Bild !). Desweiteren sollen die Wsa-werte berechnte werden. ****************************************************************/ void VergleicheAufSymetrieUndWsa() { struct BitBlockListe *P1,*P2,*P3; unsigned char wert1,wert2,wert3,wert4,hwert3,hwert2; long t,j,k,i,y1,y2; for (P1=SegmentBitBlockListeStartPtr;P1!=NULL;P1=P1->NextSegmentBlockPtr) { if (P1->Geloescht==0) { for (P2=P1->NextZeileInSegment;P2!=NULL;P2=P2->NextZeileInSegment) { if (P2->Geloescht==0) { y1=P2->Obere_Zeile-((P2->Obere_Zeile-P2->y)*0.3); y2=P2->Untere_Zeile+(((P2->y+P2->dy)-P2->Untere_Zeile)*0.3); for (P3=P2->NextPtrInZeile;P3!=NULL;P3=P3->NextPtrInZeile) { /* Ueberpruefe ob unter/uebergrosses Zeichen */ P3->Obere_Zeile=-1; P3->Untere_Zeile=-1; if (P2->Obere_Zeile>=0) if (P3->yObere_Zeile=y1; if (P2->Untere_Zeile>=0) if ((P3->y+P3->dy)>y2) P3->Untere_Zeile=y2; /* Berechne die Wsa-Werte */ BerechneWsaWerte(P3); if (P3->Geloescht==0) { i=0; j=0; k=0; for (t=0;t<16;t++) { wert1=P3->BildDaten[ (t<<1)]; wert2=P3->BildDaten[1 +(t<<1)]; wert3=P3->BildDaten[30-(t<<1)]; wert4=P3->BildDaten[31-(t<<1)]; hwert3=ByteIstGespiegelt[wert3]; hwert2=ByteIstGespiegelt[wert2]; i=i+ ((PunkteInByte[(wert1 & ( ~wert3)) | ((~wert1) & wert3)]<<1) + (PunkteInByte[(wert2 & (~wert4 )) | ((~wert2) & wert4)]<<1)); k=k+ ((PunkteInByte[(wert1 & (~hwert2)) | ((~wert1) & hwert2)]<<1) + (PunkteInByte[(wert4 & (~hwert3)) | ((~wert4) & hwert3)]<<1)); j=j+ (PunkteInByte[wert4]+ PunkteInByte[wert3]+ PunkteInByte[wert2]+ PunkteInByte[wert1]); } if (j==0) P3->Geloescht=1; if (j!=0) if (((i/(j+0.0))<0.15) || (i<9)) P3->XSpiegel=1; if (j!=0) if (((k/(j+0.0))<0.15) || (k<9)) P3->YSpiegel=1; } } } } } } } void SpeichereGelerntesZeichen(Ptr) struct LearndListe *Ptr; { FILE *file; char *a; a=(char *)&(Ptr->Daten); file=fopen("LERNED.DAT","a+b"); if (file==NULL) return; fwrite(a,1,sizeof(struct LearndDaten),file); fclose(file); } void LadeGelernteZeichen() { long a; FILE *file; struct LearndListe *Ptr; file=fopen("LERNED.DAT","a+b"); if (file==NULL) return; fseek(file,0,0); for (;;) { Ptr=(struct LearndListe *)calloc(1,sizeof(struct LearndListe)); if (Ptr==NULL) MemoryError(); Ptr->NextPtr=NULL; a=fread(&(Ptr->Daten),1,sizeof(struct LearndDaten),file); if (a==sizeof(struct LearndDaten)) { Ptr->NextPtr=ZeichenListeStart[Ptr->Daten.Klasse][Ptr->Daten.Elemente][Ptr->Daten.Flag]; ZeichenListeStart[Ptr->Daten.Klasse][Ptr->Daten.Elemente][Ptr->Daten.Flag]=Ptr; } else { free(Ptr); break; } } fclose(file); } struct LearndListe *Analy(Start,min,ErgPtr,ElementP) struct LearndListe *Start; long *min; struct LearndListe *ErgPtr; struct BitBlockListe *ElementP; { struct LearndListe *P1,*P2; long wert,t; for (P1=Start;P1!=NULL;P1=P1->NextPtr) { P1->JumpPtr=P1->NextPtr; P1->Wert=Quadrat[100+P1->Daten.WsaAchsenWerte[0]-ElementP->WsaAchsenWerte[0]]; } for (t=1;t<128;t++) { P2=NULL; for (P1=Start;P1!=NULL;P1=P1->JumpPtr) { wert=Quadrat[100+P1->Daten.WsaAchsenWerte[t]-ElementP->WsaAchsenWerte[t]]; P1->Wert+=wert; if ((P2!=NULL) && (wert>MAXDIFFERENZ)) { P2->JumpPtr=P1->JumpPtr; } P2=P1; } } P1=Start; for (;P1!=NULL;P1=P1->JumpPtr) { if (P1->Wert<(*min)) { *min=P1->Wert; ErgPtr=P1; } } return(ErgPtr); } struct LearndListe *AnalysiereAlleWerteEinesSegments(ElementP,Wert,F) struct BitBlockListe *ElementP; long *Wert; short int *F; { long min; struct LearndListe *ErgPtr; unsigned short int Flag; Flag=0; if (ElementP->Elemente>15) ElementP->Elemente=15; if (ElementP->XSpiegel) Flag = 1; if (ElementP->YSpiegel) Flag |= 2; if (ElementP->Untere_Zeile>=0) Flag |= 4; if (ElementP->Obere_Zeile>=0) Flag |= 8; min=999999; ErgPtr=NULL; ErgPtr=Analy(ZeichenListeStart[1+ElementP->Klasse][ElementP->Elemente][Flag],&min,NULL ,ElementP); ErgPtr=Analy(ZeichenListeStart[ ElementP->Klasse][ElementP->Elemente][Flag],&min,ErgPtr,ElementP); if (ElementP->Klasse>0) ErgPtr=Analy(ZeichenListeStart[ElementP->Klasse-1][ElementP->Elemente][Flag],&min,ErgPtr,ElementP); min=sqrt(min); *Wert=min; *F=Flag; return(ErgPtr); } void WoerterbuchUndSemantikCheck() { FILE *file,*file_o; unsigned char Puffer[100],Puffer1[100]; char Text[500]; long position,laenge,t,l,NOC,posi,last,max; NOC=1; position=0; posi=0; last=0; laenge=1; file=fopen("tmp.dat","rb"); strcpy(Text,"tmp1.dat"); if (ParaAktuell.UseEditor==0) { strcpy(Text,ParaAktuell.Dateiname); } file_o=fopen(Text,"w"); fseek(file,0,2); max=ftell(file); fseek(file,0,0); if (file==NULL) return; for (;;) { fseek(file,position,0); if (position>max) { fclose(file); fclose(file_o); if (ParaAktuell.UseEditor!=0) { printf("hello\n"); sprintf(Text,"%s tmp1.dat &",ParaAktuell.Editor); system(Text); } return; } strcpy(Puffer1,Puffer); fread(Puffer,1,60,file); Puffer[59]=0; last=laenge-1; for (t=0;t<60;t++) { if (Puffer[t]==1) { fclose(file); fclose(file_o); if (ParaAktuell.UseEditor!=0) { sprintf(Text,"%s tmp1.dat &",ParaAktuell.Editor); system(Text); } return; } if (Puffer[t]<32) { Puffer[t]=0; break; } } laenge=strlen(Puffer); if (laenge>0) { /* Ab hier kommen die Semantik-checks ! */ if (0==SucheElement(Puffer)) { /* Tja , nicht im woerterbuch , also Semantik-check */ l=0; for (t=0;t='0') && (Puffer[t]<='9'))) ) || ((Puffer[t]>'Z') && (Puffer[t]<'a') ))) { l=1; laenge=t+1;Puffer[t+1]=0;} } position+=laenge; if (laenge!=1) { if (l) { Puffer[laenge-1]=0; laenge--; position--; } if (0==SucheElement(Puffer)) { /* Waaa, nicht im Woerterbuch , also Semantik-Check !*/ if (SematischerCheck(Puffer,strlen(Puffer))) { if (NOC==0) { fprintf(file_o," %s",Puffer); posi++; } else { fprintf(file_o,"%s",Puffer); } posi=posi+strlen(Puffer); NOC=0; if (posi>MAXANZAHL) { fprintf(file_o,"\n"); NOC=1; posi=0; } } else { if (NOC==0) { fprintf(file_o," %s",Puffer); posi++; } else { fprintf(file_o,"%s",Puffer); } posi=posi+strlen(Puffer); NOC=0; if (posi>MAXANZAHL) { fprintf(file_o,"\n"); NOC=1; posi=0; } } } else { /* Gefunden :=) */ if (NOC==0) { fprintf(file_o," %s",Puffer); } else { fprintf(file_o,"%s",Puffer); } NOC=0; if (posi>MAXANZAHL) { fprintf(file_o,"\n"); NOC=1; posi=0; } } } else { /* nur ein buchstabe ! :=) */ posi++; switch (Puffer[0]) { case '0': fprintf(file_o,"0"); break; case '1': fprintf(file_o,"1"); break; case '2': fprintf(file_o,"2"); break; case '3': fprintf(file_o,"3"); break; case '4': fprintf(file_o,"4"); break; case '5': fprintf(file_o,"5"); break; case '6': fprintf(file_o,"6"); break; case '7': fprintf(file_o,"7"); break; case '8': fprintf(file_o,"8"); break; case '9': fprintf(file_o,"9"); break; case 'ß': fprintf(file_o,"8"); break; case 'B': fprintf(file_o,"8"); break; case 'I': fprintf(file_o,"1"); break; case 'l': fprintf(file_o,"1"); break; case 'Z': fprintf(file_o,"7"); break; case 'G': fprintf(file_o,"6"); break; case 'S': fprintf(file_o,"5"); break; case '.': if ((Puffer1[last]>='0') && (Puffer1[last]<='9')) { fprintf(file_o,"."); posi++; } else { fprintf(file_o,".\n"); posi=0; NOC=1; } break; case ',': fprintf(file_o,","); break; case ';': fprintf(file_o,";"); break; case ':': fprintf(file_o,":"); break; case '-': fprintf(file_o,"-"); break; case '*': fprintf(file_o,"*"); NOC=1; break; case '+': fprintf(file_o,"+"); break; case '/': fprintf(file_o,"/"); break; case '(': fprintf(file_o," ("); posi++; NOC=1; break; case ')': fprintf(file_o,")"); break; case '{': fprintf(file_o," {"); posi++; NOC=1; break; case '}': fprintf(file_o,"}"); break; case '[': fprintf(file_o," ["); posi++; NOC=1; break; case ']': fprintf(file_o,"]"); break; case '&': fprintf(file_o,"&"); posi++; break; case '$': fprintf(file_o,"$"); break; case '¶': fprintf(file_o,"¶"); break; case '!': fprintf(file_o,"!\n"); posi=0; NOC=1; break; case '?': fprintf(file_o,"?\n"); posi=0;NOC=1; break; default : if (NOC==0) { fprintf(file_o," %s",Puffer); } else { fprintf(file_o,"%s",Puffer); } posi++; NOC=0; if (posi>MAXANZAHL) { fprintf(file_o,"\n"); NOC=1; posi=0; } } /* switch */ } /*t == 1*/ }else { position+=laenge; posi=posi+laenge; if (NOC==0) { posi++; fprintf(file_o," %s",Puffer); } else { fprintf(file_o,"%s",Puffer); } NOC=0; if (posi>MAXANZAHL) { fprintf(file_o,"\n"); NOC=1; posi=0; } } } else { position++; } } } /*************************************************************** Procedure : leselong() Typ : Wegwerf-Routine ! Aufgabe: Wandle Intel-long in ein normales int um . ****************************************************************/ unsigned long leselong(Ptr) unsigned char *Ptr; { unsigned long r; r=0; r=((unsigned char)*(Ptr+0))+(((unsigned char)*(Ptr+1))<<8); return(r); }