def test_image_width_height(): """ Test Image.width and Image.height """ # flower (480x360) # ---------------- def image_callback_1(value, image): assert image.width == 480 assert image.height == 360 with pytest.raises(AttributeError): image.width = 256 with pytest.raises(AttributeError): image.height = 256 utils.try_multiple_values('flower', [None], image_callback=image_callback_1) # test-card (640x480) # ------------------- def image_callback_2(value, image): assert image.width == 640 assert image.height == 480 with pytest.raises(AttributeError): image.width = 256 with pytest.raises(AttributeError): image.height = 256 utils.try_multiple_values('test-card', [None], image_callback=image_callback_2)
def test_attr_set_log_callback(): """ Test Attr.set_log_callback() """ my_attr = None my_user_info = object() callback_attrs = [] callback_messages = [] callback_user_infos = [] def log_callback(attr, message, user_info): # Assertions get eaten if performed in the callback, so let's put # these objects into lists we can check later callback_attrs.append(attr) callback_messages.append(message) callback_user_infos.append(user_info) print(message) def attr_callback(value, attr): """ Set the log callback. Also grab a reference to the Attr object so we can later check that the one passed to the log callback matches """ nonlocal my_attr my_attr = attr attr.set_log_callback(log_callback, my_user_info) # Try clearing the callback (to test that code path) attr.set_log_callback(None, None) # (set it back properly again) attr.set_log_callback(log_callback, my_user_info) utils.try_multiple_values('flower', [None], attr_callback=attr_callback) # Check that we got a good amount of callback items assert len(callback_attrs) == len(callback_messages) == len( callback_user_infos) > 0 # Check that the log callback arguments were correct assert all(attr is my_attr for attr in callback_attrs) assert all(ui is my_user_info for ui in callback_user_infos) # Check the callback messages for m in callback_messages: assert isinstance(m, str) and len(m) >= 20
def test_attr_min_quality(): """ Test Attr.min_quality """ def attr_callback(value, attr): # Test both the getter and setter methods attr.min_quality = value assert attr.min_quality == value # Test bounds checking (0-100) with pytest.raises(ValueError): attr.min_quality = -1 with pytest.raises(ValueError): attr.min_quality = 101 tuples = utils.try_multiple_values('flower', [0, 25, 75, 90, 100], attr_callback=attr_callback, allow_exceptions=True) actual_exceptions = [e for (a, ii, r, e) in tuples] NoneType = type(None) expected_exceptions = [ NoneType, NoneType, NoneType, liq.QualityTooLowError, liq.QualityTooLowError ] assert all( isinstance(a, b) for a, b in zip(actual_exceptions, expected_exceptions))
def test_result_set_progress_callback_abort(): """ Test aborting from Result.set_progress_callback() """ def progress_callback(progress_percent, user_info): """ Progress callback that just returns False, which should abort the operation and cause a liq.AbortedError """ return False def attr_callback(value, attr): """ Encourage dithering by setting a strict max_colors value """ attr.max_colors = 10 def result_callback(value, result): """ Enable dithering and set the progress callback """ # Encourage dithering by setting a high dithering level result.dithering_level = 1.0 result.set_progress_callback(progress_callback, None) tuples = utils.try_multiple_values('flower', [None], attr_callback=attr_callback, result_callback=result_callback) # We need to call remap_image() on the Result to trigger the # progress callbacks with pytest.raises(liq.AbortedError): for a, ii, r, e in tuples: r.remap_image(ii)
def test_image_background(): """ Test Image.background """ backgrounds = [] def image_callback(value, image): # Load the background as an Image width, height, input_pixels = utils.load_test_image(value) attr = liq.Attr() background = attr.create_rgba(input_pixels, width, height, 0) backgrounds.append(background) # Test both the getter and setter methods image.background = background with pytest.raises(AttributeError): image.background utils.check_outputs_unique( utils.get_output_datas( utils.try_multiple_values( 'alpha-gradient', ['test-card_480_360'], # ['flower', 'test-card_480_360'], image_callback=image_callback)))
def test_attr_set_progress_callback(): """ Test Attr.set_progress_callback() """ my_attr = None my_user_info = object() callback_percentages = [] callback_user_infos = [] def progress_callback(progress_percent, user_info): # Assertions get eaten if performed in the callback, so let's put # these objects into lists we can check later callback_percentages.append(progress_percent) callback_user_infos.append(user_info) print(progress_percent) return True # returning False to abort is a separate test def attr_callback(value, attr): """ Set the progress callback. Also grab a reference to the Attr object so we can later check that the one passed to the progress callback matches. """ nonlocal my_attr my_attr = attr attr.set_progress_callback(progress_callback, my_user_info) # Try clearing the callback (to test that code path) attr.set_progress_callback(None, None) # (set it back properly again) attr.set_progress_callback(progress_callback, my_user_info) utils.try_multiple_values('flower', [None], attr_callback=attr_callback) # Check that we got a good amount of callback items assert len(callback_percentages) == len(callback_user_infos) > 0 # Check that the user infos were correct assert all(ui is my_user_info for ui in callback_user_infos) # Check that the progress percentages are in the 0.0-100.0 range assert all(0 <= pct <= 100 for pct in callback_percentages)
def test_buffer_too_small_error(): """ Trigger LIQ_BUFFER_TOO_SMALL and ensure that liq.BufferTooSmallError is raised """ # Load the background as an Image width, height, input_pixels = utils.load_test_image('test-card') attr = liq.Attr() background = attr.create_rgba(input_pixels, width, height, 0) def image_callback(value, image): # The image is too large, so using it as a background should fail with pytest.raises(liq.BufferTooSmallError): image.background = background utils.try_multiple_values('alpha-gradient', [None], image_callback=image_callback)
def test_attr_set_progress_callback_abort(): """ Test aborting from Attr.set_progress_callback() """ def progress_callback(progress_percent, user_info): """ Progress callback that just returns False, which should abort the operation and cause a liq.AbortedError """ return False def attr_callback(value, attr): """ Set the progress callback """ attr.set_progress_callback(progress_callback, None) with pytest.raises(liq.AbortedError): utils.try_multiple_values('flower', [None], attr_callback=attr_callback)
def test_result_get_palette(): """ Test Result.get_palette() """ (_, _, result, _), = utils.try_multiple_values('flower', [None]) palette = result.get_palette() assert palette assert all(isinstance(col, liq.Color) for col in palette)
def test_quality_too_low_error(): """ Trigger LIQ_QUALITY_TOO_LOW and ensure that liq.QualityTooLowError is raised """ def attr_callback(value, attr): attr.max_colors = 10 attr.min_quality = 99 with pytest.raises(liq.QualityTooLowError): utils.get_output_datas( utils.try_multiple_values('flower', [None], attr_callback=attr_callback))
def test_attr_min_opacity_stub(): """ Test Attr.min_opacity (stub implementation, >= liq 2.13.0) """ def attr_callback(value, attr): # Test both the getter and setter methods attr.min_opacity = value assert attr.min_opacity == 0 # There shouldn't be any bounds checking anymore attr.min_opacity = -1 attr.min_opacity = 256 utils.get_output_datas( utils.try_multiple_values('alpha-gradient', [0, 63, 127, 191, 255], attr_callback=attr_callback))
def test_attr_max_colors(): """ Test Attr.max_colors """ def attr_callback(value, attr): # Test both the getter and setter methods attr.max_colors = value assert attr.max_colors == value # Test bounds checking (2-256) with pytest.raises(ValueError): attr.max_colors = 1 with pytest.raises(ValueError): attr.max_colors = 257 (_, _, result, _), = utils.try_multiple_values('flower', [77], attr_callback=attr_callback) assert len(result.get_palette()) == 77
def test_attr_min_posterization(): """ Test Attr.min_posterization """ def attr_callback(value, attr): # Test both the getter and setter methods attr.min_posterization = value assert attr.min_posterization == value # Test bounds checking (0-4) with pytest.raises(ValueError): attr.min_posterization = -1 with pytest.raises(ValueError): attr.min_posterization = 5 utils.check_outputs_unique( utils.get_output_datas( utils.try_multiple_values('flower', [0, 1, 2, 3, 4], attr_callback=attr_callback)))
def test_attr_min_opacity(): """ Test Attr.min_opacity (original implementation, < liq 2.13.0) """ def attr_callback(value, attr): # Test both the getter and setter methods attr.min_opacity = value assert attr.min_opacity == value # Test bounds checking (0-255) with pytest.raises(ValueError): attr.min_opacity = -1 with pytest.raises(ValueError): attr.min_opacity = 256 utils.check_outputs_unique( utils.get_output_datas( utils.try_multiple_values('alpha-gradient', [0, 63, 127, 191, 255], attr_callback=attr_callback)))
def test_attr_speed(): """ Test Attr.speed """ def attr_callback(value, attr): # Test both the getter and setter methods attr.speed = value assert attr.speed == value # Test bounds checking (1-10) with pytest.raises(ValueError): attr.speed = 0 with pytest.raises(ValueError): attr.speed = 11 utils.check_outputs_unique( utils.get_output_datas( utils.try_multiple_values('flower', [1, 5, 10], attr_callback=attr_callback)))
def test_attr_max_quality(): """ Test Attr.max_quality """ def attr_callback(value, attr): # Test both the getter and setter methods attr.max_quality = value assert attr.max_quality == value # Test bounds checking (0-100) with pytest.raises(ValueError): attr.max_quality = -1 with pytest.raises(ValueError): attr.max_quality = 101 utils.check_outputs_unique( utils.get_output_datas( utils.try_multiple_values('flower', [0, 33, 66, 100], attr_callback=attr_callback)))
def test_result_dithering_level(): """ Test Result.dithering_level """ def result_callback(value, result): # Test the setter, and ensure the getter raises AttributeError result.dithering_level = value with pytest.raises(AttributeError): result.dithering_level # Test bounds checking (0.0-1.0) with pytest.raises(ValueError): result.dithering_level = -0.1 with pytest.raises(ValueError): result.dithering_level = 1.1 utils.check_outputs_unique( utils.get_output_datas( utils.try_multiple_values('flower', [0.0, 0.5, 1.0], result_callback=result_callback)))
def test_attr_last_index_transparent(): """ Test Attr.last_index_transparent """ def attr_callback(value, attr): # Test both the getter and setter methods attr.last_index_transparent = value with pytest.raises(AttributeError): attr.last_index_transparent tuples = utils.try_multiple_values('alpha-gradient', [False, True], attr_callback=attr_callback) palettes = [r.get_palette() for (a, ii, r, e) in tuples] # palettes[0] (last_index_transparent=False): alpha colors at beginning assert palettes[0][0].a == 0 assert palettes[0][-1].a == 255 # palettes[1] (last_index_transparent=True): alpha colors at end assert palettes[1][0].a == 255 assert palettes[1][-1].a == 0
def test_result_output_gamma(): """ Test Result.output_gamma """ def result_callback(value, result): # Test the setter, and ensure the getter raises AttributeError result.output_gamma = value assert result.output_gamma == value # Test bounds checking (0.0-1.0, not inclusive) with pytest.raises(ValueError): result.output_gamma = -0.1 with pytest.raises(ValueError): result.output_gamma = 0.0 with pytest.raises(ValueError): result.output_gamma = 1.0 with pytest.raises(ValueError): result.output_gamma = 1.1 utils.check_outputs_unique( utils.get_output_datas( utils.try_multiple_values('flower', [0.01, 0.5, 0.99], result_callback=result_callback)))
def test_image_importance_map(): """ Test Image.importance_map """ def image_callback(value, image): # Load the map as a bytearray width, height, input_pixels = utils.load_test_image(value) buffer = bytearray(width * height) for i in range(0, len(input_pixels), 4): buffer[i // 4] = input_pixels[i] # Test both the getter and setter methods image.importance_map = buffer with pytest.raises(AttributeError): image.importance_map utils.check_outputs_unique( utils.get_output_datas( utils.try_multiple_values( 'alpha-gradient', ['importance-map-1', 'importance-map-2', 'importance-map-3'], image_callback=image_callback)))
def test_image_add_fixed_color(): """ Test Image.add_fixed_color() """ def image_callback(value, image): for fixedColor in value: image.add_fixed_color(fixedColor) FIXED_COLORS = [ [liq.Color(255, 0, 0, 255)], # red [liq.Color(0, 0, 255, 255)], # blue [liq.Color(128, 0, 128, 255), liq.Color(255, 255, 0, 255)], # purple & yellow ] tuples = utils.try_multiple_values('flower', FIXED_COLORS, image_callback=image_callback) palettes = [r.get_palette() for (a, ii, r, e) in tuples] for fixedColors, pal in zip(FIXED_COLORS, palettes): for fixedColor in fixedColors: assert fixedColor in pal
def test_result_quantization_and_remapping_error_and_quality(): """ Test: - Result.quantization_error - Result.quantization_quality - Result.remapping_error - Result.remapping_quality """ (_, image, result, _), = utils.try_multiple_values('flower', [None]) # Not sure what the actual maxes for quantization_error and remapping_error are assert 0 < result.quantization_error < 255 assert 0 < result.quantization_quality < 100 # Remapping error and quality aren't available until after remapping assert result.remapping_error == -1.0 assert result.remapping_quality == -1.0 result.remap_image(image) # *Now* they're available assert 0 < result.remapping_error < 255 assert 0 < result.remapping_quality < 100
def test_result_set_progress_callback(): """ Test Result.set_progress_callback() """ my_result = None my_user_info = object() callback_percentages = [] callback_user_infos = [] def progress_callback(progress_percent, user_info): # Assertions get eaten if performed in the callback, so let's put # these objects into lists we can check later callback_percentages.append(progress_percent) callback_user_infos.append(user_info) print(progress_percent) return True # returning False to abort is a separate test def attr_callback(value, attr): """ Encourage dithering by setting a strict max_colors value """ attr.max_colors = 10 def result_callback(value, result): """ Enable dithering and set the progress callback. Also grab a reference to the Result object so we can later check that the one passed to the progress callback matches. """ nonlocal my_result my_result = result # Encourage dithering by setting a high dithering level result.dithering_level = 1.0 # Set the progress callback result.set_progress_callback(progress_callback, my_user_info) # Try clearing the callback (to test that code path) result.set_progress_callback(None, None) # (set it back properly again) result.set_progress_callback(progress_callback, my_user_info) tuples = utils.try_multiple_values('flower', [None], attr_callback=attr_callback, result_callback=result_callback) # We need to call remap_image() on the Result to trigger the # progress callbacks for a, ii, r, e in tuples: r.remap_image(ii) # Check that we got a good amount of callback items assert len(callback_percentages) == len(callback_user_infos) > 0 # Check that the user infos were correct assert all(ui is my_user_info for ui in callback_user_infos) # Check that the progress percentages are in the 0.0-100.0 range assert all(0 <= pct <= 100 for pct in callback_percentages)