From 7b07f66bfba5d33581b9cb00a1e3cfd966001a85 Mon Sep 17 00:00:00 2001 From: augustin64 Date: Thu, 3 Apr 2025 08:48:38 +0200 Subject: [PATCH] Add --until-mask-removal Are all seams contributing to mask ? --- src/seam-carving.cpp | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/seam-carving.cpp b/src/seam-carving.cpp index d840206..6891f07 100644 --- a/src/seam-carving.cpp +++ b/src/seam-carving.cpp @@ -12,9 +12,12 @@ #include #include +#define DEFAULT_SEAMS 1 + // Global flags bool silent = false; bool test_energy = false; +bool until_mask_removal = false; int max_step = 1; // Get index for any table indexed by [width*(i : height) + (j : width)], but a @@ -310,6 +313,18 @@ std::vector> mask_energy(std::vector energy, return output; } +bool does_seam_remove_mask(unsigned char* mask, int width, int height, int nbChannels, + std::vector opt_seam, bool vertical) +{ + int dim_large = vertical ? width : height; + int dim_long = vertical ? height : width; + + for (int i=0; i < dim_long; i++) { + if (mask[im_index(i, opt_seam[i])] == 0) return true; + } + return false; +} + void seam_carving(unsigned char *source, int width, int height, int nbChannels, const char *out_filename, int nbSeams, bool vertical, unsigned char* mask=nullptr) { int nbColorChannels = nbChannels > 3 ? 3 : nbChannels; @@ -384,16 +399,23 @@ void seam_carving(unsigned char *source, int width, int height, int nbChannels, } } - SimpleProgressBar::ProgressBar bar(nbSeams); + SimpleProgressBar::ProgressBar bar(until_mask_removal ? dim_large : nbSeams); bar.print(); - for (auto seam_index = 0; seam_index < nbSeams; seam_index++) { + auto seam_index = 0; + while (seam_index++ < nbSeams || until_mask_removal) { std::vector opt_seam; if (mask) { opt_seam = carving_step( source_img, masked_energy, output_img, output_masked_energy, curWidth, curHeight, nbChannels, nbColorChannels, vertical ); + + if ( + until_mask_removal && + !does_seam_remove_mask(mask, width, height, nbChannels, opt_seam, vertical) + ) break; + } else { opt_seam = carving_step( source_img, source_energy, output_img, output_energy, @@ -446,7 +468,7 @@ int main(int argc, char **argv) { std::string maskImage; std::string sourceImage; std::string outputImage = "output.png"; - int nbSeams = 1; + int nbSeams = DEFAULT_SEAMS; bool vertical = false; app.add_option("-s,--source", sourceImage, "Source image") @@ -466,6 +488,8 @@ int main(int argc, char **argv) { app.add_flag("--silent", silent, "No verbose messages"); app.add_flag("--test-energy", test_energy, "Don't resize image, just try the specified energy function"); + app.add_flag("-u,--until-mask-removal", until_mask_removal, + "Carve the image until there are no more red pixels in the mask"); CLI11_PARSE(app, argc, argv); // Image loading @@ -504,6 +528,14 @@ int main(int argc, char **argv) { //* . (2) we want to keep the pixel //* . (1) nothing in particular //* . (0) we want to remove the pixel + } + if (until_mask_removal && maskImage.empty()) { + std::cerr << "Flag --until-mask-removal but no mask provided." << std::endl; + until_mask_removal = false; + } + if (until_mask_removal && nbSeams != DEFAULT_SEAMS) { + std::cerr << "Flag --nb-seams specified but --until-mask-removal provided." << std::endl; + nbSeams = DEFAULT_SEAMS; } nbSeams = std::min(nbSeams, vertical ? width-1 : height-1); // We want to keep at least one row or column