1/*M///////////////////////////////////////////////////////////////////////////////////////
2//
3// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4//
5// By downloading, copying, installing or using the software you agree to this license.
6// If you do not agree to this license, do not download, install,
7// copy or use the software.
8//
9//
10// License Agreement
11// For Open Source Computer Vision Library
12//
13// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15// Third party copyrights are property of their respective owners.
16//
17// Redistribution and use in source and binary forms, with or without modification,
18// are permitted provided that the following conditions are met:
19//
20// * Redistribution's of source code must retain the above copyright notice,
21// this list of conditions and the following disclaimer.
22//
23// * Redistribution's in binary form must reproduce the above copyright notice,
24// this list of conditions and the following disclaimer in the documentation
25// and/or other materials provided with the distribution.
26//
27// * The name of the copyright holders may not be used to endorse or promote products
28// derived from this software without specific prior written permission.
29//
30// This software is provided by the copyright holders and contributors "as is" and
31// any express or implied warranties, including, but not limited to, the implied
32// warranties of merchantability and fitness for a particular purpose are disclaimed.
33// In no event shall the Intel Corporation or contributors be liable for any direct,
34// indirect, incidental, special, exemplary, or consequential damages
35// (including, but not limited to, procurement of substitute goods or services;
36// loss of use, data, or profits; or business interruption) however caused
37// and on any theory of liability, whether in contract, strict liability,
38// or tort (including negligence or otherwise) arising in any way out of
39// the use of this software, even if advised of the possibility of such damage.
40//
41//M*/
42
43#include "precomp.hpp"
44#include "exif.hpp"
45
46namespace {
47
48 class ExifParsingError {
49 };
50}
51
52
53namespace cv
54{
55
56ExifEntry_t::ExifEntry_t() :
57 field_float(0), field_double(0), field_u32(0), field_s32(0),
58 tag(INVALID_TAG), field_u16(0), field_s16(0), field_u8(0), field_s8(0)
59{
60}
61
62/**
63 * @brief ExifReader constructor
64 */
65ExifReader::ExifReader() : m_format(NONE)
66{
67}
68
69/**
70 * @brief ExifReader destructor
71 */
72ExifReader::~ExifReader()
73{
74}
75
76
77/**
78 * @brief Get tag value by tag number
79 *
80 * @param [in] tag The tag number
81 *
82 * @return ExifEntru_t structure. Caller has to know what tag it calls in order to extract proper field from the structure ExifEntry_t
83 *
84 */
85ExifEntry_t ExifReader::getTag(const ExifTagName tag) const
86{
87 ExifEntry_t entry;
88 std::map<int, ExifEntry_t>::const_iterator it = m_exif.find(x: tag);
89
90 if( it != m_exif.end() )
91 {
92 entry = it->second;
93 }
94 return entry;
95}
96
97
98/**
99 * @brief Parsing the exif data buffer and prepare (internal) exif directory
100 *
101 * @param [in] data The data buffer to read EXIF data starting with endianness
102 * @param [in] size The size of the data buffer
103 *
104 * @return true if parsing was successful
105 * false in case of unsuccessful parsing
106 */
107bool ExifReader::parseExif(unsigned char* data, const size_t size)
108{
109 // Populate m_data, then call parseExif() (private)
110 if( data && size > 0 )
111 {
112 m_data.assign(first: data, last: data + size);
113 }
114 else
115 {
116 return false;
117 }
118
119 try {
120 parseExif();
121 if( !m_exif.empty() )
122 {
123 return true;
124 }
125 return false;
126 }
127 catch( ExifParsingError& ) {
128 return false;
129 }
130}
131
132/**
133 * @brief Filling m_exif member with exif directory elements
134 * This is internal function and is not exposed to client
135 *
136 * The function doesn't return any value. In case of unsuccessful parsing
137 * the m_exif member is not filled up
138 */
139void ExifReader::parseExif()
140{
141 m_format = getFormat();
142
143 if( !checkTagMark() )
144 {
145 return;
146 }
147
148 uint32_t offset = getStartOffset();
149
150 size_t numEntry = getNumDirEntry( offsetNumDir: offset );
151
152 offset += 2; //go to start of tag fields
153
154 for( size_t entry = 0; entry < numEntry; entry++ )
155 {
156 ExifEntry_t exifEntry = parseExifEntry( offset );
157 m_exif.insert( x: std::make_pair( x&: exifEntry.tag, y&: exifEntry ) );
158 offset += tiffFieldSize;
159 }
160}
161
162/**
163 * @brief Get endianness of exif information
164 * This is internal function and is not exposed to client
165 *
166 * @return INTEL, MOTO or NONE
167 */
168Endianess_t ExifReader::getFormat() const
169{
170 if (m_data.size() < 1)
171 return NONE;
172
173 if( m_data.size() > 1 && m_data[0] != m_data[1] )
174 {
175 return NONE;
176 }
177
178 if( m_data[0] == 'I' )
179 {
180 return INTEL;
181 }
182
183 if( m_data[0] == 'M' )
184 {
185 return MOTO;
186 }
187
188 return NONE;
189}
190
191/**
192 * @brief Checking whether Tag Mark (0x002A) correspond to one contained in the Jpeg file
193 * This is internal function and is not exposed to client
194 *
195 * @return true if tag mark equals 0x002A, false otherwise
196 */
197bool ExifReader::checkTagMark() const
198{
199 uint16_t tagMark = getU16( offset: 2 );
200
201 if( tagMark != tagMarkRequired )
202 {
203 return false;
204 }
205 return true;
206}
207
208/**
209 * @brief The utility function for extracting actual offset exif IFD0 info is started from
210 * This is internal function and is not exposed to client
211 *
212 * @return offset of IFD0 field
213 */
214uint32_t ExifReader::getStartOffset() const
215{
216 return getU32( offset: 4 );
217}
218
219/**
220 * @brief Get the number of Directory Entries in Jpeg file
221 *
222 * @return The number of directory entries
223 */
224size_t ExifReader::getNumDirEntry(const size_t offsetNumDir) const
225{
226 return getU16( offset: offsetNumDir );
227}
228
229/**
230 * @brief Parsing particular entry in exif directory
231 * This is internal function and is not exposed to client
232 *
233 * Entries are divided into 12-bytes blocks each
234 * Each block corresponds the following structure:
235 *
236 * +------+-------------+-------------------+------------------------+
237 * | Type | Data format | Num of components | Data or offset to data |
238 * +======+=============+===================+========================+
239 * | TTTT | ffff | NNNNNNNN | DDDDDDDD |
240 * +------+-------------+-------------------+------------------------+
241 *
242 * Details can be found here: http://www.media.mit.edu/pia/Research/deepview/exif.html
243 *
244 * @param [in] offset Offset to entry in bytes inside raw exif data
245 * @return ExifEntry_t structure which corresponds to particular entry
246 *
247 */
248ExifEntry_t ExifReader::parseExifEntry(const size_t offset)
249{
250 ExifEntry_t entry;
251 uint16_t tagNum = getExifTag( offset );
252 entry.tag = tagNum;
253
254 switch( tagNum )
255 {
256 case IMAGE_DESCRIPTION:
257 entry.field_str = getString( offset );
258 break;
259 case MAKE:
260 entry.field_str = getString( offset );
261 break;
262 case MODEL:
263 entry.field_str = getString( offset );
264 break;
265 case ORIENTATION:
266 entry.field_u16 = getOrientation( offset );
267 break;
268 case XRESOLUTION:
269 entry.field_u_rational = getResolution( offset );
270 break;
271 case YRESOLUTION:
272 entry.field_u_rational = getResolution( offset );
273 break;
274 case RESOLUTION_UNIT:
275 entry.field_u16 = getResolutionUnit( offset );
276 break;
277 case SOFTWARE:
278 entry.field_str = getString( offset );
279 break;
280 case DATE_TIME:
281 entry.field_str = getString( offset );
282 break;
283 case WHITE_POINT:
284 entry.field_u_rational = getWhitePoint( offset );
285 break;
286 case PRIMARY_CHROMATICIES:
287 entry.field_u_rational = getPrimaryChromaticies( offset );
288 break;
289 case Y_CB_CR_COEFFICIENTS:
290 entry.field_u_rational = getYCbCrCoeffs( offset );
291 break;
292 case Y_CB_CR_POSITIONING:
293 entry.field_u16 = getYCbCrPos( offset );
294 break;
295 case REFERENCE_BLACK_WHITE:
296 entry.field_u_rational = getRefBW( offset );
297 break;
298 case COPYRIGHT:
299 entry.field_str = getString( offset );
300 break;
301 case EXIF_OFFSET:
302 break;
303 default:
304 entry.tag = INVALID_TAG;
305 break;
306 }
307 return entry;
308}
309
310/**
311 * @brief Get tag number from raw exif data
312 * This is internal function and is not exposed to client
313 * @param [in] offset Offset to entry in bytes inside raw exif data
314 * @return tag number
315 */
316uint16_t ExifReader::getExifTag(const size_t offset) const
317{
318 return getU16( offset );
319}
320
321/**
322 * @brief Get string information from raw exif data
323 * This is internal function and is not exposed to client
324 * @param [in] offset Offset to entry in bytes inside raw exif data
325 * @return string value
326 */
327std::string ExifReader::getString(const size_t offset) const
328{
329 size_t size = getU32( offset: offset + 4 );
330 size_t dataOffset = 8; // position of data in the field
331 if( size > maxDataSize )
332 {
333 dataOffset = getU32( offset: offset + 8 );
334 }
335 if (dataOffset > m_data.size() || dataOffset + size > m_data.size()) {
336 throw ExifParsingError();
337 }
338 std::vector<uint8_t>::const_iterator it = m_data.begin() + dataOffset;
339 std::string result( it, it + size ); //copy vector content into result
340
341 return result;
342}
343
344/**
345 * @brief Get unsigned short data from raw exif data
346 * This is internal function and is not exposed to client
347 * @param [in] offset Offset to entry in bytes inside raw exif data
348 * @return Unsigned short data
349 */
350uint16_t ExifReader::getU16(const size_t offset) const
351{
352 if (offset + 1 >= m_data.size())
353 throw ExifParsingError();
354
355 if( m_format == INTEL )
356 {
357 return m_data[offset] + ( m_data[offset + 1] << 8 );
358 }
359 return ( m_data[offset] << 8 ) + m_data[offset + 1];
360}
361
362/**
363 * @brief Get unsigned 32-bit data from raw exif data
364 * This is internal function and is not exposed to client
365 * @param [in] offset Offset to entry in bytes inside raw exif data
366 * @return Unsigned 32-bit data
367 */
368uint32_t ExifReader::getU32(const size_t offset) const
369{
370 if (offset + 3 >= m_data.size())
371 throw ExifParsingError();
372
373 if( m_format == INTEL )
374 {
375 return m_data[offset] +
376 ( m_data[offset + 1] << 8 ) +
377 ( m_data[offset + 2] << 16 ) +
378 ( m_data[offset + 3] << 24 );
379 }
380
381 return ( m_data[offset] << 24 ) +
382 ( m_data[offset + 1] << 16 ) +
383 ( m_data[offset + 2] << 8 ) +
384 m_data[offset + 3];
385}
386
387/**
388 * @brief Get unsigned rational data from raw exif data
389 * This is internal function and is not exposed to client
390 * @param [in] offset Offset to entry in bytes inside raw exif data
391 * @return Unsigned rational data
392 *
393 * "rational" means a fractional value, it contains 2 signed/unsigned long integer value,
394 * and the first represents the numerator, the second, the denominator.
395 */
396u_rational_t ExifReader::getURational(const size_t offset) const
397{
398 uint32_t numerator = getU32( offset );
399 uint32_t denominator = getU32( offset: offset + 4 );
400
401 return std::make_pair( x&: numerator, y&: denominator );
402
403}
404
405/**
406 * @brief Get orientation information from raw exif data
407 * This is internal function and is not exposed to client
408 * @param [in] offset Offset to entry in bytes inside raw exif data
409 * @return orientation number
410 */
411uint16_t ExifReader::getOrientation(const size_t offset) const
412{
413 return getU16( offset: offset + 8 );
414}
415
416/**
417 * @brief Get resolution information from raw exif data
418 * This is internal function and is not exposed to client
419 * @param [in] offset Offset to entry in bytes inside raw exif data
420 * @return resolution value
421 */
422std::vector<u_rational_t> ExifReader::getResolution(const size_t offset) const
423{
424 std::vector<u_rational_t> result;
425 uint32_t rationalOffset = getU32( offset: offset + 8 );
426 result.push_back( x: getURational( offset: rationalOffset ) );
427
428 return result;
429}
430
431/**
432 * @brief Get resolution unit from raw exif data
433 * This is internal function and is not exposed to client
434 * @param [in] offset Offset to entry in bytes inside raw exif data
435 * @return resolution unit value
436 */
437uint16_t ExifReader::getResolutionUnit(const size_t offset) const
438{
439 return getU16( offset: offset + 8 );
440}
441
442/**
443 * @brief Get White Point information from raw exif data
444 * This is internal function and is not exposed to client
445 * @param [in] offset Offset to entry in bytes inside raw exif data
446 * @return White Point value
447 *
448 * If the image uses CIE Standard Illumination D65(known as international
449 * standard of 'daylight'), the values are '3127/10000,3290/10000'.
450 */
451std::vector<u_rational_t> ExifReader::getWhitePoint(const size_t offset) const
452{
453 std::vector<u_rational_t> result;
454 uint32_t rationalOffset = getU32( offset: offset + 8 );
455 result.push_back( x: getURational( offset: rationalOffset ) );
456 result.push_back( x: getURational( offset: rationalOffset + 8 ) );
457
458 return result;
459}
460
461/**
462 * @brief Get Primary Chromaticies information from raw exif data
463 * This is internal function and is not exposed to client
464 * @param [in] offset Offset to entry in bytes inside raw exif data
465 * @return vector with primary chromaticies values
466 *
467 */
468std::vector<u_rational_t> ExifReader::getPrimaryChromaticies(const size_t offset) const
469{
470 std::vector<u_rational_t> result;
471 uint32_t rationalOffset = getU32( offset: offset + 8 );
472 for( size_t i = 0; i < primaryChromaticiesComponents; i++ )
473 {
474 result.push_back( x: getURational( offset: rationalOffset ) );
475 rationalOffset += 8;
476 }
477 return result;
478}
479
480/**
481 * @brief Get YCbCr Coefficients information from raw exif data
482 * This is internal function and is not exposed to client
483 * @param [in] offset Offset to entry in bytes inside raw exif data
484 * @return vector with YCbCr coefficients values
485 *
486 */
487std::vector<u_rational_t> ExifReader::getYCbCrCoeffs(const size_t offset) const
488{
489 std::vector<u_rational_t> result;
490 uint32_t rationalOffset = getU32( offset: offset + 8 );
491 for( size_t i = 0; i < ycbcrCoeffs; i++ )
492 {
493 result.push_back( x: getURational( offset: rationalOffset ) );
494 rationalOffset += 8;
495 }
496 return result;
497}
498
499/**
500 * @brief Get YCbCr Positioning information from raw exif data
501 * This is internal function and is not exposed to client
502 * @param [in] offset Offset to entry in bytes inside raw exif data
503 * @return vector with YCbCr positioning value
504 *
505 */
506uint16_t ExifReader::getYCbCrPos(const size_t offset) const
507{
508 return getU16( offset: offset + 8 );
509}
510
511/**
512 * @brief Get Reference Black&White point information from raw exif data
513 * This is internal function and is not exposed to client
514 * @param [in] offset Offset to entry in bytes inside raw exif data
515 * @return vector with reference BW points
516 *
517 * In case of YCbCr format, first 2 show black/white of Y, next 2 are Cb,
518 * last 2 are Cr. In case of RGB format, first 2 show black/white of R,
519 * next 2 are G, last 2 are B.
520 *
521 */
522std::vector<u_rational_t> ExifReader::getRefBW(const size_t offset) const
523{
524 const size_t rationalFieldSize = 8;
525 std::vector<u_rational_t> result;
526 uint32_t rationalOffset = getU32( offset: offset + rationalFieldSize );
527 for( size_t i = 0; i < refBWComponents; i++ )
528 {
529 result.push_back( x: getURational( offset: rationalOffset ) );
530 rationalOffset += rationalFieldSize;
531 }
532 return result;
533}
534
535} //namespace cv
536

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of opencv/modules/imgcodecs/src/exif.cpp