Fix corruption bug with 8x8 bilinear sub-pixel positioning option
[xy_vsfilter.git] / src / dsutil / xy_utils.cpp
blob38d3b7caa4cfbad2908aa983e0e8819528f9cbd3
1 #include "stdafx.h"
2 #include "xy_utils.h"
3 #include <vector>
4 #include <algorithm>
6 void MergeRects(const CAtlList<CRect>& input, CAtlList<CRect>* output)
8 if(output==NULL || input.GetCount()==0)
9 return;
11 struct Segment
13 int top, bottom;
14 int seg_start, seg_end;
15 CAtlList<CRect>* rects;
17 Segment()
19 rects = NULL;
21 ~Segment()
23 delete rects;
27 struct BreakPoint
29 int x;
30 const RECT* rect;
32 inline bool operator<(const BreakPoint& breakpoint ) const
34 return (x < breakpoint.x);
38 int input_count = input.GetCount();
39 std::vector<int> vertical_breakpoints(2*input_count);
40 std::vector<BreakPoint> herizon_breakpoints(input_count + 1);
42 POSITION pos = input.GetHeadPosition();
43 for(int i=0; i<input_count; i++)
45 const CRect& rect = input.GetNext(pos);
46 vertical_breakpoints[2*i]=rect.top;
47 vertical_breakpoints[2*i+1]=rect.bottom;
49 herizon_breakpoints[i].x = rect.left;
50 herizon_breakpoints[i].rect = &rect;
52 CRect sentinel_rect(INT_MAX, 0, INT_MAX, INT_MAX);
53 herizon_breakpoints[input_count].x = INT_MAX;//sentinel
54 herizon_breakpoints[input_count].rect = &sentinel_rect;
56 std::sort(vertical_breakpoints.begin(), vertical_breakpoints.end());
57 std::sort(herizon_breakpoints.begin(), herizon_breakpoints.end());
59 std::vector<Segment> tempSegments(vertical_breakpoints.size()-1);
60 int ptr = 1, prev = vertical_breakpoints[0], count = 0;
61 for(int i = vertical_breakpoints.size()-1; i > 0; i--, ptr++)
63 if(vertical_breakpoints[ptr] != prev)
65 Segment& seg = tempSegments[count];
66 seg.top = prev;
67 seg.bottom = vertical_breakpoints[ptr];
68 seg.seg_end = seg.seg_start = INT_MIN;//important! cannot use =0
69 seg.rects = new CAtlList<CRect>();
71 prev = vertical_breakpoints[ptr];
72 count++;
76 for(int i=0; i<=input_count; i++)
78 const CRect& rect = *herizon_breakpoints[i].rect;
80 int start = 0, mid, end = count;
82 while(start<end)
84 mid = (start+end)>>1;
85 if(tempSegments[mid].top < rect.top)
87 start = mid+1;
89 else
91 end = mid;
94 for(; start < count && tempSegments[start].bottom <= rect.bottom; start++)
96 if(tempSegments[start].seg_end<rect.left)
98 CRect out_rect( tempSegments[start].seg_start, tempSegments[start].top, tempSegments[start].seg_end, tempSegments[start].bottom );
99 tempSegments[start].rects->AddTail( out_rect );
100 tempSegments[start].seg_start = rect.left;
101 tempSegments[start].seg_end = rect.right;
103 else if( tempSegments[start].seg_end<rect.right )
105 tempSegments[start].seg_end=rect.right;
109 for (int i=count-1;i>0;i--)
111 CAtlList<CRect>& cur_line = *tempSegments[i].rects;
112 CRect cur_rect = cur_line.RemoveTail();
113 if(tempSegments[i].top == tempSegments[i-1].bottom)
115 CAtlList<CRect>& upper_line = *tempSegments[i-1].rects;
117 POSITION pos = upper_line.GetTailPosition();
118 while(pos)
120 CRect& upper_rect = upper_line.GetPrev(pos);
121 while( upper_rect.right<cur_rect.right || upper_rect.left<cur_rect.left )
123 output->AddHead(cur_rect);
124 //if(!cur_line.IsEmpty())
125 cur_rect = cur_line.RemoveTail();
127 if(cur_line.IsEmpty())
128 break;
130 if(upper_rect.right==cur_rect.right && upper_rect.left==cur_rect.left)
132 upper_rect.bottom = cur_rect.bottom;
133 //if(!cur_line.IsEmpty())
134 cur_rect = cur_line.RemoveTail();
136 //else if ( upper_rect.right>cur_rect.right || upper_rect.left>cur_rect.left )
139 while(!cur_line.IsEmpty())
141 output->AddHead(cur_rect);
142 cur_rect = cur_line.RemoveTail();
145 if(count>0)
147 CAtlList<CRect>& cur_line = *tempSegments[0].rects;
148 CRect cur_rect = cur_line.RemoveTail();
149 while(!cur_line.IsEmpty())
151 output->AddHead(cur_rect);
152 cur_rect = cur_line.RemoveTail();