mirror of
https://invent.kde.org/frameworks/kimageformats.git
synced 2025-07-14 02:54:19 -04:00
HEIF plug-in extended to read AVCI format
AVCI is H.264 encapsulated in HEIF container
This commit is contained in:
@ -111,6 +111,12 @@ if (LibHeif_FOUND)
|
||||
hej2
|
||||
)
|
||||
endif()
|
||||
|
||||
if (LibHeif_VERSION VERSION_GREATER_EQUAL "1.19.0")
|
||||
kimageformats_read_tests(FUZZ 4
|
||||
avci
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (LibJXL_FOUND AND LibJXLThreads_FOUND)
|
||||
|
BIN
autotests/read/avci/eco_kde_gray.avci
Normal file
BIN
autotests/read/avci/eco_kde_gray.avci
Normal file
Binary file not shown.
BIN
autotests/read/avci/eco_kde_gray.png
Normal file
BIN
autotests/read/avci/eco_kde_gray.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 250 KiB |
@ -23,6 +23,7 @@ bool HEIFHandler::m_plugins_queried = false;
|
||||
bool HEIFHandler::m_heif_decoder_available = false;
|
||||
bool HEIFHandler::m_heif_encoder_available = false;
|
||||
bool HEIFHandler::m_hej2_decoder_available = false;
|
||||
bool HEIFHandler::m_avci_decoder_available = false;
|
||||
|
||||
extern "C" {
|
||||
static struct heif_error heifhandler_write_callback(struct heif_context * /* ctx */, const void *data, size_t size, void *userdata)
|
||||
@ -74,6 +75,11 @@ bool HEIFHandler::canRead() const
|
||||
setFormat("hej2");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (HEIFHandler::isSupportedAVCI(header)) {
|
||||
setFormat("avci");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -164,8 +170,15 @@ bool HEIFHandler::write_helper(const QImage &image)
|
||||
auto cs = image.colorSpace();
|
||||
if (cs.isValid() && cs.colorModel() == QColorSpace::ColorModel::Cmyk && image.format() == QImage::Format_CMYK8888) {
|
||||
tmpimage = image.convertedToColorSpace(QColorSpace(QColorSpace::SRgb), tmpformat);
|
||||
} else if (cs.isValid() && cs.colorModel() == QColorSpace::ColorModel::Gray
|
||||
&& (image.format() == QImage::Format_Grayscale8 || image.format() == QImage::Format_Grayscale16)) {
|
||||
QColorSpace::TransferFunction trc_new = cs.transferFunction();
|
||||
float gamma_new = cs.gamma();
|
||||
if (trc_new == QColorSpace::TransferFunction::Custom) {
|
||||
trc_new = QColorSpace::TransferFunction::SRgb;
|
||||
}
|
||||
else {
|
||||
tmpimage = image.convertedToColorSpace(QColorSpace(QColorSpace::Primaries::SRgb, trc_new, gamma_new), tmpformat);
|
||||
} else {
|
||||
tmpimage = image.convertToFormat(tmpformat);
|
||||
}
|
||||
#else
|
||||
@ -380,6 +393,22 @@ bool HEIFHandler::isSupportedHEJ2(const QByteArray &header)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HEIFHandler::isSupportedAVCI(const QByteArray &header)
|
||||
{
|
||||
if (header.size() < 28) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *buffer = header.constData();
|
||||
if (qstrncmp(buffer + 4, "ftyp", 4) == 0) {
|
||||
if (qstrncmp(buffer + 8, "avci", 4) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariant HEIFHandler::option(ImageOption option) const
|
||||
{
|
||||
if (option == Quality) {
|
||||
@ -455,7 +484,7 @@ bool HEIFHandler::ensureDecoder()
|
||||
}
|
||||
|
||||
const QByteArray buffer = device()->readAll();
|
||||
if (!HEIFHandler::isSupportedBMFFType(buffer) && !HEIFHandler::isSupportedHEJ2(buffer)) {
|
||||
if (!HEIFHandler::isSupportedBMFFType(buffer) && !HEIFHandler::isSupportedHEJ2(buffer) && !HEIFHandler::isSupportedAVCI(buffer)) {
|
||||
m_parseState = ParseHeicError;
|
||||
return false;
|
||||
}
|
||||
@ -808,6 +837,14 @@ bool HEIFHandler::ensureDecoder()
|
||||
case 13:
|
||||
q_trc = QColorSpace::TransferFunction::SRgb;
|
||||
break;
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 8, 0))
|
||||
case 16:
|
||||
q_trc = QColorSpace::TransferFunction::St2084;
|
||||
break;
|
||||
case 18:
|
||||
q_trc = QColorSpace::TransferFunction::Hlg;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
qWarning("CICP color_primaries: %d, transfer_characteristics: %d\nThe colorspace is unsupported by this plug-in yet.",
|
||||
nclx->color_primaries,
|
||||
@ -850,61 +887,33 @@ bool HEIFHandler::ensureDecoder()
|
||||
|
||||
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
|
||||
|
||||
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||
m_hej2_decoder_available = heif_have_decoder_for_format(heif_compression_JPEG2000);
|
||||
#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
|
||||
}
|
||||
HEIFHandler::queryHeifLib();
|
||||
|
||||
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
|
||||
|
||||
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||
m_hej2_decoder_available = heif_have_decoder_for_format(heif_compression_JPEG2000);
|
||||
#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
|
||||
}
|
||||
HEIFHandler::queryHeifLib();
|
||||
|
||||
return m_heif_encoder_available;
|
||||
}
|
||||
|
||||
bool HEIFHandler::isHej2DecoderAvailable()
|
||||
{
|
||||
HEIFHandler::queryHeifLib();
|
||||
|
||||
return m_hej2_decoder_available;
|
||||
}
|
||||
|
||||
bool HEIFHandler::isAVCIDecoderAvailable()
|
||||
{
|
||||
HEIFHandler::queryHeifLib();
|
||||
|
||||
return m_avci_decoder_available;
|
||||
}
|
||||
|
||||
void HEIFHandler::queryHeifLib()
|
||||
{
|
||||
QMutexLocker locker(&getHEIFHandlerMutex());
|
||||
|
||||
@ -919,6 +928,9 @@ bool HEIFHandler::isHej2DecoderAvailable()
|
||||
m_heif_decoder_available = heif_have_decoder_for_format(heif_compression_HEVC);
|
||||
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||
m_hej2_decoder_available = heif_have_decoder_for_format(heif_compression_JPEG2000);
|
||||
#endif
|
||||
#if LIBHEIF_HAVE_VERSION(1, 19, 0)
|
||||
m_avci_decoder_available = heif_have_decoder_for_format(heif_compression_AVC);
|
||||
#endif
|
||||
m_plugins_queried = true;
|
||||
|
||||
@ -928,8 +940,6 @@ bool HEIFHandler::isHej2DecoderAvailable()
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return m_hej2_decoder_available;
|
||||
}
|
||||
|
||||
void HEIFHandler::startHeifLib()
|
||||
@ -989,6 +999,14 @@ QImageIOPlugin::Capabilities HEIFPlugin::capabilities(QIODevice *device, const Q
|
||||
return format_cap;
|
||||
}
|
||||
|
||||
if (format == "avci") {
|
||||
Capabilities format_cap;
|
||||
if (HEIFHandler::isAVCIDecoderAvailable()) {
|
||||
format_cap |= CanRead;
|
||||
}
|
||||
return format_cap;
|
||||
}
|
||||
|
||||
if (!format.isEmpty()) {
|
||||
return {};
|
||||
}
|
||||
@ -1000,11 +1018,9 @@ QImageIOPlugin::Capabilities HEIFPlugin::capabilities(QIODevice *device, const Q
|
||||
if (device->isReadable()) {
|
||||
const QByteArray header = device->peek(28);
|
||||
|
||||
if (HEIFHandler::isSupportedBMFFType(header) && HEIFHandler::isHeifDecoderAvailable()) {
|
||||
cap |= CanRead;
|
||||
}
|
||||
|
||||
if (HEIFHandler::isSupportedHEJ2(header) && HEIFHandler::isHej2DecoderAvailable()) {
|
||||
if ((HEIFHandler::isSupportedBMFFType(header) && HEIFHandler::isHeifDecoderAvailable())
|
||||
|| (HEIFHandler::isSupportedHEJ2(header) && HEIFHandler::isHej2DecoderAvailable())
|
||||
|| (HEIFHandler::isSupportedAVCI(header) && HEIFHandler::isAVCIDecoderAvailable())) {
|
||||
cap |= CanRead;
|
||||
}
|
||||
}
|
||||
|
@ -31,9 +31,11 @@ public:
|
||||
static bool isHeifDecoderAvailable();
|
||||
static bool isHeifEncoderAvailable();
|
||||
static bool isHej2DecoderAvailable();
|
||||
static bool isAVCIDecoderAvailable();
|
||||
|
||||
static bool isSupportedBMFFType(const QByteArray &header);
|
||||
static bool isSupportedHEJ2(const QByteArray &header);
|
||||
static bool isSupportedAVCI(const QByteArray &header);
|
||||
|
||||
private:
|
||||
bool ensureParsed() const;
|
||||
@ -53,12 +55,14 @@ private:
|
||||
|
||||
static void startHeifLib();
|
||||
static void finishHeifLib();
|
||||
static void queryHeifLib();
|
||||
static size_t m_initialized_count;
|
||||
|
||||
static bool m_plugins_queried;
|
||||
static bool m_heif_decoder_available;
|
||||
static bool m_heif_encoder_available;
|
||||
static bool m_hej2_decoder_available;
|
||||
static bool m_avci_decoder_available;
|
||||
|
||||
static QMutex &getHEIFHandlerMutex();
|
||||
};
|
||||
|
Reference in New Issue
Block a user