From 099e54cc1b20e5d8ba0b14ba7dd8c989dfa9c7fa Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Tue, 5 Sep 2023 16:25:13 +0300 Subject: [PATCH] Fixed error for non-jpeg compressed images in original chunks (#6789) Resolved #6598 --- CHANGELOG.md | 1 + cvat/apps/engine/media_extractors.py | 22 +++++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86071589ce77..d3c79bb34cba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Zooming canvas when scrooling comments list in an issue () - Issues can be created many times when initial submit () +- Running deep learning models on non-jpeg compressed tif images () - Paddings on tasks/projects/models pages () - Memory leak in the logging system () diff --git a/cvat/apps/engine/media_extractors.py b/cvat/apps/engine/media_extractors.py index 65ab80ae4745..c81efc82b145 100644 --- a/cvat/apps/engine/media_extractors.py +++ b/cvat/apps/engine/media_extractors.py @@ -80,6 +80,9 @@ def image_size_within_orientation(img: Image): return img.height, img.width return img.width, img.height +def has_exif_rotation(img: Image): + return img.getexif().get(ORIENTATION_EXIF_TAG, ORIENTATION.NORMAL_HORIZONTAL) != ORIENTATION.NORMAL_HORIZONTAL + def rotate_within_exif(img: Image): orientation = img.getexif().get(ORIENTATION_EXIF_TAG, ORIENTATION.NORMAL_HORIZONTAL) if orientation in [ORIENTATION.NORMAL_180_ROTATED, ORIENTATION.MIRROR_VERTICAL]: @@ -661,12 +664,25 @@ def save_as_chunk(self, images, chunk_path): ext = os.path.splitext(path)[1].replace('.', '') output = io.BytesIO() if self._dimension == DimensionType.DIM_2D: - pil_image = rotate_within_exif(Image.open(image)) - pil_image.save(output, format=pil_image.format if pil_image.format else self.IMAGE_EXT, quality=100, subsampling=0) + pil_image = Image.open(image) + if has_exif_rotation(pil_image): + rot_image = rotate_within_exif(pil_image) + if rot_image.format == 'TIFF': + # https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html + # use loseless lzw compression for tiff images + rot_image.save(output, format='TIFF', compression='tiff_lzw') + else: + rot_image.save(output, format=rot_image.format if rot_image.format else self.IMAGE_EXT, quality=100, subsampling=0) + else: + output = image else: output, ext = self._write_pcd_file(image)[0:2] arcname = '{:06d}.{}'.format(idx, ext) - zip_chunk.writestr(arcname, output.getvalue()) + + if isinstance(output, io.BytesIO): + zip_chunk.writestr(arcname, output.getvalue()) + else: + zip_chunk.write(filename=output, arcname=arcname) # return empty list because ZipChunkWriter write files as is # and does not decode it to know img size. return []