def _extract_metadata( self, rpd_file: RPDFile, processing: Set[ExtractionProcessing] ) -> PhotoDetails: thumbnail = orientation = None try: orientation = rpd_file.metadata.orientation() except Exception: pass rpd_file.mdatatime = rpd_file.metadata.timestamp(missing=0.0) # Not all files have an exif preview, but some do # (typically CR2, ARW, PEF, RW2). # If they exist, they are (almost!) always 160x120 # TODO how about thumbnail_cache_status? if self.write_fdo_thumbnail and rpd_file.fdo_thumbnail_256 is None: photo_details = self._extract_256_thumb( rpd_file=rpd_file, processing=processing, orientation=orientation ) if photo_details.thumbnail is not None: return photo_details # if no valid preview found, fall back to the code below and make do with # the best we can get preview = rpd_file.metadata.get_small_thumbnail_or_first_indexed_preview() if preview: thumbnail = QImage.fromData(preview) if thumbnail.isNull(): thumbnail = None else: if thumbnail.width() < thumbnail.height() and orientation in ( self.rotate_270, self.rotate_90, ): # The orientation has already been applied to the thumbnail logging.debug( "Already rotated: %s", rpd_file.get_current_full_file_name() ) orientation = self.rotate_0 if max(thumbnail.width(), thumbnail.height()) > 160: logging.debug("Resizing: %s", rpd_file.get_current_full_file_name()) processing.add(ExtractionProcessing.resize) elif not rpd_file.is_jpeg(): processing.add(ExtractionProcessing.strip_bars_photo) return PhotoDetails(thumbnail, orientation)
def preprocess_thumbnail_from_disk( rpd_file: RPDFile, processing: Set[ExtractionProcessing]) -> ExtractionTask: """ Determine how to get a thumbnail from a photo or video that is not on a camera (although it may have directly come from there during the download process) Does not return the name of the file to be worked on -- that's the responsibility of the method calling it. :param rpd_file: details about file from which to get thumbnail from :param processing: set that holds processing tasks for the extractors to perform :return: extraction task required """ if rpd_file.file_type == FileType.photo: if rpd_file.is_heif(): if have_heif_module: bytes_to_read = rpd_file.size if rpd_file.mdatatime: task = ExtractionTask.load_heif_directly else: task = ExtractionTask.load_heif_and_exif_directly processing.add(ExtractionProcessing.resize) # For now, do not orient, as it seems pyheif or libheif does that # automatically processing.add(ExtractionProcessing.orient) else: # We have no way to convert the file task = ExtractionTask.bypass bytes_to_read = 0 elif rpd_file.is_tiff(): available = psutil.virtual_memory().available if rpd_file.size <= available: bytes_to_read = rpd_file.size if rpd_file.mdatatime: task = ExtractionTask.load_file_directly else: task = ExtractionTask.load_file_and_exif_directly processing.add(ExtractionProcessing.resize) else: # Don't try to extract a thumbnail from # a file that is larger than available # memory task = ExtractionTask.bypass bytes_to_read = 0 else: if rpd_file.is_jpeg( ) and rpd_file.from_camera and rpd_file.is_mtp_device: # jpeg photos from smartphones don't have embedded thumbnails task = ExtractionTask.load_file_and_exif_directly processing.add(ExtractionProcessing.resize) else: task = ExtractionTask.load_from_exif processing.add(ExtractionProcessing.orient) bytes_to_read = cached_read.get(rpd_file.extension, 400 * 1024) if bytes_to_read: if not rpd_file.download_full_file_name: try: with open(rpd_file.full_file_name, "rb") as photo: # Bring the file into the operating system's disk cache photo.read(bytes_to_read) except FileNotFoundError: logging.error( "The download file %s does not exist", rpd_file.download_full_file_name, ) else: # video if rpd_file.thm_full_name is not None: if not rpd_file.mdatatime: task = ExtractionTask.load_file_directly_metadata_from_secondary # It's the responsibility of the calling code to assign the # secondary_full_file_name else: task = ExtractionTask.load_file_directly processing.add(ExtractionProcessing.strip_bars_video) processing.add(ExtractionProcessing.add_film_strip) else: if rpd_file.mdatatime: task = ExtractionTask.extract_from_file else: task = ExtractionTask.extract_from_file_and_load_metadata return task