source: gsdl/trunk/trunk/mg/src/images/marklist.c@ 16583

Last change on this file since 16583 was 16583, checked in by davidb, 16 years ago

Undoing change commited in r16582

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 14.4 KB
Line 
1/**************************************************************************
2 *
3 * marklist.c -- Functions managing the list of marks
4 * Copyright (C) 1994 Stuart Inglis
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * $Id: marklist.c 16583 2008-07-29 10:20:36Z davidb $
21 *
22 **************************************************************************/
23
24#include "sysfuncs.h"
25
26#include "marklist.h"
27#include "pbmtools.h"
28#include "utils.h"
29
30void
31marktype_dump (marktype d)
32{
33 fprintf (stderr, "symnum: %d\n", d.symnum);
34 fprintf (stderr, "xpos: %d, ypos: %d\n", d.xpos, d.ypos);
35 fprintf (stderr, "w: %d, h: %d\n", d.w, d.h);
36 fprintf (stderr, "xcen: %d, ycen: %d\n", d.xcen, d.ycen);
37 write_library_mark (stderr, d);
38}
39
40
41/* copy, including make a copy of the bitmap */
42marktype
43marktype_copy (marktype d)
44{
45 marktype d2;
46 int i, j;
47
48 d2 = d;
49 d2.bitmap = pbm_allocarray (d2.w, d2.h);
50 for (i = 0; i < d2.w; i++)
51 for (j = 0; j < d2.h; j++)
52 pbm_putpixel (d2.bitmap, i, j, pbm_getpixel (d.bitmap, i, j));
53 return d2;
54}
55
56
57float
58marktype_density (marktype d)
59{
60 return d.set / (float) (d.w * d.h);
61}
62
63
64
65void
66marktype_calc_centroid (marktype * b)
67{
68 int r, c;
69 int count = 0;
70 int xtot = 0, ytot = 0;
71
72 for (r = 0; r < b->h; r++)
73 for (c = 0; c < b->w; c++)
74 if (pbm_getpixel (b->bitmap, c, r))
75 {
76 count++;
77 xtot += c;
78 ytot += r;
79 }
80 if (count)
81 {
82 xtot /= count;
83 ytot /= count;
84 }
85 b->xcen = xtot;
86 b->ycen = ytot;
87}
88
89
90
91static void
92marktype_area (marktype * d)
93{
94 int x, y;
95 int set = 0;
96
97 for (y = 0; y < d->h; y++)
98 for (x = 0; x < d->w; x++)
99 if (pbm_getpixel (d->bitmap, x, y))
100 set++;
101 d->set = set;
102}
103
104
105static void
106marktype_h_runs (marktype * d)
107{
108 int x, y;
109 int inrun = 0, num = 0;
110 int foundblack = 0;
111
112 for (y = 0; y < d->h; y++)
113 {
114 inrun = 0;
115 foundblack = 0;
116 for (x = 0; x < d->w; x++)
117 {
118 if ((!foundblack) && (pbm_getpixel (d->bitmap, x, y)))
119 foundblack = 1;
120 if ((foundblack) && (pbm_getpixel (d->bitmap, x, y) == 0))
121 inrun = 1;
122 if ((inrun) && (pbm_getpixel (d->bitmap, x, y)))
123 {
124 num++;
125 inrun = 0;
126 foundblack = 0;
127 }
128 }
129 }
130 d->h_runs = num;
131}
132
133static void
134marktype_v_runs (marktype * d)
135{
136 int x, y;
137 int inrun = 0, num = 0;
138 int foundblack = 0;
139
140
141 for (x = 0; x < d->w; x++)
142 {
143 inrun = 0;
144 foundblack = 0;
145 for (y = 0; y < d->h; y++)
146 {
147 if ((!foundblack) && (pbm_getpixel (d->bitmap, x, y)))
148 foundblack = 1;
149 if ((foundblack) && (pbm_getpixel (d->bitmap, x, y) == 0))
150 inrun = 1;
151 if ((inrun) && (pbm_getpixel (d->bitmap, x, y)))
152 {
153 num++;
154 inrun = 0;
155 foundblack = 0;
156 }
157 }
158 }
159 d->v_runs = num;
160}
161
162
163/* assume we already have the centroid! */
164static void
165marktype_prog_cent (marktype * d)
166{
167 int x, y;
168 int xtot = 0, ytot = 0;
169 int num = 0;
170
171 xtot = ytot = num = 0;
172 for (x = 0; x < d->xcen; x++)
173 for (y = 0; y < d->ycen; y++)
174 if (pbm_getpixel (d->bitmap, x, y))
175 {
176 xtot += x;
177 ytot += y;
178 num++;
179 }
180 if (num == 0)
181 {
182 d->xcen1 = -1;
183 d->ycen1 = -1;
184 }
185 else
186 {
187 d->xcen1 = xtot / num;
188 d->ycen1 = ytot / num;
189 }
190
191
192 xtot = ytot = num = 0;
193 for (x = d->xcen; x < d->w; x++)
194 for (y = 0; y < d->ycen; y++)
195 if (pbm_getpixel (d->bitmap, x, y))
196 {
197 xtot += x;
198 ytot += y;
199 num++;
200 }
201 if (num == 0)
202 {
203 d->xcen2 = -1;
204 d->ycen2 = -1;
205 }
206 else
207 {
208 d->xcen2 = xtot / num;
209 d->ycen2 = ytot / num;
210 }
211
212
213
214 xtot = ytot = num = 0;
215 for (x = 0; x < d->xcen; x++)
216 for (y = d->ycen; y < d->h; y++)
217 if (pbm_getpixel (d->bitmap, x, y))
218 {
219 xtot += x;
220 ytot += y;
221 num++;
222 }
223
224
225 if (num == 0)
226 {
227 d->xcen3 = -1;
228 d->ycen3 = -1;
229 }
230 else
231 {
232 d->xcen3 = xtot / num;
233 d->ycen3 = ytot / num;
234 }
235
236 xtot = ytot = num = 0;
237 for (x = d->xcen; x < d->w; x++)
238 for (y = d->ycen; y < d->h; y++)
239 if (pbm_getpixel (d->bitmap, x, y))
240 {
241 xtot += x;
242 ytot += y;
243 num++;
244 }
245 if (num == 0)
246 {
247 d->xcen4 = -1;
248 d->ycen4 = -1;
249 }
250 else
251 {
252 d->xcen4 = xtot / num;
253 d->ycen4 = ytot / num;
254 }
255}
256
257
258
259/* call this to get all features */
260void
261marktype_calc_features (marktype * d, char str[])
262{
263 if (strlen (str))
264 strcpy (d->name, str);
265 marktype_calc_centroid (d);
266 marktype_area (d);
267 marktype_prog_cent (d);
268 marktype_h_runs (d);
269 marktype_v_runs (d);
270}
271
272
273
274
275
276void
277marktype_adj_bound (marktype * m)
278{
279 int x, y, w, h;
280 int xpos, ypos;
281 int top = 0, left = 0, right = 0, bot = 0;
282 marktype temp;
283
284 w = m->w;
285 h = m->h;
286 xpos = m->xpos;
287 ypos = m->ypos;
288
289 for (y = 0; y < h; y++)
290 for (x = 0; x < w; x++)
291 if (pbm_getpixel (m->bitmap, x, y))
292 {
293 top = y;
294 x = w;
295 y = h;
296 }
297
298 for (y = h - 1; y >= 0; y--)
299 for (x = 0; x < w; x++)
300 if (pbm_getpixel (m->bitmap, x, y))
301 {
302 bot = y;
303 x = w;
304 y = -1;
305 }
306
307 for (x = 0; x < w; x++)
308 for (y = 0; y < h; y++)
309 if (pbm_getpixel (m->bitmap, x, y))
310 {
311 left = x;
312 x = w;
313 y = h;
314 }
315
316 for (x = w - 1; x >= 0; x--)
317 for (y = 0; y < h; y++)
318 if (pbm_getpixel (m->bitmap, x, y))
319 {
320 right = x;
321 x = -1;
322 y = h;
323 }
324
325 temp.w = right - left + 1;
326 temp.h = bot - top + 1;
327 temp.xpos = xpos + left;
328 temp.ypos = ypos + top;
329 temp.bitmap = pbm_allocarray (temp.w, temp.h);
330
331 for (x = 0; x < temp.w; x++)
332 for (y = 0; y < temp.h; y++)
333 pbm_putpixel (temp.bitmap, x, y, pbm_getpixel (m->bitmap, x + left, y + top));
334
335 pbm_freearray (&(m->bitmap), h);
336
337 marktype_calc_features (&temp, "?");
338 *m = temp;
339}
340
341
342
343
344
345
346/* returns a newly created mark reprenting the average of the marklist */
347void
348marklist_average (marklistptr list, marktype * avgmark)
349{
350 int w = 0, h = 0;
351 int t = INT_MAX, b = 0, l = INT_MAX, r = 0, matched = 0;
352 marktype d, temp;
353 marklistptr step;
354 static int a[100][100];
355 int x, y;
356
357 if (list == NULL)
358 error_msg ("marklist_average", "Can't average 'nothing'!", "");
359
360 for (step = list; step; step = step->next)
361 {
362 matched++;
363 temp = step->data;
364 w = max (w, temp.w);
365 h = max (h, temp.h);
366 r = max (r, temp.xcen);
367 l = min (l, temp.xcen);
368 b = max (b, temp.ycen);
369 t = min (t, temp.ycen);
370 }
371 w = w + (r - l);
372 h = h + (b - t);
373 if ((w >= 100) || (h >= 100))
374 matched = 0;
375
376 if (matched > 1)
377 {
378 int x_off, y_off;
379 for (x = 0; x < w; x++)
380 for (y = 0; y < h; y++)
381 a[x][y] = 0;
382
383 for (step = list; step; step = step->next)
384 {
385 x_off = r - step->data.xcen;
386 y_off = b - step->data.ycen;
387 for (x = 0; x < step->data.w; x++)
388 for (y = 0; y < step->data.h; y++)
389 if (pbm_getpixel (step->data.bitmap, x, y))
390 a[x + x_off][y + y_off]++;
391 }
392
393 d.w = w;
394 d.h = h;
395 d.bitmap = pbm_allocarray (w, h);
396 for (x = 0; x < w; x++)
397 for (y = 0; y < h; y++)
398 if (a[x][y] > max (1, (matched / 2))) /* > gives better CR than >= */
399 pbm_putpixel (d.bitmap, x, y, 1);
400 marktype_adj_bound (&d);
401 strcpy (d.name, "?");
402 marktype_calc_centroid (&d);
403 }
404 else
405 d = marktype_copy (list->data);
406
407 *avgmark = d;
408}
409
410
411
412
413
414
415void
416marklist_setnull (marklistptr * list)
417{
418 *list = NULL;
419}
420
421
422marklistptr
423marklist_add (marklistptr * list, marktype m)
424{
425 marklistptr p;
426
427 if (*list == NULL)
428 {
429 *list = (marklistptr) malloc (sizeof (marklisttype));
430 if ((*list) == NULL)
431 error_msg ("marklist_add", "OUT of Memory in marklist_add", "");
432 p = *list;
433 }
434 else
435 {
436 p = *list;
437 while (p->next != NULL)
438 p = p->next;
439 p->next = (marklistptr) malloc (sizeof (marklisttype));
440 if (p->next == NULL)
441 error_msg ("marklist_add", "OUT of Memory in marklist_add", "");
442 p = p->next;
443 }
444 p->data = m;
445 p->next = NULL;
446 return p;
447
448}
449
450
451
452marklistptr
453marklist_addcopy (marklistptr * list, marktype m)
454{
455 marktype d;
456
457 d = marktype_copy (m);
458 return marklist_add (list, d);
459}
460
461
462
463int
464marklist_length (marklistptr list)
465{
466 int count = 0;
467
468 while (list)
469 {
470 count++;
471 list = list->next;
472 }
473 return count;
474}
475
476
477
478
479
480void
481marklist_dump (marklistptr list)
482{
483 int count = 0;
484 marktype d;
485
486 while (list)
487 {
488 d = list->data;
489 marktype_dump (d);
490
491 count++;
492 list = list->next;
493 }
494}
495
496
497
498
499/* pos starts from 0, to up marklist_length-1 */
500marklistptr
501marklist_getat (marklistptr list, int pos, marktype * d)
502{
503 int count = 0;
504
505 while (list)
506 {
507 if (count == pos)
508 {
509 *d = list->data;
510 return list;
511 }
512 count++;
513 list = list->next;
514 }
515 fprintf (stderr, "marklist_getat(): access off ends of list: pos %d\n", pos);
516 return NULL;
517}
518
519
520
521void
522marklist_free (marklistptr * list)
523{
524 marklistptr n;
525
526 while ((*list) != NULL)
527 {
528 n = (*list)->next;
529 pbm_freearray (&((*list)->data.bitmap), (*list)->data.h);
530 free ((*list));
531 (*list) = n;
532 }
533}
534
535
536
537int
538marklist_removeat (marklistptr * list, int pos)
539{
540 marklistptr c, n, p = NULL;
541 int count = 0;
542
543 if ((pos == 0) && (*list))
544 { /* if removing the 1st element */
545 *list = (*list)->next;
546 return 1;
547 }
548 else
549 {
550 c = *list;
551 while (c)
552 {
553 if (count == pos)
554 { /* two cases, no previous, >=1 previous */
555 if (p == NULL) /* no previous */
556 {
557 n = c->next;
558 pbm_freearray (&c->data.bitmap, c->data.h);
559 free (c);
560 c = n;
561 return 1;
562 }
563 else
564 /* >=1 previous */
565 {
566 n = c->next;
567 pbm_freearray (&c->data.bitmap, c->data.h);
568 free (c);
569 p->next = n;
570 return 1;
571 }
572 }
573 count++;
574 p = c;
575 c = c->next;
576 }
577 }
578 fprintf (stderr, "marklist_removeat(): access off ends of list: pos %d\n", pos);
579 return 0; /* nothing was removed */
580}
581
582
583
584marklistptr
585marklist_next (marklistptr list)
586{
587 return list->next;
588}
589
590
591/* only writes out ascii form */
592void
593write_library_mark (FILE * fp, marktype d)
594{
595 int r, c, rows, cols;
596 int xtot = d.xcen, ytot = d.ycen;
597
598 rows = d.h;
599 cols = d.w;
600
601 fprintf (fp, "Mark: %d\n", d.symnum);
602 fprintf (fp, "Char: %s\n", d.name);
603 fprintf (fp, "Cols: %d Rows: %d\n", d.w, d.h);
604 for (r = 0; r < d.h; r++)
605 {
606 for (c = 0; c < d.w; c++)
607 if ((r == ytot) && (c == xtot))
608 putc (pbm_getpixel (d.bitmap, c, r) ? 'C' : '!', fp);
609 else
610 putc (pbm_getpixel (d.bitmap, c, r) ? 'X' : '.', fp);
611 putc ('\n', fp);
612 }
613}
614
615
616
617/* only reads in ascii library */
618int
619read_library_mark (FILE * fp, marktype * d)
620{
621 int r, c, rows, cols, numread, ch1 = 'C';
622 char str1[100], str2[100];
623
624 numread = fscanf (fp, "%s %d\n", str1, &(d->symnum));
625 if ((numread != 2) || (strcmp (str1, "Mark:") != 0))
626 return 0;
627 fscanf (fp, "%s %s\n", str1, (d->name));
628 fscanf (fp, "%s %d %s %d\n", str1, &(d->w), str2, &(d->h));
629 cols = d->w;
630 rows = d->h;
631 d->bitmap = pbm_allocarray (cols, rows);
632 for (r = 0; r < rows; r++)
633 {
634 for (c = 0; c < cols; c++)
635 {
636 ch1 = getc (fp);
637 if ((ch1 == 'X') || (ch1 == 'C'))
638 pbm_putpixel (d->bitmap, c, r, 1);
639 else
640 pbm_putpixel (d->bitmap, c, r, 0);
641 }
642 ch1 = getc (fp);
643 }
644 marktype_calc_features (d, "?");
645
646 return 1;
647}
648
649
650
651
652
653
654
655int
656read_library (char libraryname[], marklistptr * library)
657{
658 int err, count;
659 FILE *lib;
660 marktype d;
661 marklistptr step;
662
663 lib = fopen (libraryname, "rb");
664 if (lib == NULL)
665 error_msg ("read_library()", "Trouble opening library file", "");
666 *library = NULL;
667 count = 0;
668 while (!isEOF (lib))
669 {
670 err = read_library_mark (lib, &d);
671 if (!err)
672 error_msg ("read_library()", "unknown format of the library file.", "");
673 d.symnum = count;
674 count++;
675 if ((*library) == NULL)
676 step = marklist_add (library, d);
677 else
678 step = marklist_add (&step, d);
679 }
680 count = marklist_length (*library);
681 fclose (lib);
682
683 return count;
684}
685
686
687
688
689
690
691/**********************************************************************
692
693'elem' routines for coding offsets
694
695the elem datatype contains the 3 params for arithmetic coding,
696stored as a no-duplicates order linked list.
697
698************************************************************************/
699
700
701
702
703void
704elem_add (elemlist * list, int num)
705{
706 elemptr temp, nn;
707 int p, f;
708
709 list->tot++;
710 if (list->head == NULL)
711 {
712 list->head = (elemptr) malloc (sizeof (elem));
713 if ((list->head) == NULL)
714 error_msg ("", "ekk", "");
715 temp = list->head;
716 temp->next = NULL;
717 temp->num = num;
718 temp->pos = 0;
719 temp->freq = 1;
720 }
721 else
722 { /* add to list */
723 temp = list->head;
724 p = 0;
725 f = 0;
726 while ((num > temp->num) && (temp->next != NULL))
727 {
728 p = temp->pos;
729 f = temp->freq;
730 temp = temp->next;
731 }
732
733 if (temp->num == num)
734 temp->freq++;
735 else
736 { /* insert it */
737 nn = (elemptr) malloc (sizeof (elem));
738 if (nn == NULL)
739 error_msg ("", "ekk", "");
740
741 if (num < temp->num)
742 {
743 nn->num = temp->num;
744 nn->pos = temp->pos;
745 nn->freq = temp->freq;
746 nn->next = temp->next;
747 temp->num = num;
748 temp->pos = p + f;
749 temp->freq = 1;
750 temp->next = nn;
751 }
752 else
753 {
754 nn->next = temp->next;
755 temp->next = nn;
756 nn->pos = temp->pos + temp->freq;
757 nn->num = num;
758 nn->freq = 1;
759 temp = nn;
760 }
761 }
762 }
763 /* update frequencies */
764 temp = temp->next;
765 if (temp)
766 do
767 {
768 temp->pos++;
769 temp = temp->next;
770 }
771 while (temp);
772}
773
774
775void
776elem_free (elemlist * list)
777{
778 elemptr n, p;
779
780 p = list->head;
781 while (p != NULL)
782 {
783 n = p->next;
784 free (p);
785 p = n;
786 }
787 list->head = NULL;
788}
789
790int
791elem_find (elemlist * list, int n, int *p, int *f, int *t)
792{
793 elemptr temp;
794
795 temp = list->head;
796 while (temp)
797 {
798 if (temp->num == n)
799 {
800 *p = temp->pos;
801 *f = temp->freq + temp->pos;
802 *t = list->tot;
803 return 1;
804 }
805 temp = temp->next;
806 }
807 return 0;
808}
809
810
811int
812elem_getrange (elemlist * list, int range, int *num)
813{
814 elemptr temp;
815
816 temp = list->head;
817 while (temp)
818 {
819 if ((range >= temp->pos) && (range < (temp->pos + temp->freq)))
820 {
821 *num = temp->num;
822 return 1;
823 }
824 temp = temp->next;
825 }
826 return 0;
827}
Note: See TracBrowser for help on using the repository browser.