mirror of
https://invent.kde.org/frameworks/kimageformats.git
synced 2025-05-28 00:30:23 -04:00
heif: use heif_init/heif_deinit with libheif 1.13.0+
In recent libheif, application should use heif_init/heif_deinit calls. Unfortunately, these calls are not thread-safe in released 1.13.0 version yet (will be in the future) and HEIFHandler is often created in different threads. So we have to guard their use with a mutex.
This commit is contained in:
parent
20f74ce5e6
commit
9ab64dbf22
@ -52,6 +52,11 @@ private:
|
||||
|
||||
} // namespace
|
||||
|
||||
size_t HEIFHandler::m_initialized_count = 0;
|
||||
bool HEIFHandler::m_plugins_queried = false;
|
||||
bool HEIFHandler::m_heif_decoder_available = false;
|
||||
bool HEIFHandler::m_heif_encoder_available = false;
|
||||
|
||||
HEIFHandler::HEIFHandler()
|
||||
: m_parseState(ParseHeicNotParsed)
|
||||
, m_quality(100)
|
||||
@ -88,6 +93,21 @@ bool HEIFHandler::write(const QImage &image)
|
||||
return false;
|
||||
}
|
||||
|
||||
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||
startHeifLib();
|
||||
#endif
|
||||
|
||||
bool success = write_helper(image);
|
||||
|
||||
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||
finishHeifLib();
|
||||
#endif
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool HEIFHandler::write_helper(const QImage &image)
|
||||
{
|
||||
int save_depth; // 8 or 10bit per channel
|
||||
QImage::Format tmpformat; // format for temporary image
|
||||
const bool save_alpha = image.hasAlphaChannel();
|
||||
@ -356,8 +376,18 @@ bool HEIFHandler::ensureParsed() const
|
||||
|
||||
HEIFHandler *that = const_cast<HEIFHandler *>(this);
|
||||
|
||||
return that->ensureDecoder();
|
||||
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||
startHeifLib();
|
||||
#endif
|
||||
|
||||
bool success = that->ensureDecoder();
|
||||
|
||||
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||
finishHeifLib();
|
||||
#endif
|
||||
return success;
|
||||
}
|
||||
|
||||
bool HEIFHandler::ensureDecoder()
|
||||
{
|
||||
if (m_parseState != ParseHeicNotParsed) {
|
||||
@ -696,14 +726,100 @@ bool HEIFHandler::ensureDecoder()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HEIFHandler::isHeifDecoderAvailable()
|
||||
{
|
||||
QMutexLocker locker(&getHEIFHandlerMutex());
|
||||
|
||||
if (!m_plugins_queried) {
|
||||
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||
if (m_initialized_count == 0) {
|
||||
heif_init(nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
m_heif_encoder_available = heif_have_encoder_for_format(heif_compression_HEVC);
|
||||
m_heif_decoder_available = heif_have_decoder_for_format(heif_compression_HEVC);
|
||||
m_plugins_queried = true;
|
||||
|
||||
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||
if (m_initialized_count == 0) {
|
||||
heif_deinit();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return m_heif_decoder_available;
|
||||
}
|
||||
|
||||
bool HEIFHandler::isHeifEncoderAvailable()
|
||||
{
|
||||
QMutexLocker locker(&getHEIFHandlerMutex());
|
||||
|
||||
if (!m_plugins_queried) {
|
||||
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||
if (m_initialized_count == 0) {
|
||||
heif_init(nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
m_heif_decoder_available = heif_have_decoder_for_format(heif_compression_HEVC);
|
||||
m_heif_encoder_available = heif_have_encoder_for_format(heif_compression_HEVC);
|
||||
m_plugins_queried = true;
|
||||
|
||||
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||
if (m_initialized_count == 0) {
|
||||
heif_deinit();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return m_heif_encoder_available;
|
||||
}
|
||||
|
||||
void HEIFHandler::startHeifLib()
|
||||
{
|
||||
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||
QMutexLocker locker(&getHEIFHandlerMutex());
|
||||
|
||||
if (m_initialized_count == 0) {
|
||||
heif_init(nullptr);
|
||||
}
|
||||
|
||||
m_initialized_count++;
|
||||
#endif
|
||||
}
|
||||
|
||||
void HEIFHandler::finishHeifLib()
|
||||
{
|
||||
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||
QMutexLocker locker(&getHEIFHandlerMutex());
|
||||
|
||||
if (m_initialized_count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_initialized_count--;
|
||||
if (m_initialized_count == 0) {
|
||||
heif_deinit();
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
QMutex &HEIFHandler::getHEIFHandlerMutex()
|
||||
{
|
||||
static QMutex heif_handler_mutex;
|
||||
return heif_handler_mutex;
|
||||
}
|
||||
|
||||
QImageIOPlugin::Capabilities HEIFPlugin::capabilities(QIODevice *device, const QByteArray &format) const
|
||||
{
|
||||
if (format == "heif" || format == "heic") {
|
||||
Capabilities format_cap;
|
||||
if (heif_have_decoder_for_format(heif_compression_HEVC)) {
|
||||
if (HEIFHandler::isHeifDecoderAvailable()) {
|
||||
format_cap |= CanRead;
|
||||
}
|
||||
if (heif_have_encoder_for_format(heif_compression_HEVC)) {
|
||||
if (HEIFHandler::isHeifEncoderAvailable()) {
|
||||
format_cap |= CanWrite;
|
||||
}
|
||||
return format_cap;
|
||||
@ -716,11 +832,11 @@ QImageIOPlugin::Capabilities HEIFPlugin::capabilities(QIODevice *device, const Q
|
||||
}
|
||||
|
||||
Capabilities cap;
|
||||
if (device->isReadable() && HEIFHandler::canRead(device) && heif_have_decoder_for_format(heif_compression_HEVC)) {
|
||||
if (device->isReadable() && HEIFHandler::canRead(device) && HEIFHandler::isHeifDecoderAvailable()) {
|
||||
cap |= CanRead;
|
||||
}
|
||||
|
||||
if (device->isWritable() && heif_have_encoder_for_format(heif_compression_HEVC)) {
|
||||
if (device->isWritable() && HEIFHandler::isHeifEncoderAvailable()) {
|
||||
cap |= CanWrite;
|
||||
}
|
||||
return cap;
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <QByteArray>
|
||||
#include <QImage>
|
||||
#include <QImageIOPlugin>
|
||||
#include <QMutex>
|
||||
|
||||
class HEIFHandler : public QImageIOHandler
|
||||
{
|
||||
@ -29,6 +30,9 @@ public:
|
||||
void setOption(ImageOption option, const QVariant &value) override;
|
||||
bool supportsOption(ImageOption option) const override;
|
||||
|
||||
static bool isHeifDecoderAvailable();
|
||||
static bool isHeifEncoderAvailable();
|
||||
|
||||
private:
|
||||
static bool isSupportedBMFFType(const QByteArray &header);
|
||||
bool ensureParsed() const;
|
||||
@ -43,6 +47,18 @@ private:
|
||||
ParseHeicState m_parseState;
|
||||
int m_quality;
|
||||
QImage m_current_image;
|
||||
|
||||
bool write_helper(const QImage &image);
|
||||
|
||||
static void startHeifLib();
|
||||
static void finishHeifLib();
|
||||
static size_t m_initialized_count;
|
||||
|
||||
static bool m_plugins_queried;
|
||||
static bool m_heif_decoder_available;
|
||||
static bool m_heif_encoder_available;
|
||||
|
||||
static QMutex &getHEIFHandlerMutex();
|
||||
};
|
||||
|
||||
class HEIFPlugin : public QImageIOPlugin
|
||||
|
Loading…
Reference in New Issue
Block a user