                                  command=lambda cmd=action: cmd(config_key))
              btnutl.pack(padx=2, side=tk.RIGHT)
              Tooltip(btnutl, text=text, wraplength=200)
          logger.debug("Added util buttons")
  
  
  class ControlBuilder():
      """
      Builds and returns a frame containing a tkinter control with label
  
      Currently only setup for config items
  
      Parameters
      ----------
      parent: tkinter object
          Parent tkinter object
      title: str
          Title of the control. Will be used for label text
      dtype: datatype object
          Datatype of the control
      default: str
          Default value for the control
      selected_value: str, optional
          Selected value for the control. If None, default will be used
      choices: list or tuple, object
          Used for combo boxes and radio control option setting
      is_radio: bool, optional
          Specifies to use a Radio control instead of combobox if choices are passed
      rounding: int or float, optional
          For slider controls. Sets the stepping
      min_max: int or float, optional
          For slider controls. Sets the min and max values
      helptext: str, optional
          Sets the tooltip text
      radio_columns: int, optional
          Sets the number of columns to use for grouping radio buttons
      label_width: int, optional
          Sets the width of the control label. Defaults to 20
      control_width: int, optional
          Sets the width of the control. Default is to auto expand
      """
      def __init__(self, parent, title, dtype, default,
                   selected_value=None, choices=None, is_radio=False, rounding=None,
                   min_max=None, helptext=None, radio_columns=3, label_width=20, control_width=None):
          logger.debug("Initializing %s: (parent: %s, title: %s, dtype: %s, default: %s, "
                       "selected_value: %s, choices: %s, is_radio: %s, rounding: %s, min_max: %s, "
                       "helptext: %s, radio_columns: %s, label_width: %s, control_width: %s)",
                       self.__class__.__name__, parent, title, dtype, default, selected_value,
                       choices, is_radio, rounding, min_max, helptext, radio_columns, label_width,
                       control_width)
  
          self.title = title
          self.default = default
  
          self.frame = self.control_frame(parent, helptext)
          self.control = self.set_control(dtype, choices, is_radio)
          self.tk_var = self.set_tk_var(dtype, selected_value)
  
          self.build_control(choices,
                             dtype,
                             rounding,
                             min_max,
                             radio_columns,
                             label_width,
                             control_width)
          logger.debug("Initialized: %s", self.__class__.__name__)
  
      # Frame, control type and varable
      def control_frame(self, parent, helptext):
          """ Frame to hold control and it's label """
          logger.debug("Build control frame")
          frame = ttk.Frame(parent)
          frame.pack(side=tk.TOP, fill=tk.X)
          if helptext is not None:
              helptext = self.format_helptext(helptext)
              Tooltip(frame, text=helptext, wraplength=720)
          logger.debug("Built control frame")
          return frame
  
      def format_helptext(self, helptext):
          """ Format the help text for tooltips """
          logger.debug("Format control help: '%s'", self.title)
          helptext = helptext.replace("\n\t", "\n  - ").replace("%%", "%")
          helptext = self.title + " - " + helptext
          logger.debug("Formatted control help: (title: '%s', help: '%s'", self.title, helptext)
          return helptext
  
      def set_control(self, dtype, choices, is_radio):
          """ Set the correct control type based on the datatype or for this option """
          if choices and is_radio:
              control = ttk.Radiobutton
          elif choices:
              control = ttk.Combobox
          elif dtype == bool:
              control = ttk.Checkbutton
          elif dtype in (int, float):
              control = ttk.Scale
          else:
              control = ttk.Entry
          logger.debug("Setting control '%s' to %s", self.title, control)
          return control
  
      def set_tk_var(self, dtype, selected_value):
          """ Correct variable type for control """
          logger.debug("Setting tk variable: (title: '%s', dtype: %s, selected_value: %s)",
                       self.title, dtype, selected_value)
          if dtype == bool:
              var = tk.BooleanVar
          elif dtype == int:
              var = tk.IntVar
          elif dtype == float:
              var = tk.DoubleVar
          else:
              var = tk.StringVar
          var = var(self.frame)
          val = self.default if selected_value is None else selected_value
          var.set(val)
          logger.debug("Set tk variable: (title: '%s', type: %s, value: '%s')",
                       self.title, type(var), val)
          return var
  
      # Build the full control
      def build_control(self, choices, dtype, rounding, min_max, radio_columns,
                        label_width, control_width):
          """ Build the correct control type for the option passed through """
          logger.debug("Build confog option control")
          self.build_control_label(label_width)
          self.build_one_control(choices, dtype, rounding, min_max, radio_columns, control_width)
          logger.debug("Built option control")
  
      def build_control_label(self, label_width):
          """ Label for control """
          logger.debug("Build control label: (title: '%s', label_width: %s)",
                       self.title, label_width)
          title = self.title.replace("_", " ").title()
          lbl = ttk.Label(self.frame, text=title, width=label_width, anchor=tk.W)
          lbl.pack(padx=5, pady=5, side=tk.LEFT, anchor=tk.N)
          logger.debug("Built control label: '%s'", self.title)
  
      def build_one_control(self, choices, dtype, rounding, min_max, radio_columns, control_width):
          """ Build and place the option controls """
          logger.debug("Build control: (title: '%s', control: %s, choices: %s, dtype: %s, "
                       "rounding: %s, min_max: %s: radio_columns: %s, control_width: %s)",
                       self.title, self.control, choices, dtype, rounding, min_max, radio_columns,
                       control_width)
          if self.control == ttk.Scale:
              ctl = self.slider_control(dtype, rounding, min_max)
          elif self.control == ttk.Radiobutton:
              ctl = self.radio_control(choices, radio_columns)
          else:
              ctl = self.control_to_optionsframe(choices)
          self.set_control_width(ctl, control_width)
          ctl.pack(padx=5, pady=5, fill=tk.X, expand=True)
          logger.debug("Built control: '%s'", self.title)
  
      @staticmethod
      def set_control_width(ctl, control_width):
          """ Set the control width if required """
          if control_width is not None:
              ctl.config(width=control_width)
  
      def radio_control(self, choices, columns):
          """ Create a group of radio buttons """
          logger.debug("Adding radio group: %s", self.title)
          ctl = ttk.Frame(self.frame)
          frames = list()
          for _ in range(columns):
              frame = ttk.Frame(ctl)
              frame.pack(padx=5, pady=5, fill=tk.X, expand=True, side=tk.LEFT, anchor=tk.N)
              frames.append(frame)
  
          for idx, choice in enumerate(choices):
              frame_id = idx % columns
              radio = ttk.Radiobutton(frames[frame_id],
                                      text=choice.title(),
                                      value=choice,
                                      variable=self.tk_var)
              radio.pack(anchor=tk.W)
              logger.debug("Adding radio option %s to column %s", choice, frame_id)
          logger.debug("Added radio group: '%s'", self.title)
          return ctl
  
      def slider_control(self, dtype, rounding, min_max):
          """ A slider control with corresponding Entry box """
          logger.debug("Add slider control to Options Frame: (title: '%s', dtype: %s, rounding: %s, "
                       "min_max: %s)", self.title, dtype, rounding, min_max)
          tbox = ttk.Entry(self.frame, width=8, textvariable=self.tk_var, justify=tk.RIGHT)
          tbox.pack(padx=(0, 5), side=tk.RIGHT)
          ctl = self.control(
              self.frame,
              variable=self.tk_var,
              command=lambda val, var=self.tk_var, dt=dtype, rn=rounding, mm=min_max:
              set_slider_rounding(val, var, dt, rn, mm))
          rc_menu = ContextMenu(tbox)
          rc_menu.cm_bind()
          ctl["from_"] = min_max[0]
          ctl["to"] = min_max[1]
          logger.debug("Added slider control to Options Frame: %s", self.title)
          return ctl
  
      def control_to_optionsframe(self, choices):
          """ Standard non-check buttons sit in the main options frame """
          logger.debug("Add control to Options Frame: (title: '%s', control: %s, choices: %s)",
                       self.title, self.control, choices)
          if self.control == ttk.Checkbutton:
              ctl = self.control(self.frame, variable=self.tk_var, text=None)
          else:
              ctl = self.control(self.frame, textvariable=self.tk_var)
              rc_menu = ContextMenu(ctl)
              rc_menu.cm_bind()
          if choices:
              logger.debug("Adding combo choices: %s", choices)
              ctl["values"] = [choice for choice in choices]
          logger.debug("Added control to Options Frame: %s", self.title)
          return ctl
 
</s> remove                     self.config.config[section][item] = new_value

    def get_config_dicts(self):
        """ Hold a custom config dict for the config """
 </s> add                     self._config.config[section][item] = new_value

    def _get_config_dicts(self):
        """ Obtain a custom configuration dictionary for convert configuration items in use
        by the preview tool formatted for control helper.

        Returns
        -------
        dict
            Each configuration section as keys, with the values as a dict of option:
            :class:`lib.gui.control_helper.ControlOption` pairs. """
        logger.debug("Formatting Config for GUI") </s> remove                 choices = get_available_masks() + ["predicted"]
 </s> add                 choices = self._create_mask_choices(defaults, available_masks, has_predicted_mask) </s> remove         for key, val in self.options.items():
            if key == "helptext":
                continue
            value = val.get("value", val["default"])
            ctl = ControlBuilder(self.optsframe,
                                 key,
                                 val["type"],
                                 value,
                                 selected_value=None,
                                 choices=val["choices"],
                                 is_radio=val["gui_radio"],
                                 rounding=val["rounding"],
                                 min_max=val["min_max"],
                                 helptext=val["helptext"],
                                 radio_columns=4)
            parent.config_tools.tk_vars.setdefault(config_key, dict())[key] = ctl.tk_var
        self.add_frame_separator()
        self.add_actions(parent, config_key)
 </s> add         Parameters
        ----------
        parent: tkinter object
            The tkinter object that will hold this configuration frame
        config_key: str
            The section/plugin key for these configuration options
        """
        logger.debug("Add Config Frame")
        panel_kwargs = dict(columns=2, option_columns=2, blank_nones=False)
        frame = ttk.Frame(self)
        frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
        cp_options = [opt for key, opt in self._options.items() if key != "helptext"]
        ControlPanel(frame, cp_options, header_text=None, **panel_kwargs)
        self._add_actions(parent, config_key) </s> remove     """ Swap a source face with a target """
    def __init__(self, output_dir, output_size, output_has_mask,
                 draw_transparent, pre_encode, arguments, configfile=None):
        logger.debug("Initializing %s: (output_dir: '%s', output_size: %s,  output_has_mask: %s, "
                     "draw_transparent: %s, pre_encode: %s, arguments: %s, configfile: %s)",
                     self.__class__.__name__, output_dir, output_size, output_has_mask,
                     draw_transparent, pre_encode, arguments, configfile)
        self.output_dir = output_dir
        self.draw_transparent = draw_transparent
        self.writer_pre_encode = pre_encode
        self.scale = arguments.output_scale / 100
        self.output_size = output_size
        self.output_has_mask = output_has_mask
        self.args = arguments
        self.configfile = configfile
        self.adjustments = dict(box=None, mask=None, color=None, seamless=None, scaling=None)
        self.load_plugins()
 </s> add     """ The converter is responsible for swapping the original face(s) in a frame with the output
    of a trained Faceswap model.

    Parameters
    ----------
    output_size: int
        The size of the face, in pixels, that is output from the Faceswap model
    coverage_ratio: float
        The ratio of the training image that was used for training the Faceswap model
    draw_transparent: bool
        Whether the final output should be drawn onto a transparent layer rather than the original
        frame. Only available with certain writer plugins.
    pre_encode: python function
        Some writer plugins support the pre-encoding of images prior to saving out. As patching is
        done in multiple threads, but writing is done in a single thread, it can speed up the
        process to do any pre-encoding as part of the converter process.
    arguments: :class:`argparse.Namespace`
        The arguments that were passed to the convert process as generated from Faceswap's command
        line arguments
    configfile: str, optional
        Optional location of custom configuration ``ini`` file. If ``None`` then use the default
        config location. Default: ``None``
    """
    def __init__(self, output_size, coverage_ratio, draw_transparent, pre_encode,
                 arguments, configfile=None):
        logger.debug("Initializing %s: (output_size: %s,  coverage_ratio: %s, draw_transparent: "
                     "%s, pre_encode: %s, arguments: %s, configfile: %s)", self.__class__.__name__,
                     output_size, coverage_ratio, draw_transparent, pre_encode, arguments,
                     configfile)
        self._output_size = output_size
        self._coverage_ratio = coverage_ratio
        self._draw_transparent = draw_transparent
        self._writer_pre_encode = pre_encode
        self._args = arguments
        self._configfile = configfile

        self._scale = arguments.output_scale / 100
        self._adjustments = dict(box=None, mask=None, color=None, seamless=None, scaling=None)

        self._load_plugins()
                                  command=lambda cmd=action: cmd(config_key))
              btnutl.pack(padx=2, side=tk.RIGHT)
              Tooltip(btnutl, text=text, wraplength=200)
          logger.debug("Added util buttons")



















































































































































































































keep keep keep keep replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace replace
 Smart Masks to Convert (#957)

- scripts.convert - Use Smart Masks for Convert
    * Make on-the-fly conversion an explicit option

- Move BlurMask to lib.faces_detect

- tools.preview - Fix for smart masks
    * Subclass from tk.Tk
    * Options to lib.gui.control_helper
    *variable cleanup

- lib.logger - Demote more tensorflow deprecation messages

- Documentation:
    * lib.faces_detect.BlurMask
    * plugins.convert.mask
    * lib.convert
    * scripts.convert
    * scripts.fsmedia
    * tools.preview 
tools/preview.py