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 | ||
24 | GOOD_JPG = pkg_resources.resource_filename( | |
25 | 'mediagoblin.tests', | |
26 | os.path.join( | |
27 | 'test_exif', | |
28 | 'good.jpg')) | |
29 | EMPTY_JPG = pkg_resources.resource_filename( | |
30 | 'mediagoblin.tests', | |
31 | os.path.join( | |
32 | 'test_exif', | |
33 | 'empty.jpg')) | |
34 | BAD_JPG = pkg_resources.resource_filename( | |
35 | 'mediagoblin.tests', | |
36 | os.path.join( | |
37 | 'test_exif', | |
38 | 'bad.jpg')) | |
39 | GPS_JPG = pkg_resources.resource_filename( | |
40 | 'mediagoblin.tests', | |
41 | os.path.join( | |
42 | 'test_exif', | |
43 | 'has-gps.jpg')) | |
44 | ||
45 | def test_exif_extraction(): | |
46 | ''' | |
47 | Test EXIF extraction from a good image | |
48 | ''' | |
49 | result = extract_exif(GOOD_JPG) | |
50 | clean = clean_exif(result) | |
51 | useful = get_useful(clean) | |
52 | gps = get_gps_data(result) | |
53 | ||
54 | # Do we have the result? | |
55 | assert len(result) == 108 | |
56 | ||
57 | # Do we have clean data? | |
58 | assert len(clean) == 105 | |
59 | ||
60 | # GPS data? | |
61 | assert gps == {} | |
62 | ||
63 | # Do we have the "useful" tags? | |
64 | assert useful == { | |
65 | 'EXIF Flash': { | |
66 | 'field_type': 3, | |
67 | 'printable': 'No', | |
68 | 'field_offset': 380, | |
69 | 'tag': 37385, | |
70 | 'values': [0], | |
71 | 'field_length': 2}, | |
72 | 'EXIF ExposureTime': { | |
73 | 'field_type': 5, | |
74 | 'printable': '1/125', | |
75 | 'field_offset': 700, | |
76 | 'tag': 33434, | |
77 | 'values': [[1, 125]], | |
78 | 'field_length': 8}, | |
79 | 'EXIF FocalLength': { | |
80 | 'field_type': 5, | |
81 | 'printable': '18', | |
82 | 'field_offset': 780, | |
83 | 'tag': 37386, | |
84 | 'values': [[18, 1]], | |
85 | 'field_length': 8}, | |
86 | 'Image Model': { | |
87 | 'field_type': 2, | |
88 | 'printable': 'NIKON D80', | |
89 | 'field_offset': 152, | |
90 | 'tag': 272, | |
91 | 'values': 'NIKON D80', | |
92 | 'field_length': 10}, | |
93 | 'Image Make': { | |
94 | 'field_type': 2, | |
95 | 'printable': 'NIKON CORPORATION', | |
96 | 'field_offset': 134, | |
97 | 'tag': 271, | |
98 | 'values': 'NIKON CORPORATION', | |
99 | 'field_length': 18}, | |
100 | 'EXIF ExposureMode': { | |
101 | 'field_type': 3, | |
102 | 'printable': 'Manual Exposure', | |
103 | 'field_offset': 584, | |
104 | 'tag': 41986, | |
105 | 'values': [1], | |
106 | 'field_length': 2}, | |
107 | 'EXIF ISOSpeedRatings': { | |
108 | 'field_type': 3, | |
109 | 'printable': '100', | |
110 | 'field_offset': 260, | |
111 | 'tag': 34855, | |
112 | 'values': [100], | |
113 | 'field_length': 2}, | |
114 | 'EXIF FNumber': { | |
115 | 'field_type': 5, | |
116 | 'printable': '10', | |
117 | 'field_offset': 708, | |
118 | 'tag': 33437, | |
119 | 'values': [[10, 1]], | |
120 | 'field_length': 8}, | |
121 | 'EXIF UserComment': { | |
122 | 'field_type': 7, | |
123 | 'printable': 'Joar Wandborg ', | |
124 | 'field_offset': 26180, | |
125 | 'tag': 37510, | |
126 | 'values': [ | |
127 | 65, 83, 67, 73, 73, 0, 0, 0, 74, 111, 97, 114, 32, 87, | |
128 | 97, 110, 100, 98, 111, 114, 103, 32, 32, 32, 32, 32, 32, | |
129 | 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, | |
130 | 32, 32, 32], | |
131 | 'field_length': 44}} | |
132 | ||
133 | def test_exif_image_orientation(): | |
134 | ''' | |
135 | Test image reorientation based on EXIF data | |
136 | ''' | |
137 | result = extract_exif(GOOD_JPG) | |
138 | ||
139 | image = exif_fix_image_orientation( | |
140 | Image.open(GOOD_JPG), | |
141 | result) | |
142 | ||
143 | # Are the dimensions correct? | |
144 | assert image.size == (428, 640) | |
145 | ||
146 | # If this pixel looks right, the rest of the image probably will too. | |
147 | assert image.getdata()[10000] == (41, 28, 11) | |
148 | ||
149 | def test_exif_no_exif(): | |
150 | ''' | |
151 | Test an image without exif | |
152 | ''' | |
153 | result = extract_exif(EMPTY_JPG) | |
154 | clean = clean_exif(result) | |
155 | useful = get_useful(clean) | |
156 | gps = get_gps_data(result) | |
157 | ||
158 | assert result == {} | |
159 | assert clean == {} | |
160 | assert gps == {} | |
161 | assert useful == {} | |
162 | ||
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 | ||
177 | def test_exif_gps_data(): | |
178 | ''' | |
179 | Test extractiion of GPS data | |
180 | ''' | |
181 | result = extract_exif(GPS_JPG) | |
182 | gps = get_gps_data(result) | |
183 | ||
184 | assert gps == { | |
185 | 'latitude': 59.336666666666666, | |
186 | 'direction': 25.674046740467404, | |
187 | 'altitude': 37.64365671641791, | |
188 | 'longitude': 18.016166666666667} | |
189 |