              return None
          remainder = (cols * rows) - num_images
          if remainder != 0:
              logger.debug("Padding sample display. Remainder: %s", remainder)
              placeholder = np.concatenate([np.expand_dims(
                  cast(np.ndarray, self._previewcache["placeholder"]), 0)] * remainder)
              samples = np.concatenate((samples, placeholder))
  
          display = np.vstack([np.hstack(cast(Sequence, samples[row * cols: (row + 1) * cols]))
                               for row in range(rows)])
          logger.debug("display shape: %s", display.shape)
 
</s> remove         asamples = np.array(samples)
        if not np.any(asamples):
            logger.debug("No preview images collected.")
            return False

        self._previewcache["filenames"] = (cast(List[str], self._previewcache["filenames"]) +
                                           filenames)[-num_images:]
        cache = cast(Optional[np.ndarray], self._previewcache["images"])
        if cache is None:
            logger.debug("Creating new cache")
            cache = asamples[-num_images:]
        else:
            logger.debug("Appending to existing cache")
            cache = np.concatenate((cache, asamples))[-num_images:]
        self._previewcache["images"] = cache
        logger.debug("Cache shape: %s", cast(np.ndarray, self._previewcache["images"]).shape)
        return True
 </s> add         logger.debug("Creating placeholder. thumbnail_size: %s", thumbnail_size)
        placeholder = Image.new("RGB", (thumbnail_size, thumbnail_size))
        draw = ImageDraw.Draw(placeholder)
        draw.rectangle(((0, 0), (thumbnail_size, thumbnail_size)), outline="#E5E5E5", width=1)
        placeholder = np.array(placeholder)
        self._placeholder = placeholder
        logger.debug("Created placeholder. shape: %s", placeholder.shape) </s> remove         if self._scale != 1.0:
 </s> add         if self._scale not in (0.0, 1.0):  # Scale will be 0,0 on initial load in GUI </s> remove         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> add         logger.debug("Saving preview to %s", filename)
        assert self._preview_image is not None
        self._preview_image.save(filename) </s> remove         size = 256 if self.command == "convert" else 128
        get_images().load_latest_preview(thumbnail_size=int(size * get_config().scaling_factor),
                                         frame_dims=(self.winfo_width(), self.winfo_height()))
        self.display_item = get_images().previewoutput
 </s> add         size = int(256 if self.command == "convert" else 128 * get_config().scaling_factor)
        if not self._preview.load_latest_preview(thumbnail_size=size,
                                                 frame_dims=(self.winfo_width(),
                                                             self.winfo_height())):
            logger.trace("Preview not updated")  # type:ignore
            return
        logger.debug("Preview loaded")
        self.display_item = True </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)
            assert self._placeholder is not None
            placeholder = np.concatenate([np.expand_dims(self._placeholder, 0)] * remainder)
              return None
          remainder = (cols * rows) - num_images
          if remainder != 0:
              logger.debug("Padding sample display. Remainder: %s", remainder)
            assert self._placeholder is not None
            placeholder = np.concatenate([np.expand_dims(self._placeholder, 0)] * remainder)
            assert self._placeholder is not None
            placeholder = np.concatenate([np.expand_dims(self._placeholder, 0)] * remainder)
              samples = np.concatenate((samples, placeholder))
  
          display = np.vstack([np.hstack(cast(Sequence, samples[row * cols: (row + 1) * cols]))
                               for row in range(rows)])
          logger.debug("display shape: %s", display.shape)
keep keep keep keep 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