OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimRectanglePartitioner.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2004 David Burken, all rights reserved.
3 //
4 // License: LGPL
5 //
6 // See LICENSE.txt file in the top level directory for more details.
7 //
8 // Author: David Burken
9 //
10 // Description:
11 // Utility class to partition up a rectangle.
12 //
13 // $Id: ossimRectanglePartitioner.cpp 9094 2006-06-13 19:12:40Z dburken $
14 //----------------------------------------------------------------------------
15 
17 #include <ossim/base/ossimIrect.h>
19 #include <ossim/base/ossimTrace.h>
20 using namespace std;
21 
22 static ossimTrace traceDebug("ossimRectanglePartitioner:debug");
23 
25 {
26 }
27 
29 {
30 }
31 
33  const ossimIrect& inputRectangle,
34  vector<ossimIrect>& result,
35  ossim_uint64 maxSizeInBytes,
36  ossim_uint32 bands,
37  ossim_uint32 bytesPerPixel,
38  ossim_uint32 internalOverlapPixels) const
39 {
40  // Clear the result rect for starters.
41  result.clear();
42 
43  // Some sanity checks.
44  if (maxSizeInBytes == 0)
45  {
47  << "Waning: 0 passed for max size in bytes. Returning..."
48  << endl;
49  return;
50  }
51  if (bands == 0)
52  {
54  << "Waning: 0 passed for number of bands. Returning..."
55  << endl;
56  return;
57  }
58  if (bytesPerPixel == 0)
59  {
61  << "Waning: 0 passed for bytes per pixel. Returning..."
62  << endl;
63  return;
64  }
65  if (inputRectangle.hasNans())
66  {
68  << "Waning: Input rectangle has nans in it! Returning..."
69  << endl;
70  return;
71  }
72  if ( (maxSizeInBytes / (bands*bytesPerPixel)) < 4)
73  {
74  // Come on now you have to have at least four pixels.
76  << "Waning: Max size in bytes too small. Returning..."
77  << endl;
78  return;
79  }
80  // End of sanity checks...
81 
82  // Check the size... We could already be there.
83  if (getSize(inputRectangle, bands, bytesPerPixel) <= maxSizeInBytes)
84  {
85  result.push_back(inputRectangle);
86 
87  if (traceDebug())
88  {
89  trace(inputRectangle, result, maxSizeInBytes, bands, bytesPerPixel);
90  }
91 
92  return;
93  }
94 
95  // OK, find the rectangle size that gets that will fit the max size.
96  ossimIrect tileRect = inputRectangle;
97 
98  splitUntilLessThanMax(tileRect,
99  maxSizeInBytes,
100  bands,
101  bytesPerPixel,
102  internalOverlapPixels);
103 
104  ossim_int32 input_width = static_cast<ossim_int32>(inputRectangle.width());
105  ossim_int32 input_height = static_cast<ossim_int32>(inputRectangle.height());
106 
107  ossim_int32 tile_width = static_cast<ossim_int32>(tileRect.width());
108  ossim_int32 tile_height = static_cast<ossim_int32>(tileRect.height());
109 
110  ossim_int32 tiles_wide = (input_width % tile_width) ?
111  ( (input_width/tile_width)+1) : (input_width/tile_width);
112  ossim_int32 tiles_high = (input_height % tile_height) ?
113  ( (input_height/tile_height)+1) : (input_height/tile_height);
114 
115  ossim_int32 y_start = inputRectangle.ul().y;
116  ossim_int32 y_stop = y_start + tile_height - 1 + internalOverlapPixels;
117 
118  for (ossim_int32 y = 0; y < tiles_high; ++y)
119  {
120  // Clip to bottom if needed.
121  if (y_stop > inputRectangle.lr().y)
122  {
123  y_stop = inputRectangle.lr().y;
124  }
125 
126  ossim_int32 x_start = inputRectangle.ul().x;
127  ossim_int32 x_stop = x_start + tile_width - 1 + internalOverlapPixels;
128 
129  for (ossim_int32 x = 0; x < tiles_wide; ++x)
130  {
131  // Clip to right edge is needed.
132  if (x_stop > inputRectangle.lr().x)
133  {
134  x_stop = inputRectangle.lr().x;
135  }
136 
137  ossimIrect r(x_start, y_start, x_stop, y_stop);
138 
139  // Add it to the result.
140  result.push_back(r);
141 
142  if( 0 == x )
143  {
144  x_start += tile_width - internalOverlapPixels;
145  }
146  else
147  {
148  x_start += tile_width;
149  }
150  x_stop += tile_width;
151 
152  } // End of tiles_wide loop.
153 
154  if( 0 == y )
155  {
156  y_start += tile_height - internalOverlapPixels;
157  }
158  else
159  {
160  y_start += tile_height;
161  }
162  y_stop += tile_height;
163 
164  } // End of tiles_high loop.
165 
166  if (traceDebug())
167  {
168  trace(inputRectangle, result, maxSizeInBytes, bands, bytesPerPixel);
169  }
170 }
171 
173  ossimIrect& rect,
174  ossim_uint64 maxSizeInBytes,
175  ossim_uint32 bands,
176  ossim_uint32 bytesPerPixel,
177  ossim_uint32 internalOverlapPixels) const
178 {
179  do
180  {
181  splitRect(rect);
182 
183  } while ( getSize(rect,
184  bands,
185  bytesPerPixel,
186  internalOverlapPixels) > maxSizeInBytes );
187 }
188 
190 {
191  ossim_int32 width = static_cast<ossim_int32>(rect.width());
192  ossim_int32 height = static_cast<ossim_int32>(rect.height());
193  ossim_int32 new_width;
194  ossim_int32 new_height;
195 
196  if (height > width)
197  {
198  new_width = width;
199  new_height = (height % 2) ? ( (height/2) + 1 ) : (height/2);
200  }
201  else
202  {
203  new_width = (width % 2) ? ( (width/2) + 1) : (width/2);
204  new_height = height;
205  }
206 
207  rect = ossimIrect(0, 0, new_width-1, new_height-1);
208 }
209 
211  const ossimIrect& rect,
212  ossim_uint32 bands,
213  ossim_uint32 bytesPerPixel,
214  ossim_uint32 internalOverlapPixels) const
215 {
216  return( ( rect.width() + 2 * internalOverlapPixels ) *
217  ( rect.height() + 2 * internalOverlapPixels ) *
218  bands * bytesPerPixel );
219 }
220 
222  const std::vector<ossimIrect>& v,
223  ossim_uint64 maxSizeInBytes,
224  ossim_uint32 bands,
225  ossim_uint32 bytesPerPixel) const
226 {
228  << "ossimRectanglePartitioner DEBUG:"
229  << "\nInput rectangle: " << r
230  << "\nInput rectangle byte size: " << getSize(r, bands, bytesPerPixel)
231  << "\nTile max size in bytes: " << maxSizeInBytes
232  << "\nbands: " << bands
233  << "\nbytesPerPixel: " << bytesPerPixel
234  << "\nNumber of output tiles: " << v.size()
235  << "\nTiled rectangles:\n";
236 
237  int index = 0;
238  vector<ossimIrect>::const_iterator i = v.begin();
239  while(i != v.end())
240  {
242  << "tile[" << index << "]: " << *i
243  << "\nsize in bytes: " << getSize(*i, bands, bytesPerPixel)
244  << endl;
245  ++i;
246  ++index;
247  }
248 }
ossim_uint32 x
ossim_uint32 y
ossimRectanglePartitioner()
default construtor
ossim_uint64 getSize(const ossimIrect &rect, ossim_uint32 bands, ossim_uint32 bytesPerPixel, ossim_uint32 internalOverlapPixels=0) const
ossim_uint32 height() const
Definition: ossimIrect.h:487
const ossimIpt & ul() const
Definition: ossimIrect.h:274
ossimIpt size() const
Definition: ossimIrect.h:510
void trace(const ossimIrect &r, const std::vector< ossimIrect > &v, ossim_uint64 maxSizeInBytes, ossim_uint32 bands, ossim_uint32 bytesPerPixel) const
Convenience trace method.
void splitUntilLessThanMax(ossimIrect &rect, ossim_uint64 maxSizeInBytes, ossim_uint32 bands, ossim_uint32 bytesPerPixel, ossim_uint32 internalOverlapPixels=0) const
Recursively splits the input rectangle until the size is less than or equal to maxSizeInBytes.
unsigned long long ossim_uint64
unsigned int ossim_uint32
void splitRect(ossimIrect &rect) const
Splits rectangle in half rounding up if needed.
const ossimIpt & lr() const
Definition: ossimIrect.h:276
ossim_uint32 width() const
Definition: ossimIrect.h:500
void binaryPartition(const ossimIrect &inputRectangle, std::vector< ossimIrect > &result, ossim_uint64 maxSizeInBytes, ossim_uint32 bands, ossim_uint32 bytesPerPixel, ossim_uint32 internalOverlapPixels=0) const
Partitions the rectangle doing a binary split on the longest dimension until the total size is less t...
ossim_int32 y
Definition: ossimIpt.h:142
bool hasNans() const
Definition: ossimIrect.h:337
ossim_int32 x
Definition: ossimIpt.h:141
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
int ossim_int32