Skip to content

Commit e8d7b55

Browse files
author
Steve Canny
committed
img: substitute Image for Image_OLD
Remove now-dead code
1 parent 38afcb6 commit e8d7b55

File tree

7 files changed

+43
-258
lines changed

7 files changed

+43
-258
lines changed

docx/image/__init__.py

Lines changed: 0 additions & 183 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,11 @@
99
absolute_import, division, print_function, unicode_literals
1010
)
1111

12-
import hashlib
13-
import os
14-
15-
try:
16-
from PIL import Image as PIL_Image
17-
except ImportError:
18-
import Image as PIL_Image
19-
20-
from docx.compat import BytesIO, is_string
2112
from docx.image.bmp import Bmp
2213
from docx.image.gif import Gif
2314
from docx.image.jpeg import Exif, Jfif
2415
from docx.image.png import Png
2516
from docx.image.tiff import Tiff
26-
from docx.opc.constants import CONTENT_TYPE as CT
27-
from docx.shared import lazyproperty
2817

2918

3019
SIGNATURES = (
@@ -38,175 +27,3 @@
3827
(Tiff, 0, b'II*\x00'), # little-endian (Intel) TIFF
3928
(Bmp, 0, b'BM'),
4029
)
41-
42-
43-
class Image_OLD(object):
44-
"""
45-
A helper object that knows how to analyze an image file.
46-
"""
47-
def __init__(
48-
self, blob, filename, content_type, px_width, px_height,
49-
horz_dpi, vert_dpi):
50-
super(Image_OLD, self).__init__()
51-
self._blob = blob
52-
self._filename = filename
53-
self._content_type = content_type
54-
self._px_width = px_width
55-
self._px_height = px_height
56-
self._horz_dpi = horz_dpi
57-
self._vert_dpi = vert_dpi
58-
59-
@property
60-
def blob(self):
61-
"""
62-
The bytes of the image 'file'
63-
"""
64-
return self._blob
65-
66-
@property
67-
def content_type(self):
68-
"""
69-
The MIME type of the image, e.g. 'image/png'.
70-
"""
71-
return self._content_type
72-
73-
@lazyproperty
74-
def ext(self):
75-
"""
76-
The file extension for the image. If an actual one is available from
77-
a load filename it is used. Otherwise a canonical extension is
78-
assigned based on the content type.
79-
"""
80-
return os.path.splitext(self._filename)[1][1:]
81-
82-
@property
83-
def filename(self):
84-
"""
85-
Original image file name, if loaded from disk, or a generic filename
86-
if loaded from an anonymous stream.
87-
"""
88-
return self._filename
89-
90-
@classmethod
91-
def from_blob(cls, blob):
92-
stream = BytesIO(blob)
93-
return cls._from_stream(stream, blob)
94-
95-
@classmethod
96-
def from_file(cls, image_descriptor):
97-
"""
98-
Return a new |Image| instance loaded from the image file identified
99-
by *image_descriptor*, a path or file-like object.
100-
"""
101-
if is_string(image_descriptor):
102-
path = image_descriptor
103-
with open(path, 'rb') as f:
104-
blob = f.read()
105-
stream = BytesIO(blob)
106-
filename = os.path.basename(path)
107-
else:
108-
stream = image_descriptor
109-
stream.seek(0)
110-
blob = stream.read()
111-
filename = None
112-
return cls._from_stream(stream, blob, filename)
113-
114-
@property
115-
def horz_dpi(self):
116-
"""
117-
The horizontal dots per inch (dpi) of the image, defaults to 72 when
118-
no dpi information is stored in the image, as is often the case.
119-
"""
120-
return self._horz_dpi
121-
122-
@property
123-
def px_width(self):
124-
"""
125-
The horizontal pixel dimension of the image
126-
"""
127-
return self._px_width
128-
129-
@property
130-
def px_height(self):
131-
"""
132-
The vertical pixel dimension of the image
133-
"""
134-
return self._px_height
135-
136-
@lazyproperty
137-
def sha1(self):
138-
"""
139-
SHA1 hash digest of the image blob
140-
"""
141-
return hashlib.sha1(self._blob).hexdigest()
142-
143-
@property
144-
def vert_dpi(self):
145-
"""
146-
The vertical dots per inch (dpi) of the image, defaults to 72 when no
147-
dpi information is stored in the image.
148-
"""
149-
return self._vert_dpi
150-
151-
@classmethod
152-
def _analyze_image(cls, stream):
153-
pil_image = cls._open_pillow_image(stream)
154-
content_type = cls._format_content_type(pil_image.format)
155-
px_width, px_height = pil_image.size
156-
try:
157-
horz_dpi, vert_dpi = pil_image.info.get('dpi')
158-
except:
159-
horz_dpi, vert_dpi = (72, 72)
160-
return content_type, px_width, px_height, horz_dpi, vert_dpi
161-
162-
@classmethod
163-
def _def_mime_ext(cls, mime_type):
164-
"""
165-
Return the default file extension, e.g. ``'.png'``, corresponding to
166-
*mime_type*. Raises |KeyError| for unsupported image types.
167-
"""
168-
content_type_extensions = {
169-
CT.BMP: '.bmp', CT.GIF: '.gif', CT.JPEG: '.jpg', CT.PNG: '.png',
170-
CT.TIFF: '.tiff', CT.X_WMF: '.wmf'
171-
}
172-
return content_type_extensions[mime_type]
173-
174-
@classmethod
175-
def _format_content_type(cls, format):
176-
"""
177-
Return the content type string (MIME type for images) corresponding
178-
to the Pillow image format string *format*.
179-
"""
180-
format_content_types = {
181-
'BMP': CT.BMP, 'GIF': CT.GIF, 'JPEG': CT.JPEG, 'PNG': CT.PNG,
182-
'TIFF': CT.TIFF, 'WMF': CT.X_WMF
183-
}
184-
return format_content_types[format]
185-
186-
@classmethod
187-
def _from_stream(cls, stream, blob, filename=None):
188-
content_type, px_width, px_height, horz_dpi, vert_dpi = (
189-
cls._analyze_image(stream)
190-
)
191-
if filename is None:
192-
filename = 'image%s' % cls._def_mime_ext(content_type)
193-
return cls(
194-
blob, filename, content_type, px_width, px_height, horz_dpi,
195-
vert_dpi
196-
)
197-
198-
@classmethod
199-
def _open_pillow_image(cls, stream):
200-
"""
201-
Return a Pillow ``Image`` instance loaded from the image file-like
202-
object *stream*. The image is validated to confirm it is a supported
203-
image type.
204-
"""
205-
stream.seek(0)
206-
pil_image = PIL_Image.open(stream)
207-
try:
208-
cls._format_content_type(pil_image.format)
209-
except KeyError:
210-
tmpl = "unsupported image format '%s'"
211-
raise ValueError(tmpl % (pil_image.format))
212-
return pil_image

docx/package.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66

77
from __future__ import absolute_import, print_function, unicode_literals
88

9+
from docx.image.image import Image
910
from docx.opc.constants import RELATIONSHIP_TYPE as RT
1011
from docx.opc.package import OpcPackage
1112
from docx.opc.packuri import PackURI
12-
from docx.parts.image import Image_OLD, ImagePart
13+
from docx.parts.image import ImagePart
1314
from docx.shared import lazyproperty
1415

1516

@@ -72,7 +73,7 @@ def get_or_add_image_part(self, image_descriptor):
7273
*image_descriptor*, newly created if a matching one is not present in
7374
the collection.
7475
"""
75-
image = Image_OLD.from_file(image_descriptor)
76+
image = Image.from_file(image_descriptor)
7677
matching_image_part = self._get_by_sha1(image.sha1)
7778
if matching_image_part is not None:
7879
return matching_image_part

docx/parts/image.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
import hashlib
1212

13-
from docx.image import Image_OLD
13+
from docx.image.image import Image
1414
from docx.opc.package import Part
1515
from docx.shared import Emu, Inches
1616

@@ -70,7 +70,7 @@ def from_image(cls, image, partname):
7070
@property
7171
def image(self):
7272
if self._image is None:
73-
self._image = Image_OLD.from_blob(self.blob)
73+
self._image = Image.from_blob(self.blob)
7474
return self._image
7575

7676
@classmethod

features/img-characterize-image.feature

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ Feature: Characterize an image file
33
As a programmer using the advanced python-docx API
44
I need a way to determine the image content type and size
55

6-
@wip
76
Scenario Outline: Characterize an image file
87
Given the image file '<filename>'
98
When I construct an image using the image path

tests/image/test_image.py

Lines changed: 31 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import pytest
1010

1111
from docx.compat import BytesIO
12-
from docx.image import Image_OLD
1312
from docx.image.bmp import Bmp
1413
from docx.image.exceptions import UnrecognizedImageError
1514
from docx.image.gif import Gif
@@ -98,6 +97,20 @@ def it_knows_the_sha1_of_its_image(self):
9897
image = Image(blob, None, None)
9998
assert image.sha1 == '4921e7002ddfba690a937d54bda226a7b8bdeb68'
10099

100+
def it_correctly_characterizes_known_images(self, known_image_fixture):
101+
image_path, characteristics = known_image_fixture
102+
ext, content_type, px_width, px_height, horz_dpi, vert_dpi = (
103+
characteristics
104+
)
105+
with open(test_file(image_path), 'rb') as stream:
106+
image = Image.from_file(stream)
107+
assert image.content_type == content_type
108+
assert image.ext == ext
109+
assert image.px_width == px_width
110+
assert image.px_height == px_height
111+
assert image.horz_dpi == horz_dpi
112+
assert image.vert_dpi == vert_dpi
113+
101114
# fixtures -------------------------------------------------------
102115

103116
@pytest.fixture
@@ -191,6 +204,23 @@ def image_header_(self, request):
191204
def Image__init_(self, request):
192205
return initializer_mock(request, Image)
193206

207+
@pytest.fixture(params=[0, 1, 2, 3, 4, 5, 6, 7, 8])
208+
def known_image_fixture(self, request):
209+
cases = (
210+
('python.bmp', ('bmp', CT.BMP, 211, 71, 96, 96)),
211+
('sonic.gif', ('gif', CT.GIF, 290, 360, 72, 72)),
212+
('python-icon.jpeg', ('jpg', CT.JPEG, 204, 204, 72, 72)),
213+
('300-dpi.jpg', ('jpg', CT.JPEG, 1504, 1936, 300, 300)),
214+
('monty-truth.png', ('png', CT.PNG, 150, 214, 72, 72)),
215+
('150-dpi.png', ('png', CT.PNG, 901, 1350, 150, 150)),
216+
('300-dpi.png', ('png', CT.PNG, 860, 579, 300, 300)),
217+
('72-dpi.tiff', ('tiff', CT.TIFF, 48, 48, 72, 72)),
218+
('300-dpi.TIF', ('tiff', CT.TIFF, 2464, 3248, 300, 300)),
219+
# ('CVS_LOGO.WMF', ('wmf', CT.X_WMF, 149, 59, 72, 72)),
220+
)
221+
image_filename, characteristics = cases[request.param]
222+
return image_filename, characteristics
223+
194224
@pytest.fixture
195225
def stream_(self, request):
196226
return instance_mock(request, BytesIO)
@@ -253,66 +283,3 @@ def it_knows_the_horz_and_vert_dpi_of_the_image(self):
253283
image_header = BaseImageHeader(None, None, horz_dpi, vert_dpi)
254284
assert image_header.horz_dpi == horz_dpi
255285
assert image_header.vert_dpi == vert_dpi
256-
257-
258-
class DescribeImage_OLD(object):
259-
260-
def it_can_construct_from_an_image_path(self):
261-
image_file_path = test_file('monty-truth.png')
262-
image = Image_OLD.from_file(image_file_path)
263-
assert isinstance(image, Image_OLD)
264-
assert image.sha1 == '79769f1e202add2e963158b532e36c2c0f76a70c'
265-
assert image.filename == 'monty-truth.png'
266-
267-
def it_can_construct_from_an_image_stream(self):
268-
image_file_path = test_file('monty-truth.png')
269-
with open(image_file_path, 'rb') as image_file_stream:
270-
image = Image_OLD.from_file(image_file_stream)
271-
assert isinstance(image, Image_OLD)
272-
assert image.sha1 == '79769f1e202add2e963158b532e36c2c0f76a70c'
273-
assert image.filename == 'image.png'
274-
275-
def it_knows_the_extension_of_a_file_based_image(self):
276-
image_file_path = test_file('monty-truth.png')
277-
image = Image_OLD.from_file(image_file_path)
278-
assert image.ext == 'png'
279-
280-
def it_knows_the_extension_of_a_stream_based_image(self):
281-
image_file_path = test_file('monty-truth.png')
282-
with open(image_file_path, 'rb') as image_file_stream:
283-
image = Image_OLD.from_file(image_file_stream)
284-
assert image.ext == 'png'
285-
286-
def it_correctly_characterizes_a_few_known_images(
287-
self, known_image_fixture):
288-
image_path, characteristics = known_image_fixture
289-
ext, content_type, px_width, px_height, horz_dpi, vert_dpi = (
290-
characteristics
291-
)
292-
with open(test_file(image_path), 'rb') as stream:
293-
image = Image_OLD.from_file(stream)
294-
assert image.ext == ext
295-
assert image.content_type == content_type
296-
assert image.px_width == px_width
297-
assert image.px_height == px_height
298-
assert image.horz_dpi == horz_dpi
299-
assert image.vert_dpi == vert_dpi
300-
301-
# fixtures -------------------------------------------------------
302-
303-
@pytest.fixture(params=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
304-
def known_image_fixture(self, request):
305-
cases = (
306-
('python.bmp', ('bmp', CT.BMP, 211, 71, 72, 72)),
307-
('sonic.gif', ('gif', CT.GIF, 290, 360, 72, 72)),
308-
('python-icon.jpeg', ('jpg', CT.JPEG, 204, 204, 72, 72)),
309-
('300-dpi.jpg', ('jpg', CT.JPEG, 1504, 1936, 300, 300)),
310-
('monty-truth.png', ('png', CT.PNG, 150, 214, 72, 72)),
311-
('150-dpi.png', ('png', CT.PNG, 901, 1350, 150, 150)),
312-
('300-dpi.png', ('png', CT.PNG, 860, 579, 300, 300)),
313-
('72-dpi.tiff', ('tiff', CT.TIFF, 48, 48, 72, 72)),
314-
('300-dpi.TIF', ('tiff', CT.TIFF, 2464, 3248, 300, 300)),
315-
('CVS_LOGO.WMF', ('wmf', CT.X_WMF, 149, 59, 72, 72)),
316-
)
317-
image_filename, characteristics = cases[request.param]
318-
return image_filename, characteristics

tests/parts/test_image.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import pytest
1010

11-
from docx.image import Image_OLD
11+
from docx.image.image import Image
1212
from docx.opc.constants import CONTENT_TYPE as CT, RELATIONSHIP_TYPE as RT
1313
from docx.opc.package import PartFactory
1414
from docx.opc.packuri import PackURI
@@ -68,7 +68,7 @@ def blob_(self, request):
6868
@pytest.fixture(params=['loaded', 'new'])
6969
def dimensions_fixture(self, request):
7070
image_file_path = test_file('monty-truth.png')
71-
image = Image_OLD.from_file(image_file_path)
71+
image = Image.from_file(image_file_path)
7272
expected_cx, expected_cy = 1905000, 2717800
7373

7474
# case 1: image part is loaded by PartFactory w/no Image inst
@@ -102,7 +102,7 @@ def from_image_fixture(self, image_, partname_, ImagePart__init__):
102102

103103
@pytest.fixture
104104
def image_(self, request):
105-
return instance_mock(request, Image_OLD)
105+
return instance_mock(request, Image)
106106

107107
@pytest.fixture
108108
def ImagePart__init__(self, request):

0 commit comments

Comments
 (0)