00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifndef __CMV_REGION_H__
00016 #define __CMV_REGION_H__
00017
00018
00019 const unsigned int MAX_COLORS=20;
00020
00021
00022 #include <stdio.h>
00023
00024
00025
00026 #include "cmv_types.h"
00027 #include <ext/hash_map>
00028
00029 struct hashcmp_eqstr { bool operator()(const char* s1, const char* s2) const
00030 { return strcasecmp(s1, s2) == 0; } };
00031
00032 namespace CMVision{
00033
00034 template<class T>
00035 class DummyT1 {
00036 };
00037
00038
00039
00040
00041 inline int range_sum(int x,int w)
00042 {
00043 return(w*(2*x + w-1) / 2);
00044 }
00045
00046
00047 const int log2modp[37] = {
00048 0, 1, 2,27, 3,24,28, 0, 4,17,25,31,29,12, 0,14, 5, 8,18,
00049 0,26,23,32,16,30,11,13, 7, 0,22,15,10, 6,21, 9,20,19
00050 };
00051
00052
00053 template <class num>
00054 inline int bottom_bit(num n)
00055 {
00056 return(log2modp[(n & -n) % 37]);
00057 }
00058
00059
00060 template <class num>
00061 inline num top_bit(num n)
00062 {
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 n |= (n >> 1) | (n >> 2) | (n >> 3);
00074 n |= (n >> 4) | (n >> 8) | (n >> 12);
00075 n |= (n >> 16);
00076 n -= (n >> 1);
00077 return(log2modp[n % 37]);
00078
00079
00080
00081
00082
00083
00084
00085 }
00086
00087
00088
00089 #define REMOVE_NOISE
00090
00091 template <class rle_t,class tmap_t>
00092 int EncodeRuns(rle_t *rle,tmap_t *map,int width,int height,int max_runs)
00093
00094
00095
00096 {
00097 tmap_t m,save;
00098 tmap_t *row;
00099 int x,y,j,l;
00100
00101 #ifdef REMOVE_NOISE
00102 int lastcolor;
00103 int noise;
00104 int noise_back;
00105 #endif
00106
00107 rle_t r;
00108
00109 r.next = 0;
00110
00111
00112 save = map[0];
00113
00114 j = 0;
00115
00116 for(y=0; y<height; y++){
00117 row = &map[y * width];
00118
00119
00120
00121 row[0] = save;
00122 save = row[width];
00123 row[width] = MAX_COLORS;
00124 r.y = y;
00125
00126 x = 0;
00127
00128 #ifdef REMOVE_NOISE
00129 lastcolor=0;
00130 noise=0;
00131 noise_back=0;
00132 #endif
00133 while(x < width){
00134 m = row[x];
00135 r.x = x;
00136
00137 l = x;
00138 while(row[x] == m) x++;
00139
00140 #ifdef REMOVE_NOISE
00141 if (x - l > 4) {
00142 if (noise>=4) {
00143 j=j-noise_back;
00144 lastcolor=0;
00145 }
00146 noise=0;
00147 noise_back=0;
00148 } else {
00149 noise++;
00150 if (m) noise_back++;
00151 }
00152 #endif
00153
00154 if(m!=0 || x>=width){
00155 r.color = m;
00156 r.width = x - l;
00157 r.parent = j;
00158 rle[j++] = r;
00159
00160 if(j >= max_runs) {
00161 row[width] = save;
00162 return(j);
00163 }
00164 }
00165 #ifdef REMOVE_NOISE
00166 else if (!m && lastcolor && x-l<5) {
00167 rle[j-1].width+=x-l;
00168 }
00169
00170 lastcolor=m;
00171 #endif
00172 }
00173 }
00174
00175 return(j);
00176 }
00177
00178 template <class rle_t,class tmap_t,class edge_t>
00179 int EncodeRunsUseEdges(rle_t *rle,tmap_t *map,edge_t *edge_map,int width,int height,int max_runs)
00180
00181
00182
00183 {
00184 tmap_t m,save;
00185 tmap_t *row;
00186 int x,y,j,l;
00187 rle_t r;
00188
00189 r.next = 0;
00190
00191
00192 save = map[0];
00193
00194 j = 0;
00195 for(y=0; y<height; y++){
00196 row = &map[y * width];
00197
00198
00199
00200 row[0] = save;
00201 save = row[width];
00202 row[width] = MAX_COLORS;
00203 r.y = y;
00204
00205 x = 0;
00206 while(x < width){
00207 m = row[x];
00208 r.x = x;
00209
00210 l = x;
00211 while(row[x] == m) x++;
00212
00213 if(m!=0 || x>=width){
00214 r.color = m;
00215 r.width = x - l;
00216 r.parent = j;
00217 rle[j++] = r;
00218
00219
00220
00221 if(j >= max_runs) return(j);
00222 }
00223 }
00224 }
00225
00226 return(j);
00227 }
00228
00229 #ifdef ENABLE_JOIN_NEARBY
00230 template<class rle_t>
00231 inline int AdvanceToNextRun(int run_idx, rle_t *runs) {
00232 run_idx++;
00233 if(runs[run_idx].x==-1)
00234 run_idx=runs[run_idx].next;
00235 return run_idx;
00236 }
00237 #else
00238 #define AdvanceToNextRun(x,y) (x+1)
00239 #endif
00240
00241
00242
00243
00244 template<class rle_t>
00245 bool CheckRuns(rle_t *rle,int num_runs,int width,int height) {
00246 bool error;
00247 int x,y;
00248 int run_idx;
00249
00250 error=false;
00251 x = y = 0;
00252
00253 run_idx = 0;
00254 while(run_idx < num_runs && !error) {
00255 rle_t *cur_run=&rle[run_idx];
00256
00257 if(cur_run->x < x) {
00258 printf("\nat (%d,%d) backwards x movement, cur x=%d run x=%d\n",x,y,x,cur_run->x);
00259 error=true;
00260 }
00261
00262 if(cur_run->width < 0) {
00263 printf("\nat (%d,%d) negative run width %d\n",x,y,cur_run->width);
00264 error=true;
00265 }
00266
00267 if(cur_run->y != y) {
00268 printf("\nat (%d,%d) wrong y value, cur y=%d run y=%d\n",x,y,y,cur_run->y);
00269 error=true;
00270 }
00271
00272 x = cur_run->x + cur_run->width;
00273 if(x == width) {
00274 x = 0;
00275 y++;
00276 }
00277
00278 run_idx++;
00279 }
00280
00281 if(!error && (x!=0 || y!=height)) {
00282 printf("at (%d,%d) wrong ending position\n",x,y);
00283 error=true;
00284 }
00285
00286 return !error;
00287 }
00288
00289 #ifdef ENABLE_JOIN_NEARBY
00290
00291
00292 template <class rle_t>
00293 int JoinNearbyRuns(rle_t *rle_from,rle_t *rle_to,int num_runs,int width,int height) {
00294 int fup,fon,fdn;
00295 int ton;
00296 int fup_n,fon_n,fdn_n;
00297 int x,y;
00298 int next_x,cand_next_x;
00299 int which_bump;
00300 rle_t rup,ron,rdn;
00301 rle_t rup_n,ron_n,rdn_n;
00302 rle_t rout;
00303
00304 fup = -1;
00305 fup=AdvanceToNextRun(fup,rle_from);
00306 rup = rle_from[fup];
00307 fup_n=AdvanceToNextRun(fup,rle_from);
00308 rup_n=rle_from[fup_n];
00309
00310 fon = fup;
00311 fon=AdvanceToNextRun(fon,rle_from);
00312 ron = rle_from[fon];
00313 fon_n=AdvanceToNextRun(fon,rle_from);
00314 ron_n=rle_from[fon_n];
00315
00316 fdn = fon;
00317 while(rle_from[fdn].y==0)
00318 fdn=AdvanceToNextRun(fdn,rle_from);
00319 rdn = rle_from[fdn];
00320
00321 ton = 0;
00322
00323
00324 rout.color = 0;
00325 rout.width = width;
00326 rout.x = 0;
00327 rout.y = -1;
00328 rout.parent = ton;
00329 rle_to[ton++] = rout;
00330
00331 rout = ron;
00332
00333 y = 0;
00334 x = ron.x+ron.width-1;
00335
00336 while(rup_n.x <= x && rup_n.y < y) {
00337 fup=fup_n;
00338 rup=rup_n;
00339 fup_n=AdvanceToNextRun(fup,rle_from);
00340 rup_n=rle_from[fup_n];
00341 }
00342
00343 while(y < height && fon < num_runs-1) {
00344 static const int bridge_width=1;
00345
00346 bool output=true;
00347 bool advance=true;
00348
00349
00350
00351 if(rout.x+rout.width+bridge_width >= ron_n.x && rout.color == ron_n.color && rout.y == ron_n.y) {
00352
00353 rout.width = ron_n.x+ron_n.width - rout.x;
00354 output = false;
00355 }
00356 else {
00357
00358
00359 int x_diff;
00360 x_diff = rup_n.x - (rout.x+rout.width-1);
00361 if(0 < x_diff && x_diff<=2 && rout.color == rup_n.color && rout.y == rup_n.y+1 && (rup_n.x < ron_n.x || rout.y != ron_n.y)) {
00362
00363 rout.width += x_diff;
00364 output = false;
00365 advance = false;
00366 }
00367 }
00368
00369 if(output) {
00370
00371 rout.parent = ton;
00372 rle_to[ton++] = rout;
00373 rout = ron_n;
00374 }
00375
00376 if(advance) {
00377 fon=fon_n;
00378 fon_n=AdvanceToNextRun(fon,rle_from);
00379 ron_n=rle_from[fon_n];
00380 }
00381
00382 next_x = rout.x + rout.width - 1;
00383 x = next_x;
00384 if(x==width-1) {
00385 y++;
00386 x=0;
00387 }
00388
00389 while(rup.y < y-1 || (rup_n.x <= x && rup_n.y < y)) {
00390 fup=fup_n;
00391 rup=rup_n;
00392 fup_n=AdvanceToNextRun(fup,rle_from);
00393 rup_n=rle_from[fup_n];
00394 }
00395 }
00396
00397
00398 rout.parent = ton;
00399 rle_to[ton++] = rout;
00400
00401
00402 rout.color = 0;
00403 rout.width = width;
00404 rout.x = 0;
00405 rout.y = height;
00406 rout.parent = ton;
00407 rle_to[ton++] = rout;
00408
00409 return ton;
00410 }
00411 #endif
00412
00413 template <class rle_t>
00414 void ConnectComponents(rle_t *map,int num)
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425 {
00426 int l1,l2;
00427 rle_t r1,r2;
00428 int i,j,s;
00429
00430
00431 l2 = 0;
00432 #ifdef ENABLE_JOIN_NEARBY
00433 l2=AdvanceToNextRun(l2,map);
00434 #endif
00435 l1 = 1;
00436 while(map[l1].y == 0)
00437 l1=AdvanceToNextRun(l1,map);
00438
00439
00440 r1 = map[l1];
00441 r2 = map[l2];
00442 s = l1;
00443 while(l1 < num){
00444
00445
00446
00447
00448
00449
00450 if(r1.color==r2.color && r1.color){
00451
00452
00453 if((r2.x<=r1.x && r1.x<r2.x+r2.width) ||
00454 (r1.x<=r2.x && r2.x<r1.x+r1.width)){
00455 if(s != l1){
00456
00457 map[l1].parent = r1.parent = r2.parent;
00458 s = l1;
00459 }else if(r1.parent != r2.parent){
00460
00461
00462
00463 i = r1.parent;
00464 while(i != map[i].parent) i = map[i].parent;
00465 j = r2.parent;
00466 while(j != map[j].parent) j = map[j].parent;
00467
00468
00469
00470 if(i < j){
00471 map[j].parent = i;
00472 map[l1].parent = map[l2].parent = r1.parent = r2.parent = i;
00473 }else{
00474 map[i].parent = j;
00475 map[l1].parent = map[l2].parent = r1.parent = r2.parent = j;
00476 }
00477 }
00478 }
00479 }
00480
00481
00482 i = (r2.x + r2.width) - (r1.x + r1.width);
00483 if(i >= 0) r1 = map[l1=AdvanceToNextRun(l1,map)];
00484 if(i <= 0) r2 = map[l2=AdvanceToNextRun(l2,map)];
00485 }
00486
00487
00488 i=0;
00489 #ifdef ENABLE_JOIN_NEARBY
00490 if(map[i].x==-1)
00491 i = map[i].next;
00492 #endif
00493 while(i<num) {
00494 j = map[i].parent;
00495 map[i].parent = map[j].parent;
00496
00497 i=AdvanceToNextRun(i,map);
00498 }
00499 }
00500
00501 template <class region_t,class rle_t>
00502 int ExtractRegions(region_t *reg,int max_reg,rle_t *rmap,int num)
00503
00504
00505
00506
00507
00508 {
00509 int b,i,n,a;
00510 rle_t r;
00511
00512 n = 0;
00513 i=0;
00514 #ifdef ENABLE_JOIN_NEARBY
00515 i=AdvanceToNextRun(i,rmap);
00516 #endif
00517 while(i<num) {
00518 if(rmap[i].color){
00519 r = rmap[i];
00520 if(r.parent == i){
00521
00522 rmap[i].parent = b = n;
00523 reg[b].color = r.color;
00524 reg[b].area = r.width;
00525 reg[b].x1 = r.x;
00526 reg[b].y1 = r.y;
00527 reg[b].x2 = r.x + r.width;
00528 reg[b].y2 = r.y;
00529 reg[b].cen_x = range_sum(r.x,r.width);
00530 reg[b].cen_y = r.y * r.width;
00531 reg[b].run_start = i;
00532 reg[b].iterator_id = i;
00533 n++;
00534 if(n >= max_reg) return(max_reg);
00535 }else{
00536
00537 b = rmap[r.parent].parent;
00538 rmap[i].parent = b;
00539 reg[b].area += r.width;
00540 reg[b].x2 = std::max(r.x + r.width,reg[b].x2);
00541 reg[b].x1 = std::min((int)r.x,reg[b].x1);
00542 reg[b].y2 = r.y;
00543 reg[b].cen_x += range_sum(r.x,r.width);
00544 reg[b].cen_y += r.y * r.width;
00545
00546 rmap[reg[b].iterator_id].next = i;
00547 reg[b].iterator_id = i;
00548 }
00549 }
00550
00551 i=AdvanceToNextRun(i,rmap);
00552 }
00553
00554
00555 i=0;
00556 #ifdef ENABLE_JOIN_NEARBY
00557 i=AdvanceToNextRun(i,rmap);
00558 #endif
00559 while(i<n) {
00560 a = reg[i].area;
00561 reg[i].cen_x = (float)reg[i].cen_x / a;
00562 reg[i].cen_y = (float)reg[i].cen_y / a;
00563 reg[i].iterator_id = 0;
00564 reg[i].x2--;
00565 i=AdvanceToNextRun(i,rmap);
00566 }
00567
00568 return(n);
00569 }
00570
00571 template <class color_class_state_t,class region_t>
00572 int SeparateRegions(color_class_state_t *color,int colors,
00573 region_t *reg,int num)
00574
00575
00576
00577
00578 {
00579 region_t *p;
00580 int i;
00581 int c;
00582 int area,max_area;
00583
00584
00585 for(i=0; i<colors; i++){
00586 color[i].list = NULL;
00587 color[i].num = 0;
00588 }
00589
00590
00591
00592 max_area = 0;
00593 for(i=0; i<num; i++){
00594 p = ®[i];
00595 c = p->color;
00596 area = p->area;
00597
00598 if(area >= color[c].min_area){
00599 if(area > max_area) max_area = area;
00600 color[c].num++;
00601 p->next = color[c].list;
00602 color[c].list = p;
00603 }
00604 }
00605
00606 return(max_area);
00607 }
00608
00609
00610
00611
00612
00613
00614 #define CMV_RBITS 6
00615 #define CMV_RADIX (1 << CMV_RBITS)
00616 #define CMV_RMASK (CMV_RADIX-1)
00617
00618 template <class region_t>
00619 region_t *SortRegionListByArea(region_t *list,int passes)
00620
00621
00622 {
00623 region_t *tbl[CMV_RADIX],*p,*pn;
00624 int slot,shift;
00625 int i,j;
00626
00627
00628 if(!list || !list->next) return(list);
00629
00630
00631 for(j=0; j<CMV_RADIX; j++) tbl[j] = NULL;
00632
00633 for(i=0; i<passes; i++){
00634
00635 shift = CMV_RBITS * i;
00636 p = list;
00637 while(p){
00638 pn = p->next;
00639 slot = ((p->area) >> shift) & CMV_RMASK;
00640 p->next = tbl[slot];
00641 tbl[slot] = p;
00642 p = pn;
00643 }
00644
00645
00646 list = NULL;
00647 for(j=0; j<CMV_RADIX; j++){
00648 p = tbl[j];
00649 tbl[j] = NULL;
00650 while(p){
00651 pn = p->next;
00652 p->next = list;
00653 list = p;
00654 p = pn;
00655 }
00656 }
00657 }
00658
00659 return(list);
00660 }
00661
00662 template <class color_class_state_t>
00663 void SortRegions(color_class_state_t *color,int colors,int max_area)
00664
00665
00666 {
00667 int i,p;
00668
00669
00670 p = (top_bit(max_area) + CMV_RBITS-1) / CMV_RBITS;
00671
00672
00673 for(i=0; i<colors; i++){
00674 color[i].list = SortRegionListByArea(color[i].list,p);
00675 }
00676 }
00677
00678
00679
00680
00681
00682 template<class region,class rle_t>
00683 void MergeRegions(region *p,region *q,region **q_prev_next,rle_t *runs) {
00684 int l,r,t,b;
00685 int a;
00686
00687
00688 l = std::min(p->x1,q->x1);
00689 r = std::max(p->x2,q->x2);
00690 t = std::min(p->y1,q->y1);
00691 b = std::max(p->y2,q->y2);
00692
00693
00694 a = p->area + q->area;
00695 p->x1 = l;
00696 p->x2 = r;
00697 p->y1 = t;
00698 p->y2 = b;
00699 p->cen_x = ((p->cen_x * p->area) + (q->cen_x * q->area)) / a;
00700 p->cen_y = ((p->cen_y * p->area) + (q->cen_y * q->area)) / a;
00701 p->area = a;
00702
00703
00704 int parent_run_idx;
00705 int p_run_idx,q_run_idx;
00706 rle_t *p_run,*q_run,*last_run;
00707
00708 last_run = NULL;
00709 p_run_idx = p->run_start;
00710 p_run = &runs[p_run_idx];
00711 parent_run_idx = p_run->parent;
00712 q_run_idx = q->run_start;
00713 q_run = &runs[q_run_idx];
00714
00715 if(p_run_idx == 0) {
00716 last_run = p_run;
00717 p_run_idx = p_run->next;
00718 p_run = &runs[p_run_idx];
00719 } else if(q_run_idx == 0) {
00720 p->run_start = q_run_idx;
00721 last_run = q_run;
00722 last_run->parent = parent_run_idx;
00723 q_run_idx = q_run->next;
00724 q_run = &runs[q_run_idx];
00725 }
00726
00727 if(p_run_idx!=0 &&
00728 (p_run_idx < q_run_idx || q_run_idx==0)) {
00729 if(last_run)
00730 last_run->next = p_run_idx;
00731 last_run = p_run;
00732 p_run_idx = p_run->next;
00733 p_run = &runs[p_run_idx];
00734 while(p_run_idx != 0 && p_run_idx < q_run_idx) {
00735 last_run = p_run;
00736 p_run_idx = p_run->next;
00737 p_run = &runs[p_run_idx];
00738 }
00739 } else {
00740 if(last_run)
00741 last_run->next = q_run_idx;
00742 else
00743 p->run_start = q_run_idx;
00744 last_run = q_run;
00745 last_run->parent = parent_run_idx;
00746 q_run_idx = q_run->next;
00747 q_run = &runs[q_run_idx];
00748 }
00749
00750
00751
00752
00753 while(q_run_idx!=0 && p_run_idx!=0) {
00754 if(p_run_idx < q_run_idx) {
00755 last_run->next = p_run_idx;
00756 last_run = p_run;
00757 p_run_idx = p_run->next;
00758 p_run = &runs[p_run_idx];
00759 } else {
00760 last_run->next = q_run_idx;
00761 last_run = q_run;
00762 last_run->parent = parent_run_idx;
00763 q_run_idx = q_run->next;
00764 q_run = &runs[q_run_idx];
00765 }
00766 }
00767
00768 if(p_run_idx != 0) {
00769 last_run->next = p_run_idx;
00770 }
00771 if(q_run_idx != 0) {
00772 do {
00773 last_run->next = q_run_idx;
00774 last_run = q_run;
00775 last_run->parent = parent_run_idx;
00776 q_run_idx = q_run->next;
00777 q_run = &runs[q_run_idx];
00778 } while(q_run_idx != 0);
00779 last_run->next = 0;
00780 }
00781
00782
00783 *q_prev_next = q->next;
00784 }
00785
00786 template<class region>
00787 void CalcXYBounds(region *p,double density_thresh,int area,int &xl,int &xh,int &yl,int& yh) {
00788 int a,l,r,t,b;
00789 int width,height;
00790 int xexp,yexp;
00791
00792 a = p->area;
00793 l = p->x1;
00794 r = p->x2;
00795 t = p->y1;
00796 b = p->y2;
00797
00798 width = r - l + 1;
00799 height = b - t + 1;
00800
00801
00802
00803 xexp = (int) ((a + area) / (density_thresh * height) - width);
00804
00805 xl = l - xexp;
00806 xh = r + xexp;
00807
00808
00809
00810 yexp = (int) ((a + area) / (density_thresh * width) - height);
00811
00812 yl = t - yexp;
00813 yh = b + yexp;
00814 }
00815
00816 template<class region,class rle_t>
00817 int MergeRegions(region *p,double density_thresh,rle_t *runs)
00818 {
00819 region *q,*s;
00820 int l,r,t,b;
00821 int a;
00822 int merged;
00823 int last_area;
00824 int xbl,xbh;
00825 int ybl,ybh;
00826
00827 merged = 0;
00828 last_area = 0;
00829
00830 while(p){
00831 q = p->next;
00832 s = p;
00833
00834 if(q) {
00835 CalcXYBounds(p,density_thresh,q->area,xbl,xbh,ybl,ybh);
00836 last_area = q->area;
00837 }
00838
00839 while(q){
00840 bool advance=true;
00841
00842 if(q->area > last_area) {
00843 CalcXYBounds(p,density_thresh,q->area,xbl,xbh,ybl,ybh);
00844 last_area = q->area;
00845 }
00846
00847 if(q->x1 >= xbl &&
00848 q->x2 <= xbh &&
00849 q->y1 >= ybl &&
00850 q->y2 <= ybh) {
00851
00852 l = std::min(p->x1,q->x1);
00853 r = std::max(p->x2,q->x2);
00854 t = std::min(p->y1,q->y1);
00855 b = std::max(p->y2,q->y2);
00856 a = (r-l+1) * (b-t+1);
00857
00858 CalcXYBounds(p,density_thresh,q->area,xbl,xbh,ybl,ybh);
00859 last_area = q->area;
00860
00861
00862 if((double)(p->area + q->area) / a > density_thresh){
00863
00864 MergeRegions(p,q,&s->next,runs);
00865
00866
00867 q = p->next;
00868 s = p;
00869 merged++;
00870 advance=false;
00871 }
00872 }
00873
00874 if(advance) {
00875 s = q;
00876 q = q->next;
00877 }
00878 }
00879 p = p->next;
00880 }
00881
00882 return(merged);
00883 }
00884
00885 template<class color_class_state_t,class rle_t>
00886 int MergeRegions(color_class_state_t *color,int colors,rle_t *runs)
00887 {
00888 int i,m;
00889 int num;
00890
00891 num = 0;
00892
00893 for(i=0; i<colors; i++){
00894 if(color[i].merge_threshold >= 1.0)
00895 m = 0;
00896 else
00897 m = MergeRegions(color[i].list,color[i].merge_threshold,runs);
00898 num += m;
00899 color[i].num -= m;
00900 }
00901
00902 return(num);
00903 }
00904
00905 template<class region, class rle_t>
00906 bool CheckRegions(region *p,rle_t *runs) {
00907 bool ok=true;
00908
00909 while(p && ok) {
00910 int area;
00911 int run_idx,next_run_idx;
00912 rle_t *currun,*next_run;
00913
00914 run_idx = p->run_start;
00915 currun = &runs[run_idx];
00916 area = 0;
00917
00918 do {
00919 area += currun->width;
00920
00921 if(currun->parent != runs[p->run_start].parent) {
00922 printf("wrong parent id on run %d (claims parent %d should be %d)\n",
00923 run_idx,currun->parent,runs[p->run_start].parent);
00924 ok = false;
00925 }
00926
00927 next_run_idx = currun->next;
00928 next_run = (next_run_idx!=0 ? &runs[next_run_idx] : NULL);
00929
00930 if(next_run_idx != 0 &&
00931 next_run_idx <= run_idx) {
00932 printf("failed to progress, going from run %d to run %d\n",run_idx,next_run_idx);
00933 ok = false;
00934 }
00935
00936 run_idx = next_run_idx;
00937 currun = next_run;
00938 } while(run_idx != 0 && ok);
00939
00940 if(p->area != area) {
00941 ok = false;
00942 printf("area mismatch, claimed %d actually %d\n",p->area,area);
00943 }
00944
00945 p = p->next;
00946 }
00947
00948 return ok;
00949 }
00950
00951 template<class color_class_state_t,class rle_t>
00952 bool CheckRegions(color_class_state_t *color,int colors,rle_t *runs) {
00953 bool ok=true;
00954 int i;
00955
00956 for(i=0; i<colors && ok; i++){
00957 ok = CheckRegions(color[i].list,runs);
00958 if(!ok) {
00959 printf("region check failed for color %d\n",i);
00960 }
00961 }
00962
00963 return(ok);
00964 }
00965
00966 template <class region_t,class rle_t>
00967 int FindStart(rle_t *rmap,int left,int right,int x,DummyT1<region_t> dummy=DummyT1<region_t>())
00968
00969
00970 {
00971 int m;
00972
00973 while(right > left){
00974 m = (left + right) / 2;
00975 if(x > rmap[m].x+rmap[m].width){
00976 left = m + 1;
00977 }else if(x < rmap[m].x){
00978 right = m;
00979 }else{
00980 return(m);
00981 }
00982 }
00983
00984 return(m);
00985 }
00986
00987 template <class rle_t>
00988 int FindStart(rle_t *rmap,int left,int right,int x,int y)
00989
00990
00991 {
00992 int m=0;
00993
00994 while(right > left){
00995 m = (left + right) / 2;
00996 if(y > rmap[m].y ||
00997 (y == rmap[m].y && x > rmap[m].x+rmap[m].width)){
00998 left = m + 1;
00999 }else if(y < rmap[m].y ||
01000 (y == rmap[m].y && x < rmap[m].x)){
01001 right = m;
01002 }else{
01003 return(m);
01004 }
01005 }
01006
01007 return(m);
01008 }
01009
01010 template <class region_t,class rle_t>
01011 void CreateRunIndex(int *yindex,rle_t *rmap,int num,DummyT1<region_t> dummy=DummyT1<region_t>())
01012
01013
01014
01015 {
01016 y = 0;
01017 yindex[y] = 0;
01018
01019 for(i=0; i<num; i++){
01020 if(rmap[i].y > y){
01021 y = rmap[i].y;
01022 yindex[y] = i;
01023 }
01024 }
01025 }
01026
01027 template <class color_class_state_t>
01028 void GetNextRegion(color_class_state_t *color,int colors,int max_area)
01029 {
01030
01031 }
01032
01033 template <class color_class_state_t>
01034 void CalcTotalArea(color_class_state_t *color)
01035 {
01036 region *cur_reg;
01037
01038 cur_reg = color->list;
01039 color->total_area = 0;
01040 while(cur_reg!=NULL) {
01041 color->total_area += cur_reg->area;
01042 cur_reg = cur_reg->next;
01043 }
01044 }
01045
01046 template <class color_class_state_t>
01047 void CalcTotalArea(color_class_state_t *color,int colors)
01048 {
01049 for(int i=0; i<colors; i++)
01050 CalcTotalArea(&color[i]);
01051 }
01052
01053 template <class data>
01054 int find(data *arr,int start,int end,data key)
01055 {
01056 int i;
01057
01058 for(i=start; i<end; i++){
01059 if(arr[i] == key) return(i);
01060 }
01061
01062 return(end);
01063 }
01064
01065 using namespace __gnu_cxx;
01066
01067 template <class color_class_state_t>
01068 int LoadColorInformation(color_class_state_t *color,int max,const char *filename, hash_map<const char*, unsigned int, hash<const char*>, hashcmp_eqstr> &color_names)
01069 {
01070 char buf[512];
01071 FILE *in;
01072 int len;
01073 int sl,sr;
01074 int num;
01075
01076 int idx,r,g,b,ms;
01077 float merge_threshold;
01078 char *name;
01079
01080
01081 in = fopen(filename,"rt");
01082 if(!in) return(0);
01083
01084 memset(color,0,sizeof(color_class_state_t)*max);
01085 num = 0;
01086
01087
01088 while(fgets(buf,256,in)){
01089
01090 len = strlen(buf) - 1;
01091 buf[len] = 0;
01092
01093 if(len && buf[0]!='#'){
01094 sl = find(buf, 0,len,'"');
01095 sr = find(buf,sl+1,len,'"');
01096 if(sl<len && sr<len){
01097 buf[sl] = buf[sr] = 0;
01098 idx = r = g = b = ms = 0;
01099 sscanf(buf,"%d (%d %d %d)",&idx,&r,&g,&b);
01100 name = buf+sl+1;
01101 merge_threshold = 1.0;
01102 sscanf(buf+sr+1,"%d %g",&ms,&merge_threshold);
01103
01104 if(idx>=0 && idx<max && ms>0){
01105 color[idx].min_area = ms;
01106 color[idx].merge_threshold = merge_threshold;
01107 color[idx].color.red = r;
01108 color[idx].color.green = g;
01109 color[idx].color.blue = b;
01110 color[idx].name = strdup(name);
01111 color_names[color[idx].name]=idx;
01112 if(idx >= num) num = idx+1;
01113 } else {
01114 printf("Options error: %2d (%3d %3d %3d) '%s' %d\n",
01115 idx,r,g,b,name,ms);
01116 }
01117 }
01118 }
01119 }
01120
01121 fclose(in);
01122
01123 return(num);
01124 }
01125
01126 }
01127
01128 #endif