Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: chrome/utility/media_galleries/image_metadata_extractor.cc

Issue 191583002: Media Galleries API Metadata: Image metadata (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/utility/media_galleries/image_metadata_extractor.h"
6
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/numerics/safe_conversions.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "media/base/data_source.h"
13 #include "net/base/io_buffer.h"
14
15 extern "C" {
16 #include <libexif/exif-data.h>
17 } // extern "C"
18
19 namespace metadata {
20
21 namespace {
22
23 const int kMaxBufferSize = 50 * 1024 * 1024; // Arbitrary maximum of 50MB.
24
25 void FinishGetImageBytes(
26 net::DrainableIOBuffer* buffer,
27 media::DataSource* source,
28 const base::Callback<void(net::DrainableIOBuffer*)>& callback,
29 int bytes_read) {
30 if (bytes_read == media::DataSource::kReadError) {
31 callback.Run(NULL);
32 return;
33 }
34
35 buffer->DidConsume(bytes_read);
36 // Didn't get the whole file. Continue reading to get the rest.
37 if (buffer->BytesRemaining() > 0) {
38 source->Read(0, buffer->BytesRemaining(), (uint8*)buffer->data(),
39 base::Bind(&FinishGetImageBytes, make_scoped_refptr(buffer),
40 base::Unretained(source), callback));
41 return;
42 }
43
44 buffer->SetOffset(0);
45 callback.Run(make_scoped_refptr(buffer));
46 }
47
48 void GetImageBytes(
49 media::DataSource* source,
50 const base::Callback<void(net::DrainableIOBuffer*)>& callback) {
51 int64 size64 = 0;
52 if (!source->GetSize(&size64) || size64 > kMaxBufferSize)
53 return callback.Run(NULL);
54 int size = base::checked_cast<int>(size64);
55
56 scoped_refptr<net::DrainableIOBuffer> buffer(
57 new net::DrainableIOBuffer(new net::IOBuffer(size), size));
58 source->Read(0, buffer->BytesRemaining(), (uint8*)buffer->data(),
59 base::Bind(&FinishGetImageBytes, buffer,
60 base::Unretained(source), callback));
61 }
62
63 void ExtractInt(ExifData* data, ExifTag tag, int* result) {
64 DCHECK(result);
65
66 ExifEntry* entry = exif_data_get_entry(data, tag);
67
68 if (entry) {
69 ExifByteOrder order = exif_data_get_byte_order(data);
70
71 switch (entry->format) {
72 case EXIF_FORMAT_SHORT: {
73 ExifShort v = exif_get_short(entry->data, order);
74 *result = base::checked_cast<int>(v);
75 break;
76 }
77 case EXIF_FORMAT_LONG: {
78 ExifLong v = exif_get_long(entry->data, order);
79 // Ignore values that don't fit in a signed int - probably invalid data.
80 if (base::IsValueInRangeForNumericType<int>(v))
81 *result = base::checked_cast<int>(v);
82 break;
83 }
84 default: {
85 // Ignore all other entry formats.
86 }
87 }
88 }
89 }
90
91 void ExtractDouble(ExifData* data, ExifTag tag, double* result) {
92 DCHECK(result);
93
94 ExifEntry* entry = exif_data_get_entry(data, tag);
95
96 if (entry) {
97 ExifByteOrder order = exif_data_get_byte_order(data);
98
99 if (entry->format == EXIF_FORMAT_RATIONAL) {
100 ExifRational v = exif_get_rational(entry->data, order);
101 *result = base::checked_cast<double>(v.numerator) /
102 base::checked_cast<double>(v.denominator);
103 }
104 }
105 }
106
107 void ExtractString(ExifData* data, ExifTag tag, std::string* result) {
108 DCHECK(result);
109
110 ExifEntry* entry = exif_data_get_entry(data, tag);
111
112 if (entry) {
113 char buf[1024];
114 exif_entry_get_value(entry, buf, sizeof(buf));
115 *result = buf;
116 }
117 }
118
119 } // namespace
120
121 ImageMetadataExtractor::ImageMetadataExtractor()
122 : extracted_(false),
123 width_(-1),
124 height_(-1),
125 rotation_(-1),
126 x_resolution_(-1),
127 y_resolution_(-1),
128 exposure_time_sec_(-1),
129 flash_fired_(false),
130 f_number_(-1),
131 focal_length_mm_(-1),
132 iso_equivalent_(-1) {
133 }
134
135 ImageMetadataExtractor::~ImageMetadataExtractor() {
136 }
137
138 void ImageMetadataExtractor::Extract(media::DataSource* source,
139 const DoneCallback& callback) {
140 DCHECK(!extracted_);
141
142 GetImageBytes(source, base::Bind(&ImageMetadataExtractor::FinishExtraction,
143 base::Unretained(this), callback));
144
145 }
146
147 int ImageMetadataExtractor::width() const {
148 DCHECK(extracted_);
149 return width_;
150 }
151
152 int ImageMetadataExtractor::height() const {
153 DCHECK(extracted_);
154 return height_;
155 }
156
157 int ImageMetadataExtractor::rotation() const {
158 DCHECK(extracted_);
159 return rotation_;
160 }
161
162 double ImageMetadataExtractor::x_resolution() const {
163 DCHECK(extracted_);
164 return x_resolution_;
165 }
166
167 double ImageMetadataExtractor::y_resolution() const {
168 DCHECK(extracted_);
169 return y_resolution_;
170 }
171
172 const std::string& ImageMetadataExtractor::date() const {
173 DCHECK(extracted_);
174 return date_;
175 }
176
177 const std::string& ImageMetadataExtractor::camera_make() const {
178 DCHECK(extracted_);
179 return camera_make_;
180 }
181
182 const std::string& ImageMetadataExtractor::camera_model() const {
183 DCHECK(extracted_);
184 return camera_model_;
185 }
186
187 double ImageMetadataExtractor::exposure_time_sec() const {
188 DCHECK(extracted_);
189 return exposure_time_sec_;
190 }
191
192 bool ImageMetadataExtractor::flash_fired() const {
193 DCHECK(extracted_);
194 return flash_fired_;
195 }
196
197 double ImageMetadataExtractor::f_number() const {
198 DCHECK(extracted_);
199 return f_number_;
200 }
201
202 double ImageMetadataExtractor::focal_length_mm() const {
203 DCHECK(extracted_);
204 return focal_length_mm_;
205 }
206
207 int ImageMetadataExtractor::iso_equivalent() const {
208 DCHECK(extracted_);
209 return iso_equivalent_;
210 }
211
212 void ImageMetadataExtractor::FinishExtraction(
213 const DoneCallback& callback, net::DrainableIOBuffer* buffer) {
214 if (!buffer) {
215 callback.Run(false);
216 return;
217 }
218
219 ExifData* data = exif_data_new_from_data(
220 (unsigned char*)buffer->data(), buffer->BytesRemaining());
221
222 if (!data) {
223 callback.Run(false);
224 return;
225 }
226
227 ExtractInt(data, EXIF_TAG_IMAGE_WIDTH, &width_);
228 ExtractInt(data, EXIF_TAG_IMAGE_LENGTH, &height_);
229
230 // We ignore the mirrored-aspect of the mirrored-orientations and just
231 // indicate the rotation. Mirrored-orientations are very rare.
232 int orientation = 0;
233 ExtractInt(data, EXIF_TAG_ORIENTATION, &orientation);
234 switch (orientation) {
235 case 1:
236 case 2:
237 rotation_ = 0;
238 break;
239 case 3:
240 case 4:
241 rotation_ = 180;
242 break;
243 case 5:
244 case 6:
245 rotation_ = 90;
246 break;
247 case 7:
248 case 8:
249 rotation_ = 270;
250 break;
251 }
252
253 ExtractDouble(data, EXIF_TAG_X_RESOLUTION, &x_resolution_);
254 ExtractDouble(data, EXIF_TAG_Y_RESOLUTION, &y_resolution_);
255
256 ExtractString(data, EXIF_TAG_DATE_TIME, &date_);
257
258 ExtractString(data, EXIF_TAG_MAKE, &camera_make_);
259 ExtractString(data, EXIF_TAG_MODEL, &camera_model_);
260 ExtractDouble(data, EXIF_TAG_EXPOSURE_TIME, &exposure_time_sec_);
261
262 int flash_value = -1;
263 ExtractInt(data, EXIF_TAG_FLASH, &flash_value);
264 if (flash_value >= 0) {
265 flash_fired_ = (flash_value & 0x1) != 0;
266 }
267
268 ExtractDouble(data, EXIF_TAG_FNUMBER, &f_number_);
269 ExtractDouble(data, EXIF_TAG_FOCAL_LENGTH, &focal_length_mm_);
270 ExtractInt(data, EXIF_TAG_ISO_SPEED_RATINGS, &iso_equivalent_);
271
272 exif_data_free(data);
273
274 extracted_ = true;
275
276 callback.Run(true);
277 }
278
279 } // namespace metadata
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698