1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
# vim: set fileencoding=utf-8 :
import pytest
import pyvips
from helpers import *
class TestColour:
def test_colourspace(self):
# mid-grey in Lab ... put 42 in the extra band, it should be copied
# unmodified
test = pyvips.Image.black(100, 100) + [50, 0, 0, 42]
test = test.copy(interpretation=pyvips.Interpretation.LAB)
# a long series should come in a circle
im = test
for col in colour_colourspaces + [pyvips.Interpretation.LAB]:
im = im.colourspace(col)
assert im.interpretation == col
for i in range(0, 4):
min_l = im.extract_band(i).min()
max_h = im.extract_band(i).max()
assert pytest.approx(min_l) == max_h
pixel = im(10, 10)
if col == pyvips.Interpretation.SCRGB:
assert pytest.approx(pixel[3], 0.0001) == 42.0 / 255.0
else:
assert pytest.approx(pixel[3], 0.01) == 42
# alpha won't be equal for RGB16, but it should be preserved if we go
# there and back
im = im.colourspace(pyvips.Interpretation.RGB16)
im = im.colourspace(pyvips.Interpretation.LAB)
before = test(10, 10)
after = im(10, 10)
assert_almost_equal_objects(before, after, threshold=0.1)
# go between every pair of colour spaces
for start in colour_colourspaces:
for end in colour_colourspaces:
im = test.colourspace(start)
im2 = im.colourspace(end)
im3 = im2.colourspace(pyvips.Interpretation.LAB)
before = test(10, 10)
after = im3(10, 10)
assert_almost_equal_objects(before, after, threshold=0.1)
# test Lab->XYZ on mid-grey
# checked against http://www.brucelindbloom.com
im = test.colourspace(pyvips.Interpretation.XYZ)
after = im(10, 10)
assert_almost_equal_objects(after, [17.5064, 18.4187, 20.0547, 42])
# grey->colour->grey should be equal
for mono_fmt in mono_colourspaces:
test_grey = test.colourspace(mono_fmt)
im = test_grey
for col in colour_colourspaces + [mono_fmt]:
im = im.colourspace(col)
assert im.interpretation == col
[before, alpha_before] = test_grey(10, 10)
[after, alpha_after] = im(10, 10)
assert abs(alpha_after - alpha_before) < 1
if mono_fmt == pyvips.Interpretation.GREY16:
# GREY16 can wind up rather different due to rounding
assert abs(after - before) < 30
else:
# but 8-bit we should hit exactly
assert abs(after - before) < 1
# we should be able to go from cmyk to any 3-band space and back again,
# approximately
cmyk = test.colourspace(pyvips.Interpretation.CMYK)
for end in colour_colourspaces:
im = cmyk.colourspace(end)
im2 = im.colourspace(pyvips.Interpretation.CMYK)
before = cmyk(10, 10)
after = im2(10, 10)
assert_almost_equal_objects(before, after, threshold=10)
# test results from Bruce Lindbloom's calculator:
# http://www.brucelindbloom.com
def test_dE00(self):
# put 42 in the extra band, it should be copied unmodified
reference = pyvips.Image.black(100, 100) + [50, 10, 20, 42]
reference = reference.copy(interpretation=pyvips.Interpretation.LAB)
sample = pyvips.Image.black(100, 100) + [40, -20, 10]
sample = sample.copy(interpretation=pyvips.Interpretation.LAB)
difference = reference.dE00(sample)
result, alpha = difference(10, 10)
assert pytest.approx(result, 0.001) == 30.238
assert pytest.approx(alpha, 0.001) == 42.0
def test_dE76(self):
# put 42 in the extra band, it should be copied unmodified
reference = pyvips.Image.black(100, 100) + [50, 10, 20, 42]
reference = reference.copy(interpretation=pyvips.Interpretation.LAB)
sample = pyvips.Image.black(100, 100) + [40, -20, 10]
sample = sample.copy(interpretation=pyvips.Interpretation.LAB)
difference = reference.dE76(sample)
result, alpha = difference(10, 10)
assert pytest.approx(result, 0.001) == 33.166
assert pytest.approx(alpha, 0.001) == 42.0
# the vips CMC calculation is based on distance in a colorspace
# derived from the CMC formula, so it won't match exactly ...
# see vips_LCh2CMC() for details
def test_dECMC(self):
reference = pyvips.Image.black(100, 100) + [50, 10, 20, 42]
reference = reference.copy(interpretation=pyvips.Interpretation.LAB)
sample = pyvips.Image.black(100, 100) + [55, 11, 23]
sample = sample.copy(interpretation=pyvips.Interpretation.LAB)
difference = reference.dECMC(sample)
result, alpha = difference(10, 10)
assert abs(result - 4.97) < 0.5
assert pytest.approx(alpha, 0.001) == 42.0
@skip_if_no("icc_import")
def test_icc(self):
test = pyvips.Image.new_from_file(JPEG_FILE)
im = test.icc_import().icc_export()
assert im.dE76(test).max() < 6
im = test.icc_import()
im2 = im.icc_export(depth=16)
assert im2.format == pyvips.BandFormat.USHORT
im3 = im2.icc_import()
assert (im - im3).abs().max() < 3
im = test.icc_import(intent=pyvips.Intent.ABSOLUTE)
im2 = im.icc_export(intent=pyvips.Intent.ABSOLUTE)
assert im2.dE76(test).max() < 6
im = test.icc_import()
im2 = im.icc_export(output_profile=SRGB_FILE)
im3 = im.colourspace(pyvips.Interpretation.SRGB)
assert im2.dE76(im3).max() < 6
before_profile = test.get("icc-profile-data")
im = test.icc_transform(SRGB_FILE)
after_profile = im.get("icc-profile-data")
im2 = test.icc_import()
im3 = im2.colourspace(pyvips.Interpretation.SRGB)
assert im.dE76(im3).max() < 6
assert len(before_profile) != len(after_profile)
im = test.icc_import(input_profile=SRGB_FILE)
im2 = test.icc_import()
assert 6 < im.dE76(im2).max()
im = test.icc_import(pcs=pyvips.PCS.XYZ)
assert im.interpretation == pyvips.Interpretation.XYZ
im = test.icc_import()
assert im.interpretation == pyvips.Interpretation.LAB
# even without lcms, we should have a working approximation
def test_cmyk(self):
test = pyvips.Image.new_from_file(JPEG_FILE)
im = test.colourspace("cmyk").colourspace("srgb")
before = test(150, 210)
after = im(150, 210)
assert_almost_equal_objects(before, after, threshold=10)
if __name__ == '__main__':
pytest.main()
|