OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimBumpShadeTileSource.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 // Copyright (C) 2000 ImageLinks Inc.
3 //
4 // License: LGPL
5 //
6 // See LICENSE.txt file in the top level directory for more details.
7 //
8 // Author: Garrett Potts
9 //
10 //*************************************************************************
11 // $Id: ossimBumpShadeTileSource.cpp 23165 2015-02-24 18:01:52Z dburken $
12 
25 
26 static const char COLOR_RED_KW[] = "color_red";
27 static const char COLOR_GREEN_KW[] = "color_green";
28 static const char COLOR_BLUE_KW[] = "color_blue";
29 
31  "ossimBumpShadeTileSource",
33 
34 
36  :ossimImageCombiner(0, 2, 0, true, false),
37  m_tile(0),
38  m_lightSourceElevationAngle(45.0),
39  m_lightSourceAzimuthAngle(45.0),
40  m_lightDirection(3),
41  m_r(255),
42  m_g(255),
43  m_b(255)
44 {
45  initialize();
46 }
47 
49 {
50 }
51 
53  const ossimIrect& tileRect,
54  ossim_uint32 resLevel)
55 {
56  if (!getInput(0))
57  return 0;
58 
59  if(!m_tile.get())
60  {
61  allocate();
62  }
63  if(!m_tile.valid())
64  {
65  return m_tile;
66  }
67 
68  m_tile->setImageRectangle(tileRect);
69  m_tile->initialize();
70  getTile(m_tile.get(), resLevel);
71  return m_tile;
72 
73 }
74 
76 {
77  if (!getInput(0) || !tile) return false;
78  if(!isSourceEnabled()) return true;
79 
80  tile->makeBlank();
81 
82  ossimIrect tileRect = tile->getImageRectangle();
84  ossimRefPtr<ossimImageData> colorData = 0;
85  if(colorSource)
86  {
87  colorData = new ossimImageData(colorSource, colorSource->getOutputScalarType(),
88  colorSource->getNumberOfOutputBands(),
89  tile->getWidth(), tile->getHeight());
90 
91  // Caution: Must set rect prior to getTile:
92  colorData->setImageRectangle(tileRect);
93 
94  colorSource->getTile(colorData.get(), resLevel);
95  }
96 
98  ossimRefPtr<ossimImageData> normalData =
99  new ossimImageData(normalSource, normalSource->getOutputScalarType(),
100  normalSource->getNumberOfOutputBands(),
101  tile->getWidth(), tile->getHeight());
102 
103  // Caution: Must set rect prior to getTile:
104  normalData->setImageRectangle(tileRect);
105 
106  normalSource->getTile(normalData.get(), resLevel);
108  if ((status == OSSIM_NULL) || (status == OSSIM_EMPTY) ||
109  (normalData->getNumberOfBands() != 3) ||
110  (normalData->getScalarType() != OSSIM_DOUBLE))
111  {
112  return false;
113  }
114 
115  ossim_float64* normalBuf[3];
116  normalBuf[0] = static_cast<ossim_float64*>(normalData->getBuf(0));
117  normalBuf[1] = static_cast<ossim_float64*>(normalData->getBuf(1));
118  normalBuf[2] = static_cast<ossim_float64*>(normalData->getBuf(2));
119  ossim_float64 normalNp = normalData->getNullPix(0);
120 
121  //---
122  // If we have some color data then use it for the bump
123  // else we will default to a grey scale bump shade.
124  //---
125  if ( colorData.get() &&
126  (colorData->getDataObjectStatus() != OSSIM_EMPTY) &&
127  (colorData->getDataObjectStatus() != OSSIM_NULL) )
128  {
129  switch(colorData->getScalarType())
130  {
131  case OSSIM_UCHAR:
132  {
133  ossim_uint8* resultBuf[3];
134  ossim_uint8* colorBuf[3];
135  resultBuf[0] = static_cast<ossim_uint8*>(tile->getBuf(0));
136  resultBuf[1] = static_cast<ossim_uint8*>(tile->getBuf(1));
137  resultBuf[2] = static_cast<ossim_uint8*>(tile->getBuf(2));
138  colorBuf[0] = static_cast<ossim_uint8*>(colorData->getBuf(0));
139  if(colorData->getBuf(1))
140  {
141  colorBuf[1] = static_cast<ossim_uint8*>(colorData->getBuf(1));
142  }
143  else
144  {
145  colorBuf[1] = colorBuf[0];
146  }
147  if(colorData->getBuf(2))
148  {
149  colorBuf[2] = static_cast<ossim_uint8*>(colorData->getBuf(2));
150  }
151  else
152  {
153  colorBuf[2] = colorBuf[0];
154  }
155 
156  long h = m_tile->getHeight();
157  long w = m_tile->getWidth();
158  for(long y = 0; y < h; ++y)
159  {
160  for(long x = 0; x < w; ++x)
161  {
162  if((*normalBuf[0] != normalNp) &&
163  (*normalBuf[1] != normalNp) &&
164  (*normalBuf[2] != normalNp) )
165  {
166  if((*colorBuf[0])||(*colorBuf[1])||(*colorBuf[2]))
167  {
168  computeColor(*resultBuf[0],
169  *resultBuf[1],
170  *resultBuf[2],
171  *normalBuf[0],
172  *normalBuf[1],
173  *normalBuf[2],
174  *colorBuf[0],
175  *colorBuf[1],
176  *colorBuf[2]);
177  }
178  else
179  {
180  computeColor(*resultBuf[0],
181  *resultBuf[1],
182  *resultBuf[2],
183  *normalBuf[0],
184  *normalBuf[1],
185  *normalBuf[2],
186  m_r,
187  m_g,
188  m_b);
189  }
190  }
191  else
192  {
193  *resultBuf[0] = *colorBuf[0];
194  *resultBuf[1] = *colorBuf[1];
195  *resultBuf[2] = *colorBuf[2];
196  }
197  resultBuf[0]++;
198  resultBuf[1]++;
199  resultBuf[2]++;
200  colorBuf[0]++;
201  colorBuf[1]++;
202  colorBuf[2]++;
203  normalBuf[0]++;
204  normalBuf[1]++;
205  normalBuf[2]++;
206  }
207  }
208  break;
209  }
210  default:
211  {
213  << "ossimBumpShadeTileSource::getTile NOTICE:\n"
214  << "only 8-bit unsigned char is supported." << endl;
215  }
216  }
217  }
218  else
219  {
220  ossim_uint8* resultBuf[3];
221  resultBuf[0] = static_cast<ossim_uint8*>(tile->getBuf(0));
222  resultBuf[1] = static_cast<ossim_uint8*>(tile->getBuf(1));
223  resultBuf[2] = static_cast<ossim_uint8*>(tile->getBuf(2));
224  long h = tile->getHeight();
225  long w = tile->getWidth();
226  for(long y = 0; y < h; ++y)
227  {
228  for(long x = 0; x < w; ++x)
229  {
230  if((*normalBuf[0] != normalNp) &&
231  (*normalBuf[1] != normalNp) &&
232  (*normalBuf[2] != normalNp) )
233  {
234  computeColor(*resultBuf[0],
235  *resultBuf[1],
236  *resultBuf[2],
237  *normalBuf[0],
238  *normalBuf[1],
239  *normalBuf[2],
240  m_r,
241  m_g,
242  m_b);
243  }
244  else
245  {
246  *resultBuf[0] = 0;
247  *resultBuf[1] = 0;
248  *resultBuf[2] = 0;
249  }
250  resultBuf[0]++;
251  resultBuf[1]++;
252  resultBuf[2]++;
253  normalBuf[0]++;
254  normalBuf[1]++;
255  normalBuf[2]++;
256  }
257  }
258  }
259 
260  tile->validate();
261  return true;
262 }
263 
265  ossim_uint8& g,
266  ossim_uint8& b,
267  ossim_float64 normalX,
268  ossim_float64 normalY,
269  ossim_float64 normalZ,
270  ossim_uint8 dr,
271  ossim_uint8 dg,
272  ossim_uint8 db)const
273 {
274  double c = /*fabs*/(normalX*m_lightDirection[0] +
275  normalY*m_lightDirection[1] +
276  normalZ*m_lightDirection[2]);
277 
278  r = ossimRgbVector::clamp(ossim::round<int>(c*dr), 1, 255);
279  g = ossimRgbVector::clamp(ossim::round<int>(c*dg), 1, 255);
280  b = ossimRgbVector::clamp(ossim::round<int>(c*db), 1, 255);
281 }
282 
284 {
286 
287  ossimImageSource* normalSource = dynamic_cast<ossimImageSource*>( getInput(0) );
288  if ( normalSource )
289  {
290  normalSource->initialize();
291  }
292 
293  ossimImageSource* colorSource = dynamic_cast<ossimImageSource*>( getInput(1) );
294  if ( colorSource )
295  {
296  colorSource->initialize();
297  }
298 
299  m_tile = 0;
300 
302 }
303 
305 {
307  m_tile->initialize();
308 }
309 
311 {
313  0.0,
314  -m_lightSourceAzimuthAngle); // make positive rotation clockwise for azimuth
315  NEWMAT::ColumnVector v(3);
316  v[0] = 0;
317  v[1] = 1;
318  v[2] = 0;
319  v = m*v;
320  // reflect Z. We need the Z pointing up from the surface and not into it.
321  //
322  ossimColumnVector3d d(v[0], v[1], -v[2]);
323  d = d.unit();
324  m_lightDirection[0] = d[0];
325  m_lightDirection[1] = d[1];
326  m_lightDirection[2] = d[2];
327 }
328 
330  const char* prefix)
331 {
332  const char* elevationAngle = kwl.find(prefix, ossimKeywordNames::ELEVATION_ANGLE_KW);
333  const char* azimuthAngle = kwl.find(prefix, ossimKeywordNames::AZIMUTH_ANGLE_KW);
334 
335 
336  if(elevationAngle)
337  {
339  }
340 
341  if(azimuthAngle)
342  {
344  }
345 
346  const char* lookup = kwl.find(prefix, COLOR_RED_KW);
347  if (lookup)
348  {
349  m_r = ossimString(lookup).toUInt8();
350  }
351 
352  lookup = kwl.find(prefix, COLOR_GREEN_KW);
353  if (lookup)
354  {
355  m_g = ossimString(lookup).toUInt8();
356  }
357 
358  lookup = kwl.find(prefix, COLOR_BLUE_KW);
359  if (lookup)
360  {
361  m_b = ossimString(lookup).toUInt8();
362  }
363 
364 
366 
367  bool result = ossimImageSource::loadState(kwl, prefix);
368 
370  theOutputListIsFixedFlag = false;
372 
373  return result;
374 }
375 
377  const char* prefix)const
378 {
379  kwl.add(prefix,
382  true);
383 
384  kwl.add(prefix,
387  true);
388 
389  kwl.add(prefix, COLOR_RED_KW, m_r, true);
390  kwl.add(prefix, COLOR_GREEN_KW, m_g, true);
391  kwl.add(prefix, COLOR_BLUE_KW, m_b, true);
392 
393  return ossimImageSource::saveState(kwl, prefix);
394 }
395 
397 {
398  return ossimString("bump shader");
399 }
400 
402 {
403  return ossimString("Blinn's bump map filter");
404 }
405 
407 {
408  return 3;
409 }
410 
412 {
413  return OSSIM_UCHAR;
414 }
415 
417 {
418  return 0.0;
419 }
420 
422 {
423  return 1.0;
424 }
425 
427 {
428  return 255.0;
429 }
430 
432 {
434 }
435 
437 {
439 }
440 
442 {
444 }
445 
447 {
449 }
450 
452  const ossimConnectableObject* object)const
453 {
454  return (object&&
455  ( (inputIndex>=0) && inputIndex < 2)&&
456  PTR_CAST(ossimImageSource, object));
457 
458 }
459 
461 {
462  initialize();
463 }
464 
466 {
467  initialize();
468 }
469 
471 {
472  initialize();
473 }
474 
476 {
477  initialize();
478 }
479 
481 {
482  ossimString name = property->getName();
483  if(name == "lightSourceElevationAngle")
484  {
485  m_lightSourceElevationAngle = property->valueToString().toDouble();
486  }
487  else if(name == "lightSourceAzimuthAngle")
488  {
489  m_lightSourceAzimuthAngle = property->valueToString().toDouble();
490  }
491  else
492  {
494  }
495 }
496 
498 {
499  if(name == "lightSourceElevationAngle")
500  {
502  prop->setCacheRefreshBit();
503  return prop;
504  }
505  else if(name == "lightSourceAzimuthAngle")
506  {
508  prop->setCacheRefreshBit();
509  return prop;
510  }
511 
512  return ossimImageCombiner::getProperty(name);
513 }
514 
515 void ossimBumpShadeTileSource::getPropertyNames(std::vector<ossimString>& propertyNames)const
516 {
518  propertyNames.push_back("lightSourceElevationAngle");
519  propertyNames.push_back("lightSourceAzimuthAngle");
520 }
521 
523  ossim_uint8 g,
524  ossim_uint8 b)
525 {
526  m_r = r;
527  m_g = g;
528  m_b = b;
529 }
530 
532  ossim_uint8& g,
533  ossim_uint8& b) const
534 {
535  r = m_r;
536  g = m_g;
537  b = m_b;
538 }
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
virtual void setNumberOfInputs(ossim_int32 numberOfInputs)
Will set the number of inputs.
virtual ossim_uint32 getWidth() const
ossim_uint32 x
virtual bool isSourceEnabled() const
Definition: ossimSource.cpp:79
virtual double getAzimuthAngle() const
ossim_uint8 m_r
rgb values used when no color source (2nd layer) is present.
This uses a derivative of Blinn&#39;s bump function to compute a 3-D looking image.
virtual ossim_uint32 getNumberOfBands() const
virtual void refreshEvent(ossimRefreshEvent &event)
virtual void setImageRectangle(const ossimIrect &rect)
This will be a base for all combiners.
static long clamp(long colorValue, unsigned char min=0, unsigned char max=255)
Represents serializable keyword/value map.
ossim_uint8 toUInt8() const
virtual ossim_uint32 getNumberOfOutputBands() const
Returns the number of bands in a tile returned from this TileSource.
ossim_uint32 y
bool valid() const
Definition: ossimRefPtr.h:75
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
const char * find(const char *key) const
void computeLightDirection()
Will re-compute the light direction given the elevation angle and azimuth angle.
virtual void propertyEvent(ossimPropertyEvent &event)
static ossimString toString(bool aValue)
Numeric to string methods.
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
ossimColumnVector3d unit() const
virtual ossimDataObjectStatus getDataObjectStatus() const
virtual ossim_uint32 getHeight() const
virtual ossim_uint32 getNumberOfOutputBands() const
This should always return 3.
bool canConnectMyInputTo(ossim_int32 inputIndex, const ossimConnectableObject *object) const
required to be overriden by derived classes
virtual void initialize()
Initialize the data buffer.
virtual void setElevationAngle(double angle)
double m_lightSourceAzimuthAngle
Used for the light vector computation.
ossimConnectableObject * getInput(ossim_uint32 index=0)
returns the object at the specified index.
NEWMAT::ColumnVector m_lightDirection
This is computed from the elevation and azimuth angles of the light source.
double ossim_float64
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
virtual void setProperty(ossimRefPtr< ossimProperty > property)
static ossimImageDataFactory * instance()
virtual ossimScalarType getOutputScalarType() const
The output scalar type should always be 8-bit.
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
void computeColor(ossim_uint8 &r, ossim_uint8 &g, ossim_uint8 &b, ossim_float64 normalX, ossim_float64 normalY, ossim_float64 normalZ, ossim_uint8 dr, ossim_uint8 dg, ossim_uint8 db) const
RTTI_DEF1(ossimBumpShadeTileSource, "ossimBumpShadeTileSource", ossimImageCombiner)
virtual ossimDataObjectStatus validate() const
unsigned int ossim_uint32
virtual const ossim_float64 * getNullPix() const
void getRgbColorSource(ossim_uint8 &r, ossim_uint8 &g, ossim_uint8 &b) const
Gets the red, green and blue color source values.
void setRgbColorSource(ossim_uint8 r, ossim_uint8 g, ossim_uint8 b)
Set the red, green and blue color source values.
double toDouble() const
#define PTR_CAST(T, p)
Definition: ossimRtti.h:321
virtual void setAzimuthAngle(double angle)
virtual ossimIrect getImageRectangle() const
static const char * AZIMUTH_ANGLE_KW
virtual ossimRefPtr< ossimImageData > create(ossimSource *owner, ossimScalarType scalar, ossim_uint32 bands=1) const
ossimScalarType
return status
virtual ossimScalarType getScalarType() const
virtual void makeBlank()
Initializes data to null pixel values.
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
virtual ossimScalarType getOutputScalarType() const
This will be used to query the output pixel type of the tile source.
virtual void disconnectInputEvent(ossimConnectionEvent &event)
virtual double getMaxPixelValue(ossim_uint32 band=0) const
the max pixel is 255.
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
virtual const void * getBuf() const
virtual ossim_uint32 getNumberOfInputs() const
Returns the number of input objects.
virtual double getNullPixelValue() const
the null pixel is 0.0.
virtual double getMinPixelValue(ossim_uint32 band=0) const
the min pixel is 1.0.
bool theInputListIsFixedFlag
Indicates whether the theInputObjectList is fixed.
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
virtual void setProperty(ossimRefPtr< ossimProperty > property)
ossimRefPtr< ossimImageData > m_tile
The result of the illumination equation is stored in here.
virtual void initialize()=0
static const char * ELEVATION_ANGLE_KW
ossimDataObjectStatus
Definitions for data object status.
bool theOutputListIsFixedFlag
Indicates whether the theOutputObjectList is fixed.
ossimRefPtr< ossimImageData > getTile(const ossimIrect &tileRect, ossim_uint32 resLevel=0)
virtual void connectInputEvent(ossimConnectionEvent &event)
64 bit floating point
unsigned char ossim_uint8
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
double m_lightSourceElevationAngle
Used for the light vector computation.
virtual double getElevationAngle() const
void setCacheRefreshBit()
8 bit unsigned iteger
int ossim_int32
static NEWMAT::Matrix createRotationMatrix(double angleX, double angleY, double angleZ, ossimCoordSysOrientMode orientationMode=OSSIM_RIGHT_HANDED)
virtual ossimRefPtr< ossimImageData > getTile(const ossimIpt &origin, ossim_uint32 resLevel=0)