15#define _CRT_SECURE_NO_DEPRECATE
16#define _CRT_SECURE_NO_WARNINGS
17#pragma warning(disable : 4067)
18#pragma warning(disable : 4333)
19#pragma warning(disable : 4312)
23#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
24#pragma GCC diagnostic ignored "-Wformat-security"
28#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
29#pragma GCC diagnostic ignored "-Wformat-security"
35inline T
pw(T val, T power)
37 return copysign(1.0, val) * pow(abs(val), power);
40namespace cmap = tinycolormap;
45 static_cast<std::underlying_type_t<GIM_Flags>
>(lhs) |
46 static_cast<std::underlying_type_t<GIM_Flags>
>(rhs));
52 static_cast<std::underlying_type_t<GIM_Flags>
>(lhs) &
53 static_cast<std::underlying_type_t<GIM_Flags>
>(rhs));
59 return static_cast<bool>(flags & flag);
72 int binned_nx = (nx + bin_factor - 1) / bin_factor;
73 int binned_ny = (ny + bin_factor - 1) / bin_factor;
74 for (
int by = 0; by < binned_ny; by++)
76 for (
int bx = 0; bx < binned_nx; bx++)
78 set_pixel_binned(bx, by);
88 int last_yt = (last_idr / nx);
91 set_min_max(last_idr);
92 int binned_nx = (nx + bin_factor - 1) / bin_factor;
93 int y_start = (std::max)(0, this->last_y - render_update_offset);
94 int y_end = (std::min)(last_yt + render_update_offset, ny);
95 int by_start = y_start / bin_factor;
96 int by_end = (y_end + bin_factor - 1) / bin_factor;
97 for (
int by = by_start; by < by_end; by++)
99 for (
int bx = 0; bx < binned_nx; bx++)
101 set_pixel_binned(bx, by);
105 this->last_y = last_yt;
106 this->last_idr = last_idr;
113 int idr = idy * nx + idx;
114 float val =
pw((data->at(idr) - data_min) / data_range, power);
124 int idr = idy * nx + idx;
127 float mag = (abs(data->at(idr)) - data_min) / data_range;
128 float ang = arg(data->at(idr));
129 ang = (ang / M_PI + 1) / 2;
130 mag =
pw(mag, power);
142 for (
int dy = 0; dy < bin_factor; dy++)
144 for (
int dx = 0; dx < bin_factor; dx++)
146 int x = bx * bin_factor + dx;
147 int y = by * bin_factor + dy;
148 if (x < nx && y < ny)
150 sum += data->at(y * nx + x);
155 float avg = (count > 0) ? sum / count : 0.0f;
156 float val =
pw((avg - data_min) / data_range, power);
164 float mag_sum = 0.0f;
165 float ang_sin_sum = 0.0f;
166 float ang_cos_sum = 0.0f;
168 for (
int dy = 0; dy < bin_factor; dy++)
170 for (
int dx = 0; dx < bin_factor; dx++)
172 int x = bx * bin_factor + dx;
173 int y = by * bin_factor + dy;
174 if (x < nx && y < ny)
176 std::complex<float> val = data->at(y * nx + x);
178 float ang = arg(val);
179 ang_sin_sum += sin(ang);
180 ang_cos_sum += cos(ang);
185 float mag = (count > 0) ? (mag_sum / count - data_min) / data_range : 0.0f;
186 float ang = (count > 0) ? atan2(ang_sin_sum / count, ang_cos_sum / count) : 0.0f;
187 ang = (ang / M_PI + 1) / 2;
188 mag =
pw(mag, power);
201 return abs((*data)[idr]);
207 for (
int idr = this->last_idr; idr < last_idr; idr++)
209 float val = get_val(idr);
213 data_range = data_max - data_min;
214 b_trigger_update =
true;
219 data_range = data_max - data_min;
220 b_trigger_update =
true;
228 for (
int idr = 0; idr < nxy; idr++)
230 float val = get_val(idr);
234 data_range = data_max - data_min;
235 b_trigger_update =
true;
240 data_range = data_max - data_min;
241 b_trigger_update =
true;
252 this->tex_id = tex_id;
253 this->pb_open = visible;
254 this->auto_render = auto_render;
255 this->data_cmap = data_cmap;
264 this->render_update_offset = 0;
265 this->b_trigger_update =
false;
266 this->bin_factor = 1;
267 this->bin_factor_idx = 0;
268 saveFileDialog = ImGui::FileBrowser(ImGuiFileBrowserFlags_EnterNewFilename | ImGuiFileBrowserFlags_CreateNewDir);
269 saveFileDialog.SetTitle(
"Save " + title +
" image as .png");
270 saveDataDialog = ImGui::FileBrowser(ImGuiFileBrowserFlags_EnterNewFilename | ImGuiFileBrowserFlags_CreateNewDir);
271 saveDataDialog.SetTitle(
"Save " + title +
"-data as numpy array (.npy)");
273 uv_min = ImVec2(0.0f, 0.0f);
274 uv_max = ImVec2(1.0f, 1.0f);
275 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
276 border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f);
277 sdl_srf = SDL_CreateRGBSurface(0, this->nx, this->ny, 32, 0, 0, 0, 0);
280 std::cout <<
"Surface could not be created! SDL Error: " << SDL_GetError() << std::endl;
282 this->b_data_set =
false;
289 set_nx_ny(width, height);
306 data_range = FLT_MAX;
314 this->nxy = height * width;
316 data_fft.resize(nxy);
317 data_fft_f.resize(nxy);
318 data_val.resize(nxy);
329 SDL_FreeSurface(sdl_srf);
331 int binned_nx = (nx + bin_factor - 1) / bin_factor;
332 int binned_ny = (ny + bin_factor - 1) / bin_factor;
333 sdl_srf = SDL_CreateRGBSurface(0, binned_nx, binned_ny, 32, 0, 0, 0, 0);
336 std::cout <<
"Surface could not be created! SDL Error: " << SDL_GetError() << std::endl;
343 this->render_update_offset = render_update_offset;
344 render_window(b_redraw, last_y, b_trigger_update);
352 data_range = FLT_MAX;
359 FFT2D::r2c(*data, data_val);
360 fft2d.fft(data_val, data_fft);
361 FFT2D::c2abs(data_fft, data_fft_f);
368 fft2d.fft(*data, data_fft);
369 FFT2D::c2abs(data_fft, data_fft_f);
377 int n_im = (fr_count) / nxy;
387 fr_count -= (n_im * nxy);
397 val = data->at(y * nx + x);
398 ImGui::BeginTooltip();
399 ImGui::Text(
"XY: %i, %i", x, y);
400 ImGui::Text(
"Value: %.2f", val);
401 ImGui::Text(
"Zoom: %.2f", zoom);
408 std::complex<float> val = 0.0;
410 val = data->at(y * nx + x);
411 ImGui::BeginTooltip();
412 ImGui::Text(
"XY: %i, %i", x, y);
413 ImGui::Text(
"Angle: %.2f", arg(val));
414 ImGui::Text(
"Magnitude: %.2f", abs(val));
415 ImGui::Text(
"Zoom: %.2f", zoom);
423 ImGui::SetNextWindowSize(ImVec2{256, 256}, ImGuiCond_FirstUseEver);
424 bool t_open = ImGui::Begin(title.c_str(), pb_open, ImGuiWindowFlags_NoScrollbar);
427 bool fr_switch = detect_frame_switch(fr_count);
428 b_trigger_update = b_trigger_update || b_trigger_ext || fr_switch;
429 if (b_trigger_update)
437 if (ImGui::Button(
"Save Image as..."))
439 saveFileDialog.Open();
441 saveFileDialog.Display();
442 if (saveFileDialog.HasSelected())
444 std::string img_file = saveFileDialog.GetSelected().string();
445 saveFileDialog.ClearSelected();
453 if (ImGui::Button(
"Save Data as..."))
455 saveDataDialog.Open();
457 saveDataDialog.Display();
458 if (saveDataDialog.HasSelected())
460 std::string com_file = saveDataDialog.GetSelected().string();
461 saveDataDialog.ClearSelected();
469 bool fft_button_press = ImGui::Button(
"Compute FFT");
470 if (fft_button_press)
472 *fft_window->pb_open =
true;
474 if (fft_button_press || (*fft_window->pb_open && b_trigger_update))
479 fft_window->set_data(nx, ny, &data_fft_f);
480 fft_window->b_trigger_update =
true;
484 std::cout <<
"FFT was not performed, because no data was found in " + this->title +
"!" << std::endl;
492 ImGui::SetNextItemWidth(64);
493 if (ImGui::DragFloat(
"Power", &power, 0.05f, 0.05f, 2.0f,
"%.2f"))
497 render_image((fr_count == 0) ? nxy : fr_count);
498 b_trigger_update =
true;
505 ImGui::SetNextItemWidth(100);
506 if (ImGui::Combo(
"Colormap", &data_cmap, cmaps, IM_ARRAYSIZE(cmaps)))
510 render_image((fr_count == 0) ? nxy : fr_count);
511 b_trigger_update =
true;
517 ImGui::SetNextItemWidth(60);
518 if (ImGui::Combo(
"Bin", &bin_factor_idx, bin_options, IM_ARRAYSIZE(bin_options)))
520 bin_factor = 1 << bin_factor_idx;
524 render_image((fr_count == 0) ? nxy : fr_count);
525 b_trigger_update =
true;
528 if (b_redraw && auto_render && fr_count > 0)
529 render_image(fr_count);
531 ImGui::SetNextWindowBgAlpha(0.0f);
532 ImGui::BeginChildFrame(ImGui::GetID(
"ImageFrame"), ImVec2(0.0f, 0.0f), ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
533 ImVec2 vAvail = ImGui::GetContentRegionAvail();
534 float scale = (std::min)(vAvail.x / sdl_srf->w, vAvail.y / sdl_srf->h);
535 float tex_h = sdl_srf->h * scale;
536 float tex_w = sdl_srf->w * scale;
537 float tex_h_z = tex_h * zoom;
538 float tex_w_z = tex_w * zoom;
539 if (b_redraw || b_trigger_update)
541 glBindTexture(GL_TEXTURE_2D, (*tex_id));
542 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, sdl_srf->w, sdl_srf->h, 0,
543 GL_BGRA, GL_UNSIGNED_BYTE, sdl_srf->pixels);
545 ImVec2 pos = ImGui::GetCursorScreenPos();
546 ImGui::Image((ImTextureID)(*tex_id), ImVec2(tex_w_z, tex_h_z), uv_min, uv_max, tint_col, border_col);
547 if (ImGui::IsItemHovered())
551 float dz = (float)io.MouseWheel;
552 ImVec2 xy = ImGui::GetMousePos();
555 float rel_x = xy.x - pos.x - ImGui::GetScrollX();
556 float rel_y = xy.y - pos.y - ImGui::GetScrollY();
560 if ((std::abs(dz) > 0.0f) || ImGui::IsMouseClicked(ImGuiMouseButton_Left))
564 start_xs = ImGui::GetScrollX();
565 start_ys = ImGui::GetScrollY();
569 if (ImGui::IsMouseDown(ImGuiMouseButton_Left))
571 ImGui::SetScrollX(start_xs - (rel_x - start_x));
572 ImGui::SetScrollY(start_ys - (rel_y - start_y));
576 if (std::abs(dz) > 0.0f)
579 float zoom2 = zoom + dz * 0.1;
580 zoom2 = (std::max)(1.0f, zoom2);
582 float dx = ((xy.x - pos.x) / tex_w_z) * tex_w * (zoom2 - zoom);
583 float dy = ((xy.y - pos.y) / tex_h_z) * tex_h * (zoom2 - zoom);
585 ImGui::SetScrollX(start_xs + dx);
586 ImGui::SetScrollY(start_ys + dy);
592 if (ImGui::IsMouseDown(ImGuiMouseButton_Right))
594 float scale_fct = scale * zoom;
595 int x = (int)std::floor((xy.x - pos.x) / scale_fct);
596 int y = (int)std::floor((xy.y - pos.y) / scale_fct);
597 value_tooltip(x, y, zoom);
599 if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
602 ImGui::SetScrollX(0.0f);
603 ImGui::SetScrollY(0.0f);
606 ImGui::EndChildFrame();
609 b_trigger_update =
false;
void save_numpy(std::string *path, int nx, int ny, std::vector< T > *data)
void save_image(std::string *path, SDL_Surface *sdl_srf)
GIM_Flags operator|(GIM_Flags lhs, GIM_Flags rhs)
GIM_Flags operator&(GIM_Flags lhs, GIM_Flags rhs)
ImGuiImageWindow(const std::string &title, GLuint *tex_id, bool auto_render, int data_cmap, GIM_Flags flags=GIM_Flags::None, bool *visible=nullptr)
void set_nx_ny(int width, int height)
void set_data(int width, int height, std::vector< T > *data)
void render_window(bool b_redraw, int last_y, int render_update_offset, bool b_trigger_update)
void draw_pixel(SDL_Surface *surface, int x, int y, float val, int col_map)