Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

https://doi.org/10.5201/ipol.2022.215
11 April 2026, 15:45:18 UTC
  • Code
  • Branches (0)
  • Releases (2)
  • Visits
    • Branches
    • Releases
      • 2
      • 2
      • 1
    • c530314
    • /
    • paraws
    • /
    • paraws.cpp
    Raw File Download

    To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
    Select below a type of object currently browsed in order to display its associated SWHID and permalink.

    • content
    • directory
    • snapshot
    • release
    origin badgecontent badge
    swh:1:cnt:57f48b168e521b8692adaa66007eaedbc2add313
    origin badgedirectory badge
    swh:1:dir:bb309b6c220124321a1ac969488a1621c674679d
    origin badgesnapshot badge
    swh:1:snp:78d18a3e9f4a56ecaf1e6817d370abae618d0a7c
    origin badgerelease badge
    swh:1:rel:f3a4320e8346f38185539583336571c1b856fc47

    This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
    Select below a type of object currently browsed in order to generate citations for them.

    • content
    • directory
    • snapshot
    • release
    (requires biblatex-software package)
    Generating citation ...
    (requires biblatex-software package)
    Generating citation ...
    (requires biblatex-software package)
    Generating citation ...
    (requires biblatex-software package)
    Generating citation ...
    paraws.cpp
    /*
     * Copyright 2018, Theodore Chabardes
     * <theodore.chabardes@mines-paristech.fr>
     *
     * This program is free software: you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation, either version 3 of the License, or
     * (at your option) any later version.
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     * You should have received a copy of the GNU General Public License
     * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     *
     */
    
    #include "src/paraws.hpp"
    #include "src/io_png_raw.hpp"
    #include "src/output_color.hpp"
    #include <iostream>
    #include <limits>
    #include <string>
    // Portable version of getopt.
    #define OPTPARSE_IMPLEMENTATION
    #define OPTPARSE_API static
    #include "src/optparse.h"
    #ifdef BENCH
    #include "src/bench.hpp"
    #include "src/debug.hpp"
    #include "src/label.hpp"
    #endif // BENCH
    
    bool check_compliance_image(const char *path, bool is_uint8, bool is_uint16,
                                bool is_uint32, size_t x, size_t y,
                                std::string &ext) {
      if (path == NULL)
        return false;
      std::string path_str = std::string(path);
      ext = path_str.substr(path_str.find_last_of(".") + 1);
      if (ext == "raw" && (x == 0 || y == 0))
        return false;
      return (is_uint8 + is_uint16 + is_uint32) == 1 &&
             (ext == "png" || ext == "raw");
    }
    
    bool check_structuring_element(bool cross, bool hexa, bool square, bool cross3d,
                                   bool cube) {
      return (cross + hexa + square + cross3d + cube) == 1;
    }
    
    void usage(const char *execName) {
      std::cout
          << execName << " [options]" << std::endl
          << "Options:" << std::endl
    #ifdef BENCH
          << "-A | --paraws_bench           Benchs paraws" << std::endl
          << "-B | --hqws_bench             Benchs hqws" << std::endl
    #endif // BENCH
          << "-h | --help                   Print this help" << std::endl
          << "-i | --input_uint8            Path to uint8 input image" << std::endl
          << "-I | --input_uint16           Path to uint16 input image" << std::endl
          << "-m | --marker_uint8           Path to uint8 marker image" << std::endl
          << "-M | --marker_uint16          Path to uint16 marker image"
          << std::endl
          << "-N | --marker_uint32          Path to uint32 marker image"
          << std::endl
          << "-o | --output_uint8           Path to uint8 output image" << std::endl
          << "-O | --output_uint16          Path to uint16 output image"
          << std::endl
          << "-P | --output_uint32          Path to uint32 output image"
          << std::endl
          << "-C | --cross                  4-connex structuring element"
          << std::endl
          << "-H | --hexa                   Hexagonal structuring element"
          << std::endl
          << "-S | --square                 8-connex structuring element"
          << std::endl
          << "-R | --cross3d                6-connex structuring element (3d)"
          << std::endl
          << "-U | --cube                   26-connex structuring element (3d)"
          << std::endl
          << "-x | --size_x                 Width dimension (only for raw images)"
          << std::endl
          << "-y | --size_y                 Height dimension (only for raw images)"
          << std::endl
          << "-z | --size_z                 Depth dimension (only for raw images)"
          << std::endl
          << "-w | --without_labels_limit   Ignore errors due to label number "
             "overflow"
          << std::endl
          << "-g | --export_RGB             Export the output image in RGB format."
          << std::endl
          << std::endl
          << "This program needs at least one input image, one output image and a "
             "structuring element. Only png and raw format are supported, and it "
             "should be identical for the input and the ouput. If raw format is "
             "used, dimensions must be specified. An additional markers image can "
             "be used for constrained watershed, whose type should match the "
             "output image.."
          << std::endl;
    }
    
    template <class Tin, class Tout>
    int exec_paraws(const char *inp, const char *outp, const char *markp,
                    std::string ext1, std::string ext2, std::string ext3, size_t &x,
                    size_t &y, size_t &z, const structuring_element &se,
                    bool ignore_label_limit, bool export_RGB) {
      Tin *im = NULL;
      Tout *out = NULL;
    
      int result = RES_OK;
    
      if (ext1 == "png") {
        io_png_read(im, inp, &x, &y);
      } else if (ext1 == "raw") {
        io_raw_read(im, inp, x, y, z);
      }
    
      if (im == NULL)
        return ERROR_IN;
    
      out = new Tout[x * y * z];
    
      if (markp) {
        Tout *markers = NULL;
        if (ext3 == "png") {
          io_png_read(markers, markp, &x, &y);
        } else if (ext3 == "raw") {
          io_raw_read(markers, markp, x, y, z);
        }
        if (markers == NULL)
          return ERROR_IN;
        result = paraws(im, markers, out, x, y, z, se, ignore_label_limit);
        delete[] markers;
      } else {
        result = paraws(im, out, x, y, z, se, ignore_label_limit);
      }
    
      if(result == RES_OK) {
        if (!export_RGB) {
          if (ext2 == "png") {
            if (io_png_write(outp, out, x, y) != 0)
              result = ERROR_IN;
          } else if (ext2 == "raw") {
            if (io_raw_write(outp, out, x, y, z) != 0)
              result = ERROR_IN;
          }
        } else {
          io_png_write_color (outp, out, x, y);
        }
      }
    
      delete[] im;
      delete[] out;
      return result;
    }
    
    template <class Tin, class Tout>
    ERROR benchmark(size_t x, size_t y, size_t z, const structuring_element &se,
                    bool ignore_label_limit, bool paraws_bench, bool hqws_bench) {
      Tin *im = new Tin[x * y * z];
      Tout *out = new Tout[x * y * z]();
    
      random_matrix(im, false, domain(x, y, z));
    
      ERROR result = RES_OK;
    
      if (paraws_bench) {
        result = paraws(im, out, x, y, z, se, ignore_label_limit);
        if (result != RES_OK) {
          delete[] im;
          delete[] out;
          return result;
        }
      }
      if (hqws_bench) {
        result = hqws(im, out, x, y, z, se, ignore_label_limit);
      }
    
      delete[] im;
      delete[] out;
    
      return result;
    }
    
    int main(const int __attribute__((__unused__)) argc, char **argv) {
      // Data types
      bool in8 = false, in16 = false, mark8 = false, mark16 = false, mark32 = false,
           out8 = false, out16 = false, out32 = false;
      // Connectivity
      bool cross = false, hexa = false, square = false, cross3d = false,
           cube = false;
    #ifdef BENCH
      // Bench
      bool paraws_bench = false;
      bool hqws_bench = false;
    #endif // BENCH
      // paths
      char *inp = NULL, *markp = NULL, *outp = NULL;
      // Dimensions
      size_t x = 0, y = 0, z = 1; // Default value for z.
      // Labels overflow
      bool ignore_label_limit = false;
      // Export the output image in RGB format for visualisation purposes.
      bool export_RGB = false;
    
      struct optparse_long long_options[] = {
    #ifdef BENCH
          {"paraws_bench", 'A', OPTPARSE_NONE},
          {"hqws_bench", 'B', OPTPARSE_NONE},
    #endif // BENCH
          {"input_uint8", 'i', OPTPARSE_REQUIRED},
          {"input_uint16", 'I', OPTPARSE_REQUIRED},
          {"marker_uint8", 'm', OPTPARSE_REQUIRED},
          {"marker_uint16", 'M', OPTPARSE_REQUIRED},
          {"marker_uint32", 'N', OPTPARSE_REQUIRED},
          {"output_uint8", 'o', OPTPARSE_REQUIRED},
          {"output_uint16", 'O', OPTPARSE_REQUIRED},
          {"output_uint32", 'P', OPTPARSE_REQUIRED},
          {"cross", 'C', OPTPARSE_NONE},
          {"hexa", 'H', OPTPARSE_NONE},
          {"square", 'S', OPTPARSE_NONE},
          {"cross3d", 'R', OPTPARSE_NONE},
          {"cube", 'U', OPTPARSE_NONE},
          {"size_x", 'x', OPTPARSE_REQUIRED},
          {"size_y", 'y', OPTPARSE_REQUIRED},
          {"size_z", 'z', OPTPARSE_REQUIRED},
          {"without_labels_limit", 'w', OPTPARSE_NONE},
          {"export_RGB", 'g', OPTPARSE_NONE},
          {"help", 'h', OPTPARSE_NONE},
          {0, 0, OPTPARSE_NONE}};
    
      // optparse variables.
      int option;
      struct optparse options;
    
      optparse_init(&options, argv);
    
      while ((option = optparse_long(&options, long_options, NULL)) != -1) {
        switch (option) {
    #ifdef BENCH
        case 'A':
          paraws_bench = true;
          break;
        case 'B':
          hqws_bench = true;
          break;
    #endif // BENCH
        case 'i':
          inp = options.optarg;
          in8 = true;
          break;
        case 'I':
          inp = options.optarg;
          in16 = true;
          break;
        case 'm':
          markp = options.optarg;
          mark8 = true;
          break;
        case 'M':
          markp = options.optarg;
          mark16 = true;
          break;
        case 'N':
          markp = options.optarg;
          mark32 = true;
          break;
        case 'o':
          outp = options.optarg;
          out8 = true;
          break;
        case 'O':
          outp = options.optarg;
          out16 = true;
          break;
        case 'P':
          outp = options.optarg;
          out32 = true;
          break;
        case 'C':
          cross = true;
          break;
        case 'H':
          hexa = true;
          break;
        case 'S':
          square = true;
          break;
        case 'R':
          cross3d = true;
          break;
        case 'U':
          cube = true;
          break;
        case 'x':
          x = atoi(options.optarg);
          break;
        case 'y':
          y = atoi(options.optarg);
          break;
        case 'z':
          z = atoi(options.optarg);
          break;
        case 'w':
          ignore_label_limit = true;
          break;
        case 'g':
          export_RGB = true;
          break;
        case 'h':
          break;
        case '?':
          std::cerr << argv[0] << ": " << options.errmsg << std::endl;
          exit(EXIT_FAILURE);
        }
      }
    
      // If arguments remain, then failure.
      if ((optparse_arg(&options))) {
        std::cerr << argv[0] << ": "
                  << "Unknown arguments." << std::endl;
      }
    
      // Checking if everything is correct, before reading...
      bool is_compliant = true;
      is_compliant &= check_structuring_element(cross, hexa, square, cross3d, cube);
    
      // Loading the appropriate structuring element.
      structuring_element se;
      if (cross) {
        se = get_structuring_element(SE_CROSS);
      } else if (hexa) {
        se = get_structuring_element(SE_HEX);
      } else if (square) {
        se = get_structuring_element(SE_SQUARE);
      } else if (cross3d) {
        se = get_structuring_element(SE_CROSS_3D);
      } else if (cube) {
        se = get_structuring_element(SE_CUBE);
      }
    
      // For Benchs
    #ifdef BENCH
      bool bench = paraws_bench || hqws_bench;
      if (bench) {
        // Something is wrong, print the help message and exit.
        if (!is_compliant) {
          usage(argv[0]);
          exit(EXIT_FAILURE);
        }
        if (x == 0 || y == 0) {
          usage(argv[0]);
          exit(EXIT_FAILURE);
        }
        if (benchmark<uint8_t, uint8_t>(x, y, z, se, ignore_label_limit,
                                        paraws_bench, hqws_bench) == RES_OK)
          exit(EXIT_SUCCESS);
        exit(EXIT_FAILURE);
      }
    #endif // BENCH
    
      size_t x1 = x, y1 = y, z1 = z;
      std::string ext1;
      is_compliant &= check_compliance_image(inp, in8, in16, false, x1, y1, ext1);
      size_t x2 = x, y2 = y, z2 = z;
      std::string ext2;
      is_compliant &=
          check_compliance_image(outp, out8, out16, out32, x2, y2, ext2);
      is_compliant &= x1 == x2 && y1 == y2 && z1 == z2;
      is_compliant &= ext1 == ext2;
    
      // Color images are only available in png format.
      if (ext2 == "raw" && export_RGB)
          is_compliant = false;
    
      size_t x3 = x, y3 = y, z3 = z;
      std::string ext3;
      if (mark8 || mark16) {
        is_compliant &=
            check_compliance_image(markp, mark8, mark16, mark32, x3, y3, ext3);
        is_compliant &= ext2 == ext3;
        is_compliant &= (out8 == mark8) && (out16 == mark16) && (out32 == mark32);
        is_compliant &= x1 == x3 && y1 == y3 && z1 == z3;
      }
    
      // Something is wrong, print the help message and exit.
      if (!is_compliant) {
        usage(argv[0]);
        exit(EXIT_FAILURE);
      }
    
      int result = EXIT_SUCCESS;
    
      if (in8) {
        if (out8) {
          result = exec_paraws<uint8_t, uint8_t>(inp, outp, markp, ext1, ext2, ext3,
                                                 x, y, z, se, ignore_label_limit, export_RGB);
        } else if (out16) {
          result = exec_paraws<uint8_t, uint16_t>(
              inp, outp, markp, ext1, ext2, ext3, x, y, z, se, ignore_label_limit, export_RGB);
        } else if (out32) {
          result = exec_paraws<uint8_t, uint32_t>(
              inp, outp, markp, ext1, ext2, ext3, x, y, z, se, ignore_label_limit, export_RGB);
        }
      } else if (in16) {
        if (out8) {
          result = exec_paraws<uint16_t, uint8_t>(
              inp, outp, markp, ext1, ext2, ext3, x, y, z, se, ignore_label_limit, export_RGB);
        } else if (out16) {
          result = exec_paraws<uint16_t, uint16_t>(
              inp, outp, markp, ext1, ext2, ext3, x, y, z, se, ignore_label_limit, export_RGB);
        } else if (out32) {
          result = exec_paraws<uint16_t, uint32_t>(
              inp, outp, markp, ext1, ext2, ext3, x, y, z, se, ignore_label_limit, export_RGB);
        }
      }
      if (result != 0) {
        if (result == ERROR_IN) {
          std::cerr << "Error: in/out error..." << std::endl;
          usage(argv[0]);
        } else if (result == ERROR_LABEL) {
          std::cerr << "Error: maximum label value reached..." << std::endl;
        }
        exit(EXIT_FAILURE);
      }
      exit(EXIT_SUCCESS);
    }
    

    back to top

    Software Heritage — Copyright (C) 2015–2026, The Software Heritage developers. License: GNU AGPLv3+.
    The source code of Software Heritage itself is available on our development forge.
    The source code files archived by Software Heritage are available under their own copyright and licenses.
    Terms of use: Archive access, API— Content policy— Contact— JavaScript license information— Web API