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