  
          If the canvas that holds the preview image changes, update the image size
          to fit the new canvas and refresh :attr:`previewtrain`.
  
          Parameters
          ----------
          name: str
              The name of the training image to be resized
          frame_dims: tuple, optional
              The (width (`int`), height (`int`)) of the display panel that will display the preview.
              ``None`` if the frame dimensions are not known.
          """
          logger.debug("Resizing image: (name: '%s', frame_dims: %s", name, frame_dims)
          displayimg = cast(Image.Image, self._previewtrain[name][0])
          if frame_dims:
              frameratio = float(frame_dims[0]) / float(frame_dims[1])
 
</s> remove         logger.debug("Resizing image: (name: '%s', frame_dims: %s", name, frame_dims)
        displayimg = cast(Image.Image, self._previewtrain[name][0])
        if frame_dims:
            frameratio = float(frame_dims[0]) / float(frame_dims[1])
            imgratio = float(displayimg.size[0]) / float(displayimg.size[1])

            if frameratio <= imgratio:
                scale = frame_dims[0] / float(displayimg.size[0])
                size = (frame_dims[0], int(displayimg.size[1] * scale))
            else:
                scale = frame_dims[1] / float(displayimg.size[1])
                size = (int(displayimg.size[0] * scale), frame_dims[1])
            logger.debug("Scaling: (scale: %s, size: %s", scale, size)

            # Hacky fix to force a reload if it happens to find corrupted
            # data, probably due to reading the image whilst it is partially
            # saved. If it continues to fail, then eventually raise.
            for i in range(0, 1000):
                try:
                    displayimg = displayimg.resize(size, Image.ANTIALIAS)
                except OSError:
                    if i == 999:
                        raise
                    continue
                break
        self._previewtrain[name][1] = ImageTk.PhotoImage(displayimg)
 </s> add         logger.debug("Deleting previews")
        for item in os.listdir(self._pathpreview):
            if item.startswith(os.path.splitext(TRAININGPREVIEW)[0]) and item.endswith((".jpg",
                                                                                        ".png")):
                fullitem = os.path.join(self._pathpreview, item)
                logger.debug("Deleting: '%s'", fullitem)
                os.remove(fullitem)

        self._preview_extract.delete_previews()
        del self._preview_train
        del self._preview_extract
        self._preview_train = PreviewTrain(self._pathpreview)
        self._preview_extract = PreviewExtract(self._pathpreview) </s> remove     def resize_image(self, name: str, frame_dims: Optional[Tuple[int, int]]) -> None:
        """ Resize the training preview image based on the passed in frame size.
 </s> add         """
        size = get_config().user_config_dict.get("icon_size", 16)
        size = int(round(size * get_config().scaling_factor))
        icons: Dict[str, ImageTk.PhotoImage] = {}
        pathicons = os.path.join(PATHCACHE, "icons")
        for fname in os.listdir(pathicons):
            name, ext = os.path.splitext(fname)
            if ext != ".png":
                continue
            img = Image.open(os.path.join(pathicons, fname))
            img = ImageTk.PhotoImage(img.resize((size, size), resample=Image.HAMMING))
            icons[name] = img
        logger.debug(icons)
        return icons </s> remove             The size of the thumbnail that the placeholder should replicate
 </s> add             The size of each thumbnail that should be created
        frame_dims: tuple
            The (width (`int`), height (`int`)) of the display panel that will display the preview

        Returns
        -------
        bool
            ``True`` if a preview was succesfully loaded otherwise ``False`` </s> remove         logger.trace("Displaying preview")  # type:ignore
        sortednames = sorted(list(get_images().previewtrain.keys()))
        existing = self.subnotebook_get_titles_ids()
        should_update = self.update_preview.get()

        for name in sortednames:
            if name not in existing:
                self.add_child(name)
            elif should_update:
                tab_id = existing[name]
                self.update_child(tab_id, name)

        if should_update:
            self.update_preview.set(False)

    def add_child(self, name: str) -> None:
        """ Add the preview canvas child

        Parameters
        ----------
        name: str
            The name of the notebook tab to add
        """
        logger.debug("Adding child")
        preview = PreviewTrainCanvas(self.subnotebook, name)
        preview = self.subnotebook_add_page(name, widget=preview)
        Tooltip(preview, text=self.helptext, wrap_length=200)
        self.vars["modified"].set(get_images().previewtrain[name][2])

    def update_child(self, tab_id: int, name: str) -> None:
        """ Update the preview canvas
 </s> add         if self.subnotebook.children:
            return </s> remove         Parameters
        ----------
        tab_id: int
            The index of the tab to update
        name: str
            The name of the tab to update
        """
        logger.debug("Updating preview")
        if self.vars["modified"].get() != get_images().previewtrain[name][2]:
            self.vars["modified"].set(get_images().previewtrain[name][2])
            widget = self.subnotebook_page_from_id(tab_id)
            widget.reload()
 </s> add         logger.debug("Displaying preview")
        self._display = PreviewTk(self._preview.buffer, self.subnotebook, self.optsframe, None)
        self.subnotebook_add_page(self.tabname, widget=self._display.master_frame)
        Should be called when terminating tasks, or when Faceswap starts up or shuts down.
  
          If the canvas that holds the preview image changes, update the image size
          to fit the new canvas and refresh :attr:`previewtrain`.
  
        Should be called when terminating tasks, or when Faceswap starts up or shuts down.
        Should be called when terminating tasks, or when Faceswap starts up or shuts down.
        Should be called when terminating tasks, or when Faceswap starts up or shuts down.
        Should be called when terminating tasks, or when Faceswap starts up or shuts down.
        Should be called when terminating tasks, or when Faceswap starts up or shuts down.
        Should be called when terminating tasks, or when Faceswap starts up or shuts down.
        Should be called when terminating tasks, or when Faceswap starts up or shuts down.
          """
          logger.debug("Resizing image: (name: '%s', frame_dims: %s", name, frame_dims)
          displayimg = cast(Image.Image, self._previewtrain[name][0])
          if frame_dims:
              frameratio = float(frame_dims[0]) / float(frame_dims[1])
keep keep keep keep replace replace replace replace replace replace replace keep keep keep keep keep
 GUI - Preview updates
  - Training preview. Embed preview pop-out window
  - Bugfix - convert/extract previews 
lib/gui/utils/image.py