SMIL  0.9.1
DBlob.hpp
1 /*
2  * Copyright (c) 2011-2016, Matthieu FAESSEL and ARMINES
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of Matthieu FAESSEL, or ARMINES nor the
14  * names of its contributors may be used to endorse or promote products
15  * derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 
30 #ifndef _D_BLOB_HPP
31 #define _D_BLOB_HPP
32 
33 #include "Core/include/private/DImage.hpp"
34 #include <map>
35 
36 namespace smil
37 {
38 
49  {
50  size_t offset;
51  size_t size;
52  PixelSequence() : offset(0), size(0) {}
53  ~PixelSequence() {}
54  PixelSequence(size_t off, size_t siz) : offset(off), size(siz) {}
55  };
56 
62  struct Blob
63  {
64  vector<PixelSequence> sequences;
65  typedef vector<PixelSequence>::iterator sequences_iterator;
66  typedef vector<PixelSequence>::const_iterator sequences_const_iterator;
67  typedef vector<PixelSequence>::const_reverse_iterator sequences_const_reverse_iterator;
68  };
69 
70 
74  template <class T>
75  map<T, Blob> computeBlobs(const Image<T> &imIn, bool onlyNonZero=true)
76  {
77  map<T, Blob> blobs;
78 
79  ASSERT(CHECK_ALLOCATED(&imIn), RES_ERR_BAD_ALLOCATION, blobs);
80 
81  typename ImDtTypes<T>::sliceType lines = imIn.getLines();
82  typename ImDtTypes<T>::lineType pixels;
83  size_t npix = imIn.getWidth();
84  size_t nlines = imIn.getLineCount();
85 
86  T curVal;
87 
88  for (size_t l=0;l<nlines;l++)
89  {
90  size_t curSize = 0;
91  size_t curStart = l*npix;
92 
93  pixels = lines[l];
94  curVal = pixels[0];
95  if (curVal!=0 || !onlyNonZero)
96  curSize++;
97 
98  for (size_t i=1;i<npix;i++)
99  {
100  if (pixels[i]==curVal)
101  curSize++;
102  else
103  {
104  if (curVal!=0 || !onlyNonZero)
105  blobs[curVal].sequences.push_back(PixelSequence(curStart, curSize));
106  curStart = i + l*npix;
107  curSize = 1;
108  curVal = pixels[i];
109  }
110  }
111  if (curVal!=0 || !onlyNonZero)
112  blobs[curVal].sequences.push_back(PixelSequence(curStart, curSize));
113 
114  }
115 
116  return blobs;
117  }
118 
124  template <class labelT, class T>
125  RES_T drawBlobs(map<labelT, Blob> &blobs, Image<T> &imOut, T blobsValue=ImDtTypes<T>::max(), bool fillFirst = true, T defaultValue=T(0))
126  {
127  ASSERT_ALLOCATED(&imOut);
128 
129  ImageFreezer freeze(imOut);
130 
131  if (fillFirst)
132  ASSERT(fill(imOut, defaultValue)==RES_OK);
133 
134  typename ImDtTypes<T>::lineType pixels = imOut.getPixels();
135  size_t pixCount = imOut.getPixelCount();
136  bool allBlobsFit = true;
137 
138  typename map<labelT, Blob>::const_iterator blob_it;
139  for (blob_it=blobs.begin();blob_it!=blobs.end();blob_it++)
140  {
141  // Verify that the blob can fit in the image
142  Blob::sequences_const_reverse_iterator last = blob_it->second.sequences.rbegin();
143  if ((*last).offset + (*last).size >= pixCount)
144  {
145  allBlobsFit = false;
146  }
147  else
148  {
149  Blob::sequences_const_iterator it = blob_it->second.sequences.begin();
150  Blob::sequences_const_iterator it_end = blob_it->second.sequences.end();
151 
152  T outVal = blobsValue!=defaultValue ? blobsValue : blob_it->first;
153  for (;it!=it_end;it++)
154  {
155  typename ImDtTypes<T>::lineType line = pixels + (*it).offset;
156  for (size_t i=0;i<it->size;i++)
157  line[i] = outVal;
158  }
159  }
160  }
161  imOut.modified();
162 
163  ASSERT(allBlobsFit, "Some blobs are outside the image", RES_ERR);
164 
165  return RES_OK;
166  }
167 
172  template <class labelT, class T>
173  RES_T drawBlobs(map<labelT, Blob> &blobs, map<labelT,T> &lut, Image<T> &imOut, bool fillFirst = true, T defaultValue=T(0))
174  {
175  ASSERT_ALLOCATED(&imOut);
176 
177  ImageFreezer freeze(imOut);
178 
179  if (fillFirst)
180  ASSERT(fill(imOut, defaultValue)==RES_OK);
181 
182  typename ImDtTypes<T>::lineType pixels = imOut.getPixels();
183  size_t pixCount = imOut.getPixelCount();
184  bool allBlobsFit = true;
185 
186  typename map<labelT, Blob>::const_iterator blob_it;
187  for (blob_it=blobs.begin();blob_it!=blobs.end();blob_it++)
188  {
189  // Verify that the blob can fit in the image
190  Blob::sequences_const_reverse_iterator last = blob_it->second.sequences.rbegin();
191  if ((*last).offset + (*last).size >= pixCount)
192  {
193  allBlobsFit = false;
194  }
195  else
196  {
197  Blob::sequences_const_iterator it = blob_it->second.sequences.begin();
198  Blob::sequences_const_iterator it_end = blob_it->second.sequences.end();
199 
200  typename map<labelT,T>::const_iterator valIt = lut.find(blob_it->first);
201  T outVal = valIt!=lut.end() ? valIt->second : defaultValue;
202  for (;it!=it_end;it++)
203  {
204  typename ImDtTypes<T>::lineType line = pixels + (*it).offset;
205  for (size_t i=0;i<it->size;i++)
206  line[i] = outVal;
207  }
208  }
209  }
210  imOut.modified();
211 
212  ASSERT(allBlobsFit, "Some blobs are outside the image", RES_ERR);
213 
214  return RES_OK;
215  }
216 
217 
218 
219 
220 // @}
221 
222 
223 } // namespace smil
224 
225 
226 #endif // _D_BASE_MEASURE_OPERATIONS_HPP
227 
RES_T drawBlobs(map< labelT, Blob > &blobs, map< labelT, T > &lut, Image< T > &imOut, bool fillFirst=true, T defaultValue=T(0))
Represent Blobs in an image with a lookup map.
Definition: DBlob.hpp:173
Definition: DColorConvert.h:38
sliceType getLines() const
Get an array containing the start offset of each line.
Definition: DImage.hpp:114
Definition: DBaseImage.h:235
map< T, Blob > computeBlobs(const Image< T > &imIn, bool onlyNonZero=true)
Create a map of Blob from a labelized image.
Definition: DBlob.hpp:75
lineType getPixels() const
Get the pixels as a 1D array.
Definition: DImage.hpp:110
Start offset and length of pixels in an image.
Definition: DBlob.hpp:48
RES_T fill(Image< T > &imOut, const T &value)
Fill an image with a given value.
Definition: DImageArith.hpp:62
List of offset and size of line contiguous pixels.
Definition: DBlob.hpp:62
virtual void modified()
Trigger modified event (allows to force display update)
Definition: DImage.hxx:223
size_t getWidth() const
Get image width.
Definition: DBaseImage.h:87
size_t getPixelCount() const
Get the number of pixels.
Definition: DBaseImage.h:150
Definition: DTypes.hpp:78
Main Image class.
Definition: DQVtkViewer.hpp:44
size_t getLineCount() const
Get the number of lines.
Definition: DBaseImage.h:154