File: test_colour.py

package info (click to toggle)
vips 8.18.0-2
  • links: PTS
  • area: main
  • in suites: forky
  • size: 53,448 kB
  • sloc: ansic: 172,621; cpp: 12,257; python: 5,077; sh: 773; perl: 40; makefile: 25; javascript: 6
file content (181 lines) | stat: -rw-r--r-- 6,873 bytes parent folder | download | duplicates (3)
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()