OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimBitMaskTileSource.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 //
3 // License: LGPL
4 //
5 // See LICENSE.txt file in the top level directory for more details.
6 //
7 // Author: Oscar Kramer
8 //
9 // Description:
10 //
11 // Contains class definition for ossimBitMaskTileSource.
12 //*******************************************************************
13 // $Id: ossimBitMaskTileSource.cpp 2644 2011-05-26 15:20:11Z oscar.kramer $
14 
20 #include <ossim/base/ossimIrect.h>
24 #include <ossim/base/ossimTrace.h>
28 #include <cmath>
29 
30 RTTI_DEF1_INST(ossimBitMaskTileSource, "ossimBitMaskTileSource", ossimImageHandler);
31 
32 //*******************************************************************
33 // Public Constructor:
34 //*******************************************************************
36  :
38  m_tile(NULL)
39 {
40 }
41 
42 //*************************************************************************************************
43 // Destructor must free the buffers for each res level
44 //*************************************************************************************************
46 {
47  close();
48 }
49 
50 //*************************************************************************************************
51 // Reset
52 //*************************************************************************************************
54 {
55  ossimImageHandler::close(); // base class
56 
57  // Wipe the mask buffers:
58  vector<ossim_uint8*>::iterator iter = m_buffers.begin();
59  while (iter != m_buffers.end())
60  {
61  delete [] (*iter);
62  iter++;
63  }
64  m_buffers.clear();
65  m_bufferSizes.clear();
66  m_tile = NULL;
67 }
68 
69 //*************************************************************************************************
70 // Opens an OSSIM Bit Mask raster file. This is a custom formatted file with header info
71 //**************************************************************************************************
73 {
74  static const char MODULE[] = "ossimBitMaskTileSource::open()";
75 
76  if (!isSupportedExtension())
77  {
78  close();
79  return false;
80  }
81 
82  close();
83 
84  // Open the mask file and verify magic number, read header info as well and verify good values:
85  std::ifstream fileStream(theImageFile.chars(), ios::in|ios::binary);
86  if (!fileStream.good())
87  return false;
88  ossimString magic_number;
89  int num_res_levels = 0;
90  char space;
91  fileStream >> magic_number;
93  {
94  // This is a next-generation mask file with header:
95  fileStream >> theStartingResLevel >> num_res_levels;
96  for (int r=0; r<num_res_levels; r++)
97  {
98  ossimIpt buffer_size;
99  fileStream >> buffer_size.x >> buffer_size.y;
100  m_bufferSizes.push_back(buffer_size);
101  }
102  fileStream >> space;
103  }
104  else
105  {
106  // This is the old headerless "Ming mask" format. Need to query the source image for image size.
107  // This format implies a starting res level of 1:
108  if (!m_handler.valid())
109  {
111  << MODULE << " ERROR:\nInput file <"<<theImageFile<<"> has no header information and "
112  "no valid source image has been provided. Cannot process mask" << std::endl;
113  fileStream.close();
114  close();
115  return false;
116  }
118  num_res_levels = m_handler->getNumberOfDecimationLevels() - 1;
119  fileStream.seekg(0);
120 
121  // Need to compute buffer sizes since they are not available in the mask header:
122  ossimIpt image_size = m_handler->getBoundingRect(1).size();
123  ossimIpt buffer_size ((image_size.x+7)/8, image_size.y);
124  for (int r=0; r<num_res_levels; r++)
125  {
126  m_bufferSizes.push_back(buffer_size);
127  buffer_size.x = (buffer_size.x+1)/2;
128  buffer_size.y = (buffer_size.y+1)/2;
129  }
130  }
131 
132  if (m_bufferSizes.empty())
133  {
135  << MODULE << " ERROR:\nInput file <"<<theImageFile<<"> is not recognized or has invalid "
136  "header information." << std::endl;
137  fileStream.close();
138  close();
139  return false;
140  }
141 
142  // Good to go, Need to now establish sizes for and offsets to each res level:
143  for (int r=0; r<num_res_levels; ++r)
144  {
145  // Allocate buffer for this res level:
147  ossim_uint8* buffer = new ossim_uint8[size];
148  m_buffers.push_back((ossim_uint8*) buffer);
149 
150  // Read from disk:
151  fileStream.read((char*)buffer, size);
152  if (fileStream.fail())
153  {
155  << MODULE << " ERROR:"
156  << "\nError encountered reading mask file <" << theImageFile << ">"<<std::endl;
157  fileStream.close();
158  close();
159  return false;
160  }
161  }
162 
163  fileStream.close();
164 
165  // Allocate the mask tile. This will be 8-bits per pixel (i.e., decompressed):
167  m_tile->initialize();
168 
169  // Computes decimation factors for additional reduced res sets:
171 
172  return true;
173 }
174 
175 //**************************************************************************************************
176 // "Open" here means only that the mask buffers are valid and ready for access
177 //**************************************************************************************************
179 {
180  return ((m_buffers.size() != 0) || (m_maskWriter.valid()));
181 }
182 
183 //*******************************************************************
184 // Public method:
185 //*******************************************************************
187 {
188  ossimString ext = theImageFile.ext();
189  if (ext == "mask")
190  return true;
191 
192  return false;
193 }
194 
195 //*************************************************************************************************
196 // Unpacks the mask data into a destination tile
197 //*************************************************************************************************
199  ossim_uint32 resLevel)
200 {
201  static const ossim_uint8 MASK_BITS[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
202 
203  // Allocate the mask tile. This will be 8-bits per pixel (i.e., decompressed):
204  if (!m_tile.valid())
205  {
207  m_tile->initialize();
208  }
209 
210  // Initial screening:
211  if (!(isOpen() && isSourceEnabled() && isValidRLevel(resLevel)))
212  return NULL;
213 
214  // Check if requested rect falls inside valid mask area:
215  if (!getImageRectangle(resLevel).intersects(tile_rect))
216  return NULL;
217 
218  // Check if tile size matches requested size:
219  if ((m_tile->getWidth() != tile_rect.width()) || (m_tile->getHeight() != tile_rect.height()))
220  {
221  m_tile->setWidthHeight(tile_rect.width(), tile_rect.height());
222  m_tile->initialize();
223  }
224  m_tile->setImageRectangle(tile_rect);
225 
226  // Start with blank tile if rect partially intersects defined mask area:
227  ossimIrect image_rect (getImageRectangle(resLevel));
228  if (!tile_rect.completely_within(image_rect))
229  m_tile->makeBlank();
230 
231  //##### START DEBUG CODE #########################
232  // This else if identifies unassigned mask pixels being returned by this method incorrectly.
233  // See ossimMaskFilter::executeMaskFilterSelection() (OLK 2/11)
234  //m_tile->fill(128.0);//###
235  //##### END DEBUG CODE #########################
236 
237  ossimIpt image_size (image_rect.size());
238  ossim_uint32 num_mask_cols = (image_size.x+7)/8;
239  ossim_uint8* tilebuf = (ossim_uint8*) m_tile->getBuf(0);
240  ossim_uint32 tile_index = 0, mask_index = 0, start_bit=0;
241  ossimIpt ul (tile_rect.ul());
242  ossimIpt lr (tile_rect.lr());
243 
244  // Decide if we use our own mask buffer (read from file) or borrow tha active mask writer's
245  // buffer:
246  ossim_uint8* maskbuf;
247  if (m_maskWriter.valid())
248  maskbuf = m_maskWriter->m_buffers[resLevel-theStartingResLevel];
249  else
250  maskbuf = m_buffers[resLevel-theStartingResLevel];
251 
252  // Nested loop to fill tile:
253  for (int y=ul.y; (y<=lr.y)&&(y<image_size.y); y++)
254  {
255  mask_index = y*num_mask_cols + ul.x/8;
256  start_bit = ul.x % 8; // may not start on even mask byte boundary
257  for (int x=ul.x; x<=lr.x;)
258  {
259  if (x < image_size.x)
260  {
261  // fetch mask pixel and isolate bit of interest:
262  for (ossim_uint32 mask_bit=start_bit; mask_bit<8; ++mask_bit)
263  {
264  if (maskbuf[mask_index] & MASK_BITS[mask_bit])
265  tilebuf[tile_index++] = 255;
266  else
267  tilebuf[tile_index++] = 0;
268 
269  // Advance the pixel column and check for end of image rect:
270  ++x;
271  if ((x >= image_size.x) || (x>lr.x))
272  break;
273  }
274 
275  ++mask_index; // advance the mask buffer index 1 after processing 8 tile samples
276  start_bit = 0;
277  }
278  else
279  {
280  // Tile buffer extends beyond valid mask rect, so assume it is masked (0):
281  tilebuf[tile_index++] = 0;
282  ++x;
283  }
284  }
285  }
286 
287  m_tile->validate();
288  return m_tile;
289 }
290 
291 //*******************************************************************
292 // Argument res_Level is relative to the full image
293 //*******************************************************************
295 {
296  ossim_uint32 num_rlevels;
297  if (m_maskWriter.valid())
298  num_rlevels = (ossim_uint32) m_maskWriter->m_buffers.size();
299  else
300  num_rlevels = (ossim_uint32) m_buffers.size();
301 
302  return ((res_Level >= theStartingResLevel) &&
303  ((res_Level-theStartingResLevel) < num_rlevels));
304 }
305 
306 //*******************************************************************
307 // Public method:
308 //*******************************************************************
310 {
311  if (!isValidRLevel(res_Level))
312  return 0;
313 
314  if (m_maskWriter.valid())
315  return m_maskWriter->m_bufferSizes[res_Level-theStartingResLevel].y;
316 
317  return m_bufferSizes[res_Level-theStartingResLevel].y;
318 }
319 
320 //*******************************************************************
321 // Public method:
322 //*******************************************************************
324 {
325  if (!isValidRLevel(res_Level))
326  return 0;
327 
328  ossim_uint32 n = 0;
329  if (m_maskWriter.valid())
331  else
332  n = m_bufferSizes[res_Level-theStartingResLevel].x;
333 
334  return n*8; // 8 pixels represented in one mask byte entry
335 }
336 
338 {
339  return 0;
340 }
341 
342 //*******************************************************************
344 //*******************************************************************
346 {
347  return (ossim_uint32) theDecimationFactors.size();
348 }
349 
350 //*******************************************************************
352 //*******************************************************************
354 {
355  theDecimationFactors.clear();
356  ossim_uint32 num_res_levels = (ossim_uint32) m_buffers.size();
357  ossimDpt decimation(1, 1);
358  for (ossim_uint32 r=0; r<num_res_levels; r++)
359  {
360  theDecimationFactors.push_back(decimation);
361  decimation = decimation/2.0;
362  }
363 }
364 
365 //*************************************************************************************************
369 //*************************************************************************************************
371 {
372  m_maskWriter = maskWriter;
373  if (m_maskWriter.valid())
375 }
376 
377 //*************************************************************************************************
380 //*************************************************************************************************
382 {
383  m_handler = handler;
384 }
385 
virtual ossim_uint32 getWidth() const
ossim_uint32 x
virtual bool isSourceEnabled() const
Definition: ossimSource.cpp:79
RTTI_DEF1_INST(ossimGeneralRasterTileSource, "ossimGeneralRasterTileSource", ossimImageHandler) static ossimTrace traceDebug("ossimGeneralRasterTileSource for(ossim_uint32 i=0;i< aList.size();++i)
ossimFilename theImageFile
virtual void setImageRectangle(const ossimIrect &rect)
RTTI_DEF1_INST(ossimBitMaskTileSource, "ossimBitMaskTileSource", ossimImageHandler)
virtual void setWidthHeight(ossim_uint32 w, ossim_uint32 h)
vector< ossimIpt > m_bufferSizes
ossim_uint32 y
ossim_uint32 m_startingResLevel
std::basic_ifstream< char > ifstream
Class for char input file streams.
Definition: ossimIosFwd.h:44
bool valid() const
Definition: ossimRefPtr.h:75
std::vector< ossimDpt > theDecimationFactors
static const char * MASK_FILE_MAGIC_NUMBER
ossim_uint32 height() const
Definition: ossimIrect.h:487
ossimRefPtr< ossimImageHandler > m_handler
For backward compatibility with older mask format ("Ming Mask"), provide for associating the mask wit...
virtual ossimRefPtr< ossimImageData > getTile(const ossimIrect &tile_rect, ossim_uint32 rLevel=0)
Return a tile of masks.
const ossimIpt & ul() const
Definition: ossimIrect.h:274
virtual ossim_uint32 getHeight() const
bool isSupportedExtension()
Returns true if this handler recognizes the file name extension as an OSSIM raster mask file...
vector< ossim_uint8 * > m_buffers
ossimIpt size() const
Definition: ossimIrect.h:510
virtual void initialize()
Initialize the data buffer.
virtual ossim_uint32 getNumberOfDecimationLevels() const
This returns the total number of decimation levels.
bool completely_within(const ossimIrect &rect) const
Definition: ossimIrect.cpp:425
static ossimImageDataFactory * instance()
vector< ossimIpt > m_bufferSizes
yy_size_t size
virtual ossimDataObjectStatus validate() const
os2<< "> n<< " > nendobj n
virtual void close()
Deletes the overview and clears the valid image vertices.
unsigned int ossim_uint32
const char * chars() const
For backward compatibility.
Definition: ossimString.h:77
This is the image handler for providing mask pixels to an ossimMaskFilter object. ...
virtual bool open()
Pure virtual open.
void setAssociatedMaskWriter(ossimBitMaskWriter *maskWriter)
This class can be used during overview generation, in which case there will be a simultaneous mask wr...
const ossimIpt & lr() const
Definition: ossimIrect.h:276
virtual void close()
Deletes the overview and clears the valid image vertices.
Class for computing a mask from an input image source and writing the mask file to disk...
virtual ossimIrect getImageRectangle(ossim_uint32 resLevel=0) const
Returns zero-based bounding rectangle of the image.
virtual ossimRefPtr< ossimImageData > create(ossimSource *owner, ossimScalarType scalar, ossim_uint32 bands=1) const
ossim_uint32 width() const
Definition: ossimIrect.h:500
virtual void makeBlank()
Initializes data to null pixel values.
ossimRefPtr< ossimImageData > m_tile
virtual ossimRefPtr< ossimImageGeometry > getImageGeometry()
There is no geometry associated with a mask file – it is pixel-for-pixel mapped to an image file...
This class defines an abstract Handler which all image handlers(loaders) should derive from...
ossimRefPtr< ossimBitMaskWriter > m_maskWriter
This class can be used during overview generation, in which case there will be a simultaneous mask wr...
ossim_int32 y
Definition: ossimIpt.h:142
virtual ossim_uint32 getNumberOfDecimationLevels() const
Overrides base class implementation.
virtual const void * getBuf() const
virtual ossim_uint32 getNumberOfSamples(ossim_uint32 res_level=0) const
Pure virtual, derived classes must implement.
virtual void establishDecimationFactors()
Overrides base class implementation.
virtual ossim_uint32 getNumberOfLines(ossim_uint32 res_level=0) const
Pure virtual, derived classes must implement.
ossimString ext() const
virtual bool isOpen() const
Derived classes must implement this method to be concrete.
virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0) const
Returns zero-based bounding rectangle of the image.
ossim_int32 x
Definition: ossimIpt.h:141
vector< ossim_uint8 * > m_buffers
virtual bool isValidRLevel(ossim_uint32 res_level) const
Determines if the passed in reslution level is valid.
unsigned char ossim_uint8
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
ossim_uint32 theStartingResLevel
theStartingResLevel If set to something other than zero(default) this is indicative that the reader i...
void setAssociatedImageHandler(ossimImageHandler *handler)
For backward compatibility with older mask format ("Ming Mask"), provide for associating the mask wit...