@@ -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