Skip to content

Commit f1f2aa0

Browse files
committed
Refactor image save and GPU texture code
Extract common image-writing logic into write_imagebuf_to_path and consolidate save-dialog default name routines into a single save_dialog_default_name with fallback/suffix handling to reduce duplication. Add OpenGL helper routines (bind_preview_texture_with_filter, begin_preview_draw, cleanup_preview_draw, finish_preview_draw) and simplify preview rendering flow via a small render_preview lambda to remove repeated GL setup/teardown. In Vulkan setup, introduce portability extension name constants and unify instance API version selection into choose_instance_api_version (cap to 1.3), replacing older helpers. In Vulkan texture creation, factor image/view/framebuffer/sampler creation into reusable lambdas (create_viewable_image, create_preview_framebuffer, create_texture_sampler) and improve resource naming and error reporting. Overall this reduces duplicate code paths and centralizes error handling for image IO and GPU resource setup. Signed-off-by: Vlad <shaamaan@gmail.com>
1 parent 6a42f23 commit f1f2aa0

4 files changed

Lines changed: 279 additions & 341 deletions

File tree

src/imiv/imiv_file_actions.cpp

Lines changed: 54 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -362,16 +362,29 @@ namespace {
362362
output, error_message);
363363
}
364364

365-
bool save_selection_image(const LoadedImage& image,
366-
const ViewerState& viewer,
367-
const std::string& path,
368-
std::string& error_message)
365+
bool write_imagebuf_to_path(ImageBuf& image, const std::string& path,
366+
TypeDesc format, std::string& error_message)
369367
{
370368
error_message.clear();
371369
if (path.empty()) {
372370
error_message = "save path is empty";
373371
return false;
374372
}
373+
if (!image.write(path, format)) {
374+
error_message = image.geterror();
375+
if (error_message.empty())
376+
error_message = "image write failed";
377+
return false;
378+
}
379+
return true;
380+
}
381+
382+
bool save_selection_image(const LoadedImage& image,
383+
const ViewerState& viewer,
384+
const std::string& path,
385+
std::string& error_message)
386+
{
387+
error_message.clear();
375388

376389
ImageBuf result;
377390
if (!build_selection_source_image(image, viewer, result, error_message))
@@ -391,38 +404,22 @@ namespace {
391404
}
392405

393406
result.specmod().attribute("Orientation", 1);
394-
if (!result.write(path, result.spec().format)) {
395-
error_message = result.geterror();
396-
if (error_message.empty())
397-
error_message = "image write failed";
398-
return false;
399-
}
400-
return true;
407+
return write_imagebuf_to_path(result, path, result.spec().format,
408+
error_message);
401409
}
402410

403411
bool save_window_image(const LoadedImage& image, const ViewRecipe& recipe,
404412
const PlaceholderUiState& ui_state,
405413
const std::string& path, std::string& error_message)
406414
{
407415
error_message.clear();
408-
if (path.empty()) {
409-
error_message = "save path is empty";
410-
return false;
411-
}
412416

413417
ImageBuf output;
414418
if (!build_window_export_rgba_image(image, recipe, ui_state, output,
415419
error_message)) {
416420
return false;
417421
}
418-
419-
if (!output.write(path, TypeFloat)) {
420-
error_message = output.geterror();
421-
if (error_message.empty())
422-
error_message = "image write failed";
423-
return false;
424-
}
425-
return true;
422+
return write_imagebuf_to_path(output, path, TypeFloat, error_message);
426423
}
427424

428425
bool save_export_selection_image(const LoadedImage& image,
@@ -432,10 +429,6 @@ namespace {
432429
std::string& error_message)
433430
{
434431
error_message.clear();
435-
if (path.empty()) {
436-
error_message = "save path is empty";
437-
return false;
438-
}
439432

440433
ImageBuf selection;
441434
if (!build_selection_source_image(image, viewer, selection,
@@ -448,24 +441,13 @@ namespace {
448441
ui_state, output, error_message)) {
449442
return false;
450443
}
451-
452-
if (!output.write(path, TypeFloat)) {
453-
error_message = output.geterror();
454-
if (error_message.empty())
455-
error_message = "image write failed";
456-
return false;
457-
}
458-
return true;
444+
return write_imagebuf_to_path(output, path, TypeFloat, error_message);
459445
}
460446

461447
bool save_loaded_image(const LoadedImage& image, const std::string& path,
462448
std::string& error_message)
463449
{
464450
error_message.clear();
465-
if (path.empty()) {
466-
error_message = "save path is empty";
467-
return false;
468-
}
469451
if (image.width <= 0 || image.height <= 0 || image.nchannels <= 0) {
470452
error_message = "no valid image is loaded";
471453
return false;
@@ -507,14 +489,7 @@ namespace {
507489
error_message = "failed to copy pixels into save buffer";
508490
return false;
509491
}
510-
511-
if (!output.write(path, format)) {
512-
error_message = output.geterror();
513-
if (error_message.empty())
514-
error_message = "image write failed";
515-
return false;
516-
}
517-
return true;
492+
return write_imagebuf_to_path(output, path, format, error_message);
518493
}
519494

520495
bool open_directory_into_library(RendererState& renderer_state,
@@ -591,50 +566,29 @@ namespace {
591566
return std::string();
592567
}
593568

594-
std::string save_dialog_default_name(const ViewerState& viewer)
595-
{
596-
if (viewer.image.path.empty())
597-
return "image.exr";
598-
std::filesystem::path p(viewer.image.path);
599-
if (p.filename().empty())
600-
return "image.exr";
601-
return p.filename().string();
602-
}
603-
604-
std::string save_selection_default_name(const ViewerState& viewer)
605-
{
606-
if (viewer.image.path.empty())
607-
return "selection.exr";
608-
std::filesystem::path p(viewer.image.path);
609-
const std::string stem = p.stem().empty() ? "selection"
610-
: p.stem().string();
611-
const std::string ext = p.extension().empty() ? ".exr"
612-
: p.extension().string();
613-
return stem + "_selection" + ext;
614-
}
615-
616-
std::string export_selection_default_name(const ViewerState& viewer)
617-
{
618-
if (viewer.image.path.empty())
619-
return "selection_export.exr";
620-
std::filesystem::path p(viewer.image.path);
621-
const std::string stem = p.stem().empty() ? "selection_export"
622-
: p.stem().string();
623-
const std::string ext = p.extension().empty() ? ".exr"
624-
: p.extension().string();
625-
return stem + "_selection_export" + ext;
626-
}
627-
628-
std::string save_window_default_name(const ViewerState& viewer)
569+
std::string save_dialog_default_name(const ViewerState& viewer,
570+
const char* fallback_name,
571+
const char* suffix)
629572
{
630573
if (viewer.image.path.empty())
631-
return "window.exr";
632-
std::filesystem::path p(viewer.image.path);
633-
const std::string stem = p.stem().empty() ? "window"
634-
: p.stem().string();
635-
const std::string ext = p.extension().empty() ? ".exr"
636-
: p.extension().string();
637-
return stem + "_window" + ext;
574+
return fallback_name;
575+
576+
const std::filesystem::path path(viewer.image.path);
577+
if (suffix[0] == '\0') {
578+
if (!path.filename().empty())
579+
return path.filename().string();
580+
return fallback_name;
581+
}
582+
583+
const std::filesystem::path fallback(fallback_name);
584+
const std::string stem = path.stem().empty() ? fallback.stem().string()
585+
: path.stem().string();
586+
const std::string ext = path.extension().empty()
587+
? (fallback.extension().empty()
588+
? ".exr"
589+
: fallback.extension().string())
590+
: path.extension().string();
591+
return stem + suffix + ext;
638592
}
639593

640594
struct SaveDialogSpec {
@@ -651,26 +605,32 @@ namespace {
651605
SaveDialogSpec spec;
652606
switch (kind) {
653607
case SaveDialogKind::SaveImage:
654-
spec.default_name = save_dialog_default_name(viewer);
608+
spec.default_name = save_dialog_default_name(viewer, "image.exr",
609+
"");
655610
return spec;
656611
case SaveDialogKind::SaveWindow:
657612
spec.cancel_message = "Save window cancelled";
658-
spec.default_name = save_window_default_name(viewer);
613+
spec.default_name = save_dialog_default_name(viewer, "window.exr",
614+
"_window");
659615
return spec;
660616
case SaveDialogKind::SaveSelection:
661617
spec.missing_selection_error = "No selection to save";
662618
spec.cancel_message = "Save selection cancelled";
663-
spec.default_name = save_selection_default_name(viewer);
619+
spec.default_name = save_dialog_default_name(viewer,
620+
"selection.exr",
621+
"_selection");
664622
return spec;
665623
case SaveDialogKind::ExportSelection:
666624
spec.missing_image_error = "No image loaded to export";
667625
spec.missing_selection_error = "No selection to export";
668626
spec.cancel_message = "Export selection cancelled";
669627
spec.failure_prefix = "export failed";
670-
spec.default_name = export_selection_default_name(viewer);
628+
spec.default_name = save_dialog_default_name(viewer,
629+
"selection_export.exr",
630+
"_selection_export");
671631
return spec;
672632
}
673-
spec.default_name = save_dialog_default_name(viewer);
633+
spec.default_name = save_dialog_default_name(viewer, "image.exr", "");
674634
return spec;
675635
}
676636

0 commit comments

Comments
 (0)