Пример #1
0
 def dimensions_and_resize(max_dim: int, vault: Vault, sub_path: str, image_to_write: Bean) -> Optional[str]:
     """
         Get dimensions from given image, return a string with the error in case of issue.
         It is assumed that the image is valid, i.e. did not throw an exception in above validate()
     """
     im = PIL_Image.open(vault.path_to(sub_path))
     image_to_write.width = im.size[0]
     image_to_write.height = im.size[1]
     # Generate a thumbnail if image is too large
     if (im.size[0] > max_dim) or (im.size[1] > max_dim):
         if im.mode == 'P' or im.mode[0] == 'I':
             # (8-bit pixels, mapped to any other mode using a color palette)
             # from https://pillow.readthedocs.io/en/latest/handbook/concepts.html#modes
             # Tested using a PNG with palette
             im = im.convert("RGB")
         im.thumbnail((max_dim, max_dim))
         thumb_relative_path, thumb_full_path = vault.thumbnail_paths(image_to_write.imgid)
         im.save(thumb_full_path)
         image_to_write.thumb_file_name = thumb_relative_path
         image_to_write.thumb_width = im.size[0]
         image_to_write.thumb_height = im.size[1]
     else:
         # Close the PIL image, when resized it was done during im.save
         # Otherwise there is a FD exhaustion on PyPy
         im.close()
         # Need empty fields for bulk insert
         image_to_write.thumb_file_name = None
         image_to_write.thumb_width = None
         image_to_write.thumb_height = None
     return None
Пример #2
0
 def dimensions_and_resize(max_dim: int, vault: Vault, sub_path: str,
                           image_to_write: Bean) -> Optional[str]:
     try:
         im = PIL_Image.open(vault.path_to(sub_path))
     except DecompressionBombError:
         return "Image too large: %s" % sub_path
     image_to_write.width = im.size[0]
     image_to_write.height = im.size[1]
     # Generate a thumbnail if image is too large
     if (im.size[0] > max_dim) or (im.size[1] > max_dim):
         im.thumbnail((max_dim, max_dim))
         if im.mode == 'P':
             # (8-bit pixels, mapped to any other mode using a color palette)
             # from https://pillow.readthedocs.io/en/latest/handbook/concepts.html#modes
             # Tested using a PNG with palette
             im = im.convert("RGB")
         thumb_relative_path, thumb_full_path = vault.thumbnail_paths(
             image_to_write.imgid)
         im.save(thumb_full_path)
         image_to_write.thumb_file_name = thumb_relative_path
         image_to_write.thumb_width = im.size[0]
         image_to_write.thumb_height = im.size[1]
     else:
         # Close the PIL image, when resized it was done during im.save
         # Otherwise there is a FD exhaustion on PyPy
         im.close()
         # Need empty fields for bulk insert
         image_to_write.thumb_file_name = None
         image_to_write.thumb_width = None
         image_to_write.thumb_height = None
     return None
Пример #3
0
    def deal_with_images(self,
                         where: ImportWhere,
                         how: ImportHow,
                         image_to_write: Bean,
                         instead_image: Path = None):
        """
            Generate image, eventually the vignette, create DB line(s) and copy image file into vault.
        :param where:
        :param how:
        :param image_to_write:
        :param instead_image: Store this image instead of the one in Image record.
        :return:
        """
        if instead_image:
            # Source file is a replacement
            img_file_path = instead_image
        else:
            # Files are in a subdirectory for UVP6, same directory for non-UVP6
            # TODO: Unsure if it works on Windows, as there is a "/" for UVP6
            img_file_path = self.path_for_image(image_to_write.orig_file_name)

        sub_path = where.vault.store_image(img_file_path, image_to_write.imgid)
        image_to_write.file_name = sub_path
        present_ranks = how.image_ranks_per_obj.setdefault(
            image_to_write.objid, set())
        if image_to_write.get("imgrank") is None:
            self.compute_rank(image_to_write, present_ranks)
        else:
            # The TSV format is float
            image_to_write.imgrank = int(image_to_write.imgrank)
            if image_to_write.imgrank in present_ranks:
                tsv_rank = image_to_write.imgrank
                self.compute_rank(image_to_write, present_ranks)
                logger.info(
                    'For %s, cannot use rank from TSV %d, using %d instead',
                    image_to_write.file_name, tsv_rank, image_to_write.imgrank)
        present_ranks.add(image_to_write.imgrank)

        err = ImageBO.dimensions_and_resize(how.max_dim, where.vault, sub_path,
                                            image_to_write)
        if err:
            logger.error(err + ", not copied")
Пример #4
0
 def add_db_entities(self, object_head_to_write: Bean,
                     object_fields_to_write: Bean,
                     image_to_write: Optional[Bean], new_records: int):
     # Bulk mode or Core do not create links (using ORM relationship), so we have to do manually
     if new_records > 1:
         # There is a new image and more
         #assert object_head_to_write.projid is not None
         assert object_head_to_write.orig_id is not None
         # Default value from sequences
         object_head_to_write.objid = self.obj_seq_cache.next()
         object_fields_to_write.objfid = object_head_to_write.objid
     if new_records >= 1 and image_to_write:
         # There is (potentially just) a new image
         image_to_write.imgid = self.img_seq_cache.next()
         image_to_write.objid = object_head_to_write.objid
     if new_records > 1:
         # There is a new image and more
         self.obj_fields_bulks.append(object_fields_to_write)
         self.obj_bulks.append(object_head_to_write)
     if new_records >= 1 and image_to_write:
         # There is (potentially just) a new image
         self.img_bulks.append(image_to_write)
Пример #5
0
 def do_sun_position_field(object_head_to_write: Bean):
     """
         Initial compute or update of sun position field.
     """
     # Default value, so there is something to write into the DB in case of problem
     object_head_to_write.sunpos = "?"
     # Is there enough data for computation?
     nb_fields = object_head_to_write.nb_fields_from(USED_FIELDS_FOR_SUNPOS)
     if nb_fields < len(USED_FIELDS_FOR_SUNPOS):
         if nb_fields > 0:
             # Warn if only a few fields, but not if 0
             logger.warning("Not enough fields for computing sun position")
         return
     # All fields are in, so give it a try
     try:
         object_head_to_write.sunpos = compute_sun_position(
             object_head_to_write)
     except Exception as e:
         # See astral.py for cases
         # Astral error : Sun never reaches 12.0 degrees below the horizon, at this location.
         # for {'objtime': datetime.time(12, 29), 'latitude': -64.2, 'objdate': datetime.date(2011, 1, 9),
         # 'longitude': -52.59 }
         logger.error("Astral error : %s for %s", e, object_head_to_write)
Пример #6
0
 def add_cnn_features(self, object_head_to_write, cnn_features: Bean):
     cnn_features.objcnnid = object_head_to_write.objid
     self.obj_cnn_bulks.append(cnn_features)