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