Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linphone-desktop
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
linphone-desktop
Commits
e249bc3e
Commit
e249bc3e
authored
Jul 16, 2017
by
Wescoeur
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix(QExifImageHeader): use app indentation
parent
8d46bcb1
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
1305 additions
and
1440 deletions
+1305
-1440
QExifImageHeader.cpp
src/utils/QExifImageHeader.cpp
+1047
-1170
QExifImageHeader.h
src/utils/QExifImageHeader.h
+258
-270
No files found.
src/utils/QExifImageHeader.cpp
View file @
e249bc3e
...
...
@@ -56,153 +56,136 @@
A synonym for \c QPair<qint32,qint32> representing a signed rational number as stored in EXIF
headers. The first integer in the pair is the numerator and the second the denominator.
*/
*/
/*!
\typedef QExifURational
A synonym for \c QPair<qint32,qint32> representing an unsigned rational number as stored in
EXIF headers. The first integer in the pair is the numerator and the second the denominator.
*/
struct
ExifIfdHeader
{
quint16
tag
;
quint16
type
;
quint32
count
;
union
{
quint32
offset
;
quint8
offsetBytes
[
4
];
char
offsetAscii
[
4
];
quint16
offsetShorts
[
2
];
};
*/
struct
ExifIfdHeader
{
quint16
tag
;
quint16
type
;
quint32
count
;
union
{
quint32
offset
;
quint8
offsetBytes
[
4
];
char
offsetAscii
[
4
];
quint16
offsetShorts
[
2
];
};
};
QDataStream
&
operator
>>
(
QDataStream
&
stream
,
ExifIfdHeader
&
header
)
{
stream
>>
header
.
tag
;
stream
>>
header
.
type
;
stream
>>
header
.
count
;
QDataStream
&
operator
>>
(
QDataStream
&
stream
,
ExifIfdHeader
&
header
)
{
stream
>>
header
.
tag
;
stream
>>
header
.
type
;
stream
>>
header
.
count
;
if
(
header
.
type
==
QExifValue
::
Byte
&&
header
.
count
<=
4
)
{
stream
.
readRawData
(
header
.
offsetAscii
,
4
);
}
else
if
(
header
.
type
==
QExifValue
::
Ascii
&&
header
.
count
<=
4
)
{
stream
.
readRawData
(
header
.
offsetAscii
,
4
);
}
else
if
(
header
.
type
==
QExifValue
::
Short
&&
header
.
count
<=
2
)
{
stream
>>
header
.
offsetShorts
[
0
];
stream
>>
header
.
offsetShorts
[
1
];
}
else
{
stream
>>
header
.
offset
;
}
if
(
header
.
type
==
QExifValue
::
Byte
&&
header
.
count
<=
4
)
{
stream
.
readRawData
(
header
.
offsetAscii
,
4
);
}
else
if
(
header
.
type
==
QExifValue
::
Ascii
&&
header
.
count
<=
4
)
{
stream
.
readRawData
(
header
.
offsetAscii
,
4
);
}
else
if
(
header
.
type
==
QExifValue
::
Short
&&
header
.
count
<=
2
)
{
stream
>>
header
.
offsetShorts
[
0
];
stream
>>
header
.
offsetShorts
[
1
];
}
else
{
stream
>>
header
.
offset
;
}
return
stream
;
return
stream
;
}
class
QExifValuePrivate
:
public
QSharedData
{
class
QExifValuePrivate
:
public
QSharedData
{
public:
QExifValuePrivate
(
quint16
t
,
int
c
)
:
type
(
t
),
count
(
c
)
{}
virtual
~
QExifValuePrivate
(){}
QExifValuePrivate
(
quint16
t
,
int
c
)
:
type
(
t
),
count
(
c
)
{}
virtual
~
QExifValuePrivate
()
{}
quint16
type
;
int
count
;
quint16
type
;
int
count
;
};
class
QExifByteValuePrivate
:
public
QExifValuePrivate
{
class
QExifByteValuePrivate
:
public
QExifValuePrivate
{
public:
QExifByteValuePrivate
()
:
QExifValuePrivate
(
QExifValue
::
Byte
,
0
)
{
ref
.
ref
();
}
QExifByteValuePrivate
(
const
QVector
<
quint8
>
&
v
)
:
QExifValuePrivate
(
QExifValue
::
Byte
,
v
.
size
()
),
value
(
v
)
{}
QVector
<
quint8
>
value
;
QExifByteValuePrivate
()
:
QExifValuePrivate
(
QExifValue
::
Byte
,
0
)
{
ref
.
ref
();
}
QExifByteValuePrivate
(
const
QVector
<
quint8
>
&
v
)
:
QExifValuePrivate
(
QExifValue
::
Byte
,
v
.
size
()),
value
(
v
)
{}
QVector
<
quint8
>
value
;
};
class
QExifUndefinedValuePrivate
:
public
QExifValuePrivate
{
class
QExifUndefinedValuePrivate
:
public
QExifValuePrivate
{
public:
QExifUndefinedValuePrivate
(
const
QByteArray
&
v
)
:
QExifValuePrivate
(
QExifValue
::
Undefined
,
v
.
size
()
),
value
(
v
)
{}
QExifUndefinedValuePrivate
(
const
QByteArray
&
v
)
:
QExifValuePrivate
(
QExifValue
::
Undefined
,
v
.
size
()),
value
(
v
)
{}
QByteArray
value
;
QByteArray
value
;
};
class
QExifAsciiValuePrivate
:
public
QExifValuePrivate
{
class
QExifAsciiValuePrivate
:
public
QExifValuePrivate
{
public:
QExifAsciiValuePrivate
(
const
QString
&
v
)
:
QExifValuePrivate
(
QExifValue
::
Ascii
,
v
.
size
()
+
1
),
value
(
v
)
{}
QExifAsciiValuePrivate
(
const
QString
&
v
)
:
QExifValuePrivate
(
QExifValue
::
Ascii
,
v
.
size
()
+
1
),
value
(
v
)
{}
QString
value
;
QString
value
;
};
class
QExifShortValuePrivate
:
public
QExifValuePrivate
{
class
QExifShortValuePrivate
:
public
QExifValuePrivate
{
public:
QExifShortValuePrivate
(
const
QVector
<
quint16
>
&
v
)
:
QExifValuePrivate
(
QExifValue
::
Short
,
v
.
size
()
),
value
(
v
)
{}
QExifShortValuePrivate
(
const
QVector
<
quint16
>
&
v
)
:
QExifValuePrivate
(
QExifValue
::
Short
,
v
.
size
()),
value
(
v
)
{}
QVector
<
quint16
>
value
;
QVector
<
quint16
>
value
;
};
class
QExifLongValuePrivate
:
public
QExifValuePrivate
{
class
QExifLongValuePrivate
:
public
QExifValuePrivate
{
public:
QExifLongValuePrivate
(
const
QVector
<
quint32
>
&
v
)
:
QExifValuePrivate
(
QExifValue
::
Long
,
v
.
size
()
),
value
(
v
)
{}
QExifLongValuePrivate
(
const
QVector
<
quint32
>
&
v
)
:
QExifValuePrivate
(
QExifValue
::
Long
,
v
.
size
()),
value
(
v
)
{}
QVector
<
quint32
>
value
;
QVector
<
quint32
>
value
;
};
class
QExifSignedLongValuePrivate
:
public
QExifValuePrivate
{
class
QExifSignedLongValuePrivate
:
public
QExifValuePrivate
{
public:
QExifSignedLongValuePrivate
(
const
QVector
<
qint32
>
&
v
)
:
QExifValuePrivate
(
QExifValue
::
SignedLong
,
v
.
size
()
),
value
(
v
)
{}
QExifSignedLongValuePrivate
(
const
QVector
<
qint32
>
&
v
)
:
QExifValuePrivate
(
QExifValue
::
SignedLong
,
v
.
size
()),
value
(
v
)
{}
QVector
<
qint32
>
value
;
QVector
<
qint32
>
value
;
};
class
QExifRationalValuePrivate
:
public
QExifValuePrivate
{
class
QExifRationalValuePrivate
:
public
QExifValuePrivate
{
public:
QExifRationalValuePrivate
(
const
QVector
<
QExifURational
>
&
v
)
:
QExifValuePrivate
(
QExifValue
::
Rational
,
v
.
size
()
),
value
(
v
)
{}
QExifRationalValuePrivate
(
const
QVector
<
QExifURational
>
&
v
)
:
QExifValuePrivate
(
QExifValue
::
Rational
,
v
.
size
()),
value
(
v
)
{}
QVector
<
QExifURational
>
value
;
QVector
<
QExifURational
>
value
;
};
class
QExifSignedRationalValuePrivate
:
public
QExifValuePrivate
{
class
QExifSignedRationalValuePrivate
:
public
QExifValuePrivate
{
public:
QExifSignedRationalValuePrivate
(
const
QVector
<
QExifSRational
>
&
v
)
:
QExifValuePrivate
(
QExifValue
::
SignedRational
,
v
.
size
()
),
value
(
v
)
{}
QExifSignedRationalValuePrivate
(
const
QVector
<
QExifSRational
>
&
v
)
:
QExifValuePrivate
(
QExifValue
::
SignedRational
,
v
.
size
()),
value
(
v
)
{}
QVector
<
QExifSRational
>
value
;
QVector
<
QExifSRational
>
value
;
};
Q_GLOBAL_STATIC
(
QExifByteValuePrivate
,
qExifValuePrivateSharedNull
)
Q_GLOBAL_STATIC
(
QExifByteValuePrivate
,
qExifValuePrivateSharedNull
)
/*!
\class QExifValue
...
...
@@ -228,7 +211,7 @@ Q_GLOBAL_STATIC(QExifByteValuePrivate,qExifValuePrivateSharedNull)
\sa QExifImageHeader
\preliminary
*/
*/
/*!
\enum QExifValue::Type
...
...
@@ -243,7 +226,7 @@ Q_GLOBAL_STATIC(QExifByteValuePrivate,qExifValuePrivateSharedNull)
\value Undefined An array of 8 bit integers.
\value SignedLong A signed 32 bit integer.
\value SignedRational Two signed 32 bit integers representing the numerator and denominator of a signed rational number.
*/
*/
/*!
\enum QExifValue::TextEncoding
...
...
@@ -255,481 +238,425 @@ Q_GLOBAL_STATIC(QExifByteValuePrivate,qExifValuePrivateSharedNull)
\value JisEncoding A JIS X208-1990 string of Undefined type.
\value UnicodeEncoding A Unicode string of Undefined type.
\value UndefinedEncoding An unspecified string encoding of Undefined type. Assumed to be the local 8-bit encoding.
*/
*/
/*!
Constructs a null QExifValue.
*/
QExifValue
::
QExifValue
()
:
d
(
qExifValuePrivateSharedNull
()
)
{
}
*/
QExifValue
::
QExifValue
()
:
d
(
qExifValuePrivateSharedNull
())
{}
/*!
Constructs a QExifValue with a \a value of type Byte.
*/
QExifValue
::
QExifValue
(
quint8
value
)
:
d
(
new
QExifByteValuePrivate
(
QVector
<
quint8
>
(
1
,
value
)
)
)
{
}
*/
QExifValue
::
QExifValue
(
quint8
value
)
:
d
(
new
QExifByteValuePrivate
(
QVector
<
quint8
>
(
1
,
value
)))
{}
/*!
Constructs a QExifValue with an array of \a values of type Byte.
*/
QExifValue
::
QExifValue
(
const
QVector
<
quint8
>
&
values
)
:
d
(
new
QExifByteValuePrivate
(
values
)
)
{
}
*/
QExifValue
::
QExifValue
(
const
QVector
<
quint8
>
&
values
)
:
d
(
new
QExifByteValuePrivate
(
values
))
{}
/*!
Constructs a QExifValue with a \a value of type Ascii or Undefined.
If the \a encoding is NoEncoding the value will be of type Ascii, otherwise it will be Undefined and the string
encoded using the given \a encoding.
*/
QExifValue
::
QExifValue
(
const
QString
&
value
,
TextEncoding
encoding
)
:
d
(
qExifValuePrivateSharedNull
()
)
{
switch
(
encoding
)
{
*/
QExifValue
::
QExifValue
(
const
QString
&
value
,
TextEncoding
encoding
)
:
d
(
qExifValuePrivateSharedNull
())
{
switch
(
encoding
)
{
case
AsciiEncoding
:
d
=
new
QExifUndefinedValuePrivate
(
QByteArray
::
fromRawData
(
"ASCII
\0\0\0
"
,
8
)
+
value
.
toUtf8
()
);
break
;
case
JisEncoding
:
{
QTextCodec
*
codec
=
QTextCodec
::
codecForName
(
"JIS X 0208"
);
if
(
codec
)
d
=
new
QExifUndefinedValuePrivate
(
QByteArray
::
fromRawData
(
"JIS
\0\0\0\0\0
"
,
8
)
+
codec
->
fromUnicode
(
value
)
);
}
break
;
case
UnicodeEncoding
:
{
QTextCodec
*
codec
=
QTextCodec
::
codecForName
(
"UTF-16"
);
if
(
codec
)
d
=
new
QExifUndefinedValuePrivate
(
QByteArray
::
fromRawData
(
"UNICODE
\0
"
,
8
)
+
codec
->
fromUnicode
(
value
)
);
}
break
;
d
=
new
QExifUndefinedValuePrivate
(
QByteArray
::
fromRawData
(
"ASCII
\0\0\0
"
,
8
)
+
value
.
toUtf8
());
break
;
case
JisEncoding
:
{
QTextCodec
*
codec
=
QTextCodec
::
codecForName
(
"JIS X 0208"
);
if
(
codec
)
d
=
new
QExifUndefinedValuePrivate
(
QByteArray
::
fromRawData
(
"JIS
\0\0\0\0\0
"
,
8
)
+
codec
->
fromUnicode
(
value
));
}
break
;
case
UnicodeEncoding
:
{
QTextCodec
*
codec
=
QTextCodec
::
codecForName
(
"UTF-16"
);
if
(
codec
)
d
=
new
QExifUndefinedValuePrivate
(
QByteArray
::
fromRawData
(
"UNICODE
\0
"
,
8
)
+
codec
->
fromUnicode
(
value
));
}
break
;
case
UndefinedEncoding
:
d
=
new
QExifUndefinedValuePrivate
(
QByteArray
::
fromRawData
(
"
\0\0\0\0\0\0\0\\
0"
,
8
)
+
value
.
toLocal8Bit
()
);
break
;
d
=
new
QExifUndefinedValuePrivate
(
QByteArray
::
fromRawData
(
"
\0\0\0\0\0\0\0\\
0"
,
8
)
+
value
.
toLocal8Bit
()
);
break
;
default:
d
=
new
QExifAsciiValuePrivate
(
value
);
}
d
=
new
QExifAsciiValuePrivate
(
value
);
}
}
/*!
Constructs a QExifValue with a \a value of type Short.
*/
QExifValue
::
QExifValue
(
quint16
value
)
:
d
(
new
QExifShortValuePrivate
(
QVector
<
quint16
>
(
1
,
value
)
)
)
{
}
*/
QExifValue
::
QExifValue
(
quint16
value
)
:
d
(
new
QExifShortValuePrivate
(
QVector
<
quint16
>
(
1
,
value
)))
{}
/*!
Constructs a QExifValue with an array of \a values of type Short.
*/
QExifValue
::
QExifValue
(
const
QVector
<
quint16
>
&
values
)
:
d
(
new
QExifShortValuePrivate
(
values
)
)
{
}
*/
QExifValue
::
QExifValue
(
const
QVector
<
quint16
>
&
values
)
:
d
(
new
QExifShortValuePrivate
(
values
))
{}
/*!
Constructs a QExifValue with a \a value of type Long.
*/
QExifValue
::
QExifValue
(
quint32
value
)
:
d
(
new
QExifLongValuePrivate
(
QVector
<
quint32
>
(
1
,
value
)
)
)
{
}
*/
QExifValue
::
QExifValue
(
quint32
value
)
:
d
(
new
QExifLongValuePrivate
(
QVector
<
quint32
>
(
1
,
value
)))
{}
/*!
Constructs a QExifValue with an array of \a values of type Long.
*/
QExifValue
::
QExifValue
(
const
QVector
<
quint32
>
&
values
)
:
d
(
new
QExifLongValuePrivate
(
values
)
)
{
}
*/
QExifValue
::
QExifValue
(
const
QVector
<
quint32
>
&
values
)
:
d
(
new
QExifLongValuePrivate
(
values
))
{}
/*!
Constructs a QExifValue with a \a value of type Rational.
*/
QExifValue
::
QExifValue
(
const
QExifURational
&
value
)
:
d
(
new
QExifRationalValuePrivate
(
QVector
<
QExifURational
>
(
1
,
value
)
)
)
{
}
*/
QExifValue
::
QExifValue
(
const
QExifURational
&
value
)
:
d
(
new
QExifRationalValuePrivate
(
QVector
<
QExifURational
>
(
1
,
value
)))
{}
/*!
Constructs a QExifValue with an array of \a values of type Rational.
*/
QExifValue
::
QExifValue
(
const
QVector
<
QExifURational
>
&
values
)
:
d
(
new
QExifRationalValuePrivate
(
values
)
)
{
}
*/
QExifValue
::
QExifValue
(
const
QVector
<
QExifURational
>
&
values
)
:
d
(
new
QExifRationalValuePrivate
(
values
))
{}
/*!
Constructs a QExifValue with a \a value of type Undefined.
*/
QExifValue
::
QExifValue
(
const
QByteArray
&
value
)
:
d
(
new
QExifUndefinedValuePrivate
(
value
)
)
{
}
*/
QExifValue
::
QExifValue
(
const
QByteArray
&
value
)
:
d
(
new
QExifUndefinedValuePrivate
(
value
))
{}
/*!
Constructs a QExifValue with a \a value of type SignedLong.
*/
QExifValue
::
QExifValue
(
qint32
value
)
:
d
(
new
QExifSignedLongValuePrivate
(
QVector
<
qint32
>
(
1
,
value
)
)
)
{
}
*/
QExifValue
::
QExifValue
(
qint32
value
)
:
d
(
new
QExifSignedLongValuePrivate
(
QVector
<
qint32
>
(
1
,
value
)))
{}
/*!
Constructs a QExifValue with an array of \a values of type SignedLong.
*/
QExifValue
::
QExifValue
(
const
QVector
<
qint32
>
&
values
)
:
d
(
new
QExifSignedLongValuePrivate
(
values
)
)
{
}
*/
QExifValue
::
QExifValue
(
const
QVector
<
qint32
>
&
values
)
:
d
(
new
QExifSignedLongValuePrivate
(
values
))
{}
/*!
Constructs a QExifValue with a \a value of type SignedRational.
*/
QExifValue
::
QExifValue
(
const
QExifSRational
&
value
)
:
d
(
new
QExifSignedRationalValuePrivate
(
QVector
<
QExifSRational
>
(
1
,
value
)
)
)
{
}
*/
QExifValue
::
QExifValue
(
const
QExifSRational
&
value
)
:
d
(
new
QExifSignedRationalValuePrivate
(
QVector
<
QExifSRational
>
(
1
,
value
)))
{}
/*!
Constructs a QExifValue with an array of \a values of type SignedRational.
*/
QExifValue
::
QExifValue
(
const
QVector
<
QExifSRational
>
&
values
)
:
d
(
new
QExifSignedRationalValuePrivate
(
values
)
)
{
}
*/
QExifValue
::
QExifValue
(
const
QVector
<
QExifSRational
>
&
values
)
:
d
(
new
QExifSignedRationalValuePrivate
(
values
))
{}
/*!
Constructs a QExifValue of type Ascii with an ascii string formatted from a date-time \a value.
Date-times are stored as strings in the format \c {yyyy:MM:dd HH:mm:ss}.
*/
QExifValue
::
QExifValue
(
const
QDateTime
&
value
)
:
d
(
new
QExifAsciiValuePrivate
(
value
.
toString
(
QLatin1String
(
"yyyy:MM:dd HH:mm:ss"
)
)
)
)
{
}
*/
QExifValue
::
QExifValue
(
const
QDateTime
&
value
)
:
d
(
new
QExifAsciiValuePrivate
(
value
.
toString
(
QLatin1String
(
"yyyy:MM:dd HH:mm:ss"
))))
{}
/*!
Constructs a copy of the QExifValue \a other.
*/
QExifValue
::
QExifValue
(
const
QExifValue
&
other
)
:
d
(
other
.
d
)
{
}
*/
QExifValue
::
QExifValue
(
const
QExifValue
&
other
)
:
d
(
other
.
d
)
{}
/*!
Assigns the value of \a other to a QExifValue.
*/
QExifValue
&
QExifValue
::
operator
=
(
const
QExifValue
&
other
)
{
d
=
other
.
d
;
*/
QExifValue
&
QExifValue
::
operator
=
(
const
QExifValue
&
other
)
{
d
=
other
.
d
;
return
*
this
;
return
*
this
;
}
/*!
Destroys a QExifValue.
*/
QExifValue
::~
QExifValue
()
{
}
*/
QExifValue
::~
QExifValue
()
{}
/*!
Compares a QExifValue to \a other. Returns true if they are the same value and false otherwise.
*/
bool
QExifValue
::
operator
==
(
const
QExifValue
&
other
)
const
{
return
d
==
other
.
d
;
*/
bool
QExifValue
::
operator
==
(
const
QExifValue
&
other
)
const
{
return
d
==
other
.
d
;
}
/*!
Returns true if a QExifValue has a null value and false otherwise.
*/
bool
QExifValue
::
isNull
()
const
{
return
d
==
qExifValuePrivateSharedNull
();
*/
bool
QExifValue
::
isNull
()
const
{
return
d
==
qExifValuePrivateSharedNull
();
}
/*!
Returns the type of a QExifValue.
*/
int
QExifValue
::
type
()
const
{
return
d
->
type
;
*/
int
QExifValue
::
type
()
const
{
return
d
->
type
;
}
/*!
Returns the number of elements in a QExifValue. For ascii strings this is the length of the string
including the terminating null.
*/
int
QExifValue
::
count
()
const
{
return
d
->
count
;
*/
int
QExifValue
::
count
()
const
{
return
d
->
count
;
}
/*!
Returns the encoding of strings stored in Undefined values.
*/
QExifValue
::
TextEncoding
QExifValue
::
encoding
()
const
{
if
(
d
->
type
==
Undefined
&&
d
->
count
>
8
)
{
QByteArray
value
=
static_cast
<
const
QExifUndefinedValuePrivate
*
>
(
d
.
constData
()
)
->
value
;
if
(
value
.
startsWith
(
QByteArray
::
fromRawData
(
"ASCII
\0\0\0
"
,
8
)
)
)
return
AsciiEncoding
;
else
if
(
value
.
startsWith
(
QByteArray
::
fromRawData
(
"JIS
\0\0\0\0\0
"
,
8
)
)
)
return
JisEncoding
;
else
if
(
value
.
startsWith
(
QByteArray
::
fromRawData
(
"UNICODE
\0
"
,
8
)
)
)
return
UnicodeEncoding
;
else
if
(
value
.
startsWith
(
QByteArray
::
fromRawData
(
"
\0\0\0\0\0\0\0\0
"
,
8
)
)
)
return
UndefinedEncoding
;
}
return
NoEncoding
;
*/
QExifValue
::
TextEncoding
QExifValue
::
encoding
()
const
{
if
(
d
->
type
==
Undefined
&&
d
->
count
>
8
)
{
QByteArray
value
=
static_cast
<
const
QExifUndefinedValuePrivate
*>
(
d
.
constData
())
->
value
;
if
(
value
.
startsWith
(
QByteArray
::
fromRawData
(
"ASCII
\0\0\0
"
,
8
)))
return
AsciiEncoding
;
else
if
(
value
.
startsWith
(
QByteArray
::
fromRawData
(
"JIS
\0\0\0\0\0
"
,
8
)))
return
JisEncoding
;
else
if
(
value
.
startsWith
(
QByteArray
::
fromRawData
(
"UNICODE
\0
"
,
8
)))
return
UnicodeEncoding
;
else
if
(
value
.
startsWith
(
QByteArray
::
fromRawData
(
"
\0\0\0\0\0\0\0\0
"
,
8
)))
return
UndefinedEncoding
;
}
return
NoEncoding
;
}
/*!
Returns the value of a single element QExifValue of type Byte.
*/
quint8
QExifValue
::
toByte
()
const
{
return
d
->
type
==
Byte
&&
d
->
count
==
1
?
static_cast
<
const
QExifByteValuePrivate
*
>
(
d
.
constData
()
)
->
value
.
at
(
0
)
:
0
;
*/
quint8
QExifValue
::
toByte
()
const
{
return
d
->
type
==
Byte
&&
d
->
count
==
1
?
static_cast
<
const
QExifByteValuePrivate
*>
(
d
.
constData
())
->
value
.
at
(
0
)
:
0
;
}
/*!
Returns the value of a multiple element QExifValue of type Byte.
*/
QVector
<
quint8
>
QExifValue
::
toByteVector
()
const
{
return
d
->
type
==
Byte
?
static_cast
<
const
QExifByteValuePrivate
*
>
(
d
.
constData
()
)
->
value
:
QVector
<
quint8
>
();
*/
QVector
<
quint8
>
QExifValue
::
toByteVector
()
const
{
return
d
->
type
==
Byte
?
static_cast
<
const
QExifByteValuePrivate
*>
(
d
.
constData
())
->
value
:
QVector
<
quint8
>
();
}
/*!
Returns the value of a QExifValue of type Ascii.
*/
QString
QExifValue
::
toString
()
const
{
switch
(
d
->
type
)
{
*/
QString
QExifValue
::
toString
()
const
{
switch
(
d
->
type
)
{
case
Ascii
:
return
static_cast
<
const
QExifAsciiValuePrivate
*
>
(
d
.
constData
()
)
->
value
;
case
Undefined
:
{
QByteArray
string
=
static_cast
<
const
QExifUndefinedValuePrivate
*
>
(
d
.
constData
()
)
->
value
.
mid
(
8
);
switch
(
encoding
()
)
{
case
AsciiEncoding
:
return
QString
::
fromUtf8
(
string
.
constData
(),
string
.
length
()
);
case
JisEncoding
:
{
QTextCodec
*
codec
=
QTextCodec
::
codecForName
(
"JIS X 0208"
);
if
(
codec
)
return
codec
->
toUnicode
(
string
);
}
break
;
case
UnicodeEncoding
:
{
QTextCodec
*
codec
=
QTextCodec
::
codecForName
(
"UTF-16"
);
if
(
codec
)
return
codec
->
toUnicode
(
string
);
}
case
UndefinedEncoding
:
return
QString
::
fromLocal8Bit
(
string
.
constData
(),
string
.
length
()
);
default:
break
;
}
return
static_cast
<
const
QExifAsciiValuePrivate
*>
(
d
.
constData
())
->
value
;
case
Undefined
:
{
QByteArray
string
=
static_cast
<
const
QExifUndefinedValuePrivate
*>
(
d
.
constData
())
->
value
.
mid
(
8
);
switch
(
encoding
())
{
case
AsciiEncoding
:
return
QString
::
fromUtf8
(
string
.
constData
(),
string
.
length
());
case
JisEncoding
:
{
QTextCodec
*
codec
=
QTextCodec
::
codecForName
(
"JIS X 0208"
);
if
(
codec
)
return
codec
->
toUnicode
(
string
);
}
default:
return
QString
();
break
;
case
UnicodeEncoding
:
{
QTextCodec
*
codec
=
QTextCodec
::
codecForName
(
"UTF-16"
);
if
(
codec
)
return
codec
->
toUnicode
(
string
);
}
case
UndefinedEncoding
:
return
QString
::
fromLocal8Bit
(
string
.
constData
(),
string
.
length
());
default:
break
;
}
}
default:
return
QString
();
}
}
/*!
Returns the value of a single element QExifValue of type Byte or Short.
*/
quint16
QExifValue
::
toShort
()
const
{
if
(
d
->
count
==
1
)
{
switch
(
d
->
type
)
{
case
Byte
:
return
static_cast
<
const
QExifByteValuePrivate
*
>
(
d
.
constData
()
)
->
value
.
at
(
0
);
case
Short
:
return
static_cast
<
const
QExifShortValuePrivate
*
>
(
d
.
constData
()
)
->
value
.
at
(
0
);
}
*/
quint16
QExifValue
::
toShort
()
const
{
if
(
d
->
count
==
1
)
{
switch
(
d
->
type
)
{
case
Byte
:
return
static_cast
<
const
QExifByteValuePrivate
*>
(
d
.
constData
())
->
value
.
at
(
0
);
case
Short
:
return
static_cast
<
const
QExifShortValuePrivate
*>
(
d
.
constData
())
->
value
.
at
(
0
);
}
return
0
;
}
return
0
;
}
/*!
Returns the value of a single element QExifValue of type Short.
*/
QVector
<
quint16
>
QExifValue
::
toShortVector
()
const
{
return
d
->
type
==
Short
?
static_cast
<
const
QExifShortValuePrivate
*
>
(
d
.
constData
()
)
->
value
:
QVector
<
quint16
>
();
*/
QVector
<
quint16
>
QExifValue
::
toShortVector
()
const
{
return
d
->
type
==
Short
?
static_cast
<
const
QExifShortValuePrivate
*>
(
d
.
constData
())
->
value
:
QVector
<
quint16
>
();
}
/*!
Returns the value of a single element QExifValue of type Byte, Short, Long, or SignedLong.
*/
quint32
QExifValue
::
toLong
()
const
{
if
(
d
->
count
==
1
)
{
switch
(
d
->
type
)
{
case
Byte
:
return
static_cast
<
const
QExifByteValuePrivate
*
>
(
d
.
constData
()
)
->
value
.
at
(
0
);
case
Short
:
return
static_cast
<
const
QExifShortValuePrivate
*
>
(
d
.
constData
()
)
->
value
.
at
(
0
);
case
Long
:
return
static_cast
<
const
QExifLongValuePrivate
*
>
(
d
.
constData
()
)
->
value
.
at
(
0
);
case
SignedLong
:
return
static_cast
<
const
QExifSignedLongValuePrivate
*
>
(
d
.
constData
()
)
->
value
.
at
(
0
);
}
*/
quint32
QExifValue
::
toLong
()
const
{
if
(
d
->
count
==
1
)
{
switch
(
d
->
type
)
{
case
Byte
:
return
static_cast
<
const
QExifByteValuePrivate
*>
(
d
.
constData
())
->
value
.
at
(
0
);
case
Short
:
return
static_cast
<
const
QExifShortValuePrivate
*>
(
d
.
constData
())
->
value
.
at
(
0
);
case
Long
:
return
static_cast
<
const
QExifLongValuePrivate
*>
(
d
.
constData
())
->
value
.
at
(
0
);
case
SignedLong
:
return
static_cast
<
const
QExifSignedLongValuePrivate
*>
(
d
.
constData
())
->
value
.
at
(
0
);
}
return
0
;
}
return
0
;
}
/*!
Returns the value of a multiple element QExifValue of type Long.
*/
QVector
<
quint32
>
QExifValue
::
toLongVector
()
const
{
return
d
->
type
==
Long
?
static_cast
<
const
QExifLongValuePrivate
*
>
(
d
.
constData
()
)
->
value
:
QVector
<
quint32
>
();
*/
QVector
<
quint32
>
QExifValue
::
toLongVector
()
const
{
return
d
->
type
==
Long
?
static_cast
<
const
QExifLongValuePrivate
*>
(
d
.
constData
())
->
value
:
QVector
<
quint32
>
();
}
/*!
Returns the value of a multiple element QExifValue of type Rational.
*/
QExifURational
QExifValue
::
toRational
()
const
{
return
d
->
type
==
Rational
&&
d
->
count
==
1
?
static_cast
<
const
QExifRationalValuePrivate
*
>
(
d
.
constData
()
)
->
value
.
at
(
0
)
:
QExifURational
();
*/
QExifURational
QExifValue
::
toRational
()
const
{
return
d
->
type
==
Rational
&&
d
->
count
==
1
?
static_cast
<
const
QExifRationalValuePrivate
*>
(
d
.
constData
())
->
value
.
at
(
0
)
:
QExifURational
();
}
/*!
Returns the value of a multiple element QExifValue of type Rational.
*/
QVector
<
QExifURational
>
QExifValue
::
toRationalVector
()
const
{
return
d
->
type
==
Rational
?
static_cast
<
const
QExifRationalValuePrivate
*
>
(
d
.
constData
()
)
->
value
:
QVector
<
QExifURational
>
();
*/
QVector
<
QExifURational
>
QExifValue
::
toRationalVector
()
const
{
return
d
->
type
==
Rational
?
static_cast
<
const
QExifRationalValuePrivate
*>
(
d
.
constData
())
->
value
:
QVector
<
QExifURational
>
();
}
/*!
Returns the value of a QExifValue of type Undefined.
*/
QByteArray
QExifValue
::
toByteArray
()
const
{
switch
(
d
->
type
)
{
*/
QByteArray
QExifValue
::
toByteArray
()
const
{
switch
(
d
->
type
)
{
case
Ascii
:
return
static_cast
<
const
QExifAsciiValuePrivate
*
>
(
d
.
constData
()
)
->
value
.
toUtf8
();
return
static_cast
<
const
QExifAsciiValuePrivate
*>
(
d
.
constData
()
)
->
value
.
toUtf8
();
case
Undefined
:
return
static_cast
<
const
QExifUndefinedValuePrivate
*
>
(
d
.
constData
()
)
->
value
;
return
static_cast
<
const
QExifUndefinedValuePrivate
*>
(
d
.
constData
()
)
->
value
;
default:
return
QByteArray
();
}
return
QByteArray
();
}
}
/*!
Returns the value of a single element QExifValue of type Byte, Short, Long, or SignedLong.
*/
qint32
QExifValue
::
toSignedLong
()
const
{
if
(
d
->
count
==
1
)
{
switch
(
d
->
type
)
{
case
Byte
:
return
static_cast
<
const
QExifByteValuePrivate
*
>
(
d
.
constData
()
)
->
value
.
at
(
0
);
case
Short
:
return
static_cast
<
const
QExifShortValuePrivate
*
>
(
d
.
constData
()
)
->
value
.
at
(
0
);
case
Long
:
return
static_cast
<
const
QExifLongValuePrivate
*
>
(
d
.
constData
()
)
->
value
.
at
(
0
);
case
SignedLong
:
return
static_cast
<
const
QExifSignedLongValuePrivate
*
>
(
d
.
constData
()
)
->
value
.
at
(
0
);
}
*/
qint32
QExifValue
::
toSignedLong
()
const
{
if
(
d
->
count
==
1
)
{
switch
(
d
->
type
)
{
case
Byte
:
return
static_cast
<
const
QExifByteValuePrivate
*>
(
d
.
constData
())
->
value
.
at
(
0
);
case
Short
:
return
static_cast
<
const
QExifShortValuePrivate
*>
(
d
.
constData
())
->
value
.
at
(
0
);
case
Long
:
return
static_cast
<
const
QExifLongValuePrivate
*>
(
d
.
constData
())
->
value
.
at
(
0
);
case
SignedLong
:
return
static_cast
<
const
QExifSignedLongValuePrivate
*>
(
d
.
constData
())
->
value
.
at
(
0
);
}
return
0
;
}
return
0
;
}
/*!
Returns the value of a multiple element QExifValue of type SignedLong.
*/
QVector
<
qint32
>
QExifValue
::
toSignedLongVector
()
const
{
return
d
->
type
==
SignedLong
?
static_cast
<
const
QExifSignedLongValuePrivate
*
>
(
d
.
constData
()
)
->
value
:
QVector
<
qint32
>
();
*/
QVector
<
qint32
>
QExifValue
::
toSignedLongVector
()
const
{
return
d
->
type
==
SignedLong
?
static_cast
<
const
QExifSignedLongValuePrivate
*>
(
d
.
constData
())
->
value
:
QVector
<
qint32
>
();
}
/*!
Returns the value of a single element QExifValue of type SignedRational.
*/
QExifSRational
QExifValue
::
toSignedRational
()
const
{
return
d
->
type
==
SignedRational
&&
d
->
count
==
1
?
static_cast
<
const
QExifSignedRationalValuePrivate
*
>
(
d
.
constData
()
)
->
value
.
at
(
0
)
:
QExifSRational
();
*/
QExifSRational
QExifValue
::
toSignedRational
()
const
{
return
d
->
type
==
SignedRational
&&
d
->
count
==
1
?
static_cast
<
const
QExifSignedRationalValuePrivate
*>
(
d
.
constData
())
->
value
.
at
(
0
)
:
QExifSRational
();
}
/*!
Returns the value of a multiple element QExifValue of type SignedRational.
*/
QVector
<
QExifSRational
>
QExifValue
::
toSignedRationalVector
()
const
{
return
d
->
type
==
SignedRational
?
static_cast
<
const
QExifSignedRationalValuePrivate
*
>
(
d
.
constData
()
)
->
value
:
QVector
<
QExifSRational
>
();
*/
QVector
<
QExifSRational
>
QExifValue
::
toSignedRationalVector
()
const
{
return
d
->
type
==
SignedRational
?
static_cast
<
const
QExifSignedRationalValuePrivate
*>
(
d
.
constData
())
->
value
:
QVector
<
QExifSRational
>
();
}
/*!
Returns the value of QExifValue storing a date-time.
Date-times are stored as ascii strings in the format \c {yyyy:MM:dd HH:mm:ss}.
*/
QDateTime
QExifValue
::
toDateTime
()
const
{
return
d
->
type
==
Ascii
&&
d
->
count
==
20
?
QDateTime
::
fromString
(
static_cast
<
const
QExifAsciiValuePrivate
*
>
(
d
.
constData
()
)
->
value
,
QLatin1String
(
"yyyy:MM:dd HH:mm:ss"
)
)
:
QDateTime
();
*/
QDateTime
QExifValue
::
toDateTime
()
const
{
return
d
->
type
==
Ascii
&&
d
->
count
==
20
?
QDateTime
::
fromString
(
static_cast
<
const
QExifAsciiValuePrivate
*>
(
d
.
constData
())
->
value
,
QLatin1String
(
"yyyy:MM:dd HH:mm:ss"
))
:
QDateTime
();
}
class
QExifImageHeaderPrivate
{
class
QExifImageHeaderPrivate
{
public:
QSysInfo
::
Endian
byteOrder
;
mutable
qint64
size
;
QMap
<
QExifImageHeader
::
ImageTag
,
QExifValue
>
imageIfdValues
;
QMap
<
QExifImageHeader
::
ExifExtendedTag
,
QExifValue
>
exifIfdValues
;
QMap
<
QExifImageHeader
::
GpsTag
,
QExifValue
>
gpsIfdValues
;
QSize
thumbnailSize
;
QByteArray
thumbnailData
;
QExifValue
thumbnailXResolution
;
QExifValue
thumbnailYResolution
;
QExifValue
thumbnailResolutionUnit
;
QExifValue
thumbnailOrientation
;
QSysInfo
::
Endian
byteOrder
;
mutable
qint64
size
;
QMap
<
QExifImageHeader
::
ImageTag
,
QExifValue
>
imageIfdValues
;
QMap
<
QExifImageHeader
::
ExifExtendedTag
,
QExifValue
>
exifIfdValues
;
QMap
<
QExifImageHeader
::
GpsTag
,
QExifValue
>
gpsIfdValues
;
QSize
thumbnailSize
;
QByteArray
thumbnailData
;
QExifValue
thumbnailXResolution
;
QExifValue
thumbnailYResolution
;
QExifValue
thumbnailResolutionUnit
;
QExifValue
thumbnailOrientation
;
};
/*!
...
...
@@ -752,7 +679,7 @@ public:
EXIF header data itself.
\preliminary
*/
*/
/*!
\enum QExifImageHeader::ImageTag
...
...
@@ -785,7 +712,7 @@ public:
\value Software
\value Artist
\value Copyright
*/
*/
/*!
\enum QExifImageHeader::ExifExtendedTag
...
...
@@ -847,7 +774,7 @@ public:
\value Sharpness
\value DeviceSettingDescription
\value SubjectDistanceRange
*/
*/
/*!
\enum QExifImageHeader::GpsTag
...
...
@@ -884,88 +811,82 @@ public:
\value GpsAreaInformation
\value GpsDateStamp
\value GpsDifferential
*/
*/
/*!
Constructs a new EXIF image data editor.
*/
QExifImageHeader
::
QExifImageHeader
()
:
d
(
new
QExifImageHeaderPrivate
)
{
d
->
byteOrder
=
QSysInfo
::
ByteOrder
;
d
->
size
=
-
1
;
*/
QExifImageHeader
::
QExifImageHeader
()
:
d
(
new
QExifImageHeaderPrivate
)
{
d
->
byteOrder
=
QSysInfo
::
ByteOrder
;
d
->
size
=
-
1
;
}
/*!
Constructs a new EXIF image data editor and reads the meta-data from a JPEG image with the given \a fileName.
*/
QExifImageHeader
::
QExifImageHeader
(
const
QString
&
fileName
)
:
d
(
new
QExifImageHeaderPrivate
)
{
d
->
byteOrder
=
QSysInfo
::
ByteOrder
;
d
->
size
=
-
1
;
loadFromJpeg
(
fileName
);
*/
QExifImageHeader
::
QExifImageHeader
(
const
QString
&
fileName
)
:
d
(
new
QExifImageHeaderPrivate
)
{
d
->
byteOrder
=
QSysInfo
::
ByteOrder
;
d
->
size
=
-
1
;
loadFromJpeg
(
fileName
);
}
/*!
Destroys an EXIF image data editor.
*/
QExifImageHeader
::~
QExifImageHeader
()
{
clear
();
*/
QExifImageHeader
::~
QExifImageHeader
()
{
clear
();
delete
d
;
delete
d
;
}
/*!
Reads meta-data from a JPEG image with the given \a fileName.
Returns true if the data was successfully parsed and false otherwise.
*/
bool
QExifImageHeader
::
loadFromJpeg
(
const
QString
&
fileName
)
{
QFile
file
(
fileName
);
if
(
file
.
open
(
QIODevice
::
ReadOnly
))
return
loadFromJpeg
(
&
file
);
else
return
false
;
*/
bool
QExifImageHeader
::
loadFromJpeg
(
const
QString
&
fileName
)
{
QFile
file
(
fileName
);
if
(
file
.
open
(
QIODevice
::
ReadOnly
))
return
loadFromJpeg
(
&
file
);
else
return
false
;
}
/*!
Reads meta-data from an I/O \a device containing a JPEG image.
Returns true if the data was successfully parsed and false otherwise.
*/
bool
QExifImageHeader
::
loadFromJpeg
(
QIODevice
*
device
)
{
clear
();
*/
bool
QExifImageHeader
::
loadFromJpeg
(
QIODevice
*
device
)
{
clear
();
QByteArray
exifData
=
extractExif
(
device
);
QByteArray
exifData
=
extractExif
(
device
);
if
(
!
exifData
.
isEmpty
())
{
QBuffer
buffer
(
&
exifData
);
if
(
!
exifData
.
isEmpty
())
{
QBuffer
buffer
(
&
exifData
);
return
buffer
.
open
(
QIODevice
::
ReadOnly
)
&&
read
(
&
buffer
);
}
return
buffer
.
open
(
QIODevice
::
ReadOnly
)
&&
read
(
&
buffer
);
}
return
false
;
return
false
;
}
/*!
Saves meta-data to a JPEG image with the given \a fileName.
Returns true if the data was successfully written.
*/
bool
QExifImageHeader
::
saveToJpeg
(
const
QString
&
fileName
)
const
{
QFile
file
(
fileName
);
if
(
file
.
open
(
QIODevice
::
ReadWrite
))
return
saveToJpeg
(
&
file
);
else
return
false
;
*/
bool
QExifImageHeader
::
saveToJpeg
(
const
QString
&
fileName
)
const
{
QFile
file
(
fileName
);
if
(
file
.
open
(
QIODevice
::
ReadWrite
))
return
saveToJpeg
(
&
file
);
else
return
false
;
}
/*!
...
...
@@ -974,997 +895,953 @@ bool QExifImageHeader::saveToJpeg(const QString &fileName) const
The device must be non-sequential and already contain a valid JPEG image.
Returns true if the data was successfully written.
*/
bool
QExifImageHeader
::
saveToJpeg
(
QIODevice
*
device
)
const
{
if
(
device
->
isSequential
()
)
return
false
;
*/
bool
QExifImageHeader
::
saveToJpeg
(
QIODevice
*
device
)
const
{
if
(
device
->
isSequential
())
return
false
;
QByteArray
exif
;
QByteArray
exif
;
{
QBuffer
buffer
(
&
exif
);
{
QBuffer
buffer
(
&
exif
);
if
(
!
buffer
.
open
(
QIODevice
::
WriteOnly
)
)
return
false
;
if
(
!
buffer
.
open
(
QIODevice
::
WriteOnly
)
)
return
false
;
write
(
&
buffer
);
write
(
&
buffer
);
buffer
.
close
();
buffer
.
close
();
exif
=
QByteArray
::
fromRawData
(
"Exif
\0\0
"
,
6
)
+
exif
;
}
exif
=
QByteArray
::
fromRawData
(
"Exif
\0\0
"
,
6
)
+
exif
;
}
QDataStream
stream
(
device
);
QDataStream
stream
(
device
);
stream
.
setByteOrder
(
QDataStream
::
BigEndian
);
stream
.
setByteOrder
(
QDataStream
::
BigEndian
);
if
(
device
->
read
(
2
)
!=
"
\xFF\xD8
"
)
// Not a valid JPEG image.
return
false
;
if
(
device
->
read
(
2
)
!=
"
\xFF\xD8
"
)
// Not a valid JPEG image.
return
false
;
quint16
segmentId
;
quint16
segmentLength
;
quint16
segmentId
;
quint16
segmentLength
;
stream
>>
segmentId
;
stream
>>
segmentLength
;
stream
>>
segmentId
;
stream
>>
segmentLength
;
if
(
segmentId
==
0xFFE0
)
{
QByteArray
jfif
=
device
->
read
(
segmentLength
-
2
);
if
(
segmentId
==
0xFFE0
)
{
QByteArray
jfif
=
device
->
read
(
segmentLength
-
2
);
if
(
!
jfif
.
startsWith
(
"JFIF"
)
)
return
false
;
if
(
!
jfif
.
startsWith
(
"JFIF"
)
)
return
false
;
stream
>>
segmentId
;
stream
>>
segmentLength
;
stream
>>
segmentId
;
stream
>>
segmentLength
;
if
(
segmentId
==
0xFFE1
)
{
QByteArray
oldExif
=
device
->
read
(
segmentLength
-
2
);
if
(
segmentId
==
0xFFE1
)
{
QByteArray
oldExif
=
device
->
read
(
segmentLength
-
2
);
if
(
!
oldExif
.
startsWith
(
"Exif"
)
)
return
false
;
if
(
!
oldExif
.
startsWith
(
"Exif"
)
)
return
false
;
int
dSize
=
oldExif
.
size
()
-
exif
.
size
();
int
dSize
=
oldExif
.
size
()
-
exif
.
size
();
if
(
dSize
>
0
)
exif
+=
QByteArray
(
dSize
,
'\0'
);
if
(
dSize
>
0
)
exif
+=
QByteArray
(
dSize
,
'\0'
);
QByteArray
remainder
=
device
->
readAll
();
QByteArray
remainder
=
device
->
readAll
();
device
->
seek
(
0
);
device
->
seek
(
0
);
stream
<<
quint16
(
0xFFD8
);
// SOI
stream
<<
quint16
(
0xFFE0
);
// APP0
stream
<<
quint16
(
jfif
.
size
()
+
2
);
device
->
write
(
jfif
);
stream
<<
quint16
(
0xFFE1
);
//APP1
stream
<<
quint16
(
exif
.
size
()
+
2
);
device
->
write
(
exif
);
device
->
write
(
remainder
);
}
else
{
QByteArray
remainder
=
device
->
readAll
();
device
->
seek
(
0
);
stream
<<
quint16
(
0xFFD8
);
// SOI
stream
<<
quint16
(
0xFFE0
);
// APP0
stream
<<
quint16
(
jfif
.
size
()
+
2
);
device
->
write
(
jfif
);
stream
<<
quint16
(
0xFFE1
);
//APP1
stream
<<
quint16
(
exif
.
size
()
+
2
);
device
->
write
(
exif
);
stream
<<
quint16
(
0xFFE0
);
// APP0
stream
<<
segmentId
;
stream
<<
segmentLength
;
device
->
write
(
remainder
);
}
stream
<<
quint16
(
0xFFD8
);
// SOI
stream
<<
quint16
(
0xFFE0
);
// APP0
stream
<<
quint16
(
jfif
.
size
()
+
2
);
device
->
write
(
jfif
);
stream
<<
quint16
(
0xFFE1
);
// APP1
stream
<<
quint16
(
exif
.
size
()
+
2
);
device
->
write
(
exif
);
device
->
write
(
remainder
);
}
else
{
QByteArray
remainder
=
device
->
readAll
();
device
->
seek
(
0
);
stream
<<
quint16
(
0xFFD8
);
// SOI
stream
<<
quint16
(
0xFFE0
);
// APP0
stream
<<
quint16
(
jfif
.
size
()
+
2
);
device
->
write
(
jfif
);
stream
<<
quint16
(
0xFFE1
);
// APP1
stream
<<
quint16
(
exif
.
size
()
+
2
);
device
->
write
(
exif
);
stream
<<
quint16
(
0xFFE0
);
// APP0
stream
<<
segmentId
;
stream
<<
segmentLength
;
device
->
write
(
remainder
);
}
else
if
(
segmentId
==
0xFFE1
)
{
QByteArray
oldExif
=
device
->
read
(
segmentLength
-
2
);
}
else
if
(
segmentId
==
0xFFE1
)
{
QByteArray
oldExif
=
device
->
read
(
segmentLength
-
2
);
if
(
!
oldExif
.
startsWith
(
"Exif"
)
)
return
false
;
if
(
!
oldExif
.
startsWith
(
"Exif"
)
)
return
false
;
int
dSize
=
oldExif
.
size
()
-
exif
.
size
();
int
dSize
=
oldExif
.
size
()
-
exif
.
size
();
if
(
dSize
>
0
)
exif
+=
QByteArray
(
dSize
,
'\0'
);
if
(
dSize
>
0
)
exif
+=
QByteArray
(
dSize
,
'\0'
);
QByteArray
remainder
=
device
->
readAll
();
QByteArray
remainder
=
device
->
readAll
();
device
->
seek
(
0
);
device
->
seek
(
0
);
stream
<<
quint16
(
0xFFD8
);
// SOI
stream
<<
quint16
(
0xFFE1
);
//APP1
stream
<<
quint16
(
exif
.
size
()
+
2
);
device
->
write
(
exif
);
device
->
write
(
remainder
);
}
else
{
QByteArray
remainder
=
device
->
readAll
();
device
->
seek
(
0
);
stream
<<
quint16
(
0xFFD8
);
// SOI
stream
<<
quint16
(
0xFFE1
);
//APP1
stream
<<
quint16
(
exif
.
size
()
+
2
);
device
->
write
(
exif
);
stream
<<
segmentId
;
stream
<<
segmentLength
;
device
->
write
(
remainder
);
}
stream
<<
quint16
(
0xFFD8
);
// SOI
stream
<<
quint16
(
0xFFE1
);
// APP1
stream
<<
quint16
(
exif
.
size
()
+
2
);
device
->
write
(
exif
);
device
->
write
(
remainder
);
}
else
{
QByteArray
remainder
=
device
->
readAll
();
device
->
seek
(
0
);
return
true
;
stream
<<
quint16
(
0xFFD8
);
// SOI
stream
<<
quint16
(
0xFFE1
);
// APP1
stream
<<
quint16
(
exif
.
size
()
+
2
);
device
->
write
(
exif
);
stream
<<
segmentId
;
stream
<<
segmentLength
;
device
->
write
(
remainder
);
}
return
true
;
}
/*!
Returns the byte order of EXIF file.
*/
QSysInfo
::
Endian
QExifImageHeader
::
byteOrder
()
const
{
return
d
->
byteOrder
;
*/
QSysInfo
::
Endian
QExifImageHeader
::
byteOrder
()
const
{
return
d
->
byteOrder
;
}
quint32
QExifImageHeader
::
sizeOf
(
const
QExifValue
&
value
)
const
{
switch
(
value
.
type
())
{
quint32
QExifImageHeader
::
sizeOf
(
const
QExifValue
&
value
)
const
{
switch
(
value
.
type
())
{
case
QExifValue
:
:
Byte
:
case
QExifValue
:
:
Undefined
:
return
value
.
count
()
>
4
?
12
+
value
.
count
()
:
12
;
return
value
.
count
()
>
4
?
12
+
value
.
count
()
:
12
;
case
QExifValue
:
:
Ascii
:
return
value
.
count
()
>
4
?
12
+
value
.
count
()
:
12
;
return
value
.
count
()
>
4
?
12
+
value
.
count
()
:
12
;
case
QExifValue
:
:
Short
:
return
value
.
count
()
>
2
?
12
+
value
.
count
()
*
sizeof
(
quint16
)
:
12
;
return
value
.
count
()
>
2
?
12
+
value
.
count
()
*
sizeof
(
quint16
)
:
12
;
case
QExifValue
:
:
Long
:
case
QExifValue
:
:
SignedLong
:
return
value
.
count
()
>
1
?
12
+
value
.
count
()
*
sizeof
(
quint32
)
:
12
;
return
value
.
count
()
>
1
?
12
+
value
.
count
()
*
sizeof
(
quint32
)
:
12
;
case
QExifValue
:
:
Rational
:
case
QExifValue
:
:
SignedRational
:
return
value
.
count
()
>
0
?
12
+
value
.
count
()
*
sizeof
(
quint32
)
*
2
:
12
;
return
value
.
count
()
>
0
?
12
+
value
.
count
()
*
sizeof
(
quint32
)
*
2
:
12
;
default:
return
0
;
}
return
0
;
}
}
template
<
typename
T
>
quint32
QExifImageHeader
::
calculateSize
(
const
QMap
<
T
,
QExifValue
>
&
values
)
const
{
quint32
size
=
sizeof
(
quint16
);
template
<
typename
T
>
quint32
QExifImageHeader
::
calculateSize
(
const
QMap
<
T
,
QExifValue
>
&
values
)
const
{
quint32
size
=
sizeof
(
quint16
);
foreach
(
const
QExifValue
&
value
,
values
)
size
+=
sizeOf
(
value
);
foreach
(
const
QExifValue
&
value
,
values
)
size
+=
sizeOf
(
value
);
return
size
;
return
size
;
}
/*!
Returns the size of EXIF data in bytes.
*/
qint64
QExifImageHeader
::
size
()
const
{
if
(
d
->
size
==
-
1
)
{
d
->
size
=
2
// Byte Order
+
2
// Marker
+
4
// Image Ifd offset
+
12
// ExifIfdPointer Ifd
+
4
// Thumbnail Ifd offset
+
calculateSize
(
d
->
imageIfdValues
)
// Image headers and values.
+
calculateSize
(
d
->
exifIfdValues
);
// Exif headers and values.
if
(
!
d
->
gpsIfdValues
.
isEmpty
())
{
d
->
size
+=
12
// GpsInfoIfdPointer Ifd
+
calculateSize
(
d
->
gpsIfdValues
);
// Gps headers and values.
}
*/
qint64
QExifImageHeader
::
size
()
const
{
if
(
d
->
size
==
-
1
)
{
d
->
size
=
2
+
// Byte Order
2
+
// Marker
4
+
// Image Ifd offset
12
+
// ExifIfdPointer Ifd
4
+
// Thumbnail Ifd offset
calculateSize
(
d
->
imageIfdValues
)
+
// Image headers and values.
calculateSize
(
d
->
exifIfdValues
);
// Exif headers and values.
if
(
!
d
->
thumbnailData
.
isEmpty
())
{
d
->
size
+=
2
// Thumbnail Ifd count
+
12
// Compression Ifd
+
20
// XResolution Ifd
+
20
// YResolution Ifd
+
12
// ResolutionUnit Ifd
+
12
// JpegInterchangeFormat Ifd
+
12
// JpegInterchangeFormatLength Ifd
+
d
->
thumbnailData
.
size
();
// Thumbnail data size.
}
if
(
!
d
->
gpsIfdValues
.
isEmpty
())
{
d
->
size
+=
12
+
// GpsInfoIfdPointer Ifd
calculateSize
(
d
->
gpsIfdValues
);
// Gps headers and values.
}
return
d
->
size
;
if
(
!
d
->
thumbnailData
.
isEmpty
())
{
d
->
size
+=
2
+
// Thumbnail Ifd count
12
+
// Compression Ifd
20
+
// XResolution Ifd
20
+
// YResolution Ifd
12
+
// ResolutionUnit Ifd
12
+
// JpegInterchangeFormat Ifd
12
+
// JpegInterchangeFormatLength Ifd
d
->
thumbnailData
.
size
();
// Thumbnail data size.
}
}
return
d
->
size
;
}
/*!
Clears all image meta-data.
*/
void
QExifImageHeader
::
clear
()
{
d
->
imageIfdValues
.
clear
();
d
->
exifIfdValues
.
clear
();
d
->
gpsIfdValues
.
clear
();
d
->
thumbnailData
.
clear
();
d
->
size
=
-
1
;
*/
void
QExifImageHeader
::
clear
()
{
d
->
imageIfdValues
.
clear
();
d
->
exifIfdValues
.
clear
();
d
->
gpsIfdValues
.
clear
();
d
->
thumbnailData
.
clear
();
d
->
size
=
-
1
;
}
/*!
Returns a list of all image tags in an EXIF header.
*/
QList
<
QExifImageHeader
::
ImageTag
>
QExifImageHeader
::
imageTags
()
const
{
return
d
->
imageIfdValues
.
keys
();
*/
QList
<
QExifImageHeader
::
ImageTag
>
QExifImageHeader
::
imageTags
()
const
{
return
d
->
imageIfdValues
.
keys
();
}
/*!
Returns a list of all extended EXIF tags in a header.
*/
QList
<
QExifImageHeader
::
ExifExtendedTag
>
QExifImageHeader
::
extendedTags
()
const
{
return
d
->
exifIfdValues
.
keys
();
*/
QList
<
QExifImageHeader
::
ExifExtendedTag
>
QExifImageHeader
::
extendedTags
()
const
{
return
d
->
exifIfdValues
.
keys
();
}
/*!
Returns a list of all GPS tags in an EXIF header.
*/
QList
<
QExifImageHeader
::
GpsTag
>
QExifImageHeader
::
gpsTags
()
const
{
return
d
->
gpsIfdValues
.
keys
();
*/
QList
<
QExifImageHeader
::
GpsTag
>
QExifImageHeader
::
gpsTags
()
const
{
return
d
->
gpsIfdValues
.
keys
();
}
/*!
Returns true if an EXIf header contains a value for an image \a tag and false otherwise.
*/
bool
QExifImageHeader
::
contains
(
ImageTag
tag
)
const
{
return
d
->
imageIfdValues
.
contains
(
tag
);
*/
bool
QExifImageHeader
::
contains
(
ImageTag
tag
)
const
{
return
d
->
imageIfdValues
.
contains
(
tag
);
}
/*!
Returns true if a header contains a a value for an extended EXIF \a tag and false otherwise.
*/
bool
QExifImageHeader
::
contains
(
ExifExtendedTag
tag
)
const
{
return
d
->
exifIfdValues
.
contains
(
tag
);
*/
bool
QExifImageHeader
::
contains
(
ExifExtendedTag
tag
)
const
{
return
d
->
exifIfdValues
.
contains
(
tag
);
}
/*!
Returns true if an EXIf header contains a value for a GPS \a tag and false otherwise.
*/
bool
QExifImageHeader
::
contains
(
GpsTag
tag
)
const
{
return
d
->
gpsIfdValues
.
contains
(
tag
);
*/
bool
QExifImageHeader
::
contains
(
GpsTag
tag
)
const
{
return
d
->
gpsIfdValues
.
contains
(
tag
);
}
/*!
Removes the value for an image \a tag.
*/
void
QExifImageHeader
::
remove
(
ImageTag
tag
)
{
d
->
imageIfdValues
.
remove
(
tag
);
*/
void
QExifImageHeader
::
remove
(
ImageTag
tag
)
{
d
->
imageIfdValues
.
remove
(
tag
);
d
->
size
=
-
1
;
d
->
size
=
-
1
;
}
/*!
Removes the value for an extended EXIF \a tag.
*/
void
QExifImageHeader
::
remove
(
ExifExtendedTag
tag
)
{
d
->
exifIfdValues
.
remove
(
tag
);
*/
void
QExifImageHeader
::
remove
(
ExifExtendedTag
tag
)
{
d
->
exifIfdValues
.
remove
(
tag
);
d
->
size
=
-
1
;
d
->
size
=
-
1
;
}
/*!
Removes the value for a GPS \a tag.
*/
void
QExifImageHeader
::
remove
(
GpsTag
tag
)
{
d
->
gpsIfdValues
.
remove
(
tag
);
*/
void
QExifImageHeader
::
remove
(
GpsTag
tag
)
{
d
->
gpsIfdValues
.
remove
(
tag
);
d
->
size
=
-
1
;
d
->
size
=
-
1
;
}
/*!
Returns the value for an image \a tag.
*/
QExifValue
QExifImageHeader
::
value
(
ImageTag
tag
)
const
{
return
d
->
imageIfdValues
.
value
(
tag
);
*/
QExifValue
QExifImageHeader
::
value
(
ImageTag
tag
)
const
{
return
d
->
imageIfdValues
.
value
(
tag
);
}
/*!
Returns the value for an extended EXIF \a tag.
*/
QExifValue
QExifImageHeader
::
value
(
ExifExtendedTag
tag
)
const
{
return
d
->
exifIfdValues
.
value
(
tag
);
*/
QExifValue
QExifImageHeader
::
value
(
ExifExtendedTag
tag
)
const
{
return
d
->
exifIfdValues
.
value
(
tag
);
}
/*!
Returns the value for a GPS tag.
*/
QExifValue
QExifImageHeader
::
value
(
GpsTag
tag
)
const
{
return
d
->
gpsIfdValues
.
value
(
tag
);
*/
QExifValue
QExifImageHeader
::
value
(
GpsTag
tag
)
const
{
return
d
->
gpsIfdValues
.
value
(
tag
);
}
/*!
Sets the \a value for an image \a tag.
*/
void
QExifImageHeader
::
setValue
(
ImageTag
tag
,
const
QExifValue
&
value
)
{
d
->
imageIfdValues
[
tag
]
=
value
;
*/
void
QExifImageHeader
::
setValue
(
ImageTag
tag
,
const
QExifValue
&
value
)
{
d
->
imageIfdValues
[
tag
]
=
value
;
d
->
size
=
-
1
;
d
->
size
=
-
1
;
}
/*!
Sets the \a value for an extended EXIF \a tag.
*/
void
QExifImageHeader
::
setValue
(
ExifExtendedTag
tag
,
const
QExifValue
&
value
)
{
d
->
exifIfdValues
[
tag
]
=
value
;
*/
void
QExifImageHeader
::
setValue
(
ExifExtendedTag
tag
,
const
QExifValue
&
value
)
{
d
->
exifIfdValues
[
tag
]
=
value
;
d
->
size
=
-
1
;
d
->
size
=
-
1
;
}
/*!
Sets the \a value for an GPS \a tag.
*/
void
QExifImageHeader
::
setValue
(
GpsTag
tag
,
const
QExifValue
&
value
)
{
d
->
gpsIfdValues
[
tag
]
=
value
;
*/
void
QExifImageHeader
::
setValue
(
GpsTag
tag
,
const
QExifValue
&
value
)
{
d
->
gpsIfdValues
[
tag
]
=
value
;
d
->
size
=
-
1
;
d
->
size
=
-
1
;
}
/*!
Returns the image thumbnail.
*/
QImage
QExifImageHeader
::
thumbnail
()
const
{
QImage
image
;
image
.
loadFromData
(
d
->
thumbnailData
,
"JPG"
);
if
(
!
d
->
thumbnailOrientation
.
isNull
())
{
switch
(
d
->
thumbnailOrientation
.
toShort
())
{
case
1
:
return
image
;
case
2
:
return
image
.
transformed
(
QTransform
().
rotate
(
180
,
Qt
::
YAxis
));
case
3
:
return
image
.
transformed
(
QTransform
().
rotate
(
180
,
Qt
::
ZAxis
));
case
4
:
return
image
.
transformed
(
QTransform
().
rotate
(
180
,
Qt
::
XAxis
));
case
5
:
return
image
.
transformed
(
QTransform
().
rotate
(
180
,
Qt
::
YAxis
).
rotate
(
90
,
Qt
::
ZAxis
));
case
6
:
return
image
.
transformed
(
QTransform
().
rotate
(
90
,
Qt
::
ZAxis
));
case
7
:
return
image
.
transformed
(
QTransform
().
rotate
(
180
,
Qt
::
XAxis
).
rotate
(
90
,
Qt
::
ZAxis
));
case
8
:
return
image
.
transformed
(
QTransform
().
rotate
(
270
,
Qt
::
ZAxis
));
}
*/
QImage
QExifImageHeader
::
thumbnail
()
const
{
QImage
image
;
image
.
loadFromData
(
d
->
thumbnailData
,
"JPG"
);
if
(
!
d
->
thumbnailOrientation
.
isNull
())
{
switch
(
d
->
thumbnailOrientation
.
toShort
())
{
case
1
:
return
image
;
case
2
:
return
image
.
transformed
(
QTransform
().
rotate
(
180
,
Qt
::
YAxis
));
case
3
:
return
image
.
transformed
(
QTransform
().
rotate
(
180
,
Qt
::
ZAxis
));
case
4
:
return
image
.
transformed
(
QTransform
().
rotate
(
180
,
Qt
::
XAxis
));
case
5
:
return
image
.
transformed
(
QTransform
().
rotate
(
180
,
Qt
::
YAxis
).
rotate
(
90
,
Qt
::
ZAxis
));
case
6
:
return
image
.
transformed
(
QTransform
().
rotate
(
90
,
Qt
::
ZAxis
));
case
7
:
return
image
.
transformed
(
QTransform
().
rotate
(
180
,
Qt
::
XAxis
).
rotate
(
90
,
Qt
::
ZAxis
));
case
8
:
return
image
.
transformed
(
QTransform
().
rotate
(
270
,
Qt
::
ZAxis
));
}
}
return
image
;
return
image
;
}
/*!
Sets the image \a thumbnail.
*/
void
QExifImageHeader
::
setThumbnail
(
const
QImage
&
thumbnail
)
{
if
(
!
thumbnail
.
isNull
())
{
QBuffer
buffer
;
if
(
buffer
.
open
(
QIODevice
::
WriteOnly
)
&&
thumbnail
.
save
(
&
buffer
,
"JPG"
))
{
buffer
.
close
();
d
->
thumbnailSize
=
thumbnail
.
size
();
d
->
thumbnailData
=
buffer
.
data
();
d
->
thumbnailOrientation
=
QExifValue
();
}
}
else
{
d
->
thumbnailSize
=
QSize
();
d
->
thumbnailData
=
QByteArray
();
*/
void
QExifImageHeader
::
setThumbnail
(
const
QImage
&
thumbnail
)
{
if
(
!
thumbnail
.
isNull
())
{
QBuffer
buffer
;
if
(
buffer
.
open
(
QIODevice
::
WriteOnly
)
&&
thumbnail
.
save
(
&
buffer
,
"JPG"
))
{
buffer
.
close
();
d
->
thumbnailSize
=
thumbnail
.
size
();
d
->
thumbnailData
=
buffer
.
data
();
d
->
thumbnailOrientation
=
QExifValue
();
}
}
else
{
d
->
thumbnailSize
=
QSize
();
d
->
thumbnailData
=
QByteArray
();
}
d
->
size
=
-
1
;
d
->
size
=
-
1
;
}
QByteArray
QExifImageHeader
::
extractExif
(
QIODevice
*
device
)
const
{
QDataStream
stream
(
device
);
QByteArray
QExifImageHeader
::
extractExif
(
QIODevice
*
device
)
const
{
QDataStream
stream
(
device
);
stream
.
setByteOrder
(
QDataStream
::
BigEndian
);
stream
.
setByteOrder
(
QDataStream
::
BigEndian
);
if
(
device
->
read
(
2
)
!=
"
\xFF\xD8
"
)
return
QByteArray
();
if
(
device
->
read
(
2
)
!=
"
\xFF\xD8
"
)
return
QByteArray
();
while
(
device
->
read
(
2
)
!=
"
\xFF\xE1
"
)
{
if
(
device
->
atEnd
()
)
return
QByteArray
();
while
(
device
->
read
(
2
)
!=
"
\xFF\xE1
"
)
{
if
(
device
->
atEnd
())
return
QByteArray
();
quint16
length
;
quint16
length
;
stream
>>
length
;
stream
>>
length
;
device
->
seek
(
device
->
pos
()
+
length
-
2
);
}
device
->
seek
(
device
->
pos
()
+
length
-
2
);
}
quint16
length
;
quint16
length
;
stream
>>
length
;
stream
>>
length
;
if
(
device
->
read
(
4
)
!=
"Exif"
)
return
QByteArray
();
if
(
device
->
read
(
4
)
!=
"Exif"
)
return
QByteArray
();
device
->
read
(
2
);
device
->
read
(
2
);
return
device
->
read
(
length
-
8
);
return
device
->
read
(
length
-
8
);
}
QList
<
ExifIfdHeader
>
QExifImageHeader
::
readIfdHeaders
(
QDataStream
&
stream
)
const
{
QList
<
ExifIfdHeader
>
headers
;
QList
<
ExifIfdHeader
>
QExifImageHeader
::
readIfdHeaders
(
QDataStream
&
stream
)
const
{
QList
<
ExifIfdHeader
>
headers
;
quint16
count
;
quint16
count
;
stream
>>
count
;
stream
>>
count
;
for
(
quint16
i
=
0
;
i
<
count
;
i
++
)
{
ExifIfdHeader
header
;
for
(
quint16
i
=
0
;
i
<
count
;
i
++
)
{
ExifIfdHeader
header
;
stream
>>
header
;
stream
>>
header
;
headers
.
append
(
header
);
}
headers
.
append
(
header
);
}
return
headers
;
return
headers
;
}
QExifValue
QExifImageHeader
::
readIfdValue
(
QDataStream
&
stream
,
int
startPos
,
const
ExifIfdHeader
&
header
)
const
{
switch
(
header
.
type
)
{
case
QExifValue
:
:
Byte
:
{
QVector
<
quint8
>
value
(
header
.
count
);
if
(
header
.
count
>
4
)
{
stream
.
device
()
->
seek
(
startPos
+
header
.
offset
);
QExifValue
QExifImageHeader
::
readIfdValue
(
QDataStream
&
stream
,
int
startPos
,
const
ExifIfdHeader
&
header
)
const
{
switch
(
header
.
type
)
{
case
QExifValue
:
:
Byte
:
{
QVector
<
quint8
>
value
(
header
.
count
);
for
(
quint32
i
=
0
;
i
<
header
.
count
;
i
++
)
stream
>>
value
[
i
];
}
else
{
for
(
quint32
i
=
0
;
i
<
header
.
count
;
i
++
)
value
[
i
]
=
header
.
offsetBytes
[
i
];
if
(
header
.
count
>
4
)
{
stream
.
device
()
->
seek
(
startPos
+
header
.
offset
);
}
return
QExifValue
(
value
);
}
for
(
quint32
i
=
0
;
i
<
header
.
count
;
i
++
)
stream
>>
value
[
i
];
}
else
{
for
(
quint32
i
=
0
;
i
<
header
.
count
;
i
++
)
value
[
i
]
=
header
.
offsetBytes
[
i
];
}
return
QExifValue
(
value
);
}
case
QExifValue
:
:
Undefined
:
if
(
header
.
count
>
4
)
{
stream
.
device
()
->
seek
(
startPos
+
header
.
offset
);
if
(
header
.
count
>
4
)
{
stream
.
device
()
->
seek
(
startPos
+
header
.
offset
);
return
QExifValue
(
stream
.
device
()
->
read
(
header
.
count
));
}
else
{
return
QExifValue
(
QByteArray
::
fromRawData
(
header
.
offsetAscii
,
header
.
count
));
}
return
QExifValue
(
stream
.
device
()
->
read
(
header
.
count
));
}
else
{
return
QExifValue
(
QByteArray
::
fromRawData
(
header
.
offsetAscii
,
header
.
count
));
}
case
QExifValue
:
:
Ascii
:
if
(
header
.
count
>
4
)
{
stream
.
device
()
->
seek
(
startPos
+
header
.
offset
);
QByteArray
ascii
=
stream
.
device
()
->
read
(
header
.
count
);
return
QExifValue
(
QString
::
fromUtf8
(
ascii
.
constData
(),
ascii
.
size
()
-
1
));
}
else
{
return
QExifValue
(
QString
::
fromUtf8
(
header
.
offsetAscii
,
header
.
count
-
1
));
}
case
QExifValue
:
:
Short
:
{
QVector
<
quint16
>
value
(
header
.
count
);
if
(
header
.
count
>
2
)
{
stream
.
device
()
->
seek
(
startPos
+
header
.
offset
);
for
(
quint32
i
=
0
;
i
<
header
.
count
;
i
++
)
stream
>>
value
[
i
];
}
else
{
for
(
quint32
i
=
0
;
i
<
header
.
count
;
i
++
)
value
[
i
]
=
header
.
offsetShorts
[
i
];
}
return
QExifValue
(
value
);
}
case
QExifValue
:
:
Long
:
{
QVector
<
quint32
>
value
(
header
.
count
);
if
(
header
.
count
>
1
)
{
stream
.
device
()
->
seek
(
startPos
+
header
.
offset
);
for
(
quint32
i
=
0
;
i
<
header
.
count
;
i
++
)
stream
>>
value
[
i
];
}
else
if
(
header
.
count
==
1
)
{
value
[
0
]
=
header
.
offset
;
}
return
QExifValue
(
value
);
}
case
QExifValue
:
:
SignedLong
:
{
QVector
<
qint32
>
value
(
header
.
count
);
if
(
header
.
count
>
1
)
{
stream
.
device
()
->
seek
(
startPos
+
header
.
offset
);
for
(
quint32
i
=
0
;
i
<
header
.
count
;
i
++
)
stream
>>
value
[
i
];
}
else
if
(
header
.
count
==
1
)
{
value
[
0
]
=
header
.
offset
;
}
return
QExifValue
(
value
);
}
break
;
case
QExifValue
:
:
Rational
:
{
QVector
<
QExifURational
>
value
(
header
.
count
);
if
(
header
.
count
>
4
)
{
stream
.
device
()
->
seek
(
startPos
+
header
.
offset
);
QByteArray
ascii
=
stream
.
device
()
->
read
(
header
.
count
);
return
QExifValue
(
QString
::
fromUtf8
(
ascii
.
constData
(),
ascii
.
size
()
-
1
));
}
else
{
return
QExifValue
(
QString
::
fromUtf8
(
header
.
offsetAscii
,
header
.
count
-
1
));
}
case
QExifValue
:
:
Short
:
{
QVector
<
quint16
>
value
(
header
.
count
);
if
(
header
.
count
>
2
)
{
stream
.
device
()
->
seek
(
startPos
+
header
.
offset
);
for
(
quint32
i
=
0
;
i
<
header
.
count
;
i
++
)
stream
>>
value
[
i
];
}
else
{
for
(
quint32
i
=
0
;
i
<
header
.
count
;
i
++
)
value
[
i
]
=
header
.
offsetShorts
[
i
];
}
return
QExifValue
(
value
);
}
case
QExifValue
:
:
Long
:
{
QVector
<
quint32
>
value
(
header
.
count
);
if
(
header
.
count
>
1
)
{
stream
.
device
()
->
seek
(
startPos
+
header
.
offset
);
for
(
quint32
i
=
0
;
i
<
header
.
count
;
i
++
)
stream
>>
value
[
i
];
}
else
if
(
header
.
count
==
1
)
{
value
[
0
]
=
header
.
offset
;
}
return
QExifValue
(
value
);
}
case
QExifValue
:
:
SignedLong
:
{
QVector
<
qint32
>
value
(
header
.
count
);
if
(
header
.
count
>
1
)
{
stream
.
device
()
->
seek
(
startPos
+
header
.
offset
);
for
(
quint32
i
=
0
;
i
<
header
.
count
;
i
++
)
stream
>>
value
[
i
];
}
else
if
(
header
.
count
==
1
)
{
value
[
0
]
=
header
.
offset
;
}
return
QExifValue
(
value
);
}
break
;
case
QExifValue
:
:
Rational
:
{
QVector
<
QExifURational
>
value
(
header
.
count
);
stream
.
device
()
->
seek
(
startPos
+
header
.
offset
);
stream
.
device
()
->
seek
(
startPos
+
header
.
offset
);
for
(
quint32
i
=
0
;
i
<
header
.
count
;
i
++
)
stream
>>
value
[
i
];
for
(
quint32
i
=
0
;
i
<
header
.
count
;
i
++
)
stream
>>
value
[
i
];
return
QExifValue
(
value
);
}
case
QExifValue
:
:
SignedRational
:
{
QVector
<
QExifSRational
>
value
(
header
.
count
);
return
QExifValue
(
value
);
}
case
QExifValue
:
:
SignedRational
:
{
QVector
<
QExifSRational
>
value
(
header
.
count
);
stream
.
device
()
->
seek
(
startPos
+
header
.
offset
);
stream
.
device
()
->
seek
(
startPos
+
header
.
offset
);
for
(
quint32
i
=
0
;
i
<
header
.
count
;
i
++
)
stream
>>
value
[
i
];
for
(
quint32
i
=
0
;
i
<
header
.
count
;
i
++
)
stream
>>
value
[
i
];
return
QExifValue
(
value
);
}
return
QExifValue
(
value
);
}
default:
qWarning
()
<<
"Invalid Ifd Type"
<<
header
.
type
;
qWarning
()
<<
"Invalid Ifd Type"
<<
header
.
type
;
return
QExifValue
();
}
return
QExifValue
();
}
}
template
<
typename
T
>
QMap
<
T
,
QExifValue
>
QExifImageHeader
::
readIfdValues
(
QDataStream
&
stream
,
int
startPos
,
const
QList
<
ExifIfdHeader
>
&
headers
)
const
{
QMap
<
T
,
QExifValue
>
values
;
template
<
typename
T
>
QMap
<
T
,
QExifValue
>
QExifImageHeader
::
readIfdValues
(
QDataStream
&
stream
,
int
startPos
,
const
QList
<
ExifIfdHeader
>
&
headers
)
const
{
QMap
<
T
,
QExifValue
>
values
;
// This needs to be non-const so it works with gcc3
QList
<
ExifIfdHeader
>
headers_
=
headers
;
foreach
(
const
ExifIfdHeader
&
header
,
headers_
)
values
[
T
(
header
.
tag
)]
=
readIfdValue
(
stream
,
startPos
,
header
);
// This needs to be non-const so it works with gcc3
QList
<
ExifIfdHeader
>
headers_
=
headers
;
foreach
(
const
ExifIfdHeader
&
header
,
headers_
)
values
[
T
(
header
.
tag
)]
=
readIfdValue
(
stream
,
startPos
,
header
);
return
values
;
return
values
;
}
template
<
typename
T
>
QMap
<
T
,
QExifValue
>
QExifImageHeader
::
readIfdValues
(
QDataStream
&
stream
,
int
startPos
,
const
QExifValue
&
pointer
)
const
{
if
(
pointer
.
type
()
==
QExifValue
::
Long
&&
pointer
.
count
()
==
1
)
{
stream
.
device
()
->
seek
(
startPos
+
pointer
.
toLong
());
template
<
typename
T
>
QMap
<
T
,
QExifValue
>
QExifImageHeader
::
readIfdValues
(
QDataStream
&
stream
,
int
startPos
,
const
QExifValue
&
pointer
)
const
{
if
(
pointer
.
type
()
==
QExifValue
::
Long
&&
pointer
.
count
()
==
1
)
{
stream
.
device
()
->
seek
(
startPos
+
pointer
.
toLong
());
QList
<
ExifIfdHeader
>
headers
=
readIfdHeaders
(
stream
);
QList
<
ExifIfdHeader
>
headers
=
readIfdHeaders
(
stream
);
return
readIfdValues
<
T
>
(
stream
,
startPos
,
headers
);
}
else
{
return
QMap
<
T
,
QExifValue
>
();
}
return
readIfdValues
<
T
>
(
stream
,
startPos
,
headers
);
}
else
{
return
QMap
<
T
,
QExifValue
>
();
}
}
/*!
Reads the contents of an EXIF header from an I/O \a device.
Returns true if the header was read and false otherwise.
\sa loadFromJpeg(), write()
*/
bool
QExifImageHeader
::
read
(
QIODevice
*
device
)
{
clear
();
*/
bool
QExifImageHeader
::
read
(
QIODevice
*
device
)
{
clear
();
int
startPos
=
device
->
pos
();
int
startPos
=
device
->
pos
();
QDataStream
stream
(
device
);
QDataStream
stream
(
device
);
QByteArray
byteOrder
=
device
->
read
(
2
);
QByteArray
byteOrder
=
device
->
read
(
2
);
if
(
byteOrder
==
"II"
)
{
d
->
byteOrder
=
QSysInfo
::
LittleEndian
;
if
(
byteOrder
==
"II"
)
{
d
->
byteOrder
=
QSysInfo
::
LittleEndian
;
stream
.
setByteOrder
(
QDataStream
::
LittleEndian
);
}
else
if
(
byteOrder
==
"MM"
)
{
d
->
byteOrder
=
QSysInfo
::
BigEndian
;
stream
.
setByteOrder
(
QDataStream
::
LittleEndian
);
}
else
if
(
byteOrder
==
"MM"
)
{
d
->
byteOrder
=
QSysInfo
::
BigEndian
;
stream
.
setByteOrder
(
QDataStream
::
BigEndian
);
}
else
{
return
false
;
}
stream
.
setByteOrder
(
QDataStream
::
BigEndian
);
}
else
{
return
false
;
}
quint16
id
;
quint32
offset
;
quint16
id
;
quint32
offset
;
stream
>>
id
;
stream
>>
offset
;
stream
>>
id
;
stream
>>
offset
;
if
(
id
!=
0x002A
)
return
false
;
if
(
id
!=
0x002A
)
return
false
;
device
->
seek
(
startPos
+
offset
);
device
->
seek
(
startPos
+
offset
);
QList
<
ExifIfdHeader
>
headers
=
readIfdHeaders
(
stream
);
QList
<
ExifIfdHeader
>
headers
=
readIfdHeaders
(
stream
);
stream
>>
offset
;
stream
>>
offset
;
d
->
imageIfdValues
=
readIfdValues
<
ImageTag
>
(
stream
,
startPos
,
headers
);
d
->
imageIfdValues
=
readIfdValues
<
ImageTag
>
(
stream
,
startPos
,
headers
);
QExifValue
exifIfdPointer
=
d
->
imageIfdValues
.
take
(
ImageTag
(
ExifIfdPointer
));
QExifValue
gpsIfdPointer
=
d
->
imageIfdValues
.
take
(
ImageTag
(
GpsInfoIfdPointer
));
QExifValue
exifIfdPointer
=
d
->
imageIfdValues
.
take
(
ImageTag
(
ExifIfdPointer
));
QExifValue
gpsIfdPointer
=
d
->
imageIfdValues
.
take
(
ImageTag
(
GpsInfoIfdPointer
));
d
->
exifIfdValues
=
readIfdValues
<
ExifExtendedTag
>
(
stream
,
startPos
,
exifIfdPointer
);
d
->
gpsIfdValues
=
readIfdValues
<
GpsTag
>
(
stream
,
startPos
,
gpsIfdPointer
);
d
->
exifIfdValues
=
readIfdValues
<
ExifExtendedTag
>
(
stream
,
startPos
,
exifIfdPointer
);
d
->
gpsIfdValues
=
readIfdValues
<
GpsTag
>
(
stream
,
startPos
,
gpsIfdPointer
);
d
->
exifIfdValues
.
remove
(
ExifExtendedTag
(
InteroperabilityIfdPointer
));
d
->
exifIfdValues
.
remove
(
ExifExtendedTag
(
InteroperabilityIfdPointer
));
if
(
offset
)
{
device
->
seek
(
startPos
+
offset
);
if
(
offset
)
{
device
->
seek
(
startPos
+
offset
);
QMap
<
quint16
,
QExifValue
>
thumbnailIfdValues
=
readIfdValues
<
quint16
>
(
stream
,
startPos
,
readIfdHeaders
(
stream
));
QMap
<
quint16
,
QExifValue
>
thumbnailIfdValues
=
readIfdValues
<
quint16
>
(
stream
,
startPos
,
readIfdHeaders
(
stream
));
QExifValue
jpegOffset
=
thumbnailIfdValues
.
value
(
JpegInterchangeFormat
);
QExifValue
jpegLength
=
thumbnailIfdValues
.
value
(
JpegInterchangeFormatLength
);
QExifValue
jpegOffset
=
thumbnailIfdValues
.
value
(
JpegInterchangeFormat
);
QExifValue
jpegLength
=
thumbnailIfdValues
.
value
(
JpegInterchangeFormatLength
);
if
(
jpegOffset
.
type
()
==
QExifValue
::
Long
&&
jpegOffset
.
count
()
==
1
&&
jpegLength
.
type
()
==
QExifValue
::
Long
&&
jpegLength
.
count
()
==
1
)
{
device
->
seek
(
startPos
+
jpegOffset
.
toLong
());
if
(
jpegOffset
.
type
()
==
QExifValue
::
Long
&&
jpegOffset
.
count
()
==
1
&&
jpegLength
.
type
()
==
QExifValue
::
Long
&&
jpegLength
.
count
()
==
1
)
{
device
->
seek
(
startPos
+
jpegOffset
.
toLong
());
d
->
thumbnailData
=
device
->
read
(
jpegLength
.
toLong
()
);
d
->
thumbnailData
=
device
->
read
(
jpegLength
.
toLong
()
);
d
->
thumbnailXResolution
=
thumbnailIfdValues
.
value
(
XResolution
);
d
->
thumbnailYResolution
=
thumbnailIfdValues
.
value
(
YResolution
);
d
->
thumbnailResolutionUnit
=
thumbnailIfdValues
.
value
(
ResolutionUnit
);
d
->
thumbnailOrientation
=
thumbnailIfdValues
.
value
(
Orientation
);
}
d
->
thumbnailXResolution
=
thumbnailIfdValues
.
value
(
XResolution
);
d
->
thumbnailYResolution
=
thumbnailIfdValues
.
value
(
YResolution
);
d
->
thumbnailResolutionUnit
=
thumbnailIfdValues
.
value
(
ResolutionUnit
);
d
->
thumbnailOrientation
=
thumbnailIfdValues
.
value
(
Orientation
);
}
return
true
;
}
return
true
;
}
quint32
QExifImageHeader
::
writeExifHeader
(
QDataStream
&
stream
,
quint16
tag
,
const
QExifValue
&
value
,
quint32
offset
)
const
{
stream
<<
tag
;
stream
<<
quint16
(
value
.
type
());
stream
<<
quint32
(
value
.
count
());
quint32
QExifImageHeader
::
writeExifHeader
(
QDataStream
&
stream
,
quint16
tag
,
const
QExifValue
&
value
,
quint32
offset
)
const
{
stream
<<
tag
;
stream
<<
quint16
(
value
.
type
());
stream
<<
quint32
(
value
.
count
());
switch
(
value
.
type
())
{
switch
(
value
.
type
())
{
case
QExifValue
:
:
Byte
:
if
(
value
.
count
()
<=
4
)
{
foreach
(
quint8
byte
,
value
.
toByteVector
())
stream
<<
byte
;
for
(
int
j
=
value
.
count
();
j
<
4
;
j
++
)
stream
<<
quint8
(
0
);
}
else
{
stream
<<
offset
;
offset
+=
value
.
count
();
}
break
;
if
(
value
.
count
()
<=
4
)
{
foreach
(
quint8
byte
,
value
.
toByteVector
())
stream
<<
byte
;
for
(
int
j
=
value
.
count
();
j
<
4
;
j
++
)
stream
<<
quint8
(
0
);
}
else
{
stream
<<
offset
;
offset
+=
value
.
count
();
}
break
;
case
QExifValue
:
:
Undefined
:
if
(
value
.
count
()
<=
4
)
{
stream
.
device
()
->
write
(
value
.
toByteArray
());
if
(
value
.
count
()
<=
4
)
{
stream
.
device
()
->
write
(
value
.
toByteArray
());
if
(
value
.
count
()
<
4
)
stream
.
writeRawData
(
"
\0\0\0\0
"
,
4
-
value
.
count
());
}
else
{
stream
<<
offset
;
if
(
value
.
count
()
<
4
)
stream
.
writeRawData
(
"
\0\0\0\0
"
,
4
-
value
.
count
());
}
else
{
stream
<<
offset
;
offset
+=
value
.
count
();
}
break
;
offset
+=
value
.
count
();
}
break
;
case
QExifValue
:
:
Ascii
:
if
(
value
.
count
()
<=
4
)
{
QByteArray
bytes
=
value
.
toByteArray
();
stream
.
writeRawData
(
bytes
.
constData
(),
value
.
count
());
if
(
value
.
count
()
<
4
)
stream
.
writeRawData
(
"
\0\0\0\0
"
,
4
-
value
.
count
());
}
else
{
stream
<<
offset
;
offset
+=
value
.
count
();
}
break
;
if
(
value
.
count
()
<=
4
)
{
QByteArray
bytes
=
value
.
toByteArray
();
stream
.
writeRawData
(
bytes
.
constData
(),
value
.
count
());
if
(
value
.
count
()
<
4
)
stream
.
writeRawData
(
"
\0\0\0\0
"
,
4
-
value
.
count
());
}
else
{
stream
<<
offset
;
offset
+=
value
.
count
();
}
break
;
case
QExifValue
:
:
Short
:
if
(
value
.
count
()
<=
2
)
{
foreach
(
quint16
shrt
,
value
.
toShortVector
())
stream
<<
shrt
;
for
(
int
j
=
value
.
count
();
j
<
2
;
j
++
)
stream
<<
quint16
(
0
);
}
else
{
stream
<<
offset
;
offset
+=
value
.
count
()
*
sizeof
(
quint16
);
}
break
;
if
(
value
.
count
()
<=
2
)
{
foreach
(
quint16
shrt
,
value
.
toShortVector
())
stream
<<
shrt
;
for
(
int
j
=
value
.
count
();
j
<
2
;
j
++
)
stream
<<
quint16
(
0
);
}
else
{
stream
<<
offset
;
offset
+=
value
.
count
()
*
sizeof
(
quint16
);
}
break
;
case
QExifValue
:
:
Long
:
if
(
value
.
count
()
==
0
)
{
stream
<<
quint32
(
0
);
}
else
if
(
value
.
count
()
==
1
)
{
stream
<<
value
.
toLong
();
}
else
{
stream
<<
offset
;
offset
+=
value
.
count
()
*
sizeof
(
quint32
);
}
break
;
if
(
value
.
count
()
==
0
)
{
stream
<<
quint32
(
0
);
}
else
if
(
value
.
count
()
==
1
)
{
stream
<<
value
.
toLong
();
}
else
{
stream
<<
offset
;
offset
+=
value
.
count
()
*
sizeof
(
quint32
);
}
break
;
case
QExifValue
:
:
SignedLong
:
if
(
value
.
count
()
==
0
)
{
stream
<<
quint32
(
0
);
}
else
if
(
value
.
count
()
==
1
)
{
stream
<<
value
.
toSignedLong
();
}
else
{
stream
<<
offset
;
offset
+=
value
.
count
()
*
sizeof
(
qint32
);
}
break
;
if
(
value
.
count
()
==
0
)
{
stream
<<
quint32
(
0
);
}
else
if
(
value
.
count
()
==
1
)
{
stream
<<
value
.
toSignedLong
();
}
else
{
stream
<<
offset
;
offset
+=
value
.
count
()
*
sizeof
(
qint32
);
}
break
;
case
QExifValue
:
:
Rational
:
if
(
value
.
count
()
==
0
)
{
stream
<<
quint32
(
0
);
}
else
{
stream
<<
offset
;
if
(
value
.
count
()
==
0
)
{
stream
<<
quint32
(
0
);
}
else
{
stream
<<
offset
;
offset
+=
value
.
count
()
*
sizeof
(
quint32
)
*
2
;
}
break
;
offset
+=
value
.
count
()
*
sizeof
(
quint32
)
*
2
;
}
break
;
case
QExifValue
:
:
SignedRational
:
if
(
value
.
count
()
==
0
)
{
stream
<<
quint32
(
0
);
}
else
{
stream
<<
offset
;
if
(
value
.
count
()
==
0
)
{
stream
<<
quint32
(
0
);
}
else
{
stream
<<
offset
;
offset
+=
value
.
count
()
*
sizeof
(
qint32
)
*
2
;
}
break
;
offset
+=
value
.
count
()
*
sizeof
(
qint32
)
*
2
;
}
break
;
default:
qWarning
()
<<
"Invalid Ifd Type"
<<
value
.
type
();
stream
<<
quint32
(
0
);
}
qWarning
()
<<
"Invalid Ifd Type"
<<
value
.
type
();
stream
<<
quint32
(
0
);
}
return
offset
;
return
offset
;
}
void
QExifImageHeader
::
writeExifValue
(
QDataStream
&
stream
,
const
QExifValue
&
value
)
const
{
switch
(
value
.
type
())
{
void
QExifImageHeader
::
writeExifValue
(
QDataStream
&
stream
,
const
QExifValue
&
value
)
const
{
switch
(
value
.
type
())
{
case
QExifValue
:
:
Byte
:
if
(
value
.
count
()
>
4
)
foreach
(
quint8
byte
,
value
.
toByteVector
())
stream
<<
byte
;
break
;
if
(
value
.
count
()
>
4
)
foreach
(
quint8
byte
,
value
.
toByteVector
())
stream
<<
byte
;
break
;
case
QExifValue
:
:
Undefined
:
if
(
value
.
count
()
>
4
)
stream
.
device
()
->
write
(
value
.
toByteArray
());
break
;
if
(
value
.
count
()
>
4
)
stream
.
device
()
->
write
(
value
.
toByteArray
());
break
;
case
QExifValue
:
:
Ascii
:
if
(
value
.
count
()
>
4
)
{
QByteArray
bytes
=
value
.
toByteArray
();
if
(
value
.
count
()
>
4
)
{
QByteArray
bytes
=
value
.
toByteArray
();
stream
.
writeRawData
(
bytes
.
constData
(),
bytes
.
size
()
+
1
);
}
break
;
stream
.
writeRawData
(
bytes
.
constData
(),
bytes
.
size
()
+
1
);
}
break
;
case
QExifValue
:
:
Short
:
if
(
value
.
count
()
>
2
)
foreach
(
quint16
shrt
,
value
.
toShortVector
())
stream
<<
shrt
;
break
;
if
(
value
.
count
()
>
2
)
foreach
(
quint16
shrt
,
value
.
toShortVector
())
stream
<<
shrt
;
break
;
case
QExifValue
:
:
Long
:
if
(
value
.
count
()
>
1
)
foreach
(
quint32
lng
,
value
.
toLongVector
())
stream
<<
lng
;
break
;
if
(
value
.
count
()
>
1
)
foreach
(
quint32
lng
,
value
.
toLongVector
())
stream
<<
lng
;
break
;
case
QExifValue
:
:
SignedLong
:
if
(
value
.
count
()
>
1
)
foreach
(
qint32
lng
,
value
.
toSignedLongVector
())
stream
<<
lng
;
break
;
if
(
value
.
count
()
>
1
)
foreach
(
qint32
lng
,
value
.
toSignedLongVector
())
stream
<<
lng
;
break
;
case
QExifValue
:
:
Rational
:
if
(
value
.
count
()
>
0
)
foreach
(
QExifURational
rational
,
value
.
toRationalVector
())
stream
<<
rational
;
break
;
if
(
value
.
count
()
>
0
)
foreach
(
QExifURational
rational
,
value
.
toRationalVector
())
stream
<<
rational
;
break
;
case
QExifValue
:
:
SignedRational
:
if
(
value
.
count
()
>
0
)
foreach
(
QExifSRational
rational
,
value
.
toSignedRationalVector
())
stream
<<
rational
;
break
;
if
(
value
.
count
()
>
0
)
foreach
(
QExifSRational
rational
,
value
.
toSignedRationalVector
())
stream
<<
rational
;
break
;
default:
qWarning
()
<<
"Invalid Ifd Type"
<<
value
.
type
();
break
;
}
qWarning
()
<<
"Invalid Ifd Type"
<<
value
.
type
();
break
;
}
}
template
<
typename
T
>
quint32
QExifImageHeader
::
writeExifHeaders
(
QDataStream
&
stream
,
const
QMap
<
T
,
QExifValue
>
&
values
,
quint32
offset
)
const
{
offset
+=
values
.
count
()
*
12
;
template
<
typename
T
>
quint32
QExifImageHeader
::
writeExifHeaders
(
QDataStream
&
stream
,
const
QMap
<
T
,
QExifValue
>
&
values
,
quint32
offset
)
const
{
offset
+=
values
.
count
()
*
12
;
for
(
typename
QMap
<
T
,
QExifValue
>::
const_iterator
i
=
values
.
constBegin
();
i
!=
values
.
constEnd
();
i
++
)
offset
=
writeExifHeader
(
stream
,
i
.
key
(),
i
.
value
(),
offset
);
for
(
typename
QMap
<
T
,
QExifValue
>::
const_iterator
i
=
values
.
constBegin
();
i
!=
values
.
constEnd
();
i
++
)
offset
=
writeExifHeader
(
stream
,
i
.
key
(),
i
.
value
(),
offset
);
return
offset
;
return
offset
;
}
template
<
typename
T
>
void
QExifImageHeader
::
writeExifValues
(
QDataStream
&
stream
,
const
QMap
<
T
,
QExifValue
>
&
values
)
const
{
for
(
typename
QMap
<
T
,
QExifValue
>::
const_iterator
i
=
values
.
constBegin
();
i
!=
values
.
constEnd
();
i
++
)
writeExifValue
(
stream
,
i
.
value
());
template
<
typename
T
>
void
QExifImageHeader
::
writeExifValues
(
QDataStream
&
stream
,
const
QMap
<
T
,
QExifValue
>
&
values
)
const
{
for
(
typename
QMap
<
T
,
QExifValue
>::
const_iterator
i
=
values
.
constBegin
();
i
!=
values
.
constEnd
();
i
++
)
writeExifValue
(
stream
,
i
.
value
());
}
/*!
Writes an EXIF header to an I/O \a device.
Returns the total number of bytes written.
*/
qint64
QExifImageHeader
::
write
(
QIODevice
*
device
)
const
{
//#ifndef QT_NO_DEBUG
qint64
startPos
=
device
->
pos
();
//#endif
QDataStream
stream
(
device
);
if
(
d
->
byteOrder
==
QSysInfo
::
LittleEndian
)
{
stream
.
setByteOrder
(
QDataStream
::
LittleEndian
);
device
->
write
(
"II"
,
2
);
device
->
write
(
"
\x2A\x00
"
,
2
);
device
->
write
(
"
\x08\x00\x00\x00
"
,
4
);
}
else
if
(
d
->
byteOrder
==
QSysInfo
::
BigEndian
)
{
stream
.
setByteOrder
(
QDataStream
::
BigEndian
);
device
->
write
(
"MM"
,
2
);
device
->
write
(
"
\x00\x2A
"
,
2
);
device
->
write
(
"
\x00\x00\x00\x08
"
,
4
);
}
*/
qint64
QExifImageHeader
::
write
(
QIODevice
*
device
)
const
{
// #ifndef QT_NO_DEBUG
qint64
startPos
=
device
->
pos
();
// #endif
quint16
count
=
d
->
imageIfdValues
.
count
()
+
1
;
quint32
offset
=
26
;
QDataStream
stream
(
device
);
if
(
!
d
->
gpsIfdValues
.
isEmpty
())
{
count
++
;
offset
+=
12
;
}
if
(
d
->
byteOrder
==
QSysInfo
::
LittleEndian
)
{
stream
.
setByteOrder
(
QDataStream
::
LittleEndian
);
stream
<<
count
;
device
->
write
(
"II"
,
2
);
device
->
write
(
"
\x2A\x00
"
,
2
);
device
->
write
(
"
\x08\x00\x00\x00
"
,
4
);
}
else
if
(
d
->
byteOrder
==
QSysInfo
::
BigEndian
)
{
stream
.
setByteOrder
(
QDataStream
::
BigEndian
);
offset
=
writeExifHeaders
(
stream
,
d
->
imageIfdValues
,
offset
);
device
->
write
(
"MM"
,
2
);
device
->
write
(
"
\x00\x2A
"
,
2
);
device
->
write
(
"
\x00\x00\x00\x08
"
,
4
);
}
quint32
exifIfdOffset
=
offset
;
quint16
count
=
d
->
imageIfdValues
.
count
()
+
1
;
quint32
offset
=
26
;
stream
<<
quint16
(
ExifIfdPointer
);
stream
<<
quint16
(
QExifValue
::
Long
);
stream
<<
quint32
(
1
);
stream
<<
exifIfdOffset
;
offset
+=
calculateSize
(
d
->
exifIfdValues
);
if
(
!
d
->
gpsIfdValues
.
isEmpty
())
{
count
++
;
offset
+=
12
;
}
quint32
gpsIfdOffset
=
offse
t
;
stream
<<
coun
t
;
if
(
!
d
->
gpsIfdValues
.
isEmpty
())
{
stream
<<
quint16
(
GpsInfoIfdPointer
);
stream
<<
quint16
(
QExifValue
::
Long
);
stream
<<
quint32
(
1
);
stream
<<
gpsIfdOffset
;
offset
=
writeExifHeaders
(
stream
,
d
->
imageIfdValues
,
offset
);
d
->
imageIfdValues
.
insert
(
ImageTag
(
GpsInfoIfdPointer
),
QExifValue
(
offset
))
;
quint32
exifIfdOffset
=
offset
;
offset
+=
calculateSize
(
d
->
gpsIfdValues
);
}
stream
<<
quint16
(
ExifIfdPointer
);
stream
<<
quint16
(
QExifValue
::
Long
);
stream
<<
quint32
(
1
);
stream
<<
exifIfdOffset
;
offset
+=
calculateSize
(
d
->
exifIfdValues
);
if
(
!
d
->
thumbnailData
.
isEmpty
())
stream
<<
offset
;
// Write offset to thumbnail Ifd.
else
stream
<<
quint32
(
0
);
quint32
gpsIfdOffset
=
offset
;
writeExifValues
(
stream
,
d
->
imageIfdValues
);
if
(
!
d
->
gpsIfdValues
.
isEmpty
())
{
stream
<<
quint16
(
GpsInfoIfdPointer
);
stream
<<
quint16
(
QExifValue
::
Long
);
stream
<<
quint32
(
1
);
stream
<<
gpsIfdOffset
;
Q_ASSERT
(
startPos
+
exifIfdOffset
==
device
->
pos
(
));
d
->
imageIfdValues
.
insert
(
ImageTag
(
GpsInfoIfdPointer
),
QExifValue
(
offset
));
stream
<<
quint16
(
d
->
exifIfdValues
.
count
());
offset
+=
calculateSize
(
d
->
gpsIfdValues
);
}
writeExifHeaders
(
stream
,
d
->
exifIfdValues
,
exifIfdOffset
);
writeExifValues
(
stream
,
d
->
exifIfdValues
);
if
(
!
d
->
thumbnailData
.
isEmpty
())
stream
<<
offset
;
// Write offset to thumbnail Ifd.
else
stream
<<
quint32
(
0
);
Q_ASSERT
(
startPos
+
gpsIfdOffset
==
device
->
pos
()
);
writeExifValues
(
stream
,
d
->
imageIfdValues
);
if
(
!
d
->
gpsIfdValues
.
isEmpty
())
{
stream
<<
quint16
(
d
->
gpsIfdValues
.
count
());
Q_ASSERT
(
startPos
+
exifIfdOffset
==
device
->
pos
());
writeExifHeaders
(
stream
,
d
->
gpsIfdValues
,
gpsIfdOffset
);
writeExifValues
(
stream
,
d
->
gpsIfdValues
);
}
stream
<<
quint16
(
d
->
exifIfdValues
.
count
());
Q_ASSERT
(
startPos
+
offset
==
device
->
pos
());
writeExifHeaders
(
stream
,
d
->
exifIfdValues
,
exifIfdOffset
);
writeExifValues
(
stream
,
d
->
exifIfdValues
);
if
(
!
d
->
thumbnailData
.
isEmpty
())
{
offset
+=
86
;
Q_ASSERT
(
startPos
+
gpsIfdOffset
==
device
->
pos
());
stream
<<
quint16
(
7
);
if
(
!
d
->
gpsIfdValues
.
isEmpty
())
{
stream
<<
quint16
(
d
->
gpsIfdValues
.
count
());
QExifValue
xResolution
=
d
->
thumbnailXResolution
.
isNull
()
?
QExifValue
(
QExifURational
(
72
,
1
))
:
d
->
thumbnailXResolution
;
writeExifHeaders
(
stream
,
d
->
gpsIfdValues
,
gpsIfdOffset
);
writeExifValues
(
stream
,
d
->
gpsIfdValues
);
}
QExifValue
yResolution
=
d
->
thumbnailYResolution
.
isNull
()
?
QExifValue
(
QExifURational
(
72
,
1
))
:
d
->
thumbnailYResolution
;
Q_ASSERT
(
startPos
+
offset
==
device
->
pos
());
QExifValue
resolutionUnit
=
d
->
thumbnailResolutionUnit
.
isNull
()
?
QExifValue
(
quint16
(
2
))
:
d
->
thumbnailResolutionUnit
;
if
(
!
d
->
thumbnailData
.
isEmpty
())
{
offset
+=
86
;
QExifValue
orientation
=
d
->
thumbnailOrientation
.
isNull
()
?
QExifValue
(
quint16
(
0
))
:
d
->
thumbnailOrientation
;
stream
<<
quint16
(
7
);
writeExifHeader
(
stream
,
Compression
,
QExifValue
(
quint16
(
6
)),
offset
);
QExifValue
xResolution
=
d
->
thumbnailXResolution
.
isNull
()
?
QExifValue
(
QExifURational
(
72
,
1
))
:
d
->
thumbnailXResolution
;
offset
=
writeExifHeader
(
stream
,
XResolution
,
xResolution
,
offset
);
offset
=
writeExifHeader
(
stream
,
YResolution
,
yResolution
,
offset
);
QExifValue
yResolution
=
d
->
thumbnailYResolution
.
isNull
()
?
QExifValue
(
QExifURational
(
72
,
1
))
:
d
->
thumbnailYResolution
;
writeExifHeader
(
stream
,
ResolutionUnit
,
resolutionUnit
,
offset
);
writeExifHeader
(
stream
,
Orientation
,
orientation
,
offset
);
writeExifHeader
(
stream
,
JpegInterchangeFormat
,
QExifValue
(
offset
),
offset
);
writeExifHeader
(
stream
,
JpegInterchangeFormatLength
,
QExifValue
(
quint32
(
d
->
thumbnailData
.
size
())),
offset
);
QExifValue
resolutionUnit
=
d
->
thumbnailResolutionUnit
.
isNull
()
?
QExifValue
(
quint16
(
2
))
:
d
->
thumbnailResolutionUnit
;
writeExifValue
(
stream
,
xResolution
);
writeExifValue
(
stream
,
yResolution
);
QExifValue
orientation
=
d
->
thumbnailOrientation
.
isNull
()
?
QExifValue
(
quint16
(
0
))
:
d
->
thumbnailOrientation
;
Q_ASSERT
(
startPos
+
offset
==
device
->
pos
()
);
writeExifHeader
(
stream
,
Compression
,
QExifValue
(
quint16
(
6
)),
offset
);
device
->
write
(
d
->
thumbnailData
);
offset
=
writeExifHeader
(
stream
,
XResolution
,
xResolution
,
offset
);
offset
=
writeExifHeader
(
stream
,
YResolution
,
yResolution
,
offset
);
offset
+=
d
->
thumbnailData
.
size
();
}
writeExifHeader
(
stream
,
ResolutionUnit
,
resolutionUnit
,
offset
);
writeExifHeader
(
stream
,
Orientation
,
orientation
,
offset
);
writeExifHeader
(
stream
,
JpegInterchangeFormat
,
QExifValue
(
offset
),
offset
);
writeExifHeader
(
stream
,
JpegInterchangeFormatLength
,
QExifValue
(
quint32
(
d
->
thumbnailData
.
size
())),
offset
);
writeExifValue
(
stream
,
xResolution
);
writeExifValue
(
stream
,
yResolution
);
Q_ASSERT
(
startPos
+
offset
==
device
->
pos
());
d
->
size
=
offset
;
device
->
write
(
d
->
thumbnailData
);
offset
+=
d
->
thumbnailData
.
size
();
}
Q_ASSERT
(
startPos
+
offset
==
device
->
pos
());
d
->
size
=
offset
;
return
offset
;
return
offset
;
}
src/utils/QExifImageHeader.h
View file @
e249bc3e
...
...
@@ -51,298 +51,286 @@
#include <QSysInfo>
#include <QIODevice>
typedef
QPair
<
quint32
,
quint32
>
QExifURational
;
typedef
QPair
<
qint32
,
qint32
>
QExifSRational
;
//Q_DECLARE_METATYPE(QExifURational)
//Q_DECLARE_METATYPE(QExifSRational)
typedef
QPair
<
quint32
,
quint32
>
QExifURational
;
typedef
QPair
<
qint32
,
qint32
>
QExifSRational
;
class
QExifValuePrivate
;
class
QExifValue
{
class
QExifValue
{
public:
enum
Type
{
Byte
=
1
,
Ascii
=
2
,
Short
=
3
,
Long
=
4
,
Rational
=
5
,
Undefined
=
7
,
SignedLong
=
9
,
SignedRational
=
10
};
enum
TextEncoding
{
NoEncoding
,
AsciiEncoding
,
JisEncoding
,
UnicodeEncoding
,
UndefinedEncoding
};
QExifValue
();
QExifValue
(
quint8
value
);
QExifValue
(
const
QVector
<
quint8
>
&
value
);
QExifValue
(
const
QString
&
value
,
TextEncoding
encoding
=
NoEncoding
);
QExifValue
(
quint16
value
);
QExifValue
(
const
QVector
<
quint16
>
&
value
);
QExifValue
(
quint32
value
);
QExifValue
(
const
QVector
<
quint32
>
&
value
);
QExifValue
(
const
QExifURational
&
value
);
QExifValue
(
const
QVector
<
QExifURational
>
&
value
);
QExifValue
(
const
QByteArray
&
value
);
QExifValue
(
qint32
value
);
QExifValue
(
const
QVector
<
qint32
>
&
value
);
QExifValue
(
const
QExifSRational
&
value
);
QExifValue
(
const
QVector
<
QExifSRational
>
&
value
);
QExifValue
(
const
QDateTime
&
value
);
QExifValue
(
const
QExifValue
&
other
);
QExifValue
&
operator
=
(
const
QExifValue
&
other
);
~
QExifValue
();
bool
operator
==
(
const
QExifValue
&
other
)
const
;
bool
isNull
()
const
;
int
type
()
const
;
int
count
()
const
;
TextEncoding
encoding
()
const
;
quint8
toByte
()
const
;
QVector
<
quint8
>
toByteVector
()
const
;
QString
toString
()
const
;
quint16
toShort
()
const
;
QVector
<
quint16
>
toShortVector
()
const
;
quint32
toLong
()
const
;
QVector
<
quint32
>
toLongVector
()
const
;
QExifURational
toRational
()
const
;
QVector
<
QExifURational
>
toRationalVector
()
const
;
QByteArray
toByteArray
()
const
;
qint32
toSignedLong
()
const
;
QVector
<
qint32
>
toSignedLongVector
()
const
;
QExifSRational
toSignedRational
()
const
;
QVector
<
QExifSRational
>
toSignedRationalVector
()
const
;
QDateTime
toDateTime
()
const
;
enum
Type
{
Byte
=
1
,
Ascii
=
2
,
Short
=
3
,
Long
=
4
,
Rational
=
5
,
Undefined
=
7
,
SignedLong
=
9
,
SignedRational
=
10
};
enum
TextEncoding
{
NoEncoding
,
AsciiEncoding
,
JisEncoding
,
UnicodeEncoding
,
UndefinedEncoding
};
QExifValue
();
QExifValue
(
quint8
value
);
QExifValue
(
const
QVector
<
quint8
>
&
value
);
QExifValue
(
const
QString
&
value
,
TextEncoding
encoding
=
NoEncoding
);
QExifValue
(
quint16
value
);
QExifValue
(
const
QVector
<
quint16
>
&
value
);
QExifValue
(
quint32
value
);
QExifValue
(
const
QVector
<
quint32
>
&
value
);
QExifValue
(
const
QExifURational
&
value
);
QExifValue
(
const
QVector
<
QExifURational
>
&
value
);
QExifValue
(
const
QByteArray
&
value
);
QExifValue
(
qint32
value
);
QExifValue
(
const
QVector
<
qint32
>
&
value
);
QExifValue
(
const
QExifSRational
&
value
);
QExifValue
(
const
QVector
<
QExifSRational
>
&
value
);
QExifValue
(
const
QDateTime
&
value
);
QExifValue
(
const
QExifValue
&
other
);
QExifValue
&
operator
=
(
const
QExifValue
&
other
);
~
QExifValue
();
bool
operator
==
(
const
QExifValue
&
other
)
const
;
bool
isNull
()
const
;
int
type
()
const
;
int
count
()
const
;
TextEncoding
encoding
()
const
;
quint8
toByte
()
const
;
QVector
<
quint8
>
toByteVector
()
const
;
QString
toString
()
const
;
quint16
toShort
()
const
;
QVector
<
quint16
>
toShortVector
()
const
;
quint32
toLong
()
const
;
QVector
<
quint32
>
toLongVector
()
const
;
QExifURational
toRational
()
const
;
QVector
<
QExifURational
>
toRationalVector
()
const
;
QByteArray
toByteArray
()
const
;
qint32
toSignedLong
()
const
;
QVector
<
qint32
>
toSignedLongVector
()
const
;
QExifSRational
toSignedRational
()
const
;
QVector
<
QExifSRational
>
toSignedRationalVector
()
const
;
QDateTime
toDateTime
()
const
;
private:
QExplicitlySharedDataPointer
<
QExifValuePrivate
>
d
;
QExplicitlySharedDataPointer
<
QExifValuePrivate
>
d
;
};
struct
ExifIfdHeader
;
class
QExifImageHeaderPrivate
;
class
QExifImageHeader
{
Q_DISABLE_COPY
(
QExifImageHeader
)
class
QExifImageHeader
{
Q_DISABLE_COPY
(
QExifImageHeader
)
public:
enum
ImageTag
{
ImageWidth
=
0x0100
,
ImageLength
=
0x0101
,
BitsPerSample
=
0x0102
,
Compression
=
0x0103
,
PhotometricInterpretation
=
0x0106
,
Orientation
=
0x0112
,
SamplesPerPixel
=
0x0115
,
PlanarConfiguration
=
0x011C
,
YCbCrSubSampling
=
0x0212
,
XResolution
=
0x011A
,
YResolution
=
0x011B
,
ResolutionUnit
=
0x0128
,
StripOffsets
=
0x0111
,
RowsPerStrip
=
0x0116
,
StripByteCounts
=
0x0117
,
TransferFunction
=
0x012D
,
WhitePoint
=
0x013E
,
PrimaryChromaciticies
=
0x013F
,
YCbCrCoefficients
=
0x0211
,
ReferenceBlackWhite
=
0x0214
,
DateTime
=
0x0132
,
ImageDescription
=
0x010E
,
Make
=
0x010F
,
Model
=
0x0110
,
Software
=
0x0131
,
Artist
=
0x013B
,
Copyright
=
0x8298
};
enum
ExifExtendedTag
{
ExifVersion
=
0x9000
,
FlashPixVersion
=
0xA000
,
ColorSpace
=
0xA001
,
ComponentsConfiguration
=
0x9101
,
CompressedBitsPerPixel
=
0x9102
,
PixelXDimension
=
0xA002
,
PixelYDimension
=
0xA003
,
MakerNote
=
0x927C
,
UserComment
=
0x9286
,
RelatedSoundFile
=
0xA004
,
DateTimeOriginal
=
0x9003
,
DateTimeDigitized
=
0x9004
,
SubSecTime
=
0x9290
,
SubSecTimeOriginal
=
0x9291
,
SubSecTimeDigitized
=
0x9292
,
ImageUniqueId
=
0xA420
,
ExposureTime
=
0x829A
,
FNumber
=
0x829D
,
ExposureProgram
=
0x8822
,
SpectralSensitivity
=
0x8824
,
ISOSpeedRatings
=
0x8827
,
Oecf
=
0x8828
,
ShutterSpeedValue
=
0x9201
,
ApertureValue
=
0x9202
,
BrightnessValue
=
0x9203
,
ExposureBiasValue
=
0x9204
,
MaxApertureValue
=
0x9205
,
SubjectDistance
=
0x9206
,
MeteringMode
=
0x9207
,
LightSource
=
0x9208
,
Flash
=
0x9209
,
FocalLength
=
0x920A
,
SubjectArea
=
0x9214
,
FlashEnergy
=
0xA20B
,
SpatialFrequencyResponse
=
0xA20C
,
FocalPlaneXResolution
=
0xA20E
,
FocalPlaneYResolution
=
0xA20F
,
FocalPlaneResolutionUnit
=
0xA210
,
SubjectLocation
=
0xA214
,
ExposureIndex
=
0xA215
,
SensingMethod
=
0xA217
,
FileSource
=
0xA300
,
SceneType
=
0xA301
,
CfaPattern
=
0xA302
,
CustomRendered
=
0xA401
,
ExposureMode
=
0xA402
,
WhiteBalance
=
0xA403
,
DigitalZoomRatio
=
0xA404
,
FocalLengthIn35mmFilm
=
0xA405
,
SceneCaptureType
=
0xA406
,
GainControl
=
0xA407
,
Contrast
=
0xA408
,
Saturation
=
0xA409
,
Sharpness
=
0xA40A
,
DeviceSettingDescription
=
0xA40B
,
SubjectDistanceRange
=
0x40C
};
enum
GpsTag
{
GpsVersionId
=
0x0000
,
GpsLatitudeRef
=
0x0001
,
GpsLatitude
=
0x0002
,
GpsLongitudeRef
=
0x0003
,
GpsLongitude
=
0x0004
,
GpsAltitudeRef
=
0x0005
,
GpsAltitude
=
0x0006
,
GpsTimeStamp
=
0x0007
,
GpsSatellites
=
0x0008
,
GpsStatus
=
0x0009
,
GpsMeasureMode
=
0x000A
,
GpsDop
=
0x000B
,
GpsSpeedRef
=
0x000C
,
GpsSpeed
=
0x000D
,
GpsTrackRef
=
0x000E
,
GpsTrack
=
0x000F
,
GpsImageDirectionRef
=
0x0010
,
GpsImageDirection
=
0x0011
,
GpsMapDatum
=
0x0012
,
GpsDestLatitudeRef
=
0x0013
,
GpsDestLatitude
=
0x0014
,
GpsDestLongitudeRef
=
0x0015
,
GpsDestLongitude
=
0x0016
,
GpsDestBearingRef
=
0x0017
,
GpsDestBearing
=
0x0018
,
GpsDestDistanceRef
=
0x0019
,
GpsDestDistance
=
0x001A
,
GpsProcessingMethod
=
0x001B
,
GpsAreaInformation
=
0x001C
,
GpsDateStamp
=
0x001D
,
GpsDifferential
=
0x001E
};
QExifImageHeader
();
explicit
QExifImageHeader
(
const
QString
&
fileName
);
~
QExifImageHeader
();
bool
loadFromJpeg
(
const
QString
&
fileName
);
bool
loadFromJpeg
(
QIODevice
*
device
);
bool
saveToJpeg
(
const
QString
&
fileName
)
const
;
bool
saveToJpeg
(
QIODevice
*
device
)
const
;
bool
read
(
QIODevice
*
device
);
qint64
write
(
QIODevice
*
device
)
const
;
qint64
size
()
const
;
QSysInfo
::
Endian
byteOrder
()
const
;
void
clear
();
QList
<
ImageTag
>
imageTags
()
const
;
QList
<
ExifExtendedTag
>
extendedTags
()
const
;
QList
<
GpsTag
>
gpsTags
()
const
;
bool
contains
(
ImageTag
tag
)
const
;
bool
contains
(
ExifExtendedTag
tag
)
const
;
bool
contains
(
GpsTag
tag
)
const
;
void
remove
(
ImageTag
tag
);
void
remove
(
ExifExtendedTag
tag
);
void
remove
(
GpsTag
tag
);
QExifValue
value
(
ImageTag
tag
)
const
;
QExifValue
value
(
ExifExtendedTag
tag
)
const
;
QExifValue
value
(
GpsTag
tag
)
const
;
void
setValue
(
ImageTag
tag
,
const
QExifValue
&
value
);
void
setValue
(
ExifExtendedTag
tag
,
const
QExifValue
&
value
);
void
setValue
(
GpsTag
tag
,
const
QExifValue
&
value
);
QImage
thumbnail
()
const
;
void
setThumbnail
(
const
QImage
&
thumbnail
);
enum
ImageTag
{
ImageWidth
=
0x0100
,
ImageLength
=
0x0101
,
BitsPerSample
=
0x0102
,
Compression
=
0x0103
,
PhotometricInterpretation
=
0x0106
,
Orientation
=
0x0112
,
SamplesPerPixel
=
0x0115
,
PlanarConfiguration
=
0x011C
,
YCbCrSubSampling
=
0x0212
,
XResolution
=
0x011A
,
YResolution
=
0x011B
,
ResolutionUnit
=
0x0128
,
StripOffsets
=
0x0111
,
RowsPerStrip
=
0x0116
,
StripByteCounts
=
0x0117
,
TransferFunction
=
0x012D
,
WhitePoint
=
0x013E
,
PrimaryChromaciticies
=
0x013F
,
YCbCrCoefficients
=
0x0211
,
ReferenceBlackWhite
=
0x0214
,
DateTime
=
0x0132
,
ImageDescription
=
0x010E
,
Make
=
0x010F
,
Model
=
0x0110
,
Software
=
0x0131
,
Artist
=
0x013B
,
Copyright
=
0x8298
};
enum
ExifExtendedTag
{
ExifVersion
=
0x9000
,
FlashPixVersion
=
0xA000
,
ColorSpace
=
0xA001
,
ComponentsConfiguration
=
0x9101
,
CompressedBitsPerPixel
=
0x9102
,
PixelXDimension
=
0xA002
,
PixelYDimension
=
0xA003
,
MakerNote
=
0x927C
,
UserComment
=
0x9286
,
RelatedSoundFile
=
0xA004
,
DateTimeOriginal
=
0x9003
,
DateTimeDigitized
=
0x9004
,
SubSecTime
=
0x9290
,
SubSecTimeOriginal
=
0x9291
,
SubSecTimeDigitized
=
0x9292
,
ImageUniqueId
=
0xA420
,
ExposureTime
=
0x829A
,
FNumber
=
0x829D
,
ExposureProgram
=
0x8822
,
SpectralSensitivity
=
0x8824
,
ISOSpeedRatings
=
0x8827
,
Oecf
=
0x8828
,
ShutterSpeedValue
=
0x9201
,
ApertureValue
=
0x9202
,
BrightnessValue
=
0x9203
,
ExposureBiasValue
=
0x9204
,
MaxApertureValue
=
0x9205
,
SubjectDistance
=
0x9206
,
MeteringMode
=
0x9207
,
LightSource
=
0x9208
,
Flash
=
0x9209
,
FocalLength
=
0x920A
,
SubjectArea
=
0x9214
,
FlashEnergy
=
0xA20B
,
SpatialFrequencyResponse
=
0xA20C
,
FocalPlaneXResolution
=
0xA20E
,
FocalPlaneYResolution
=
0xA20F
,
FocalPlaneResolutionUnit
=
0xA210
,
SubjectLocation
=
0xA214
,
ExposureIndex
=
0xA215
,
SensingMethod
=
0xA217
,
FileSource
=
0xA300
,
SceneType
=
0xA301
,
CfaPattern
=
0xA302
,
CustomRendered
=
0xA401
,
ExposureMode
=
0xA402
,
WhiteBalance
=
0xA403
,
DigitalZoomRatio
=
0xA404
,
FocalLengthIn35mmFilm
=
0xA405
,
SceneCaptureType
=
0xA406
,
GainControl
=
0xA407
,
Contrast
=
0xA408
,
Saturation
=
0xA409
,
Sharpness
=
0xA40A
,
DeviceSettingDescription
=
0xA40B
,
SubjectDistanceRange
=
0x40C
};
enum
GpsTag
{
GpsVersionId
=
0x0000
,
GpsLatitudeRef
=
0x0001
,
GpsLatitude
=
0x0002
,
GpsLongitudeRef
=
0x0003
,
GpsLongitude
=
0x0004
,
GpsAltitudeRef
=
0x0005
,
GpsAltitude
=
0x0006
,
GpsTimeStamp
=
0x0007
,
GpsSatellites
=
0x0008
,
GpsStatus
=
0x0009
,
GpsMeasureMode
=
0x000A
,
GpsDop
=
0x000B
,
GpsSpeedRef
=
0x000C
,
GpsSpeed
=
0x000D
,
GpsTrackRef
=
0x000E
,
GpsTrack
=
0x000F
,
GpsImageDirectionRef
=
0x0010
,
GpsImageDirection
=
0x0011
,
GpsMapDatum
=
0x0012
,
GpsDestLatitudeRef
=
0x0013
,
GpsDestLatitude
=
0x0014
,
GpsDestLongitudeRef
=
0x0015
,
GpsDestLongitude
=
0x0016
,
GpsDestBearingRef
=
0x0017
,
GpsDestBearing
=
0x0018
,
GpsDestDistanceRef
=
0x0019
,
GpsDestDistance
=
0x001A
,
GpsProcessingMethod
=
0x001B
,
GpsAreaInformation
=
0x001C
,
GpsDateStamp
=
0x001D
,
GpsDifferential
=
0x001E
};
QExifImageHeader
();
explicit
QExifImageHeader
(
const
QString
&
fileName
);
~
QExifImageHeader
();
bool
loadFromJpeg
(
const
QString
&
fileName
);
bool
loadFromJpeg
(
QIODevice
*
device
);
bool
saveToJpeg
(
const
QString
&
fileName
)
const
;
bool
saveToJpeg
(
QIODevice
*
device
)
const
;
bool
read
(
QIODevice
*
device
);
qint64
write
(
QIODevice
*
device
)
const
;
qint64
size
()
const
;
QSysInfo
::
Endian
byteOrder
()
const
;
void
clear
();
QList
<
ImageTag
>
imageTags
()
const
;
QList
<
ExifExtendedTag
>
extendedTags
()
const
;
QList
<
GpsTag
>
gpsTags
()
const
;
bool
contains
(
ImageTag
tag
)
const
;
bool
contains
(
ExifExtendedTag
tag
)
const
;
bool
contains
(
GpsTag
tag
)
const
;
void
remove
(
ImageTag
tag
);
void
remove
(
ExifExtendedTag
tag
);
void
remove
(
GpsTag
tag
);
QExifValue
value
(
ImageTag
tag
)
const
;
QExifValue
value
(
ExifExtendedTag
tag
)
const
;
QExifValue
value
(
GpsTag
tag
)
const
;
void
setValue
(
ImageTag
tag
,
const
QExifValue
&
value
);
void
setValue
(
ExifExtendedTag
tag
,
const
QExifValue
&
value
);
void
setValue
(
GpsTag
tag
,
const
QExifValue
&
value
);
QImage
thumbnail
()
const
;
void
setThumbnail
(
const
QImage
&
thumbnail
);
private:
enum
PrivateTag
{
ExifIfdPointer
=
0x8769
,
GpsInfoIfdPointer
=
0x8825
,
InteroperabilityIfdPointer
=
0xA005
,
JpegInterchangeFormat
=
0x0201
,
JpegInterchangeFormatLength
=
0x0202
};
enum
PrivateTag
{
ExifIfdPointer
=
0x8769
,
GpsInfoIfdPointer
=
0x8825
,
InteroperabilityIfdPointer
=
0xA005
,
JpegInterchangeFormat
=
0x0201
,
JpegInterchangeFormatLength
=
0x0202
};
QByteArray
extractExif
(
QIODevice
*
device
)
const
;
QByteArray
extractExif
(
QIODevice
*
device
)
const
;
QList
<
ExifIfdHeader
>
readIfdHeaders
(
QDataStream
&
stream
)
const
;
QList
<
ExifIfdHeader
>
readIfdHeaders
(
QDataStream
&
stream
)
const
;
QExifValue
readIfdValue
(
QDataStream
&
stream
,
int
startPos
,
const
ExifIfdHeader
&
header
)
const
;
template
<
typename
T
>
QMap
<
T
,
QExifValue
>
readIfdValues
(
QDataStream
&
stream
,
int
startPos
,
const
QList
<
ExifIfdHeader
>
&
headers
)
const
;
template
<
typename
T
>
QMap
<
T
,
QExifValue
>
readIfdValues
(
QDataStream
&
stream
,
int
startPos
,
const
QExifValue
&
pointer
)
const
;
QExifValue
readIfdValue
(
QDataStream
&
stream
,
int
startPos
,
const
ExifIfdHeader
&
header
)
const
;
template
<
typename
T
>
QMap
<
T
,
QExifValue
>
readIfdValues
(
QDataStream
&
stream
,
int
startPos
,
const
QList
<
ExifIfdHeader
>
&
headers
)
const
;
template
<
typename
T
>
QMap
<
T
,
QExifValue
>
readIfdValues
(
QDataStream
&
stream
,
int
startPos
,
const
QExifValue
&
pointer
)
const
;
quint32
writeExifHeader
(
QDataStream
&
stream
,
quint16
tag
,
const
QExifValue
&
value
,
quint32
offset
)
const
;
void
writeExifValue
(
QDataStream
&
stream
,
const
QExifValue
&
value
)
const
;
quint32
writeExifHeader
(
QDataStream
&
stream
,
quint16
tag
,
const
QExifValue
&
value
,
quint32
offset
)
const
;
void
writeExifValue
(
QDataStream
&
stream
,
const
QExifValue
&
value
)
const
;
template
<
typename
T
>
quint32
writeExifHeaders
(
QDataStream
&
stream
,
const
QMap
<
T
,
QExifValue
>
&
values
,
quint32
offset
)
const
;
template
<
typename
T
>
void
writeExifValues
(
QDataStream
&
target
,
const
QMap
<
T
,
QExifValue
>
&
values
)
const
;
template
<
typename
T
>
quint32
writeExifHeaders
(
QDataStream
&
stream
,
const
QMap
<
T
,
QExifValue
>
&
values
,
quint32
offset
)
const
;
template
<
typename
T
>
void
writeExifValues
(
QDataStream
&
target
,
const
QMap
<
T
,
QExifValue
>
&
values
)
const
;
quint32
sizeOf
(
const
QExifValue
&
value
)
const
;
quint32
sizeOf
(
const
QExifValue
&
value
)
const
;
template
<
typename
T
>
quint32
calculateSize
(
const
QMap
<
T
,
QExifValue
>
&
values
)
const
;
template
<
typename
T
>
quint32
calculateSize
(
const
QMap
<
T
,
QExifValue
>
&
values
)
const
;
QExifImageHeaderPrivate
*
d
;
QExifImageHeaderPrivate
*
d
;
};
#endif
#endif
// ifndef QEXIFIMAGEHEADER_H
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment