NCBI C++ ToolKit
glcolortable.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: glcolortable.cpp 42536 2019-03-19 19:13:46Z katargir $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Mike DiCuccio, Andrey Yazhuk
27  *
28  * File Description:
29  * Incremental and mutually contrastive color table generator.
30  */
31 
32 #include <ncbi_pch.hpp>
34 #include <gui/opengl/glresmgr.hpp>
35 
36 
37 #include <gui/opengl/glutils.hpp>
38 
39 
41 
42 ////////////////////////////////////////////////////////////////////////////////
43 /// CRgbaGradColorTable
44 
46 : m_TextureWidth(0)
47 , m_TextureAlphaLevels(1)
48 #ifdef USE_METAL
49 , m_MaxColorTableSize(16384)
50 #else
51 , m_MaxColorTableSize(0)
52 #endif
53 {
54 }
55 
57 {
58  *this = rhs;
59 }
60 
61 
63 : m_TextureWidth(0)
64 , m_TextureAlphaLevels(1)
65 #ifdef USE_METAL
66 , m_MaxColorTableSize(16384)
67 #else
68 , m_MaxColorTableSize(0)
69 #endif
70 {
71  SetSize(size);
72 }
73 
75 {
76  m_Colors = rhs.m_Colors;
77 
78  // If user was using rhs as a texture, don't force it
79  // to be a texture here - have to call create texture again
80  // (and don't share textures between objects - they are small..)
81 
82  if (m_Texture) {
83  m_Texture->Unload();
84  m_Texture.Reset();
85  }
86 
87  m_TextureWidth = 0;
89 
90  return *this;
91 }
92 
94 {
95  if (m_Texture)
96  m_Texture->Unload();
97 }
98 
99 
101 {
102  return m_Colors.size();
103 }
104 
105 
107 {
108  _ASSERT(size < 0xFFFF);
109  m_Colors.resize(size);
110 }
111 
112 bool CRgbaGradColorTable::FindColor(const CRgbaColor& c, size_t& idx) const
113 {
114  for (size_t i=0; i<m_Colors.size(); ++i) {
115  if (m_Colors[i] == c) {
116  idx = i;
117  return true;
118  }
119  }
120 
121  return false;
122 }
123 
124 float CRgbaGradColorTable::FindClosestColor(const CRgbaColor& c, size_t& idx) const
125 {
126  float min_dist = numeric_limits<float>::max();
127 
128  for (size_t i=0; i<m_Colors.size(); ++i) {
129  float dist = CRgbaColor::ColorDistance(c, m_Colors[i]);
130  if (dist < min_dist) {
131  min_dist = dist;
132  idx = i;
133  }
134  }
135 
136  return min_dist;
137 }
138 
140 {
141  m_Colors.clear();
142 }
143 
144 /// Add a single color to the table. Do not let table get bigger than maximum texture size.
145 /// Also, as it gets closer to maximum texture size (4096 or 8192 probably) there will be
146 /// less room for alpha levels.
148 {
149  if (m_MaxColorTableSize == 0)
150  glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_MaxColorTableSize);
151 
152  size_t current_size = m_Colors.size();
153 
154  if (current_size >= m_MaxColorTableSize) {
155  _TRACE("Warning - color table full");
156  FindClosestColor(c, current_size);
157  return current_size;
158  }
159 
160  m_Colors.push_back(c);
161 
162  return current_size;
163 }
164 
165 void CRgbaGradColorTable::FillGradient(const CRgbaColor& start_c, const CRgbaColor& end_c)
166 {
167  if( ! m_Colors.empty()) {
168  FillGradient(0, (int)m_Colors.size(), start_c, end_c);
169  }
170 }
171 
172 
173 void CRgbaGradColorTable::FillGradient(int start_i, int n,
174  const CRgbaColor& start_c,
175  const CRgbaColor& end_c)
176 {
177  _ASSERT(start_i >= 0 && start_i < (int) m_Colors.size());
178  _ASSERT((start_i + n) <= (int) m_Colors.size());
179  _ASSERT(n >= 0);
180 
181  if(n) {
182  float base_r = start_c.GetRed();
183  float base_g = start_c.GetGreen();
184  float base_b = start_c.GetBlue();
185  float base_a = start_c.GetAlpha();
186 
187  float d_r = end_c.GetRed() - base_r;
188  float d_g = end_c.GetGreen() - base_g;
189  float d_b = end_c.GetBlue() - base_b;
190  float d_a = end_c.GetAlpha() - base_a;
191 
192  float K = 1.0f / (n - 1);
193  for( int i = 0; i < n; i++ ) {
194  float d = i * K;
195  float r = base_r + d * d_r;
196  float g = base_g + d * d_g;
197  float b = base_b + d * d_b;
198  float a = base_a + d * d_a;
199  m_Colors[start_i + i].Set(r, g, b, a);
200  }
201  }
202 }
203 
204 
205 void CRgbaGradColorTable::FillGradient(int start_i, int n,
206  const CRgbaColor& start_c,
207  const CRgbaColor& mid_c,
208  const CRgbaColor& end_c)
209 {
210  _ASSERT(start_i >= 0 && start_i < (int) m_Colors.size());
211 
212  if (n > 0) {
213  if ((n & 1) == 0) {
214  LOG_POST(Warning << "CRgbaGradColorTable::FillGradient() - \"n\""
215  << "is an even number. Gradient table will not be symmetrical!");
216  }
217  int half = n / 2;
218  // fill the first half
219  FillGradient(start_i, half + 1, start_c, mid_c);
220  // fill the second half
221  FillGradient(start_i + half, n - half, mid_c, end_c);
222  }
223 }
224 
225 void CRgbaGradColorTable::LoadTexture(int alpha_levels)
226 {
227  // safety first!
228  if ( m_Colors.size() == 0 ) {
229  _TRACE(" no colors to create texture");
230  return;
231  }
232 
233  if (m_MaxColorTableSize == 0)
234  glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_MaxColorTableSize);
235 
236  /// There is at least 1 alpha level - the set of values from m_Color
237  if (alpha_levels < 1)
238  alpha_levels = 1;
239 
240  // Can't go over maximum texture size so if we are too big, reduce alpha levels
241  if (alpha_levels * m_Colors.size() > m_MaxColorTableSize) {
242  alpha_levels = (int)floorf(((float)m_MaxColorTableSize)/((float)m_Colors.size()));
243  }
244 
245  m_TextureAlphaLevels = alpha_levels;
246 
247  // Get a power-of-2 size for texture that is the smallest
248  // power-of-2 size larger than a default minimum size (128)
249  // and >= m_Colors.size()*m_TextureAlphalevels
250  GLsizei size = (GLsizei)(m_TextureAlphaLevels * (int)m_Colors.size());
251 
252  // If we are larger than a normal-sized texture, cut the number of alpha
253  // levels (if possible) (This should not normally happen...)
254  if (size > 1024*1024) {
255  m_TextureAlphaLevels = (1024*1024)/(int)m_Colors.size();
256  size = (GLsizei)(m_TextureAlphaLevels * (int)m_Colors.size());
257  }
258 
259  m_TextureWidth = 128;
260  for (int i=0; i<12 && m_TextureWidth < size; ++i)
261  m_TextureWidth *= 2;
262 
263 
264  // Set up padded buffer of width m_TextureWidth for call to glTexImage1D.
265  vector<CRgbaColor> power_of_two_buffer = m_Colors;
266  float alpha_factor = 1.0f;
267  for (int i=1; i<m_TextureAlphaLevels; ++i) {
268  alpha_factor = ((float)(m_TextureAlphaLevels-i))/(float)m_TextureAlphaLevels;
269 
270  for (size_t j=0; j<m_Colors.size(); ++j) {
271  CRgbaColor c = m_Colors[j];
272  c.SetAlpha(c.GetAlpha()*alpha_factor);
273  power_of_two_buffer.push_back(c);
274  }
275  }
276  // Add default color to unused space at the end of the buffer
277  power_of_two_buffer.resize(m_TextureWidth, CRgbaColor(0.0f, 0.0f, 0.0f, 1.0f));
278 
279  if (m_Texture)
280  m_Texture->Unload();
281 
282  m_Texture.Reset(CGlResMgr::Instance().Create1DRGBATexture(m_TextureWidth, (float*)&power_of_two_buffer[0]));
283 
285 
286  if (m_Texture) {
287  m_Texture->SetWrapS(GL_CLAMP);
288  m_Texture->SetFilterMin(GL_NEAREST);
289  m_Texture->SetFilterMag(GL_NEAREST);
290  m_Texture->SetTexEnv(GL_MODULATE);
291  }
292 }
293 
295 {
296 
297  int color_idx = int(f*(float(m_TextureWidth))-0.5f);
298  int alpha_level = color_idx / int(m_Colors.size());
299  color_idx = color_idx % int(m_Colors.size());
300 
301  if (color_idx >= (int)m_Colors.size()) {
302  _TRACE("Texture coord: " << f << " mapped to an invalid color index: " << color_idx);
303  return CRgbaColor(1.0f, 1.0f, 1.0f, 1.0f);
304  }
305 
306  CRgbaColor c = m_Colors[color_idx];
307 
308  float alpha_factor = (float(m_TextureAlphaLevels-alpha_level))/(float)m_TextureAlphaLevels;
309  c.SetAlpha(c.GetAlpha()*alpha_factor);
310 
311  return c;
312 }
313 
314 float CRgbaGradColorTable::GetColorTexCoord(short idx, float alpha) const
315 {
316  /// Get alpha level of 0..m_TextureAlphaLevels -1. Texture map is
317  /// stored in order of decreasing alpha, and 'alpha' is in the standard
318  /// sense of increasing alpha, so we index for 1.0-alpha.
319  int alpha_level = (int)floorf(((1.0f-alpha)*(float)m_TextureAlphaLevels));
320 
321  /// should only happen on bad input:
322  alpha_level = std::max(alpha_level, 0);
323  alpha_level = std::min(alpha_level, m_TextureAlphaLevels-1);
324 
325  float level_offset = (float)(m_Colors.size()*(size_t)alpha_level);
326  float scaled_width = (float)(m_TextureWidth);
327 
328  return ( (((float)idx) + level_offset + 0.5f)/scaled_width );
329 }
330 
class CRgbaColor provides a simple abstraction for managing colors.
Definition: rgba_color.hpp:58
CRgbaGradColorTable Provides a storage for colors (to eliminate color creation overhead) and Function...
#define _TRACE(message)
Definition: ncbidbg.hpp:122
#define LOG_POST(message)
This macro is deprecated and it's strongly recomended to move in all projects (except tests) to macro...
Definition: ncbidiag.hpp:226
void Warning(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1191
GLsizei m_TextureWidth
Width of the 1D texture (if created).
static CGlResMgr & Instance()
Definition: glresmgr.cpp:59
CRgbaColor GetTexCoordColor(float f) const
Get color given a texture coord.
vector< CRgbaColor > m_Colors
size_t AddColor(const CRgbaColor &c)
Add a single color to the table.
size_t GetSize() const
CRgbaGradColorTable()
CRgbaGradColorTable.
CRgbaGradColorTable & operator=(const CRgbaGradColorTable &rhs)
float FindClosestColor(const CRgbaColor &c, size_t &idx) const
Return index of color with minimum color disance (as defined in CRgbaColor) from c.
void SetSize(size_t size)
float GetColorTexCoord(short idx, float alpha) const
Get position for color with alpha level closest to 'alpha'.
void FillGradient(const CRgbaColor &start_c, const CRgbaColor &end_c)
initialize the whole table with gradient colors in [start_c, end_c] range
int m_TextureAlphaLevels
Number of alpha levels stored in the texture.
static bool CheckGlError()
Check if there are any OpenGL errors.
Definition: glutils.cpp:166
GLint m_MaxColorTableSize
Maximum size of color texture.
bool FindColor(const CRgbaColor &c, size_t &idx) const
On exact match, returns true with index in idx, false otherwise.
void LoadTexture(int alpha_levels=8)
OpenGL parameters and operations to allow color table to (also) be stored as a 1D texture.
I3DTexture * Create1DRGBATexture(size_t width, float *data)
Definition: glresmgr.cpp:320
void ClearColors()
Empty color table.
CIRef< I3DTexture > m_Texture
static float ColorDistance(const CRgbaColor &c1, const CRgbaColor &c2)
returns the distance in the RGB color cube between the two colors, scaled to a range [0,...
float GetBlue(void) const
Definition: rgba_color.hpp:333
float GetGreen(void) const
Definition: rgba_color.hpp:327
void SetAlpha(float r)
Definition: rgba_color.cpp:287
float GetAlpha(void) const
Definition: rgba_color.hpp:339
float GetRed(void) const
Get specific channels in floating point values.
Definition: rgba_color.hpp:321
void Reset(void)
Reset reference object.
Definition: ncbiobj.hpp:773
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
int i
yy_size_t n
const struct ncbi::grid::netcache::search::fields::SIZE size
unsigned int a
Definition: ncbi_localip.c:102
T max(T x_, T y_)
T min(T x_, T y_)
double r(size_t dimension_, const Int4 *score_, const double *prob_, double theta_)
double f(double x_, const double &y_)
Definition: njn_root.hpp:188
#define _ASSERT
int g(Seg_Gsm *spe, Seq_Mtf *psm, Thd_Gsm *tdg)
Definition: thrddgri.c:44
Modified on Sun Jun 16 04:34:33 2024 by modify_doxy.py rev. 669887