gKit2 light
Loading...
Searching...
No Matches
ImageViewer Struct Reference
Inheritance diagram for ImageViewer:

Public Member Functions

 ImageViewer (std::vector< const char * > &filenames)
void range (const Image &image)
Image tone (const Image &image, const float saturation, const float gamma)
Image gray (const Image &image)
void title (const int index)
Image read (const char *filename)
int init ()
 a deriver pour creer les objets openGL. renvoie -1 pour indiquer une erreur, 0 sinon.
int quit ()
 a deriver pour detruire les objets openGL. renvoie -1 pour indiquer une erreur, 0 sinon.
int render ()
 a deriver pour afficher les objets. renvoie 1 pour continuer, 0 pour fermer l'application.
Public Member Functions inherited from App
 App (const int width, const int height, const int major=3, const int minor=3, const int samples=0)
 constructeur, dimensions de la fenetre et version d'openGL.
virtual int update (const float time, const float delta)
 a deriver et redefinir pour animer les objets en fonction du temps.
int run ()
 execution de l'application.

Protected Attributes

Widgets m_widgets
std::vector< std::string > m_filenames
std::vector< size_t > m_times
std::vector< Imagem_images
std::vector< GLuint > m_textures
unsigned m_width
unsigned m_height
GLuint m_program
GLuint m_vao
GLuint m_sampler_nearest
int m_red
int m_green
int m_blue
int m_alpha
int m_gray
int m_smooth
int m_difference
float m_compression
float m_saturation
float m_saturation_step
float m_saturation_max
float m_zoom
int m_index
int m_reference_index
int m_graph
Protected Attributes inherited from App
Window m_window
Context m_context
bool sync

Additional Inherited Members

Protected Member Functions inherited from App
virtual int prerender ()
virtual int postrender ()
void vsync_off ()

Detailed Description

Definition at line 20 of file image_viewer.cpp.

Constructor & Destructor Documentation

◆ ImageViewer()

ImageViewer::ImageViewer ( std::vector< const char * > & filenames)
inline

Definition at line 22 of file image_viewer.cpp.

22 : App(1024, 640), m_filenames()
23 {
24 for(unsigned i= 0; i < filenames.size(); i++)
25 m_filenames.push_back(filenames[i]);
26 }
App(const int width, const int height, const int major=3, const int minor=3, const int samples=0)
constructeur, dimensions de la fenetre et version d'openGL.
Definition app.cpp:11

Member Function Documentation

◆ range()

void ImageViewer::range ( const Image & image)
inline

Definition at line 28 of file image_viewer.cpp.

29 {
30 int bins[100] = {};
31 float ymin= FLT_MAX;
32 float ymax= 0.f;
33 for(unsigned y= 0; y < image.height(); y++)
34 for(unsigned x= 0; x < image.width(); x++)
35 {
36 Color color= image(x, y);
37 float y= color.r + color.g + color.b;
38 if(y < ymin) ymin= y;
39 if(y > ymax) ymax= y;
40 }
41
42 for(unsigned y= 0; y < image.height(); y++)
43 for(unsigned x= 0; x < image.width(); x++)
44 {
45 Color color= image(x, y);
46 float y= color.r + color.g + color.b;
47 int b= (y - ymin) * 100.f / (ymax - ymin);
48 if(b >= 99) b= 99;
49 if(b < 0) b= 0;
50 bins[b]++;
51 }
52
53 printf("range [%f..%f]\n", ymin, ymax);
54 //~ for(int i= 0; i < 100; i++)
55 //~ printf("%f ", ((float) bins[i] * 100.f / (m_width * m_height)));
56 //~ printf("\n");
57
58 float qbins= 0;
59 for(int i= 0; i < 100; i++)
60 {
61 if(qbins > .75f)
62 {
63 m_saturation= ymin + (float) i / 100.f * (ymax - ymin);
64 m_saturation_step= m_saturation / 40.f;
65 m_saturation_max= ymax;
66 break;
67 }
68
69 qbins= qbins + (float) bins[i] / (m_width * m_height);
70 }
71 m_compression= 2.2f;
72 }
void printf(Text &text, const int px, const int py, const char *format,...)
affiche un texte a la position x, y. meme utilisation que printf().
Definition text.cpp:140

◆ tone()

Image ImageViewer::tone ( const Image & image,
const float saturation,
const float gamma )
inline

Definition at line 74 of file image_viewer.cpp.

75 {
76 Image tmp(image.width(), image.height());
77
78 float invg= 1 / gamma;
79 float k= 1 / std::pow(saturation, invg);
80 for(unsigned i= 0; i < image.size(); i++)
81 {
82 Color color= image(i);
83 if(std::isnan(color.r) || std::isnan(color.g) || std::isnan(color.b))
84 // marque les pixels pourris avec une couleur improbable...
85 color= Color(1, 0, 1);
86 else
87 // sinon transformation gamma rgb -> srgb
88 color= Color(k * std::pow(color.r, invg), k * std::pow(color.g, invg), k * std::pow(color.b, invg));
89
90 tmp(i)= Color(color, 1);
91 }
92
93 return tmp;
94 }

◆ gray()

Image ImageViewer::gray ( const Image & image)
inline

Definition at line 96 of file image_viewer.cpp.

97 {
98 Image tmp(image.width(), image.height());
99
100 for(unsigned i= 0; i < image.size(); i++)
101 {
102 Color color= image(i);
103 float g= (color.r + color.b + color.b) / 3;
104 //~ float g= std::max(color.r, std::max(color.g, std::max(color.b, float(0))));
105 tmp(i)= Color(g);
106 }
107
108 return tmp;
109 }

◆ title()

void ImageViewer::title ( const int index)
inline

Definition at line 112 of file image_viewer.cpp.

113 {
114 char tmp[1024];
115 sprintf(tmp, "buffer %02d: %s", index, m_filenames[index].c_str());
116 SDL_SetWindowTitle(m_window, tmp);
117 }

◆ read()

Image ImageViewer::read ( const char * filename)
inline

Definition at line 119 of file image_viewer.cpp.

120 {
121 Image image;
122 if(is_pfm_image(filename))
123 image= read_image_pfm(filename);
124 else if(is_hdr_image(filename))
125 image= read_image_hdr(filename);
126 else
127 image= read_image(filename);
128
129 return image;
130 }
Image read_image(const char *filename, const bool flipY)
Definition image_io.cpp:171

◆ init()

int ImageViewer::init ( )
inlinevirtual

a deriver pour creer les objets openGL. renvoie -1 pour indiquer une erreur, 0 sinon.

Implements App.

Definition at line 132 of file image_viewer.cpp.

133 {
134 m_width= 0;
135 m_height= 0;
136
137 for(unsigned i= 0; i < m_filenames.size(); i++)
138 {
139 printf("loading buffer %u...\n", i);
140
141 Image image= read(m_filenames[i].c_str());
142 if(image.size() == 0)
143 continue;
144
145 m_images.push_back(image);
146 m_times.push_back(timestamp(m_filenames[i].c_str()));
147
148 m_textures.push_back(make_texture(0, image));
149
150 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
151 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
152
153 m_width= std::max(m_width, image.width());
154 m_height= std::max(m_height, image.height());
155 }
156
157 if(m_images.empty())
158 {
159 printf("no image...\n");
160 return -1;
161 }
162
163 // change le titre de la fenetre
164 title(0);
165
166 // redminsionne la fenetre
167 SDL_SetWindowSize(m_window, m_width, m_height);
168
169 glGenVertexArrays(1, &m_vao);
170 glBindVertexArray(m_vao);
171
172 m_program= read_program( smart_path("data/shaders/tonemap.glsl") );
173 program_print_errors(m_program);
174
175 //
176 m_red= 1;
177 m_green= 1;
178 m_blue= 1;
179 m_alpha= 1;
180 m_gray= 0;
181 m_smooth= 1;
182 m_difference= 0;
183 m_compression= 2.2f;
184 m_saturation= 1;
185 m_saturation_step= 1;
186 m_saturation_max= 1000;
187 m_index= 0;
188 m_reference_index= -1;
189 m_zoom= 4;
190 m_graph= 0;
191
192 // parametres d'exposition / compression
193 range(m_images.front());
194
195 //
196 m_widgets= create_widgets();
197
198 //
199 glGenSamplers(1, &m_sampler_nearest);
200 glSamplerParameteri(m_sampler_nearest, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
201 glSamplerParameteri(m_sampler_nearest, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
202 glSamplerParameteri(m_sampler_nearest, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
203 glSamplerParameteri(m_sampler_nearest, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
204
205 // etat openGL par defaut
206 glUseProgram(0);
207 glBindVertexArray(0);
208 glBindTexture(GL_TEXTURE_2D, 0);
209
210 glDisable(GL_DEPTH_TEST);
211 glDisable(GL_CULL_FACE);
212 return 0;
213 }
const char * smart_path(const char *filename)
renvoie le chemin(path) vers le fichier 'filename' apres l'avoir cherche dans un repertoire standard....
Definition window.cpp:413
Widgets create_widgets()
cree une interface graphique. a detruire avec release_widgets( ).
Definition widgets.cpp:12
GLuint make_texture(const int unit, const int width, const int height, const GLenum texel_type, const GLenum data_format, const GLenum data_type)
creation de textures filtrables / mipmaps
Definition texture.cpp:10
GLuint read_program(const char *filename, const char *definitions)
Definition program.cpp:218
int program_print_errors(const GLuint program)
affiche les erreurs de compilation.
Definition program.cpp:446

◆ quit()

int ImageViewer::quit ( )
inlinevirtual

a deriver pour detruire les objets openGL. renvoie -1 pour indiquer une erreur, 0 sinon.

Implements App.

Definition at line 215 of file image_viewer.cpp.

216 {
217 glDeleteVertexArrays(1, &m_vao);
218 glDeleteTextures(m_textures.size(), m_textures.data());
219
220 release_program(m_program);
221 release_widgets(m_widgets);
222 return 0;
223 }
void release_widgets(Widgets &w)
detruit l'interface graphique.
Definition widgets.cpp:23
int release_program(const GLuint program)
detruit les shaders et le program.
Definition program.cpp:225

◆ render()

int ImageViewer::render ( )
inlinevirtual

a deriver pour afficher les objets. renvoie 1 pour continuer, 0 pour fermer l'application.

Implements App.

Definition at line 225 of file image_viewer.cpp.

226 {
227 // effacer l'image
228 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
229
230 if(key_state('r'))
231 {
232 clear_key_state('r');
233 reload_program(m_program, smart_path("data/shaders/tonemap.glsl") );
234 program_print_errors(m_program);
235 }
236
237 if(key_state(SDLK_LEFT))
238 {
239 clear_key_state(SDLK_LEFT);
240 m_index= (m_index -1 + m_textures.size()) % m_textures.size();
241 // change aussi le titre de la fenetre
242 title(m_index);
243 }
244
245 if(key_state(SDLK_RIGHT))
246 {
247 clear_key_state(SDLK_RIGHT);
248 m_index= (m_index +1 + m_textures.size()) % m_textures.size();
249 // change aussi le titre de la fenetre
250 title(m_index);
251 }
252
253 // verification de la date de l'image
254 static float last_time= 0;
255 // quelques fois par seconde, ca suffit, pas tres malin de le faire 60 fois par seconde...
256 if(global_time() > last_time + 400)
257 {
258 size_t time= timestamp(m_filenames[m_index].c_str());
259 if(time != m_times[m_index])
260 {
261 // date modifiee, recharger l'image
262 printf("reload image '%s'...\n", m_filenames[m_index].c_str());
263
264 Image image= read(m_filenames[m_index].c_str());
265 if(image.size())
266 {
267 m_times[m_index]= time;
268 m_images[m_index]= image;
269
270 // transfere la nouvelle version
271 glBindTexture(GL_TEXTURE_2D, m_textures[m_index]);
272 glTexImage2D(GL_TEXTURE_2D, 0,
273 GL_RGBA32F, image.width(), image.height(), 0,
274 GL_RGBA, GL_FLOAT, image.data());
275
276 glGenerateMipmap(GL_TEXTURE_2D);
277 }
278 }
279
280 last_time= global_time();
281 }
282
283 if(drop_events().size())
284 {
285 for(unsigned i= 0; i < drop_events().size(); i++)
286 {
287 const char *filename= drop_events()[i].c_str();
288 if(filename && filename[0])
289 {
290 //~ printf("drop file [%d] '%s'...\n", int(m_filenames.size()), filename);
291
292 Image image= read(filename);
293 if(image.size())
294 {
295 m_images.push_back( image );
296 m_filenames.push_back( filename );
297 m_times.push_back( timestamp(filename) );
298 m_textures.push_back( make_texture(0, image) );
299
300 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
301 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
302 }
303 }
304
305 printf("index %d\n", m_index);
306 for(unsigned i= 0; i < m_filenames.size(); i++)
307 printf("images[%d] '%s'\n", i, m_filenames[i].c_str());
308 }
309
311 assert(drop_events().size() == 0);
312 }
313
314
315 int xmouse, ymouse;
316 unsigned int bmouse= SDL_GetMouseState(&xmouse, &ymouse);
317
318 glBindVertexArray(m_vao);
319 glUseProgram(m_program);
320
321 // selection des buffers + filtrage
322 GLuint sampler= 0;
323 if(!m_smooth)
324 sampler= m_sampler_nearest;
325
326 program_use_texture(m_program, "image", 0, m_textures[m_index], sampler);
327 if(m_reference_index == -1)
328 program_use_texture(m_program, "image_next", 1, m_textures[(m_index +1) % m_textures.size()], sampler);
329 else
330 program_use_texture(m_program, "image_next", 1, m_textures[m_reference_index], sampler);
331
332 // activer le split de l'ecran
333 if(bmouse & SDL_BUTTON(1))
334 program_uniform(m_program, "split", (int) xmouse);
335 else
336 program_uniform(m_program, "split", (int) window_width() +2);
337
338 // parametres
339 program_uniform(m_program, "channels", Color(m_red, m_green, m_blue, m_alpha));
340 program_uniform(m_program, "gray", float(m_gray));
341 program_uniform(m_program, "difference", float(m_difference));
342 program_uniform(m_program, "compression", m_compression);
343 program_uniform(m_program, "saturation", m_saturation);
344
345 // zoom
346 if(bmouse & SDL_BUTTON(3))
347 {
348 SDL_MouseWheelEvent wheel= wheel_event();
349 if(wheel.y != 0)
350 {
351 m_zoom= m_zoom + float(wheel.y) / 4.f;
352 if(m_zoom < .1f) m_zoom= .1f;
353 if(m_zoom > 10.f) m_zoom= 10.f;
354 }
355 }
356
357 program_uniform(m_program, "center", vec2( float(xmouse) / float(window_width()), float(window_height() - ymouse -1) / float(window_height())));
358 if(bmouse & SDL_BUTTON(3))
359 program_uniform(m_program, "zoom", m_zoom);
360 else
361 program_uniform(m_program, "zoom", 1.f);
362
363 // graphes / courbes
364 if(key_state('g'))
365 {
366 clear_key_state('g');
367 m_graph= (m_graph +1) % 2;
368 }
369
370 program_uniform(m_program, "graph", int(m_graph));
371 program_uniform(m_program, "line", vec2(float(window_height() - ymouse -1) / float(window_height()), float(window_height() - ymouse -1)));
372
373 // dessine 1 triangle plein ecran
374 glDrawArrays(GL_TRIANGLES, 0, 3);
375
376 // actions
377 if(key_state('c'))
378 {
379 clear_key_state('c');
380
381 // change l'extension
382 std::string file= m_filenames[m_index];
383 size_t ext= file.rfind(".");
384 if(ext != std::string::npos)
385 file= file.substr(0, ext) + "-tone.png";
386
387 printf("writing '%s'...\n", file.c_str());
388 screenshot(file.c_str());
389 }
390
391 begin(m_widgets);
392 value(m_widgets, "saturation", m_saturation, 0.f, m_saturation_max*10, m_saturation_step);
393 value(m_widgets, "compression", m_compression, .1f, 10.f, .1f);
394
395 int reset= 0;
396 button(m_widgets, "reset", reset);
397 if(reset) range(m_images[m_index]);
398
399 int reload= 0;
400 button(m_widgets, "reload", reload);
401 if(reload)
402 {
403 Image image= read(m_filenames[m_index].c_str());
404 {
405 m_images[m_index]= image;
406 m_times[m_index]= timestamp(m_filenames[m_index].c_str());
407
408 // transfere la nouvelle version
409 glBindTexture(GL_TEXTURE_2D, m_textures[m_index]);
410 glTexImage2D(GL_TEXTURE_2D, 0,
411 GL_RGBA32F, image.width(), image.height(), 0,
412 GL_RGBA, GL_FLOAT, image.data());
413
414 glGenerateMipmap(GL_TEXTURE_2D);
415 }
416 }
417
418 int reference= (m_index == m_reference_index) ? 1 : 0;
419 if(button(m_widgets, "reference", reference))
420 {
421 if(reference) m_reference_index= m_index; // change de reference
422 else m_reference_index= -1; // deselectionne la reference
423 }
424
425 int export_all= 0;
426 button(m_widgets, "export all", export_all);
427 if(export_all)
428 {
429 #pragma omp parallel for
430 for(unsigned i= 0; i < m_images.size(); i++)
431 {
432 Image image;
433 if(m_gray)
434 image= tone(gray(m_images[i]), m_saturation, m_compression);
435 else
436 image= tone(m_images[i], m_saturation, m_compression);
437
438 char filename[1024];
439 sprintf(filename, "%s-tone.png", m_filenames[i].c_str());
440 printf("exporting '%s'...\n", filename);
441 write_image(image, filename);
442 }
443 }
444
445 begin_line(m_widgets);
446 {
447 int px= xmouse;
448 int py= window_height() - ymouse -1;
449 float x= px / float(window_width()) * m_images[m_index].width();
450 float y= py / float(window_height()) * m_images[m_index].height();
451 Color pixel= m_images[m_index](x, y);
452 label(m_widgets, "pixel %d %d: %f %f %f", int(x), int(y), pixel.r, pixel.g, pixel.b);
453 }
454
455 begin_line(m_widgets);
456 button(m_widgets, "R", m_red);
457 button(m_widgets, "G", m_green);
458 button(m_widgets, "B", m_blue);
459 button(m_widgets, "A", m_alpha);
460 button(m_widgets, "gray", m_gray);
461 button(m_widgets, "smooth", m_smooth);
462
463 if(m_reference_index != -1)
464 button(m_widgets, "diff to reference", m_difference);
465
466 begin_line(m_widgets);
467 {
468 static int list= 0;
469 button(m_widgets, "select image...", list);
470 if(list)
471 {
472 char tmp[1024];
473 for(unsigned i= 0; i < m_filenames.size(); i++)
474 {
475 begin_line(m_widgets);
476 sprintf(tmp, "[%u] %s", i, m_filenames[i].c_str());
477 select(m_widgets, tmp, i, m_index);
478 }
479 }
480 }
481
482 end(m_widgets);
483
484 draw(m_widgets, window_width(), window_height());
485
486 if(key_state('s'))
487 {
488 clear_key_state('s');
489
490 static int calls= 0;
491 screenshot("screenshot", ++calls);
492 printf("screenshot %d...\n", calls);
493 }
494
495 if(key_state(SDLK_LCTRL) && key_state('w'))
496 {
497 clear_key_state('w');
498
499 m_filenames.erase(m_filenames.begin() + m_index);
500 m_times.erase(m_times.begin() + m_index);
501 m_images.erase(m_images.begin() + m_index);
502 m_textures.erase(m_textures.begin() + m_index);
503 if(m_reference_index == m_index)
504 m_reference_index= -1;
505
506 if(m_textures.empty())
507 return 0;
508
509 m_index= m_index % int(m_textures.size());
510 // change aussi le titre de la fenetre
511 title(m_index);
512 }
513
514 return 1;
515 }
void begin(Widgets &w)
debut de la description des elements de l'interface graphique.
Definition widgets.cpp:29
bool button(Widgets &w, const char *text, int &status)
Definition widgets.cpp:155
void clear_drop_events()
desactive drag/drop.
Definition window.cpp:93
const std::vector< std::string > & drop_events()
drag/drop. recupere tous les fichiers.
Definition window.cpp:75
int window_height()
renvoie la hauteur de la fenetre de l'application.
Definition window.cpp:27
void clear_key_state(const SDL_Keycode key)
desactive une touche du clavier.
Definition window.cpp:46
bool select(Widgets &w, const char *text, const int option, int &status)
Definition widgets.cpp:173
int key_state(const SDL_Keycode key)
renvoie l'etat d'une touche du clavier. cf la doc SDL2 pour les codes.
Definition window.cpp:40
void begin_line(Widgets &w)
place les prochains elements sur une nouvelle ligne.
Definition widgets.cpp:129
SDL_MouseWheelEvent wheel_event()
renvoie le dernier evenement. etat de la molette de la souris / glisser sur le pad.
Definition window.cpp:110
int window_width()
renvoie la largeur de la fenetre de l'application.
Definition window.cpp:23
float global_time()
renvoie le temps ecoule depuis le lancement de l'application, en millisecondes.
Definition window.cpp:126
bool write_image(const Image &image, const char *filename, const bool flipY)
enregistre une image au format .png
Definition image_io.cpp:225
int screenshot(const char *filename)
enregistre le contenu de la fenetre dans un fichier. doit etre de type .png / .bmp
Definition texture.cpp:178
void program_use_texture(const GLuint program, const char *uniform, const int unit, const GLuint texture, const GLuint sampler)
configure le pipeline et le shader program pour utiliser une texture, et des parametres de filtrage,...
Definition uniforms.cpp:198

Member Data Documentation

◆ m_widgets

Widgets ImageViewer::m_widgets
protected

Definition at line 518 of file image_viewer.cpp.

◆ m_filenames

std::vector<std::string> ImageViewer::m_filenames
protected

Definition at line 520 of file image_viewer.cpp.

◆ m_times

std::vector<size_t> ImageViewer::m_times
protected

Definition at line 521 of file image_viewer.cpp.

◆ m_images

std::vector<Image> ImageViewer::m_images
protected

Definition at line 522 of file image_viewer.cpp.

◆ m_textures

std::vector<GLuint> ImageViewer::m_textures
protected

Definition at line 523 of file image_viewer.cpp.

◆ m_width

unsigned ImageViewer::m_width
protected

Definition at line 524 of file image_viewer.cpp.

◆ m_height

unsigned ImageViewer::m_height
protected

Definition at line 524 of file image_viewer.cpp.

◆ m_program

GLuint ImageViewer::m_program
protected

Definition at line 526 of file image_viewer.cpp.

◆ m_vao

GLuint ImageViewer::m_vao
protected

Definition at line 527 of file image_viewer.cpp.

◆ m_sampler_nearest

GLuint ImageViewer::m_sampler_nearest
protected

Definition at line 528 of file image_viewer.cpp.

◆ m_red

int ImageViewer::m_red
protected

Definition at line 530 of file image_viewer.cpp.

◆ m_green

int ImageViewer::m_green
protected

Definition at line 530 of file image_viewer.cpp.

◆ m_blue

int ImageViewer::m_blue
protected

Definition at line 530 of file image_viewer.cpp.

◆ m_alpha

int ImageViewer::m_alpha
protected

Definition at line 530 of file image_viewer.cpp.

◆ m_gray

int ImageViewer::m_gray
protected

Definition at line 530 of file image_viewer.cpp.

◆ m_smooth

int ImageViewer::m_smooth
protected

Definition at line 531 of file image_viewer.cpp.

◆ m_difference

int ImageViewer::m_difference
protected

Definition at line 532 of file image_viewer.cpp.

◆ m_compression

float ImageViewer::m_compression
protected

Definition at line 534 of file image_viewer.cpp.

◆ m_saturation

float ImageViewer::m_saturation
protected

Definition at line 535 of file image_viewer.cpp.

◆ m_saturation_step

float ImageViewer::m_saturation_step
protected

Definition at line 536 of file image_viewer.cpp.

◆ m_saturation_max

float ImageViewer::m_saturation_max
protected

Definition at line 537 of file image_viewer.cpp.

◆ m_zoom

float ImageViewer::m_zoom
protected

Definition at line 539 of file image_viewer.cpp.

◆ m_index

int ImageViewer::m_index
protected

Definition at line 540 of file image_viewer.cpp.

◆ m_reference_index

int ImageViewer::m_reference_index
protected

Definition at line 541 of file image_viewer.cpp.

◆ m_graph

int ImageViewer::m_graph
protected

Definition at line 542 of file image_viewer.cpp.


The documentation for this struct was generated from the following file: