Commit e249bc3e authored by Wescoeur's avatar Wescoeur

fix(QExifImageHeader): use app indentation

parent 8d46bcb1
......@@ -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 = offset;
stream << count;
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;
}
......@@ -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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment