mirror of
https://invent.kde.org/frameworks/kimageformats.git
synced 2025-07-15 11:14:18 -04:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
1b3d2afbe3 | |||
850068c1dc | |||
6bf38ea638 | |||
2adca7c0ca | |||
dd69fdaea9 | |||
ae62ea3dfc | |||
9c47845f15 | |||
7c7fa73020 | |||
92e4271e84 |
@ -1,11 +1,11 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
set(KF_VERSION "6.13.0") # handled by release scripts
|
set(KF_VERSION "6.14.0") # handled by release scripts
|
||||||
set(KF_DEP_VERSION "6.13.0") # handled by release scripts
|
set(KF_DEP_VERSION "6.14.0") # handled by release scripts
|
||||||
project(KImageFormats VERSION ${KF_VERSION})
|
project(KImageFormats VERSION ${KF_VERSION})
|
||||||
|
|
||||||
include(FeatureSummary)
|
include(FeatureSummary)
|
||||||
find_package(ECM 6.13.0 NO_MODULE)
|
find_package(ECM 6.14.0 NO_MODULE)
|
||||||
set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://commits.kde.org/extra-cmake-modules")
|
set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://commits.kde.org/extra-cmake-modules")
|
||||||
feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ include(ECMDeprecationSettings)
|
|||||||
include(CheckIncludeFiles)
|
include(CheckIncludeFiles)
|
||||||
include(FindPkgConfig)
|
include(FindPkgConfig)
|
||||||
|
|
||||||
set(REQUIRED_QT_VERSION 6.6.0)
|
set(REQUIRED_QT_VERSION 6.7.0)
|
||||||
find_package(Qt6Gui ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE)
|
find_package(Qt6Gui ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE)
|
||||||
|
|
||||||
find_package(KF6Archive ${KF_DEP_VERSION})
|
find_package(KF6Archive ${KF_DEP_VERSION})
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key" : "Description",
|
"key" : "Description",
|
||||||
"value" : "TV broadcast test image."
|
"value" : "テレビ放送テスト映像。(TV broadcast test image.)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key" : "Latitude",
|
"key" : "Latitude",
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key" : "Description",
|
"key" : "Description",
|
||||||
"value" : "TV broadcast test image."
|
"value" : "テレビ放送テスト映像。(TV broadcast test image.)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key" : "Latitude",
|
"key" : "Latitude",
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key" : "Description",
|
"key" : "Description",
|
||||||
"value" : "TV broadcast test image."
|
"value" : "テレビ放送テスト映像。(TV broadcast test image.)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key" : "Latitude",
|
"key" : "Latitude",
|
||||||
|
@ -15,6 +15,16 @@ function(kimageformats_add_plugin plugin)
|
|||||||
target_sources(${plugin} PRIVATE ${KIF_ADD_PLUGIN_SOURCES})
|
target_sources(${plugin} PRIVATE ${KIF_ADD_PLUGIN_SOURCES})
|
||||||
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/imageformats)
|
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/imageformats)
|
||||||
target_link_libraries(${plugin} PRIVATE Qt6::Gui)
|
target_link_libraries(${plugin} PRIVATE Qt6::Gui)
|
||||||
|
|
||||||
|
if(ANDROID)
|
||||||
|
# Plugins should be named with lib prefix on Android
|
||||||
|
# Working name: libplugins_imageformats_kimg_avif_armeabi-v7a.so
|
||||||
|
# Doesn't work: plugins_imageformats_kimg_avif_armeabi-v7a.so
|
||||||
|
if(NOT ${CMAKE_SHARED_LIBRARY_PREFIX} STREQUAL "")
|
||||||
|
set_target_properties(${plugin} PROPERTIES PREFIX ${CMAKE_SHARED_LIBRARY_PREFIX})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
install(TARGETS ${plugin} DESTINATION ${KDE_INSTALL_QTPLUGINDIR}/imageformats)
|
install(TARGETS ${plugin} DESTINATION ${KDE_INSTALL_QTPLUGINDIR}/imageformats)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
// Avoid rotation on buggy Qts (see also https://bugreports.qt.io/browse/QTBUG-126575)
|
// Avoid rotation on buggy Qts (see also https://bugreports.qt.io/browse/QTBUG-126575)
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 7) && QT_VERSION < QT_VERSION_CHECK(6, 6, 0)) || (QT_VERSION >= QT_VERSION_CHECK(6, 7, 3))
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 3)
|
||||||
#ifndef JXL_QT_AUTOTRANSFORM
|
#ifndef JXL_QT_AUTOTRANSFORM
|
||||||
#define JXL_QT_AUTOTRANSFORM
|
#define JXL_QT_AUTOTRANSFORM
|
||||||
#endif
|
#endif
|
||||||
|
@ -720,11 +720,11 @@ public:
|
|||||||
|
|
||||||
auto exif = MicroExif::fromImage(image);
|
auto exif = MicroExif::fromImage(image);
|
||||||
if (!exif.isEmpty()) {
|
if (!exif.isEmpty()) {
|
||||||
auto exifIfd = exif.exifIfdByteArray(QDataStream::LittleEndian);
|
auto exifIfd = exif.exifIfdByteArray(QDataStream::LittleEndian, MicroExif::V2);
|
||||||
if (auto err = PKImageEncode_SetEXIFMetadata_WMP(pEncoder, reinterpret_cast<const quint8 *>(exifIfd.constData()), exifIfd.size())) {
|
if (auto err = PKImageEncode_SetEXIFMetadata_WMP(pEncoder, reinterpret_cast<const quint8 *>(exifIfd.constData()), exifIfd.size())) {
|
||||||
qCWarning(LOG_JXRPLUGIN) << "JXRHandler::write() error while setting EXIF data:" << err;
|
qCWarning(LOG_JXRPLUGIN) << "JXRHandler::write() error while setting EXIF data:" << err;
|
||||||
}
|
}
|
||||||
auto gpsIfd = exif.gpsIfdByteArray(QDataStream::LittleEndian);
|
auto gpsIfd = exif.gpsIfdByteArray(QDataStream::LittleEndian, MicroExif::V2);
|
||||||
if (auto err = PKImageEncode_SetGPSInfoMetadata_WMP(pEncoder, reinterpret_cast<const quint8 *>(gpsIfd.constData()), gpsIfd.size())) {
|
if (auto err = PKImageEncode_SetGPSInfoMetadata_WMP(pEncoder, reinterpret_cast<const quint8 *>(gpsIfd.constData()), gpsIfd.size())) {
|
||||||
qCWarning(LOG_JXRPLUGIN) << "JXRHandler::write() error while setting GPS data:" << err;
|
qCWarning(LOG_JXRPLUGIN) << "JXRHandler::write() error while setting GPS data:" << err;
|
||||||
}
|
}
|
||||||
@ -991,7 +991,7 @@ bool JXRHandler::read(QImage *outImage)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (qint32 y = 0, h = img.height(); y < h; ++y) {
|
for (qint32 y = 0, h = img.height(); y < h; ++y) {
|
||||||
std::memcpy(img.scanLine(y), ba.data() + convStrideSize * y, (std::min)(convStrideSize, img.bytesPerLine()));
|
std::memcpy(img.scanLine(y), ba.data() + convStrideSize * y, (std::min)(convStrideSize, qint64(img.bytesPerLine())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PKFormatConverter_Release(&pConverter);
|
PKFormatConverter_Release(&pConverter);
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
|
#include <QStringDecoder>
|
||||||
#include <QTimeZone>
|
#include <QTimeZone>
|
||||||
|
|
||||||
// TIFF 6 specs
|
// TIFF 6 specs
|
||||||
@ -111,17 +112,17 @@ static const KnownTags staticTagTypes = {
|
|||||||
TagInfo(TIFF_IMAGEWIDTH, ExifTagType::Long),
|
TagInfo(TIFF_IMAGEWIDTH, ExifTagType::Long),
|
||||||
TagInfo(TIFF_IMAGEHEIGHT, ExifTagType::Long),
|
TagInfo(TIFF_IMAGEHEIGHT, ExifTagType::Long),
|
||||||
TagInfo(TIFF_BITSPERSAMPLE, ExifTagType::Short),
|
TagInfo(TIFF_BITSPERSAMPLE, ExifTagType::Short),
|
||||||
TagInfo(TIFF_IMAGEDESCRIPTION, ExifTagType::Ascii),
|
TagInfo(TIFF_IMAGEDESCRIPTION, ExifTagType::Utf8),
|
||||||
TagInfo(TIFF_MAKE, ExifTagType::Ascii),
|
TagInfo(TIFF_MAKE, ExifTagType::Utf8),
|
||||||
TagInfo(TIFF_MODEL, ExifTagType::Ascii),
|
TagInfo(TIFF_MODEL, ExifTagType::Utf8),
|
||||||
TagInfo(TIFF_ORIENT, ExifTagType::Short),
|
TagInfo(TIFF_ORIENT, ExifTagType::Short),
|
||||||
TagInfo(TIFF_XRES, ExifTagType::Rational),
|
TagInfo(TIFF_XRES, ExifTagType::Rational),
|
||||||
TagInfo(TIFF_YRES, ExifTagType::Rational),
|
TagInfo(TIFF_YRES, ExifTagType::Rational),
|
||||||
TagInfo(TIFF_URES, ExifTagType::Short),
|
TagInfo(TIFF_URES, ExifTagType::Short),
|
||||||
TagInfo(TIFF_SOFTWARE, ExifTagType::Ascii),
|
TagInfo(TIFF_SOFTWARE, ExifTagType::Utf8),
|
||||||
TagInfo(TIFF_ARTIST, ExifTagType::Ascii),
|
TagInfo(TIFF_ARTIST, ExifTagType::Utf8),
|
||||||
TagInfo(TIFF_DATETIME, ExifTagType::Ascii),
|
TagInfo(TIFF_DATETIME, ExifTagType::Ascii),
|
||||||
TagInfo(TIFF_COPYRIGHT, ExifTagType::Ascii),
|
TagInfo(TIFF_COPYRIGHT, ExifTagType::Utf8),
|
||||||
TagInfo(EXIF_EXIFIFD, ExifTagType::Long),
|
TagInfo(EXIF_EXIFIFD, ExifTagType::Long),
|
||||||
TagInfo(EXIF_GPSIFD, ExifTagType::Long),
|
TagInfo(EXIF_GPSIFD, ExifTagType::Long),
|
||||||
TagInfo(EXIF_DATETIMEORIGINAL, ExifTagType::Ascii),
|
TagInfo(EXIF_DATETIMEORIGINAL, ExifTagType::Ascii),
|
||||||
@ -134,10 +135,10 @@ static const KnownTags staticTagTypes = {
|
|||||||
TagInfo(EXIF_PIXELYDIM, ExifTagType::Long),
|
TagInfo(EXIF_PIXELYDIM, ExifTagType::Long),
|
||||||
TagInfo(EXIF_IMAGEUNIQUEID, ExifTagType::Ascii),
|
TagInfo(EXIF_IMAGEUNIQUEID, ExifTagType::Ascii),
|
||||||
TagInfo(EXIF_BODYSERIALNUMBER, ExifTagType::Ascii),
|
TagInfo(EXIF_BODYSERIALNUMBER, ExifTagType::Ascii),
|
||||||
TagInfo(EXIF_LENSMAKE, ExifTagType::Ascii),
|
TagInfo(EXIF_LENSMAKE, ExifTagType::Utf8),
|
||||||
TagInfo(EXIF_LENSMODEL, ExifTagType::Ascii),
|
TagInfo(EXIF_LENSMODEL, ExifTagType::Utf8),
|
||||||
TagInfo(EXIF_LENSSERIALNUMBER, ExifTagType::Ascii),
|
TagInfo(EXIF_LENSSERIALNUMBER, ExifTagType::Ascii),
|
||||||
TagInfo(EXIF_IMAGETITLE, ExifTagType::Ascii),
|
TagInfo(EXIF_IMAGETITLE, ExifTagType::Utf8),
|
||||||
TagInfo(EXIF_EXIFVERSION, ExifTagType::Undefined)
|
TagInfo(EXIF_EXIFVERSION, ExifTagType::Undefined)
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
@ -367,6 +368,28 @@ static void writeData(QDataStream &ds, const QVariant &value, const ExifTagType&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ExifTagType updateDataType(const ExifTagType &dataType, const QVariant &value, const MicroExif::Version &ver)
|
||||||
|
{
|
||||||
|
if (dataType != ExifTagType::Utf8)
|
||||||
|
return dataType;
|
||||||
|
|
||||||
|
if (ver == MicroExif::V2)
|
||||||
|
return ExifTagType::Ascii;
|
||||||
|
|
||||||
|
// Note that in EXIF specs, UTF-8 is backward compatible with ASCII: all UTF-8 tags can also be ASCII.
|
||||||
|
// To maximize compatibility, I check if the string can be encoded in ASCII.
|
||||||
|
auto txt = value.toString();
|
||||||
|
|
||||||
|
// Exif ASCII data type allow only values up to 127 (7-bit ASCII).
|
||||||
|
auto u8 = txt.toUtf8();
|
||||||
|
for (auto &&c : u8) {
|
||||||
|
if (uchar(c) > 127)
|
||||||
|
return dataType;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ExifTagType::Ascii;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief writeIfd
|
* \brief writeIfd
|
||||||
* \param ds The stream.
|
* \param ds The stream.
|
||||||
@ -375,7 +398,12 @@ static void writeData(QDataStream &ds, const QVariant &value, const ExifTagType&
|
|||||||
* \param knownTags List of known and supported tags.
|
* \param knownTags List of known and supported tags.
|
||||||
* \return True on success, otherwise false.
|
* \return True on success, otherwise false.
|
||||||
*/
|
*/
|
||||||
static bool writeIfd(QDataStream &ds, const MicroExif::Tags &tags, TagPos &positions, quint32 pos = 0, const KnownTags &knownTags = staticTagTypes)
|
static bool writeIfd(QDataStream &ds,
|
||||||
|
const MicroExif::Version &ver,
|
||||||
|
const MicroExif::Tags &tags,
|
||||||
|
TagPos &positions,
|
||||||
|
quint32 pos = 0,
|
||||||
|
const KnownTags &knownTags = staticTagTypes)
|
||||||
{
|
{
|
||||||
if (tags.isEmpty())
|
if (tags.isEmpty())
|
||||||
return true;
|
return true;
|
||||||
@ -390,7 +418,7 @@ static bool writeIfd(QDataStream &ds, const MicroExif::Tags &tags, TagPos &posit
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto value = tags.value(key);
|
auto value = tags.value(key);
|
||||||
auto dataType = knownTags.value(key);
|
auto dataType = updateDataType(knownTags.value(key), value, ver);
|
||||||
auto count = countBytes(dataType, value);
|
auto count = countBytes(dataType, value);
|
||||||
|
|
||||||
ds << quint16(key);
|
ds << quint16(key);
|
||||||
@ -412,9 +440,8 @@ static bool writeIfd(QDataStream &ds, const MicroExif::Tags &tags, TagPos &posit
|
|||||||
if (!knownTags.contains(key)) {
|
if (!knownTags.contains(key)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto value = tags.value(key);
|
auto value = tags.value(key);
|
||||||
auto dataType = knownTags.value(key);
|
auto dataType = updateDataType(knownTags.value(key), value, ver);
|
||||||
auto count = countBytes(dataType, value);
|
auto count = countBytes(dataType, value);
|
||||||
auto valueSize = count * EXIF_TAG_SIZEOF(dataType);
|
auto valueSize = count * EXIF_TAG_SIZEOF(dataType);
|
||||||
if (valueSize <= 4)
|
if (valueSize <= 4)
|
||||||
@ -534,8 +561,16 @@ static bool readIfd(QDataStream &ds, MicroExif::Tags &tags, quint32 pos = 0, con
|
|||||||
|
|
||||||
if (dataType == EXIF_TAG_DATATYPE(ExifTagType::Ascii) || dataType == EXIF_TAG_DATATYPE(ExifTagType::Utf8)) {
|
if (dataType == EXIF_TAG_DATATYPE(ExifTagType::Ascii) || dataType == EXIF_TAG_DATATYPE(ExifTagType::Utf8)) {
|
||||||
auto l = readBytes(ds, count, true);
|
auto l = readBytes(ds, count, true);
|
||||||
if (!l.isEmpty())
|
if (!l.isEmpty()) {
|
||||||
tags.insert(tagId, dataType == EXIF_TAG_DATATYPE(ExifTagType::Utf8) ? QString::fromUtf8(l) : QString::fromLatin1(l));
|
// It seems that converting to Latin 1 never detects errors so, using UTF-8.
|
||||||
|
// Note that if the dataType is ASCII, by EXIF specification, it must use only the
|
||||||
|
// first 128 values so the UTF-8 conversion is correct.
|
||||||
|
auto dec = QStringDecoder(QStringDecoder::Utf8);
|
||||||
|
// QStringDecoder raise an error only after converting to QString
|
||||||
|
auto ut8 = QString(dec(l));
|
||||||
|
// If there are errors in the conversion to UTF-8, then I try with latin1 (extended ASCII)
|
||||||
|
tags.insert(tagId, dec.hasError() ? QString::fromLatin1(l) : ut8);
|
||||||
|
}
|
||||||
} else if (dataType == EXIF_TAG_DATATYPE(ExifTagType::Undefined)) {
|
} else if (dataType == EXIF_TAG_DATATYPE(ExifTagType::Undefined)) {
|
||||||
auto l = readBytes(ds, count, false);
|
auto l = readBytes(ds, count, false);
|
||||||
if (!l.isEmpty())
|
if (!l.isEmpty())
|
||||||
@ -1032,7 +1067,7 @@ void MicroExif::setImageDirection(double degree, bool isMagnetic)
|
|||||||
m_gpsTags.insert(GPS_IMGDIRECTION, degree);
|
m_gpsTags.insert(GPS_IMGDIRECTION, degree);
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray MicroExif::toByteArray(const QDataStream::ByteOrder &byteOrder) const
|
QByteArray MicroExif::toByteArray(const QDataStream::ByteOrder &byteOrder, const Version &version) const
|
||||||
{
|
{
|
||||||
QByteArray ba;
|
QByteArray ba;
|
||||||
{
|
{
|
||||||
@ -1043,16 +1078,16 @@ QByteArray MicroExif::toByteArray(const QDataStream::ByteOrder &byteOrder) const
|
|||||||
return ba;
|
return ba;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray MicroExif::exifIfdByteArray(const QDataStream::ByteOrder &byteOrder) const
|
QByteArray MicroExif::exifIfdByteArray(const QDataStream::ByteOrder &byteOrder, const Version &version) const
|
||||||
{
|
{
|
||||||
QByteArray ba;
|
QByteArray ba;
|
||||||
{
|
{
|
||||||
QDataStream ds(&ba, QIODevice::WriteOnly);
|
QDataStream ds(&ba, QIODevice::WriteOnly);
|
||||||
ds.setByteOrder(byteOrder);
|
ds.setByteOrder(byteOrder);
|
||||||
auto exifTags = m_exifTags;
|
auto exifTags = m_exifTags;
|
||||||
exifTags.insert(EXIF_EXIFVERSION, QByteArray("0300"));
|
exifTags.insert(EXIF_EXIFVERSION, version == Version::V3 ? QByteArray("0300") : QByteArray("0232"));
|
||||||
TagPos positions;
|
TagPos positions;
|
||||||
if (!writeIfd(ds, exifTags, positions))
|
if (!writeIfd(ds, version, exifTags, positions))
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
return ba;
|
return ba;
|
||||||
@ -1065,7 +1100,7 @@ bool MicroExif::setExifIfdByteArray(const QByteArray &ba, const QDataStream::Byt
|
|||||||
return readIfd(ds, m_exifTags, 0, staticTagTypes);
|
return readIfd(ds, m_exifTags, 0, staticTagTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray MicroExif::gpsIfdByteArray(const QDataStream::ByteOrder &byteOrder) const
|
QByteArray MicroExif::gpsIfdByteArray(const QDataStream::ByteOrder &byteOrder, const Version &version) const
|
||||||
{
|
{
|
||||||
QByteArray ba;
|
QByteArray ba;
|
||||||
{
|
{
|
||||||
@ -1074,7 +1109,7 @@ QByteArray MicroExif::gpsIfdByteArray(const QDataStream::ByteOrder &byteOrder) c
|
|||||||
auto gpsTags = m_gpsTags;
|
auto gpsTags = m_gpsTags;
|
||||||
gpsTags.insert(GPS_GPSVERSION, QByteArray("2400"));
|
gpsTags.insert(GPS_GPSVERSION, QByteArray("2400"));
|
||||||
TagPos positions;
|
TagPos positions;
|
||||||
if (!writeIfd(ds, gpsTags, positions, 0, staticGpsTagTypes))
|
if (!writeIfd(ds, version, gpsTags, positions, 0, staticGpsTagTypes))
|
||||||
return {};
|
return {};
|
||||||
return ba;
|
return ba;
|
||||||
}
|
}
|
||||||
@ -1087,7 +1122,7 @@ bool MicroExif::setGpsIfdByteArray(const QByteArray &ba, const QDataStream::Byte
|
|||||||
return readIfd(ds, m_gpsTags, 0, staticGpsTagTypes);
|
return readIfd(ds, m_gpsTags, 0, staticGpsTagTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MicroExif::write(QIODevice *device, const QDataStream::ByteOrder &byteOrder) const
|
bool MicroExif::write(QIODevice *device, const QDataStream::ByteOrder &byteOrder, const Version &version) const
|
||||||
{
|
{
|
||||||
if (device == nullptr || device->isSequential() || isEmpty())
|
if (device == nullptr || device->isSequential() || isEmpty())
|
||||||
return false;
|
return false;
|
||||||
@ -1096,7 +1131,7 @@ bool MicroExif::write(QIODevice *device, const QDataStream::ByteOrder &byteOrder
|
|||||||
ds.setByteOrder(byteOrder);
|
ds.setByteOrder(byteOrder);
|
||||||
if (!writeHeader(ds))
|
if (!writeHeader(ds))
|
||||||
return false;
|
return false;
|
||||||
if (!writeIfds(ds))
|
if (!writeIfds(ds, version))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
device->close();
|
device->close();
|
||||||
@ -1327,30 +1362,30 @@ bool MicroExif::writeHeader(QDataStream &ds) const
|
|||||||
return ds.status() == QDataStream::Ok;
|
return ds.status() == QDataStream::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MicroExif::writeIfds(QDataStream &ds) const
|
bool MicroExif::writeIfds(QDataStream &ds, const Version &version) const
|
||||||
{
|
{
|
||||||
auto tiffTags = m_tiffTags;
|
auto tiffTags = m_tiffTags;
|
||||||
auto exifTags = m_exifTags;
|
auto exifTags = m_exifTags;
|
||||||
auto gpsTags = m_gpsTags;
|
auto gpsTags = m_gpsTags;
|
||||||
updateTags(tiffTags, exifTags, gpsTags);
|
updateTags(tiffTags, exifTags, gpsTags, version);
|
||||||
|
|
||||||
TagPos positions;
|
TagPos positions;
|
||||||
if (!writeIfd(ds, tiffTags, positions))
|
if (!writeIfd(ds, version, tiffTags, positions))
|
||||||
return false;
|
return false;
|
||||||
if (!writeIfd(ds, exifTags, positions, positions.value(EXIF_EXIFIFD)))
|
if (!writeIfd(ds, version, exifTags, positions, positions.value(EXIF_EXIFIFD)))
|
||||||
return false;
|
return false;
|
||||||
if (!writeIfd(ds, gpsTags, positions, positions.value(EXIF_GPSIFD), staticGpsTagTypes))
|
if (!writeIfd(ds, version, gpsTags, positions, positions.value(EXIF_GPSIFD), staticGpsTagTypes))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MicroExif::updateTags(Tags &tiffTags, Tags &exifTags, Tags &gpsTags) const
|
void MicroExif::updateTags(Tags &tiffTags, Tags &exifTags, Tags &gpsTags, const Version &version) const
|
||||||
{
|
{
|
||||||
if (exifTags.isEmpty()) {
|
if (exifTags.isEmpty()) {
|
||||||
tiffTags.remove(EXIF_EXIFIFD);
|
tiffTags.remove(EXIF_EXIFIFD);
|
||||||
} else {
|
} else {
|
||||||
tiffTags.insert(EXIF_EXIFIFD, quint32());
|
tiffTags.insert(EXIF_EXIFIFD, quint32());
|
||||||
exifTags.insert(EXIF_EXIFVERSION, QByteArray("0300"));
|
exifTags.insert(EXIF_EXIFVERSION, version == Version::V3 ? QByteArray("0300") : QByteArray("0232"));
|
||||||
}
|
}
|
||||||
if (gpsTags.isEmpty()) {
|
if (gpsTags.isEmpty()) {
|
||||||
tiffTags.remove(EXIF_GPSIFD);
|
tiffTags.remove(EXIF_GPSIFD);
|
||||||
|
@ -37,6 +37,15 @@ class MicroExif
|
|||||||
public:
|
public:
|
||||||
using Tags = QMap<quint16, QVariant>;
|
using Tags = QMap<quint16, QVariant>;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The Version enum
|
||||||
|
* Exif specs version used when writing.
|
||||||
|
*/
|
||||||
|
enum Version {
|
||||||
|
V2, // V2.xx
|
||||||
|
V3 // V3.xx, use of UTF-8 data type (default)
|
||||||
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief MicroExif
|
* \brief MicroExif
|
||||||
* Constructs an empty class.
|
* Constructs an empty class.
|
||||||
@ -265,18 +274,20 @@ public:
|
|||||||
* - EXIF IFD
|
* - EXIF IFD
|
||||||
* - GPS IFD
|
* - GPS IFD
|
||||||
* \param byteOrder Sets the serialization byte order for EXIF data.
|
* \param byteOrder Sets the serialization byte order for EXIF data.
|
||||||
|
* \param version The EXIF specs version to use.
|
||||||
* \return A byte array containing the serialized data.
|
* \return A byte array containing the serialized data.
|
||||||
* \sa write
|
* \sa write
|
||||||
*/
|
*/
|
||||||
QByteArray toByteArray(const QDataStream::ByteOrder &byteOrder = EXIF_DEFAULT_BYTEORDER) const;
|
QByteArray toByteArray(const QDataStream::ByteOrder &byteOrder = EXIF_DEFAULT_BYTEORDER, const Version &version = Version::V3) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief exifIfdByteArray
|
* \brief exifIfdByteArray
|
||||||
* Convert the EXIF IFD only to RAW data. Useful when you want to add EXIF data to an existing TIFF container.
|
* Convert the EXIF IFD only to RAW data. Useful when you want to add EXIF data to an existing TIFF container.
|
||||||
* \param byteOrder Sets the serialization byte order for the data.
|
* \param byteOrder Sets the serialization byte order for the data.
|
||||||
|
* \param version The EXIF specs version to use.
|
||||||
* \return A byte array containing the serialized data.
|
* \return A byte array containing the serialized data.
|
||||||
*/
|
*/
|
||||||
QByteArray exifIfdByteArray(const QDataStream::ByteOrder &byteOrder = EXIF_DEFAULT_BYTEORDER) const;
|
QByteArray exifIfdByteArray(const QDataStream::ByteOrder &byteOrder = EXIF_DEFAULT_BYTEORDER, const Version &version = Version::V3) const;
|
||||||
/*!
|
/*!
|
||||||
* \brief setExifIfdByteArray
|
* \brief setExifIfdByteArray
|
||||||
* \param ba The RAW data of EXIF IFD.
|
* \param ba The RAW data of EXIF IFD.
|
||||||
@ -289,9 +300,10 @@ public:
|
|||||||
* \brief gpsIfdByteArray
|
* \brief gpsIfdByteArray
|
||||||
* Convert the GPS IFD only to RAW data. Useful when you want to add GPS data to an existing TIFF container.
|
* Convert the GPS IFD only to RAW data. Useful when you want to add GPS data to an existing TIFF container.
|
||||||
* \param byteOrder Sets the serialization byte order for the data.
|
* \param byteOrder Sets the serialization byte order for the data.
|
||||||
|
* \param version The EXIF specs version to use.
|
||||||
* \return A byte array containing the serialized data.
|
* \return A byte array containing the serialized data.
|
||||||
*/
|
*/
|
||||||
QByteArray gpsIfdByteArray(const QDataStream::ByteOrder &byteOrder = EXIF_DEFAULT_BYTEORDER) const;
|
QByteArray gpsIfdByteArray(const QDataStream::ByteOrder &byteOrder = EXIF_DEFAULT_BYTEORDER, const Version &version = Version::V3) const;
|
||||||
/*!
|
/*!
|
||||||
* \brief setGpsIfdByteArray
|
* \brief setGpsIfdByteArray
|
||||||
* \param ba The RAW data of GPS IFD.
|
* \param ba The RAW data of GPS IFD.
|
||||||
@ -309,10 +321,11 @@ public:
|
|||||||
* - GPS IFD
|
* - GPS IFD
|
||||||
* \param device A random access device.
|
* \param device A random access device.
|
||||||
* \param byteOrder Sets the serialization byte order for EXIF data.
|
* \param byteOrder Sets the serialization byte order for EXIF data.
|
||||||
|
* \param version The EXIF specs version to use.
|
||||||
* \return True on success, otherwise false.
|
* \return True on success, otherwise false.
|
||||||
* \sa toByteArray
|
* \sa toByteArray
|
||||||
*/
|
*/
|
||||||
bool write(QIODevice *device, const QDataStream::ByteOrder &byteOrder = EXIF_DEFAULT_BYTEORDER) const;
|
bool write(QIODevice *device, const QDataStream::ByteOrder &byteOrder = EXIF_DEFAULT_BYTEORDER, const Version &version = Version::V3) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief updateImageMetadata
|
* \brief updateImageMetadata
|
||||||
@ -373,8 +386,8 @@ private:
|
|||||||
void setGpsString(quint16 tagId, const QString& s);
|
void setGpsString(quint16 tagId, const QString& s);
|
||||||
QString gpsString(quint16 tagId) const;
|
QString gpsString(quint16 tagId) const;
|
||||||
bool writeHeader(QDataStream &ds) const;
|
bool writeHeader(QDataStream &ds) const;
|
||||||
bool writeIfds(QDataStream &ds) const;
|
bool writeIfds(QDataStream &ds, const Version &version) const;
|
||||||
void updateTags(Tags &tiffTags, Tags &exifTags, Tags &gpsTags) const;
|
void updateTags(Tags &tiffTags, Tags &exifTags, Tags &gpsTags, const Version &version) const;
|
||||||
|
|
||||||
static void setString(Tags &tags, quint16 tagId, const QString &s);
|
static void setString(Tags &tags, quint16 tagId, const QString &s);
|
||||||
static QString string(const Tags &tags, quint16 tagId);
|
static QString string(const Tags &tags, quint16 tagId);
|
||||||
|
@ -962,11 +962,7 @@ bool XCFImageFormat::loadImageProperties(QDataStream &xcf_io, XCFImage &xcf_imag
|
|||||||
case PROP_PARASITES:
|
case PROP_PARASITES:
|
||||||
while (!property.atEnd()) {
|
while (!property.atEnd()) {
|
||||||
char *tag;
|
char *tag;
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 7, 0)
|
|
||||||
quint32 size;
|
|
||||||
#else
|
|
||||||
qint64 size;
|
qint64 size;
|
||||||
#endif
|
|
||||||
|
|
||||||
property.readBytes(tag, size);
|
property.readBytes(tag, size);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user