Skip to content

Commit

Permalink
Remove colour profile mismatch exception in validation as it's only n…
Browse files Browse the repository at this point in the history
…eeded for tiff->jpeg conversion.

Move normal/depth map jp2 conversion tests to derivatives_generator and add losslessness checks. Remove colour profile check for jpg conversion tests.

Decompress normal_map.tif so demo kakadu versions can run the tests.
  • Loading branch information
mel-mason committed Feb 16, 2024
1 parent 173b443 commit 71a0872
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 30 deletions.
5 changes: 3 additions & 2 deletions image_processing/conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,12 @@ def convert_to_jpg(self, input_filepath, output_filepath, resize=None, quality=N
"""
with Image.open(input_filepath) as input_pil:
icc_profile = input_pil.info.get('icc_profile')
if input_pil.mode == 'RGBA':
if input_pil.mode in ['RGBA', 'RGBX']:
self.logger.warning(
'Image is RGBA - the alpha channel will be removed from the JPEG derivative image')
'Image is %s - the fourth channel will be removed from the JPEG derivative image', input_pil.mode)
input_pil = input_pil.convert(mode="RGB")
if input_pil.mode == 'I;16':
# JPEG doesn't support 16bit
self.logger.warning(
'Image is 16bpp - will be downsampled to 8bpp')
input_pil = input_pil.convert(mode="RGB")
Expand Down
8 changes: 3 additions & 5 deletions image_processing/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
GREYSCALE = 'L'
BITONAL = '1'
MONOTONE_COLOUR_MODES = [GREYSCALE, BITONAL]
ACCEPTED_COLOUR_MODES = ['RGB', 'RGBA', 'RGBX', 'I;16', GREYSCALE, BITONAL]
ACCEPTED_COLOUR_MODES = ['RGB', 'RGBA', 'RGBX', 'I;16', GREYSCALE, BITONAL] # todo: are there any other modes we may have to consider? Need to add test for RGBX image


def validate_jp2(image_file, output_file=None):
Expand Down Expand Up @@ -154,12 +154,9 @@ def check_colour_profiles_match(source_filepath, converted_filepath):
if source_image.mode != converted_image.mode:
if source_image.mode == BITONAL and converted_image.mode == GREYSCALE:
logger.info('Converted image is greyscale, not bitonal. This is expected')
elif source_image.mode in ['RGBX', 'I;16'] and converted_image.mode in ['RGB', 'RGBA']:
logger.info('Converted image in RGB space, but was converted from a compatible space. This is expected.')
else:
raise exceptions.ValidationError(
'Converted file {0} has different colour mode from {1}'
.format(converted_filepath, source_filepath)
f'Converted file {converted_filepath} has different colour mode ({converted_image.mode}) from {source_filepath} ({source_image.mode})'
)

source_icc = source_image.info.get('icc_profile')
Expand Down Expand Up @@ -190,6 +187,7 @@ def check_image_suitable_for_jp2_conversion(image_filepath, require_icc_profile_
if colour_mode not in ACCEPTED_COLOUR_MODES:
raise exceptions.ValidationError("Unsupported colour mode {0} for {1}".format(colour_mode, image_filepath))

# todo: do I need to warn for RGBX too?
if colour_mode == 'RGBA':
# In some cases alpha channel data is stored in a way that means it would be lost in the conversion back to
# tiff from jp2.
Expand Down
Binary file modified tests/data/normal_map.tif
100755 → 100644
Binary file not shown.
21 changes: 0 additions & 21 deletions tests/test_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,33 +51,12 @@ def test_converts_depthmap_tif_to_jpeg(self):
quality=derivative_files_generator.DEFAULT_JPG_HIGH_QUALITY_VALUE)
assert os.path.isfile(output_file)


@mark.skipif(not cmd_is_executable('/opt/kakadu/kdu_compress'), reason="requires kakadu installed")
def test_converts_depthmap_tif_to_jpeg2000(self):
with temporary_folder() as output_folder:
output_file = os.path.join(output_folder, 'output.jpg')
get_kakadu().kdu_compress(filepaths.DEPTHMAP_TIF, output_file,
kakadu_options=kakadu.DEFAULT_COMPRESS_OPTIONS + kakadu.LOSSLESS_OPTIONS)
assert os.path.isfile(output_file)


def test_converts_normalmap_tif_to_jpeg(self):
with temporary_folder() as output_folder:
output_file = os.path.join(output_folder, 'output.jpg')
conversion.Converter().convert_to_jpg(filepaths.NORMALMAP_TIF, output_file, resize=None,
quality=derivative_files_generator.DEFAULT_JPG_HIGH_QUALITY_VALUE)
assert os.path.isfile(output_file)
validation.check_colour_profiles_match(filepaths.NORMALMAP_TIF, output_file)


@mark.skipif(not cmd_is_executable('/opt/kakadu/kdu_compress'), reason="requires kakadu installed")
def test_converts_normalmap_tif_to_jpeg2000(self):
with temporary_folder() as output_folder:
output_file = os.path.join(output_folder, 'output.jpg')
get_kakadu().kdu_compress(filepaths.NORMALMAP_TIF, output_file,
kakadu_options=kakadu.DEFAULT_COMPRESS_OPTIONS + kakadu.LOSSLESS_OPTIONS)
assert os.path.isfile(output_file)


@mark.skipif(not cmd_is_executable('/opt/kakadu/kdu_compress'), reason="requires kakadu installed")
def test_converts_tif_to_lossy_jpeg2000(self):
Expand Down
25 changes: 25 additions & 0 deletions tests/test_derivatives_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,28 @@ def test_creates_correct_files_from_jpg(self):
assert image_files_match(jpg_file, filepaths.STANDARD_JPG)
assert image_files_match(jp2_file, filepaths.LOSSLESS_JP2_FROM_STANDARD_JPG_XMP)
assert xmp_files_match(embedded_metadata_file, filepaths.STANDARD_JPG_XMP)

def test_converts_depthmap_tif_to_jpeg2000_losslessly(self):
"""
Check transformations of 16 bit depthmap images do not lose data
:return:
"""
with temporary_folder() as output_folder:
generator = get_derivatives_generator()
output_file = os.path.join(output_folder, 'output.jp2')
generator.generate_jp2_from_tiff(filepaths.DEPTHMAP_TIF, output_file)
assert os.path.isfile(output_file)
generator.check_conversion_was_lossless(filepaths.DEPTHMAP_TIF, output_file)

def test_converts_normalmap_tif_to_jpeg2000_losslessly(self):
"""
Check transformations of RGBA normal map images do not lose data
:return:
"""
with temporary_folder() as output_folder:
generator = get_derivatives_generator()
output_file = os.path.join(output_folder, 'output.jp2')
# note that this method has specific handling for files with alpha channels that the direct converter method does not
generator.generate_jp2_from_tiff(filepaths.NORMALMAP_TIF, output_file)
assert os.path.isfile(output_file)
generator.check_conversion_was_lossless(filepaths.NORMALMAP_TIF, output_file)
4 changes: 2 additions & 2 deletions tests/test_utils/filepaths.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

# adobe rgb 1998 8 bit tiff file (our most common input format) + expected derivatives
STANDARD_TIF = 'tests/data/standard_adobe.tif'
DEPTHMAP_TIF = 'tests/data/depth_map.tif'
NORMALMAP_TIF = 'tests/data/normal_map.tif'
DEPTHMAP_TIF = 'tests/data/depth_map.tif' # 16 bit (I;16) archiox image
NORMALMAP_TIF = 'tests/data/normal_map.tif' # RGBA archiox image
STANDARD_TIF_SINGLE_LAYER = 'tests/data/standard_adobe_tif_single_layer.tif' # same tif but without thumbnail
LOSSY_JP2_FROM_STANDARD_TIF = 'tests/data/standard_adobe_tif_lossy.jp2'
LOSSLESS_JP2_FROM_STANDARD_TIF_XMP = 'tests/data/standard_adobe_tif_xmp.jp2'
Expand Down

0 comments on commit 71a0872

Please sign in to comment.