"SfR Fresh" - the SfR Freeware/Shareware Archive 
As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers.
Alternatively you can here view or download the uninterpreted source code file.
That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
1 /*******************************************************
2 *** Bildverarbeitungs- und OCR-Routinen ***
3 *** ***
4 *******************************************************/
5
6 /** includes **/
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <math.h>
10 #include <time.h>
11 #include <dirent.h>
12 #include <sys/stat.h>
13 #include <unistd.h>
14 #include "ocr.h"
15 #include "baum.h"
16 #include "semantik.h"
17 #include "main.h"
18
19 /** defines **/
20 #define MAXDIFFERENZ 64
21 #define Segment_X 128
22 #define Segment_Y 180
23 #define Segment_Bytes 16
24 #define MAXSTACK 30000
25 #define MAXWINKEL 0.2094395102
26
27 #define MAXANZAHL 60
28
29 /************ Globale Variablen *****************/
30 extern short int Wsa[];
31 extern long Quadrat[];
32 extern struct Parameter ParaAktuell;
33
34 struct LearndListe *ZeichenListeStart[35][16][16];
35
36 unsigned char Bits[8] = {128, 64, 32, 16, 8, 4, 2, 1};
37 unsigned char RandRechts[8] = { 1, 3, 7, 15, 31, 63,127,254};
38 unsigned char RandLinks[8] = {128,192,224,240,248,252,254,255};
39
40 struct BitBlockListe *BitBlockListeStartPtr = NULL;
41 struct BitBlockListe *SegmentBitBlockListeStartPtr = NULL;
42 struct BitBlockListe *KopierePtr = NULL;
43
44 long Page_x,Page_y,Page_Bytes_pro_Zeile;
45 long Max_x,Min_x,Min_y,Max_y;
46 long maxcount,rek_x,rek_y,xx,yy,offset_x,offset_y;
47
48 unsigned char *OrginalBildPuffer,*ArbeitsPuffer,*HilfsPtr;
49 unsigned char Value,Value1;
50 unsigned char *rek_y_zeile;
51
52 unsigned short int PunkteInByte[256];
53 unsigned short int ByteIstGespiegelt[256];
54
55 float faktorx,faktory;
56 long durch_dx, durch_dy;
57
58 /******** Sonstiges/Deklarationen *************/
59
60 void SucheBitBloecke();
61 void SucheSegmenteBitBloecke();
62
63 /***************************************************************
64 Procedure : void Spiegle()
65
66 Uebergabe : short int
67 Rueckgabe : short int
68 Zugriffe/Global : Keine
69 Autor : Martin Bauer
70 Letzte Aenderung : 1.6.1995
71
72 Getestet : JA , Resultat: fehlerfrei (1.6.1995)
73
74 Aufgabe:
75 Es soll der Eingabeparameter (8-Bit) einfach gespiegelt
76 werden. Die muss nicht effizient geloest sein !
77
78 ****************************************************************
79 Arithmetic is being able to count up to twenty without
80 taking off your shoes.
81 ****************************************************************/
82
83 unsigned short int Spiegle(wert)
84 unsigned long wert;
85 {
86 long l,r,t;
87 unsigned short int wert_1;
88 l=128;
89 r=1;
90 wert_1=0;
91 for (t=0;t<4;t++)
92 {
93 if (l & wert) wert_1 = wert_1 | r;
94 if (r & wert) wert_1 = wert_1 | l;
95 l=l>>1;
96 r=r<<1;
97 }
98 return(wert_1);
99 }
100
101
102 /***************************************************************
103 Procedure : void ZaehlePunkte()
104
105 Uebergabe : short int
106 Rueckgabe : short int
107 Zugriffe/Global : Keine
108 Autor : Martin Bauer
109 Letzte Aenderung : 1.6.1995
110
111 Getestet : JA , Resultat: fehlerfrei (1.6.1995)
112
113 Aufgabe:
114 Es sollen alle im Eingabeparameter (8-Bit) gesetzten Bits
115 gezaehlt werden. Die muss nicht effizient geloest sein !
116
117 *****************************************************************/
118 /* Remember: Silly is a state of Mind, Stupid is a way of Life.*/
119 /****************************************************************/
120 unsigned short int ZaehlePunkte(wert)
121 unsigned long wert;
122 {
123 unsigned long l,t;
124 unsigned char wert_1;
125 l=1;
126 wert_1=0;
127 for (t=0;t<8;t++)
128 {
129 if (l & wert) wert_1++;
130 l=l<<1;
131 }
132 return(wert_1);
133 }
134
135
136 /***************************************************************
137 Procedure : MemoryError()
138
139 Uebergabe : Nichts
140 Rueckgabe : Nichts
141 Autor : Martin Bauer
142 Letzte Aenderung : 3.6.1995
143
144 Getestet : JA , Resultat: fehlerfrei
145
146
147 Aufgabe:
148 Bei zuwenig Speicher soll ein Fehler ausgegeben werden.
149 ****************************************************************/
150 void MemoryError()
151 {
152 /* "Heisenberg may have slept here" */
153 fprintf(stderr," -------> FEHLER <------- \n");
154 fprintf(stderr," \n");
155 fprintf(stderr,"- Das System hat den angefordeten Speicher \n");
156 fprintf(stderr," nicht zur verfuegung gestellt ! \n");
157 fprintf(stderr," \n");
158 fprintf(stderr,"- Behebung des Fehlers: \n");
159 fprintf(stderr," \n");
160 fprintf(stderr," 1. Swapspace erhoehen \n");
161 fprintf(stderr," 2. Mehr Arbeitsspeicher kaufen \n");
162 fprintf(stderr," 3. Andere Applikationen schliessen \n");
163 fprintf(stderr," \n");
164 fflush(stderr);
165 exit(-1);
166 }
167
168
169 /***************************************************************
170 Procedure : OcrInit()
171
172 Uebergabe : Nichts
173 Rueckgabe : Nichts
174 Autor : Martin Bauer
175 Letzte Aenderung : 3.6.1995
176
177 Getestet : JA , Resultat: fehlerfrei
178
179
180 Aufgabe:
181 Es werden diverse Initialisierungen und Berechnungen
182 vorgenommen .
183 ****************************************************************/
184 void LadeGelernteZeichen();
185
186 void OcrInit()
187 {
188 unsigned long t,t1,t2;
189 for (t=0;t<256;t++)
190 {
191 PunkteInByte[t]=ZaehlePunkte(t);
192 ByteIstGespiegelt[t]=Spiegle(t);
193 }
194 /* init der Zeichenliste */
195 for (t=0;t<35;t++) for (t1=0;t1<16;t1++) for (t2=0;t2<16;t2++) ZeichenListeStart[t][t1][t2]=NULL;
196 LadeGelernteZeichen();
197 }
198
199
200 /***************************************************************
201 Procedure : void LoescheBildFeld(x,y,dx,dy)
202
203 Uebergabe : Kordinaten x,y,dx,dy
204 Rueckgabe : Nichts
205 Zugriffe/Global : OrginalBildPuffer,Page_Bytes_Pro_Zeile
206 Autor : Martin Bauer
207 Letzte Aenderung : 1.6.1995
208
209 Getestet : JA , Resultat: fehlerfrei
210
211
212 Aufgabe:
213 Es soll in dem Bild ein Bereich beginnend bei
214 x,y mit der Groesse dx,dy geloescht werden.
215
216 ****************************************************************/
217 void LoescheBildFeld(x,y,dx,dy)
218 long x,y,dx,dy;
219 {
220 char *P;
221 long xx,yy,x1,y1,beginx,endex;
222 x--;
223 dx++;
224 xx=x+dx;
225 yy=y+dy+1;
226 if (xx>=Page_x) xx=Page_x-1;
227 if (yy>=Page_y) yy=Page_y-1;
228
229
230 endex=(xx>>3);
231 beginx=(x>>3);
232
233 for (y1=y;y1<yy;y1++)
234 {
235 P=OrginalBildPuffer+Page_Bytes_pro_Zeile*y1+beginx;
236 *P=*P & RandLinks[x&7];
237 P++;
238 for (x1=beginx;x1<endex;x1++)
239 {
240 *P=0; P++;
241 }
242 *P=*P & RandRechts[xx&7];
243 }
244 }
245
246 /***************************************************************
247 Procedure : void SetzeBildFeld(x,y,dx,dy)
248
249 Uebergabe : Kordinaten x,y,dx,dy
250 Rueckgabe : Nichts
251 Zugriffe/Global : OrginalBildPuffer,Page_Bytes_Pro_Zeile
252 Autor : Martin Bauer
253 Letzte Aenderung : 1.6.1995
254
255 Getestet : JA , Resultat: fehlerfrei
256
257
258 Aufgabe:
259 Es soll in dem Bild ein Bereich beginnend bei
260 x,y mit der Groesse dx,dy gesetzt werden.
261
262 ****************************************************************/
263 void SetzeBildFeld(Puffer,max,x,y,dx,dy)
264 unsigned char *Puffer;
265 long max,x,y,dx,dy;
266 {
267 unsigned char *P;
268 long xx,yy,x1,y1,beginx,endex;
269 xx=(--x)+(++dx);
270 yy=y+dy+1;
271 if (xx>=Page_x) xx=Page_x-1;
272 if (yy>=Page_y) yy=Page_y-1;
273
274
275 endex=(xx>>3);
276 beginx=(x>>3);
277 x &= 7;
278 xx &= 7;
279 for (y1=y;y1<yy;y1++)
280 {
281 P=Puffer+max*y1+beginx;
282 *P++ |= ~RandLinks[x];
283 for (x1=beginx;x1<endex;x1++) *P++=255;
284 *P |= ~RandRechts[xx];
285 }
286 }
287
288
289 /***************************************************************
290 Procedure : void KopiereRekursiv
291
292 Uebergabe : Nichts
293 Rueckgabe : Nichts
294 Zugriffe/Global : maxcount,offset_x,offset_y, y_zeile,faktory,
295 KopierePtr,Page_y,Page_x,Value1,Value,HilfsPtr;
296 Autor : Martin Bauer
297 Letzte Aenderung : 1.6.1995
298
299 Getestet : JA , Resultat: fehlerfrei (1.6.1995)
300
301
302 Aufgabe:
303 Es wurde aus Performance- und Stackminimierungsgruenden
304 auf lokale Variablen und Parameter verzichtet !
305 Es sollen zusammenhaengende Punkte aus dem Ur-Bild wegkopiert
306 und mittels dem Wert von faktory auf ein 16x16 grosses Bild
307 Kopiert werden. Das Ziel-Bild ist: KopierePtr->Bilddaten.
308 Das Ur-Bild (y_zeile zeigt darauf) wird dabei VERNICHTET !
309
310 ****************************************************************/
311 void KopiereRekursiv()
312 {
313 maxcount++;
314 if (maxcount>MAXSTACK) { maxcount--; return; } /* notfall-rek. abbruch */
315 if ((rek_x<0) || (Page_x<rek_x) || (rek_y<0) || (Page_y<rek_y)) { maxcount--; return; }
316 HilfsPtr=(rek_y_zeile+(rek_x >> 3));
317 Value=*HilfsPtr;
318 Value1=Value & (~(128>>(rek_x&7)));
319 if ( Value!=Value1 )
320 {
321 *HilfsPtr=Value1;
322 {
323 long x,y;
324 x=((rek_x-KopierePtr->x)*faktory) ;
325 y=((rek_y-KopierePtr->y)*faktory) ;
326 x=x+offset_x;
327 y=y+offset_y;
328 if (y>15) y=15;
329 if (x>15) x=15;
330 HilfsPtr=(KopierePtr->BildDaten+y+y+(x>>3));
331 *HilfsPtr=*HilfsPtr | (128>>(x&7));
332 }
333 if (Min_x>rek_x) Min_x=rek_x; if (Min_y>rek_y) Min_y=rek_y;
334 if (Max_x<rek_x) Max_x=rek_x; if (Max_y<rek_y) Max_y=rek_y;
335 rek_x--;
336 KopiereRekursiv();
337 rek_x+=2;
338 KopiereRekursiv();
339 rek_x--;
340 rek_y--;
341 rek_y_zeile-=Page_Bytes_pro_Zeile;
342 KopiereRekursiv();
343 rek_y+=2;
344 rek_y_zeile=rek_y_zeile+Page_Bytes_pro_Zeile+Page_Bytes_pro_Zeile;
345 KopiereRekursiv();
346 rek_y--;
347 rek_y_zeile-=Page_Bytes_pro_Zeile;
348 }
349 maxcount--;
350 }
351
352
353 /***************************************************************
354 Procedure : void Finde_Bloecke()
355
356 Uebergabe : Nichts
357 Rueckgabe : Nichts
358 Autor : Martin Bauer
359 Letzte Aenderung : 1.6.1995
360
361 Getestet : JA , Resultat: fehlerfrei (1.6.1995)
362
363 Aufgabe:
364 Es sollen in einem Bild (*OrginalBildPuffer) der Groesse
365 Page_x,Page_y (Page_Bytes_pro_Zeile) einzelne zusammen-
366 haengende Punkte gefunden werden. Diese Bloecke sollen
367 dann in eine Liste eingehaengt werden. Der Startzeiger dieser
368 Liste ist: *BitBlockListeStartPtr.
369 Die Elemente dieser Liste sind vo Typ: struct BitBlockListe
370
371 ****************************************************************/
372 void Finde_Bloecke()
373 {
374 char *ArbeitsPtr,*P1,*P2;
375 long t,x,y,dx,dy,y_zeile;
376 long n_dx,n_dy,anzahl;
377 struct BitBlockListe *Ptr,*Ptr1;
378
379 /* Init der lokalen Variablen */
380 t=0; x=0; y=0; dx=0; dy=0; y_zeile=0; n_dx=0;
381 n_dy=0; anzahl=0; Ptr=NULL; Ptr1=NULL; P1=NULL; P2=NULL;
382
383 /* Kopiere Orginaldaten in einen Arbeitspuffer */
384 x=Page_y*Page_Bytes_pro_Zeile; ArbeitsPtr=malloc(x+1000);
385 if (ArbeitsPtr==NULL) { MemoryError(); }
386 P1=ArbeitsPtr; P2=OrginalBildPuffer;
387 for (t=0;t<x;t++) { *P1=*P2; P1++; P2++; }
388
389 /* untersuche nach Bloecken */
390 y_zeile=-Page_Bytes_pro_Zeile-Page_Bytes_pro_Zeile;
391 for (y=0;y<Page_y;y+=2)
392 {
393 y_zeile=y_zeile+Page_Bytes_pro_Zeile+Page_Bytes_pro_Zeile;
394 ArbeitsPuffer=ArbeitsPtr;
395 /* gehe alle 2 x-Spalten voran */
396 for (x=0;x<Page_x;x+=2)
397 {
398 /* Punkt im Bild gesetzt ? */
399 if (Bits[(x&7)] & (*(ArbeitsPuffer+y_zeile+(x>>3))))
400 {
401 /* Pixel im ArbeitsBild gesetzt ! */
402 Min_x=x; Max_x=x; Min_y=y; Max_y=y; maxcount=0;
403 rek_x=x; rek_y=y; rek_y_zeile=y_zeile+ArbeitsPuffer;
404 /* suche nun den groessten Block */
405 SucheBitBloecke();
406 dx=Max_x-Min_x; dy=Max_y-Min_y;
407 if ((dx>0) && (dy>0))
408 {
409 /* erstelle Datenelement */
410 anzahl++; n_dx+=dx; n_dy+=dy;
411 Ptr=calloc(1,sizeof(struct BitBlockListe));
412 if (Ptr==NULL) { MemoryError(); }
413 Ptr->Bytes_pro_Zeile=t;
414 Ptr->x=Min_x;
415 Ptr->y=Min_y;
416 Ptr->Startx=x;
417 Ptr->Starty=y;
418 Ptr->Geloescht=0;
419 Ptr->SpaltenNummer=0;
420 Ptr->SegmentNummer=0;
421 Ptr->XSpiegel=0;
422 Ptr->YSpiegel=0;
423 Ptr->Untere_Zeile=-1;
424 Ptr->Obere_Zeile=-1;
425 Ptr->Bild=0;
426 Ptr->dx=dx;
427 Ptr->Elemente=1;
428 Ptr->dy=dy;
429 Ptr->xx=Min_x+dx;
430 Ptr->yy=Min_y+dy;
431 Ptr->NextPtrInZeile=NULL;
432 Ptr->NextSegmentBlockPtr=NULL;
433 Ptr->NextPtrInSegment=NULL;
434 Ptr->NextPtr=BitBlockListeStartPtr;
435 BitBlockListeStartPtr=Ptr;
436 }
437 x=x+dx-1;
438 } /* punkt gesetzt */
439 } /* x loop */
440 } /* y loop */
441 if (anzahl!=0)
442 { /* es gab also Bitbloecke */
443 long schnittx,schnitty;
444 schnittx=(n_dx / (anzahl+0.0))*15;
445 schnitty=(n_dy / (anzahl+0.0))*15;
446 for (Ptr=BitBlockListeStartPtr;Ptr!=NULL;Ptr=Ptr->NextPtr)
447 {
448 if (Ptr->dx>schnittx) { Ptr->Bild=1; }
449 if (Ptr->dy>schnitty) { Ptr->Bild=1; }
450 }
451 /* suche nach bilder die sich ueberschneiden */
452 for (Ptr=BitBlockListeStartPtr;Ptr!=NULL;Ptr=Ptr->NextPtr)
453 {
454 if ((Ptr->Geloescht==0) && (Ptr->Bild==1))
455 {
456 for (Ptr1=BitBlockListeStartPtr;Ptr1!=NULL;Ptr1=Ptr1->NextPtr)
457 {
458 if ((Ptr1!=Ptr) && (Ptr1->Geloescht==0))
459 {
460 if (Ptr->x>Ptr1->x) { x=Ptr->x; } else { x=Ptr1->x; }
461 if (Ptr->y>Ptr1->y) { y=Ptr->y; } else { y=Ptr1->y; }
462 if (Ptr->xx<Ptr1->xx) { xx=Ptr->xx; } else { xx=Ptr1->xx; }
463 if (Ptr->yy<Ptr1->yy) { yy=Ptr->yy; } else { yy=Ptr1->yy; }
464 if (((xx-x)>=0) && ((yy-y)>=0))
465 { /* verschmelzen ! */
466 if (Ptr->x>Ptr1->x) { x=Ptr1->x; } else { x=Ptr->x; }
467 if (Ptr->y>Ptr1->y) { y=Ptr1->y; } else { y=Ptr->y; }
468 if (Ptr->xx<Ptr1->xx) { xx=Ptr1->xx; } else { xx=Ptr->xx; }
469 if (Ptr->yy<Ptr1->yy) { yy=Ptr1->yy; } else { yy=Ptr->yy; }
470 Ptr1->Geloescht=0;
471 Ptr1->Bild=1;
472 Ptr->x=x;
473 Ptr->Bild=1;
474 Ptr->Geloescht=0;
475 Ptr->y=y;
476 Ptr->xx=xx;
477 Ptr->yy=yy;
478 Ptr->dx=xx-x;
479 Ptr->dy=yy-y;
480 } /* diff x,y */
481 }
482 }
483 }
484 }
485 /* und loesche alle Bilder aus dem Orginal-Bild ! */
486 for (Ptr=BitBlockListeStartPtr;Ptr!=NULL;Ptr=Ptr->NextPtr)
487 {
488 if (Ptr->Bild==1)
489 {
490 Ptr->Geloescht=1;
491 LoescheBildFeld(Ptr->x,Ptr->y,Ptr->dx,Ptr->dy);
492 }
493 }
494 }
495 /* Jetzt werden alle erkannten Bloecke aus dem Bild kopiert */
496 /* resturiere ArbeitsBild */
497 x=Page_y*Page_Bytes_pro_Zeile; P1=ArbeitsPtr; P2=OrginalBildPuffer;
498 for (t=0;t<x;t++) { *P1=*P2; P1++; P2++; }
499 for (Ptr=BitBlockListeStartPtr;Ptr!=NULL;Ptr=Ptr->NextPtr)
500 {
501 if ((Ptr->Bild==0) && (Ptr->Geloescht==0))
502 {
503 for (t=0;t<32;t++) Ptr->BildDaten[t]=0; /* loesche bild */
504 offset_x=0; offset_y=0;
505 if (Ptr->dx>Ptr->dy) { faktory=16/(Ptr->dx+0.0); offset_y=(16-(faktory*Ptr->dy))/2; }
506 else { faktory=16/(Ptr->dy+0.0); offset_x=(16-(faktory*Ptr->dx))/2; }
507 if ((Ptr->dx<16) && (Ptr->dy<16)) { faktory=1.0; offset_y=(16-Ptr->dy)>>1; offset_x=(16-Ptr->dx)>>1; }
508 KopierePtr=Ptr;
509 rek_x=Ptr->Startx;
510 rek_y=Ptr->Starty;
511 maxcount=0;
512 rek_y_zeile=ArbeitsPtr+rek_y*Page_Bytes_pro_Zeile;
513 KopiereRekursiv();
514 }
515 }
516 free(ArbeitsPtr);
517 }
518
519
520 /***************************************************************
521 Procedure : void Finde_SegmentBloecke()
522
523 Uebergabe : Nichts
524 Rueckgabe : Nichts
525 Autor : Martin Bauer
526 Letzte Aenderung : 1.6.1995
527
528 Getestet : JA , Resultat: fehlerfrei (1.6.1995)
529
530 Aufgabe:
531 Es sollen in einem Bild (*OrginalBildPuffer) der Groesse
532 Page_x,Page_y (Page_Bytes_pro_Zeile) alle "Segmente", d.h.
533 alle rechteckigen Bloecke zusammengefasst werden die nach
534 einem Verkleinerungszoom des Orginalbildes sich gebildet haben.
535 Dadurch kann man einzelne Text-Bloecke gut herausfinden.
536 Diese gefundenen Bloecke werden in eine Liste eingetragen.
537 Der StartPointer der Liste ist: SegmentBitBlockListeStartPtr
538 Die Elemente der Liste haben den Typ: BitBlockListe.
539 Der Zeiger auf das naechste Segment ist: NextPtrInSegment
540 Es sollen weiterhin alle Segmente in Spalten sortiert werden.
541 Dabei gilt: Spalten von links nach rechts, Segmente in den
542 Spalten vun oben nach unten.
543
544 ****************************************************************/
545 void Finde_SegmentBloecke()
546 {
547 long t,x,y,dx,dy,y1,xx,yy,y_zeile;
548 struct BitBlockListe *Ptr,*P1,*P2,*P3,*P4,*P0;
549 unsigned char *HilfsPuffer,*P,*Pc1;
550 long SegmentNummer,x11,y11,k,min,max,Anzahl,Summe;
551 float deltax,deltay;
552
553 /* Init der lokalen Variablen */
554 t=0; x=0; y=0; dx=0; dy=0; xx=0; yy=0; y_zeile=0;
555 SegmentNummer=0; x11=0; y11=0; k=0; min=0; max=0;
556 Summe=0; Anzahl=0; y1=0;
557 P1=NULL; P2=NULL; P3=NULL; P4=NULL; P0=NULL;
558 P=NULL; HilfsPuffer=NULL; deltax=0.0; deltay=0.0;
559
560 /* lege platz fuer segment-kopie an ! */
561 k=Page_Bytes_pro_Zeile*Page_y;
562 HilfsPuffer=calloc(1,k);
563 if (HilfsPuffer==NULL) { MemoryError(); }
564 Pc1=HilfsPuffer;
565 for (t=0;t<k;t++) { *Pc1=0; Pc1++; }
566 dx=0;
567 dy=0;
568 Anzahl=0;
569
570 /* kopiere jetzt schwarz bloecke rein ! */
571 for (Ptr=BitBlockListeStartPtr;Ptr!=NULL;Ptr=Ptr->NextPtr)
572 {
573 if ((Ptr->Bild==0) && (Ptr->Geloescht==0))
574 {
575 dx=dx+Ptr->dx;
576 dy=dy+Ptr->dy;
577 Anzahl++;
578 }
579 }
580 x11=0;
581 y11=0;
582 if (Anzahl!=0)
583 {
584 x11=((dx+0.0)/Anzahl)*2;
585 y11=((dy+0.0)/Anzahl)*3;
586 }
587 for (Ptr=BitBlockListeStartPtr;Ptr!=NULL;Ptr=Ptr->NextPtr)
588 {
589 if ((Ptr->Bild==0) && (Ptr->Geloescht==0))
590 {
591 if (x11>Ptr->dx) { x=x11; } else { x=Ptr->dx*1.5; }
592 if (y11>Ptr->dy) { y=y11; } else { y=Ptr->dy*1.5; }
593 SetzeBildFeld(HilfsPuffer,Page_Bytes_pro_Zeile,Ptr->x,Ptr->y,x,y);
594 }
595 }
596
597 /* Jetzt wird nach den Bloecken im schwarzen bloecke Bild gesucht */
598 y_zeile=0-Page_Bytes_pro_Zeile;
599 for (y=0;y<Page_y;y+=1)
600 {
601 y_zeile=y_zeile+Page_Bytes_pro_Zeile;
602 for (x=0;x<Page_x;x+=1)
603 {
604 /* Punkt gesetzt ? */
605 if (Bits[(x&7)]&(*(HilfsPuffer+y_zeile+(x >> 3))))
606 {
607 /* Pixel im ArbeitsBild gesetzt ! */
608 Min_x=x; Max_x=x;
609 Min_y=y; Max_y=y;
610 maxcount=0;
611 ArbeitsPuffer=HilfsPuffer;
612 rek_x=x; rek_y=y; rek_y_zeile=y_zeile+ArbeitsPuffer;
613 SucheBitBloecke();
614 dx=Max_x-Min_x+1;
615 dy=Max_y-Min_y+1;
616 if ((dx>3) && (dy>3))
617 {
618 /* erstelle Datenelement */
619 Ptr=calloc(1,sizeof(struct BitBlockListe));
620 if (Ptr==NULL) { MemoryError(); }
621 Ptr->Bytes_pro_Zeile=0;
622 Ptr->x=Min_x;
623 Ptr->y=Min_y;
624 Ptr->Startx=x;
625 Ptr->Starty=y;
626 Ptr->Bild=0;
627 Ptr->SegmentNummer=-1;
628 Ptr->SpaltenNummer=-1;
629 Ptr->XSpiegel=0;
630 Ptr->YSpiegel=0;
631 Ptr->Untere_Zeile=-1;
632 Ptr->Obere_Zeile=-1;
633 Ptr->Geloescht=0;
634 Ptr->dx=dx;
635 Ptr->dy=dy;
636 Ptr->xx=Min_x+dx;
637 Ptr->yy=Min_y+dy;
638 Ptr->NextPtrInZeile=NULL;
639 Ptr->NextSegmentBlockPtr=NULL;
640 Ptr->NextPtrInSegment=NULL;
641 Ptr->NextPtr=SegmentBitBlockListeStartPtr;
642 SegmentBitBlockListeStartPtr=Ptr;
643 } /* min. 2 pixel */
644 x=x+dx-1;
645 } /* punkt gesetzt */
646 } /* x loop */
647 } /* y loop */
648 free(HilfsPuffer);
649 /* Wenn nun wegen max-rekursion abgebrochen wurde, muessen */
650 /* wir noch zusammenhaengende Segmente zusammenfuegen ! */
651 for (P1=SegmentBitBlockListeStartPtr;P1!=NULL;P1=P1->NextPtr)
652 {
653 if (P1->Geloescht==0)
654 {
655 for (P2=SegmentBitBlockListeStartPtr;P2!=NULL;P2=P2->NextPtr)
656 {
657 if ((P2->Geloescht==0) && (P1!=P2))
658 {
659 if (P1->x>P2->x) { x=P1->x; } else { x=P2->x; }
660 if (P1->y>P2->y) { y=P1->y; } else { y=P2->y; }
661 if (P1->xx<P2->xx) { xx=P1->xx; } else { xx=P2->xx; }
662 if (P1->yy<P2->yy) { yy=P1->yy; } else { yy=P2->yy; }
663 if (((xx-x)>=0) && ((yy-y)>=0))
664 { /* verschmelzen ! */
665 if (P1->x>P2->x) { x=P2->x; } else { x=P1->x; }
666 if (P1->y>P2->y) { y=P2->y; } else { y=P1->y; }
667 if (P1->xx<P2->xx) { xx=P2->xx; } else { xx=P1->xx; }
668 if (P1->yy<P2->yy) { yy=P2->yy; } else { yy=P1->yy; }
669 P2->Geloescht=1;
670 P1->x=x;
671 P1->y=y;
672 P1->xx=xx;
673 P1->yy=yy;
674 P1->dx=xx-x;
675 P1->dy=yy-y;
676 } /* diff x,y */
677 } /* p1!=p2 */
678 } /* for P2 */
679 } /* if */
680 if (((P1->xx-P1->x)<2) && ((P1->yy-P1->y)<3)) P1->Geloescht=1;
681 } /* for P1 */
682
683 /* Berechne nun die Spalten / Segmentreihenfolge */
684 min=9999999; max=0; Summe=0; Anzahl=0; P2=NULL;
685 for (P1=SegmentBitBlockListeStartPtr;P1!=NULL;P1=P1->NextPtr)
686 {
687 if (P1->Geloescht==0)
688 {
689 if (P1->x<min) { min=P1->x; P2=P1; }
690 if (P1->xx>max) { max=P1->xx; }
691 Anzahl++;
692 Summe=Summe+P1->xx-P1->x;
693 } /* if not killed */
694 } /* for */
695 if(Anzahl!=0)
696 {
697 float Schnitt,aha;
698 long SpaltenAnzahl,x1,SpaltenNummer;
699 Schnitt=Summe/(Anzahl+0.0);
700 SpaltenNummer=0;
701 SpaltenAnzahl=(0.5+((max-min) / Schnitt));
702 aha=((max-min) / SpaltenAnzahl)*0.7 ;
703
704 for (P1=SegmentBitBlockListeStartPtr;P1!=NULL;P1=P1->NextPtr)
705 {
706
707 if ((P1->dx<aha) )
708 {
709 dx=P1->dx+x11;
710 xx=dx+P1->x;
711 P1->dx=dx;
712 P1->xx=xx;
713 }
714 }
715
716
717 min=9999999; max=0; Summe=0; Anzahl=0; P2=NULL;
718 for (P1=SegmentBitBlockListeStartPtr;P1!=NULL;P1=P1->NextPtr)
719 {
720 if (P1->Geloescht==0)
721 {
722 if (P1->x<min) { min=P1->x; P2=P1; }
723 if (P1->xx>max) { max=P1->xx; }
724 Anzahl++;
725 Summe=Summe+P1->xx-P1->x;
726 } /* if not killed */
727 } /* for */
728
729 Schnitt=Summe/(Anzahl+0.0);
730 SpaltenNummer=0;
731 SpaltenAnzahl=(0.5+((max-min) / Schnitt));
732
733
734 /* */
735 for (SpaltenNummer=0;SpaltenNummer<=SpaltenAnzahl;)
736 {
737 x1=min+Schnitt;
738 for (P1=SegmentBitBlockListeStartPtr;P1!=NULL;P1=P1->NextPtr)
739 {
740 if ((P1->Geloescht==0) && (P1->SpaltenNummer==-1) && (P1->x<x1))
741 {
742 P1->SpaltenNummer=SpaltenNummer;
743 } /* if not killed */
744 } /* for */
745 SpaltenNummer++;
746 min=max+1;
747 for (P1=SegmentBitBlockListeStartPtr;P1!=NULL;P1=P1->NextPtr)
748 {
749 if ((P1->Geloescht==0) && (P1->SpaltenNummer==-1) && (P1->x<min))
750 {
751 min=P1->x;
752 } /* if */
753 } /* for */
754 } /* for spaltennummer */
755 P3=NULL; P4=NULL;
756 SegmentNummer=0;
757 min=9999999;
758 for (SpaltenNummer=0;SpaltenNummer<=SpaltenAnzahl;SpaltenNummer++)
759 {
760 P2=SegmentBitBlockListeStartPtr;
761 for (;P2!=NULL;)
762 {
763 P2=NULL; min=88888888;
764 for (P1=SegmentBitBlockListeStartPtr;P1!=NULL;P1=P1->NextPtr)
765 {
766 if ((P1->Geloescht==0) && (P1->SpaltenNummer==SpaltenNummer) && (P1->SegmentNummer==-1))
767 {
768 if (P1->y<min) { min=P1->y; P2=P1; }
769 } /* if */
770 } /* for */
771 if (P2!=NULL)
772 {
773 if (P3==NULL) P4=P2; /* start */
774 if (P3!=NULL) P3->NextSegmentBlockPtr=P2;
775 P3=P2;
776 P2->SegmentNummer=SegmentNummer;
777 SegmentNummer++;
778 }
779 } /* P2!=NULL */
780 } /* for spaltennummer */
781 P0=NULL;
782 if (P4!=NULL)
783 {
784 for (P1=P4;P1!=NULL;P1=P1->NextSegmentBlockPtr)
785 {
786 if (P1->NextSegmentBlockPtr!=NULL)
787 {
788 P2=P1->NextSegmentBlockPtr;
789 if (P1->y>P2->y) { y=P1->y; } else { y=P2->y; }
790 if (P1->yy<P2->yy) { yy=P1->yy; } else { yy