Skip to content

Commit 35cb783

Browse files
author
Steve Canny
committed
img: add _App1Marker._tiff_from_exif_segment()
1 parent 335dd46 commit 35cb783

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

docx/image/jpeg.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77

88
from __future__ import absolute_import, division, print_function
99

10+
from ..compat import BytesIO
1011
from .constants import JPEG_MARKER_CODE, MIME_TYPE
1112
from .helpers import BIG_ENDIAN, StreamReader
1213
from .image import Image
14+
from .tiff import Tiff
1315

1416

1517
class Jpeg(Image):
@@ -436,7 +438,11 @@ def _tiff_from_exif_segment(cls, stream, offset, segment_length):
436438
Return a |Tiff| instance parsed from the Exif APP1 segment of
437439
*segment_length* at *offset* in *stream*.
438440
"""
439-
raise NotImplementedError
441+
# wrap full segment in its own stream and feed to Tiff()
442+
stream.seek(offset+8)
443+
segment_bytes = stream.read(segment_length-8)
444+
substream = BytesIO(segment_bytes)
445+
return Tiff.from_stream(substream, None, None)
440446

441447

442448
class _SofMarker(_Marker):

tests/image/test_jpeg.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,12 +373,28 @@ def it_can_construct_from_non_Exif_APP1_segment(self, non_Exif_fixture):
373373
)
374374
assert isinstance(app1_marker, _App1Marker)
375375

376+
def it_gets_a_tiff_from_its_Exif_segment_to_help_construct(
377+
self, get_tiff_fixture):
378+
stream, offset, length = get_tiff_fixture[:3]
379+
BytesIO_, segment_bytes, substream_ = get_tiff_fixture[3:6]
380+
Tiff_, tiff_ = get_tiff_fixture[6:]
381+
tiff = _App1Marker._tiff_from_exif_segment(stream, offset, length)
382+
BytesIO_.assert_called_once_with(segment_bytes)
383+
Tiff_.from_stream.assert_called_once_with(substream_, None, None)
384+
assert tiff is tiff_
385+
376386
# fixtures -------------------------------------------------------
377387

378388
@pytest.fixture
379389
def _App1Marker__init_(self, request):
380390
return initializer_mock(request, _App1Marker)
381391

392+
@pytest.fixture
393+
def BytesIO_(self, request, substream_):
394+
return class_mock(
395+
request, 'docx.image.jpeg.BytesIO', return_value=substream_
396+
)
397+
382398
@pytest.fixture
383399
def from_stream_fixture(
384400
self, request, _App1Marker__init_, _tiff_from_exif_segment_):
@@ -391,13 +407,33 @@ def from_stream_fixture(
391407
_tiff_from_exif_segment_, horz_dpi, vert_dpi
392408
)
393409

410+
@pytest.fixture
411+
def get_tiff_fixture(self, request, BytesIO_, substream_, Tiff_, tiff_):
412+
bytes_ = b'xfillerxMM\x00*\x00\x00\x00\x42'
413+
stream_reader = StreamReader(BytesIO(bytes_), BIG_ENDIAN)
414+
offset, segment_length, segment_bytes = 0, 16, bytes_[8:]
415+
return (
416+
stream_reader, offset, segment_length, BytesIO_, segment_bytes,
417+
substream_, Tiff_, tiff_
418+
)
419+
394420
@pytest.fixture
395421
def non_Exif_fixture(self, request, _App1Marker__init_):
396422
bytes_ = b'\x00\x42Foobar'
397423
stream_reader = StreamReader(BytesIO(bytes_), BIG_ENDIAN)
398424
marker_code, offset, length = JPEG_MARKER_CODE.APP1, 0, 66
399425
return stream_reader, marker_code, offset, _App1Marker__init_, length
400426

427+
@pytest.fixture
428+
def substream_(self, request):
429+
return instance_mock(request, BytesIO)
430+
431+
@pytest.fixture
432+
def Tiff_(self, request, tiff_):
433+
Tiff_ = class_mock(request, 'docx.image.jpeg.Tiff')
434+
Tiff_.from_stream.return_value = tiff_
435+
return Tiff_
436+
401437
@pytest.fixture
402438
def tiff_(self, request):
403439
return instance_mock(request, Tiff, horz_dpi=42, vert_dpi=24)

0 commit comments

Comments
 (0)