Commit | Line | Data |
---|---|---|
63bd7c04 | 1 | # GNU MediaGoblin -- federated, autonomous media hosting |
cf29e8a8 | 2 | # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. |
63bd7c04 JW |
3 | # |
4 | # This program is free software: you can redistribute it and/or modify | |
5 | # it under the terms of the GNU Affero General Public License as published by | |
6 | # the Free Software Foundation, either version 3 of the License, or | |
7 | # (at your option) any later version. | |
8 | # | |
9 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU Affero General Public License for more details. | |
13 | # | |
14 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | ||
17 | import os | |
18 | import pkg_resources | |
19 | import Image | |
20 | ||
21 | from mediagoblin.tools.exif import exif_fix_image_orientation, \ | |
22 | extract_exif, clean_exif, get_gps_data, get_useful | |
23 | ||
ccca39f1 E |
24 | |
25 | def assert_in(a, b): | |
26 | assert a in b, "%r not in %r" % (a, b) | |
27 | ||
28 | ||
63bd7c04 JW |
29 | GOOD_JPG = pkg_resources.resource_filename( |
30 | 'mediagoblin.tests', | |
31 | os.path.join( | |
32 | 'test_exif', | |
33 | 'good.jpg')) | |
34 | EMPTY_JPG = pkg_resources.resource_filename( | |
35 | 'mediagoblin.tests', | |
36 | os.path.join( | |
37 | 'test_exif', | |
38 | 'empty.jpg')) | |
39 | BAD_JPG = pkg_resources.resource_filename( | |
40 | 'mediagoblin.tests', | |
41 | os.path.join( | |
42 | 'test_exif', | |
43 | 'bad.jpg')) | |
44 | GPS_JPG = pkg_resources.resource_filename( | |
45 | 'mediagoblin.tests', | |
46 | os.path.join( | |
47 | 'test_exif', | |
48 | 'has-gps.jpg')) | |
49 | ||
ccca39f1 | 50 | |
63bd7c04 JW |
51 | def test_exif_extraction(): |
52 | ''' | |
53 | Test EXIF extraction from a good image | |
54 | ''' | |
55 | result = extract_exif(GOOD_JPG) | |
56 | clean = clean_exif(result) | |
57 | useful = get_useful(clean) | |
58 | gps = get_gps_data(result) | |
59 | ||
60 | # Do we have the result? | |
351fd95f | 61 | assert len(result) == 56 |
63bd7c04 JW |
62 | |
63 | # Do we have clean data? | |
351fd95f | 64 | assert len(clean) == 53 |
63bd7c04 JW |
65 | |
66 | # GPS data? | |
67 | assert gps == {} | |
68 | ||
69 | # Do we have the "useful" tags? | |
70 | assert useful == { | |
71 | 'EXIF Flash': { | |
72 | 'field_type': 3, | |
351fd95f | 73 | 'printable': u'Flash did not fire', |
63bd7c04 JW |
74 | 'field_offset': 380, |
75 | 'tag': 37385, | |
76 | 'values': [0], | |
77 | 'field_length': 2}, | |
78 | 'EXIF ExposureTime': { | |
79 | 'field_type': 5, | |
80 | 'printable': '1/125', | |
81 | 'field_offset': 700, | |
82 | 'tag': 33434, | |
83 | 'values': [[1, 125]], | |
84 | 'field_length': 8}, | |
85 | 'EXIF FocalLength': { | |
86 | 'field_type': 5, | |
87 | 'printable': '18', | |
88 | 'field_offset': 780, | |
89 | 'tag': 37386, | |
90 | 'values': [[18, 1]], | |
91 | 'field_length': 8}, | |
92 | 'Image Model': { | |
93 | 'field_type': 2, | |
94 | 'printable': 'NIKON D80', | |
95 | 'field_offset': 152, | |
96 | 'tag': 272, | |
97 | 'values': 'NIKON D80', | |
98 | 'field_length': 10}, | |
99 | 'Image Make': { | |
100 | 'field_type': 2, | |
101 | 'printable': 'NIKON CORPORATION', | |
102 | 'field_offset': 134, | |
103 | 'tag': 271, | |
104 | 'values': 'NIKON CORPORATION', | |
105 | 'field_length': 18}, | |
106 | 'EXIF ExposureMode': { | |
107 | 'field_type': 3, | |
108 | 'printable': 'Manual Exposure', | |
109 | 'field_offset': 584, | |
110 | 'tag': 41986, | |
111 | 'values': [1], | |
112 | 'field_length': 2}, | |
113 | 'EXIF ISOSpeedRatings': { | |
114 | 'field_type': 3, | |
115 | 'printable': '100', | |
116 | 'field_offset': 260, | |
117 | 'tag': 34855, | |
118 | 'values': [100], | |
119 | 'field_length': 2}, | |
120 | 'EXIF FNumber': { | |
121 | 'field_type': 5, | |
122 | 'printable': '10', | |
123 | 'field_offset': 708, | |
124 | 'tag': 33437, | |
125 | 'values': [[10, 1]], | |
351fd95f | 126 | 'field_length': 8}} |
63bd7c04 | 127 | |
ccca39f1 | 128 | |
63bd7c04 JW |
129 | def test_exif_image_orientation(): |
130 | ''' | |
131 | Test image reorientation based on EXIF data | |
132 | ''' | |
133 | result = extract_exif(GOOD_JPG) | |
134 | ||
135 | image = exif_fix_image_orientation( | |
136 | Image.open(GOOD_JPG), | |
137 | result) | |
138 | ||
139 | # Are the dimensions correct? | |
140 | assert image.size == (428, 640) | |
141 | ||
142 | # If this pixel looks right, the rest of the image probably will too. | |
ccca39f1 E |
143 | assert_in(image.getdata()[10000], |
144 | ((41, 28, 11), (43, 27, 11)) | |
145 | ) | |
146 | ||
63bd7c04 JW |
147 | |
148 | def test_exif_no_exif(): | |
149 | ''' | |
150 | Test an image without exif | |
151 | ''' | |
152 | result = extract_exif(EMPTY_JPG) | |
153 | clean = clean_exif(result) | |
154 | useful = get_useful(clean) | |
155 | gps = get_gps_data(result) | |
156 | ||
157 | assert result == {} | |
158 | assert clean == {} | |
159 | assert gps == {} | |
160 | assert useful == {} | |
161 | ||
ccca39f1 | 162 | |
63bd7c04 JW |
163 | def test_exif_bad_image(): |
164 | ''' | |
165 | Test EXIF extraction from a faithful, but bad image | |
166 | ''' | |
167 | result = extract_exif(BAD_JPG) | |
168 | clean = clean_exif(result) | |
169 | useful = get_useful(clean) | |
170 | gps = get_gps_data(result) | |
171 | ||
172 | assert result == {} | |
173 | assert clean == {} | |
174 | assert gps == {} | |
175 | assert useful == {} | |
176 | ||
ccca39f1 | 177 | |
63bd7c04 JW |
178 | def test_exif_gps_data(): |
179 | ''' | |
180 | Test extractiion of GPS data | |
181 | ''' | |
182 | result = extract_exif(GPS_JPG) | |
183 | gps = get_gps_data(result) | |
184 | ||
185 | assert gps == { | |
186 | 'latitude': 59.336666666666666, | |
187 | 'direction': 25.674046740467404, | |
188 | 'altitude': 37.64365671641791, | |
189 | 'longitude': 18.016166666666667} |