1import mock
2import os
3import pytest
4import warnings
5
6from rawkit.errors import InvalidFileType, NoFileSpecified
7from rawkit.metadata import Metadata
8from rawkit.raw import Raw, DarkFrame
9from rawkit.raw import output_file_types
10
11
12@pytest.fixture
13def input_file():
14    return 'potato_salad.CR2'
15
16
17@pytest.fixture
18def output_file():
19    return 'potato_salad.out'
20
21
22@pytest.yield_fixture
23def raw(input_file):
24    with mock.patch('rawkit.raw.LibRaw'):
25        with Raw(filename=input_file) as raw_obj:
26            yield raw_obj
27        raw_obj.libraw.libraw_close.assert_called_once_with(raw_obj.data)
28
29
30@pytest.yield_fixture
31def dark_frame(input_file):
32    with mock.patch('rawkit.raw.LibRaw'):
33        with DarkFrame(filename=input_file) as raw_obj:
34            yield raw_obj
35        raw_obj.libraw.libraw_close.assert_called_once_with(raw_obj.data)
36
37
38@pytest.yield_fixture
39def mock_warning():
40    with mock.patch.object(warnings, 'warn') as mock_warning:
41        yield mock_warning
42
43
44@pytest.yield_fixture
45def mock_ctypes():
46    with mock.patch('rawkit.raw.ctypes') as mock_ctypes:
47        yield mock_ctypes
48
49
50def test_create(raw, input_file):
51    raw.libraw.libraw_init.assert_called_once_with(0)
52    raw.libraw.libraw_open_file.assert_called_once_with(
53        raw.data,
54        input_file.encode('ascii'),
55    )
56
57
58def test_create_no_filename():
59    with pytest.raises(NoFileSpecified):
60        Raw()
61
62
63def test_dark_frame_is_raw(dark_frame):
64    assert isinstance(dark_frame, Raw)
65
66
67def test_unpack(raw):
68    raw.unpack()
69    raw.libraw.libraw_unpack.assert_called_once_with(raw.data)
70
71
72def test_unpack_twice(raw):
73    raw.unpack()
74    raw.unpack()
75    raw.libraw.libraw_unpack.assert_called_once_with(raw.data)
76
77
78def test_unpack_thumb(raw):
79    raw.unpack_thumb()
80    raw.libraw.libraw_unpack_thumb.assert_called_once_with(raw.data)
81
82
83def test_unpack_thumb_twice(raw):
84    raw.unpack_thumb()
85    raw.unpack_thumb()
86    raw.libraw.libraw_unpack_thumb.assert_called_once_with(raw.data)
87
88
89def test_save_dark_frame_cached(dark_frame, tmpdir):
90    dark_frame.save()
91
92    # Touch the file (as if LibRaw were installed and saved a file)
93    with open(dark_frame.name, 'a'):
94        pass
95
96    dark_frame.save()
97    dark_frame.libraw.libraw_dcraw_ppm_tiff_writer.assert_called_once_with(
98        dark_frame.data,
99        dark_frame.name.encode('ascii'),
100    )
101
102
103def test_save_dark_frame_with_filename_cached(dark_frame, tmpdir):
104    tmpdir.join('somefile').write('')
105    fn = os.path.join(str(tmpdir), 'somefile')
106    dark_frame.save(filename=fn)
107    dark_frame.save(filename=fn, filetype=output_file_types.tiff)
108    assert not dark_frame.libraw.libraw_dcraw_ppm_tiff_writer.called
109
110
111def _test_save(raw, output_file, filetype):
112    raw.save(filename=output_file, filetype=filetype)
113
114    raw.libraw.libraw_dcraw_ppm_tiff_writer.assert_called_once_with(
115        raw.data,
116        output_file.encode('ascii'),
117    )
118
119
120def test_save_no_filename(raw):
121    with pytest.raises(NoFileSpecified):
122        raw.save(filetype=output_file_types.ppm)
123
124
125def test_save_ppm(raw, output_file):
126    _test_save(raw, output_file, output_file_types.ppm)
127    assert raw.data.contents.params.output_tiff is False
128
129
130def test_save_tiff(raw, output_file):
131    _test_save(raw, output_file, output_file_types.tiff)
132    assert raw.data.contents.params.output_tiff is True
133
134
135def test_save_invalid_extension(raw, output_file):
136    with pytest.raises(InvalidFileType):
137        _test_save(raw, output_file, None)
138
139
140def test_save_infer_type_tiff(raw, output_file):
141    _test_save(raw, output_file + '.tiff', None)
142
143    assert raw.data.contents.params.output_tiff is True
144
145
146def test_save_infer_type_no_ext(raw, output_file):
147    _test_save(raw, 'noext', None)
148
149    assert raw.data.contents.params.output_tiff is False
150
151
152def test_save_infer_type_ppm(raw, output_file):
153    _test_save(raw, output_file + '.ppm', None)
154
155    assert raw.data.contents.params.output_tiff is False
156
157
158def test_save_invalid(raw, output_file):
159    with pytest.raises(InvalidFileType):
160        _test_save(raw, output_file, 'jpg')
161
162
163def test_save_thumb(raw, output_file):
164    raw.save_thumb(filename=output_file)
165
166    raw.libraw.libraw_dcraw_thumb_writer.assert_called_once_with(
167        raw.data,
168        output_file.encode('ascii'),
169    )
170
171
172def test_save_thumb_no_filename(raw):
173    with pytest.raises(NoFileSpecified):
174        raw.save_thumb()
175
176
177def test_to_buffer(raw, mock_ctypes):
178    with mock.patch('rawkit.raw.raise_if_error'):
179        raw.to_buffer()
180
181    raw.libraw.libraw_dcraw_make_mem_image.assert_called_once_with(
182        raw.data,
183        mock.ANY,
184    )
185
186    raw.libraw.libraw_dcraw_clear_mem.assert_called_once_with(
187        raw.libraw.libraw_dcraw_make_mem_image(raw.data),
188    )
189
190
191def test_thumbnail_to_buffer(raw, mock_ctypes):
192    with mock.patch('rawkit.raw.raise_if_error'):
193        raw.thumbnail_to_buffer()
194
195    raw.libraw.libraw_dcraw_make_mem_thumb.assert_called_once_with(
196        raw.data,
197        mock.ANY,
198    )
199
200    raw.libraw.libraw_dcraw_clear_mem.assert_called_once_with(
201        raw.libraw.libraw_dcraw_make_mem_thumb(raw.data),
202    )
203
204
205def test_metadata(raw):
206    metadata = raw.metadata
207    assert type(metadata) is Metadata
208
209
210def test_get_bayer_data(raw, mock_ctypes):
211    raw.data.contents.sizes.pixel_aspect = 1
212    raw.data.contents.sizes.flip = 0
213
214    result, _ = raw.bayer_data()
215
216    assert result is not None
217
218
219def test_get_bayer_data_bad_aspect(raw, mock_ctypes, mock_warning):
220    raw.data.contents.sizes.pixel_aspect = 2
221    raw.data.contents.sizes.flip = 0
222
223    raw.bayer_data()
224
225    mock_warning.assert_called_with(
226        'The pixel aspect is not unity, it is: 2'
227    )
228
229
230def test_get_bayer_data_flip(raw, mock_ctypes, mock_warning):
231    raw.data.contents.sizes.pixel_aspect = 1
232    raw.data.contents.sizes.flip = 1
233
234    raw.bayer_data()
235
236    mock_warning.assert_called_with(
237        'The image is flipped.'
238    )
239
240
241def test_bayer_data_non_bayer_image(raw, mock_ctypes):
242    raw.data.contents.sizes.pixel_aspect = 1
243    raw.data.contents.sizes.flip = 0
244
245    # The falsiness of this value is what is tested to see if bayer data
246    # exists, so we set this to False even though it's supposed to be a
247    # pointer.
248    raw.data.contents.rawdata.raw_image = False
249
250    result, _ = raw.bayer_data()
251
252    assert result == []
253
254
255def test_bayer_data_with_margin(raw, mock_ctypes):
256    raw.data.contents.sizes.pixel_aspect = 1
257    raw.data.contents.sizes.flip = 0
258
259    result, _ = raw.bayer_data(include_margin=True)
260
261    assert result
262