12#include <libheif/heif.h>
21size_t HEIFHandler::m_initialized_count = 0;
22bool HEIFHandler::m_plugins_queried =
false;
23bool HEIFHandler::m_heif_decoder_available =
false;
24bool HEIFHandler::m_heif_encoder_available =
false;
25bool HEIFHandler::m_hej2_decoder_available =
false;
28static struct heif_error heifhandler_write_callback(struct heif_context * ,
const void *data,
size_t size,
void *userdata)
31 error.code = heif_error_Ok;
32 error.subcode = heif_suberror_Unspecified;
33 error.message =
"Success";
35 if (!userdata || !data || size == 0) {
36 error.code = heif_error_Usage_error;
37 error.subcode = heif_suberror_Null_pointer_argument;
38 error.message =
"Wrong parameters!";
43 qint64 bytesWritten = ioDevice->
write(
static_cast<const char *
>(data), size);
45 if (bytesWritten <
static_cast<qint64
>(size)) {
46 error.code = heif_error_Encoding_error;
47 error.message =
"Bytes written to QIODevice are smaller than input data size";
48 error.subcode = heif_suberror_Cannot_write_output_data;
55HEIFHandler::HEIFHandler()
56 : m_parseState(ParseHeicNotParsed)
61bool HEIFHandler::canRead()
const
63 if (m_parseState == ParseHeicNotParsed) {
68 if (HEIFHandler::isSupportedBMFFType(header)) {
73 if (HEIFHandler::isSupportedHEJ2(header)) {
81 if (m_parseState != ParseHeicError) {
87bool HEIFHandler::read(
QImage *outImage)
89 if (!ensureParsed()) {
93 *outImage = m_current_image;
97bool HEIFHandler::write(
const QImage &image)
100 qWarning(
"No image data to save");
104#if LIBHEIF_HAVE_VERSION(1, 13, 0)
108 bool success = write_helper(image);
110#if LIBHEIF_HAVE_VERSION(1, 13, 0)
117bool HEIFHandler::write_helper(
const QImage &image)
135 if (image.
depth() > 32) {
144 if (save_depth > 8) {
155 chroma = heif_chroma_interleaved_RGBA;
158 chroma = heif_chroma_interleaved_RGB;
164 struct heif_context *context = heif_context_alloc();
165 struct heif_error err;
166 struct heif_image *h_image =
nullptr;
168 err = heif_image_create(tmpimage.
width(), tmpimage.
height(), heif_colorspace_RGB, chroma, &h_image);
170 qWarning() <<
"heif_image_create error:" << err.message;
171 heif_context_free(context);
176 if (iccprofile.
size() > 0) {
177 heif_image_set_raw_color_profile(h_image,
"prof", iccprofile.
constData(), iccprofile.
size());
180 heif_image_add_plane(h_image, heif_channel_interleaved, image.
width(), image.
height(), save_depth);
182 uint8_t *
const dst = heif_image_get_plane(h_image, heif_channel_interleaved, &stride);
185 switch (save_depth) {
188 for (
int y = 0; y < tmpimage.
height(); y++) {
189 const uint16_t *src_word =
reinterpret_cast<const uint16_t *
>(tmpimage.
constScanLine(y));
190 uint16_t *dest_word =
reinterpret_cast<uint16_t *
>(dst + (y * stride));
191 for (
int x = 0; x < tmpimage.
width(); x++) {
194 tmp_pixelval = (int)(((
float)(*src_word) / 65535.0f) * 1023.0f + 0.5f);
195 *dest_word = qBound(0, tmp_pixelval, 1023);
199 tmp_pixelval = (int)(((
float)(*src_word) / 65535.0f) * 1023.0f + 0.5f);
200 *dest_word = qBound(0, tmp_pixelval, 1023);
204 tmp_pixelval = (int)(((
float)(*src_word) / 65535.0f) * 1023.0f + 0.5f);
205 *dest_word = qBound(0, tmp_pixelval, 1023);
209 tmp_pixelval = (int)(((
float)(*src_word) / 65535.0f) * 1023.0f + 0.5f);
210 *dest_word = qBound(0, tmp_pixelval, 1023);
216 for (
int y = 0; y < tmpimage.
height(); y++) {
217 const uint16_t *src_word =
reinterpret_cast<const uint16_t *
>(tmpimage.
constScanLine(y));
218 uint16_t *dest_word =
reinterpret_cast<uint16_t *
>(dst + (y * stride));
219 for (
int x = 0; x < tmpimage.
width(); x++) {
222 tmp_pixelval = (int)(((
float)(*src_word) / 65535.0f) * 1023.0f + 0.5f);
223 *dest_word = qBound(0, tmp_pixelval, 1023);
227 tmp_pixelval = (int)(((
float)(*src_word) / 65535.0f) * 1023.0f + 0.5f);
228 *dest_word = qBound(0, tmp_pixelval, 1023);
232 tmp_pixelval = (int)(((
float)(*src_word) / 65535.0f) * 1023.0f + 0.5f);
233 *dest_word = qBound(0, tmp_pixelval, 1023);
243 rowbytes = save_alpha ? (tmpimage.
width() * 4) : (tmpimage.width() * 3);
244 for (
int y = 0; y < tmpimage.
height(); y++) {
245 memcpy(dst + (y * stride), tmpimage.
constScanLine(y), rowbytes);
249 qWarning() <<
"Unsupported depth:" << save_depth;
250 heif_image_release(h_image);
251 heif_context_free(context);
256 struct heif_encoder *encoder =
nullptr;
257 err = heif_context_get_encoder_for_format(context, heif_compression_HEVC, &encoder);
259 qWarning() <<
"Unable to get an encoder instance:" << err.message;
260 heif_image_release(h_image);
261 heif_context_free(context);
265 heif_encoder_set_lossy_quality(encoder, m_quality);
266 if (m_quality > 90) {
267 if (m_quality == 100) {
268 heif_encoder_set_lossless(encoder,
true);
270 heif_encoder_set_parameter_string(encoder,
"chroma",
"444");
273 struct heif_encoding_options *encoder_options = heif_encoding_options_alloc();
274 encoder_options->save_alpha_channel = save_alpha;
276 if ((tmpimage.
width() % 2 == 1) || (tmpimage.
height() % 2 == 1)) {
277 qWarning() <<
"Image has odd dimension!\nUse even-numbered dimension(s) for better compatibility with other HEIF implementations.";
280 encoder_options->macOS_compatibility_workaround = 0;
284 err = heif_context_encode_image(context, h_image, encoder, encoder_options,
nullptr);
286 if (encoder_options) {
287 heif_encoding_options_free(encoder_options);
291 qWarning() <<
"heif_context_encode_image failed:" << err.message;
292 heif_encoder_release(encoder);
293 heif_image_release(h_image);
294 heif_context_free(context);
298 struct heif_writer writer;
299 writer.writer_api_version = 1;
300 writer.write = heifhandler_write_callback;
302 err = heif_context_write(context, &writer, device());
304 heif_encoder_release(encoder);
305 heif_image_release(h_image);
308 qWarning() <<
"Writing HEIF image failed:" << err.message;
309 heif_context_free(context);
313 heif_context_free(context);
317bool HEIFHandler::isSupportedBMFFType(
const QByteArray &header)
319 if (header.
size() < 28) {
324 if (qstrncmp(buffer + 4,
"ftyp", 4) == 0) {
325 if (qstrncmp(buffer + 8,
"heic", 4) == 0) {
328 if (qstrncmp(buffer + 8,
"heis", 4) == 0) {
331 if (qstrncmp(buffer + 8,
"heix", 4) == 0) {
336 if (qstrncmp(buffer + 8,
"mif1", 4) == 0) {
337 for (
int offset = 16; offset <= 24; offset += 4) {
338 if (qstrncmp(buffer + offset,
"avif", 4) == 0) {
345 if (qstrncmp(buffer + 8,
"mif2", 4) == 0) {
348 if (qstrncmp(buffer + 8,
"msf1", 4) == 0) {
356bool HEIFHandler::isSupportedHEJ2(
const QByteArray &header)
358 if (header.
size() < 28) {
363 if (qstrncmp(buffer + 4,
"ftyp", 4) == 0) {
364 if (qstrncmp(buffer + 8,
"j2ki", 4) == 0) {
372QVariant HEIFHandler::option(ImageOption option)
const
374 if (option == Quality) {
378 if (!supportsOption(option) || !ensureParsed()) {
384 return m_current_image.size();
392void HEIFHandler::setOption(ImageOption option,
const QVariant &value)
396 m_quality = value.
toInt();
397 if (m_quality > 100) {
399 }
else if (m_quality < 0) {
409bool HEIFHandler::supportsOption(ImageOption option)
const
411 return option == Quality || option == Size;
414bool HEIFHandler::ensureParsed()
const
416 if (m_parseState == ParseHeicSuccess) {
419 if (m_parseState == ParseHeicError) {
423 HEIFHandler *that =
const_cast<HEIFHandler *
>(
this);
425#if LIBHEIF_HAVE_VERSION(1, 13, 0)
429 bool success = that->ensureDecoder();
431#if LIBHEIF_HAVE_VERSION(1, 13, 0)
437bool HEIFHandler::ensureDecoder()
439 if (m_parseState != ParseHeicNotParsed) {
440 if (m_parseState == ParseHeicSuccess) {
446 const QByteArray buffer = device()->readAll();
447 if (!HEIFHandler::isSupportedBMFFType(buffer) && !HEIFHandler::isSupportedHEJ2(buffer)) {
448 m_parseState = ParseHeicError;
452 struct heif_context *ctx = heif_context_alloc();
453 struct heif_error err = heif_context_read_from_memory(ctx,
static_cast<const void *
>(buffer.
constData()), buffer.
size(),
nullptr);
456 qWarning() <<
"heif_context_read_from_memory error:" << err.message;
457 heif_context_free(ctx);
458 m_parseState = ParseHeicError;
462 struct heif_image_handle *handle =
nullptr;
463 err = heif_context_get_primary_image_handle(ctx, &handle);
465 qWarning() <<
"heif_context_get_primary_image_handle error:" << err.message;
466 heif_context_free(ctx);
467 m_parseState = ParseHeicError;
471 if ((heif_image_handle_get_width(handle) == 0) || (heif_image_handle_get_height(handle) == 0)) {
472 m_parseState = ParseHeicError;
473 heif_image_handle_release(handle);
474 heif_context_free(ctx);
475 qWarning() <<
"HEIC image has zero dimension";
479 const bool hasAlphaChannel = heif_image_handle_has_alpha_channel(handle);
480 const int bit_depth = heif_image_handle_get_luma_bits_per_pixel(handle);
485 if (bit_depth == 10 || bit_depth == 12) {
486 if (hasAlphaChannel) {
493 }
else if (bit_depth == 8) {
494 if (hasAlphaChannel) {
495 chroma = heif_chroma_interleaved_RGBA;
498 chroma = heif_chroma_interleaved_RGB;
502 m_parseState = ParseHeicError;
503 heif_image_handle_release(handle);
504 heif_context_free(ctx);
506 qWarning() <<
"Unsupported bit depth:" << bit_depth;
508 qWarning() <<
"Undefined bit depth.";
513 struct heif_decoding_options *decoder_option = heif_decoding_options_alloc();
515#if LIBHEIF_HAVE_VERSION(1, 13, 0)
516 decoder_option->strict_decoding = 1;
519 struct heif_image *img =
nullptr;
520 err = heif_decode_image(handle, &img, heif_colorspace_RGB, chroma, decoder_option);
522 if (decoder_option) {
523 heif_decoding_options_free(decoder_option);
527 qWarning() <<
"heif_decode_image error:" << err.message;
528 heif_image_handle_release(handle);
529 heif_context_free(ctx);
530 m_parseState = ParseHeicError;
534 const int imageWidth = heif_image_get_width(img, heif_channel_interleaved);
535 const int imageHeight = heif_image_get_height(img, heif_channel_interleaved);
537 QSize imageSize(imageWidth, imageHeight);
539 if (!imageSize.isValid()) {
540 heif_image_release(img);
541 heif_image_handle_release(handle);
542 heif_context_free(ctx);
543 m_parseState = ParseHeicError;
544 qWarning() <<
"HEIC image size invalid:" << imageSize;
549 const uint8_t *
const src = heif_image_get_plane_readonly(img, heif_channel_interleaved, &stride);
551 if (!src || stride <= 0) {
552 heif_image_release(img);
553 heif_image_handle_release(handle);
554 heif_context_free(ctx);
555 m_parseState = ParseHeicError;
556 qWarning() <<
"HEIC data pixels information not valid!";
560 m_current_image = imageAlloc(imageSize, target_image_format);
561 if (m_current_image.isNull()) {
562 heif_image_release(img);
563 heif_image_handle_release(handle);
564 heif_context_free(ctx);
565 m_parseState = ParseHeicError;
566 qWarning() <<
"Unable to allocate memory!";
572 if (hasAlphaChannel) {
573 for (
int y = 0; y < imageHeight; y++) {
574 const uint16_t *src_word =
reinterpret_cast<const uint16_t *
>(src + (y * stride));
575 uint16_t *dest_data =
reinterpret_cast<uint16_t *
>(m_current_image.scanLine(y));
576 for (
int x = 0; x < imageWidth; x++) {
579 tmpvalue = (int)(((
float)(0x0fff & (*src_word)) / 4095.0f) * 65535.0f + 0.5f);
580 tmpvalue = qBound(0, tmpvalue, 65535);
581 *dest_data = (uint16_t)tmpvalue;
585 tmpvalue = (int)(((
float)(0x0fff & (*src_word)) / 4095.0f) * 65535.0f + 0.5f);
586 tmpvalue = qBound(0, tmpvalue, 65535);
587 *dest_data = (uint16_t)tmpvalue;
591 tmpvalue = (int)(((
float)(0x0fff & (*src_word)) / 4095.0f) * 65535.0f + 0.5f);
592 tmpvalue = qBound(0, tmpvalue, 65535);
593 *dest_data = (uint16_t)tmpvalue;
597 tmpvalue = (int)(((
float)(0x0fff & (*src_word)) / 4095.0f) * 65535.0f + 0.5f);
598 tmpvalue = qBound(0, tmpvalue, 65535);
599 *dest_data = (uint16_t)tmpvalue;
605 for (
int y = 0; y < imageHeight; y++) {
606 const uint16_t *src_word =
reinterpret_cast<const uint16_t *
>(src + (y * stride));
607 uint16_t *dest_data =
reinterpret_cast<uint16_t *
>(m_current_image.scanLine(y));
608 for (
int x = 0; x < imageWidth; x++) {
611 tmpvalue = (int)(((
float)(0x0fff & (*src_word)) / 4095.0f) * 65535.0f + 0.5f);
612 tmpvalue = qBound(0, tmpvalue, 65535);
613 *dest_data = (uint16_t)tmpvalue;
617 tmpvalue = (int)(((
float)(0x0fff & (*src_word)) / 4095.0f) * 65535.0f + 0.5f);
618 tmpvalue = qBound(0, tmpvalue, 65535);
619 *dest_data = (uint16_t)tmpvalue;
623 tmpvalue = (int)(((
float)(0x0fff & (*src_word)) / 4095.0f) * 65535.0f + 0.5f);
624 tmpvalue = qBound(0, tmpvalue, 65535);
625 *dest_data = (uint16_t)tmpvalue;
636 if (hasAlphaChannel) {
637 for (
int y = 0; y < imageHeight; y++) {
638 const uint16_t *src_word =
reinterpret_cast<const uint16_t *
>(src + (y * stride));
639 uint16_t *dest_data =
reinterpret_cast<uint16_t *
>(m_current_image.scanLine(y));
640 for (
int x = 0; x < imageWidth; x++) {
643 tmpvalue = (int)(((
float)(0x03ff & (*src_word)) / 1023.0f) * 65535.0f + 0.5f);
644 tmpvalue = qBound(0, tmpvalue, 65535);
645 *dest_data = (uint16_t)tmpvalue;
649 tmpvalue = (int)(((
float)(0x03ff & (*src_word)) / 1023.0f) * 65535.0f + 0.5f);
650 tmpvalue = qBound(0, tmpvalue, 65535);
651 *dest_data = (uint16_t)tmpvalue;
655 tmpvalue = (int)(((
float)(0x03ff & (*src_word)) / 1023.0f) * 65535.0f + 0.5f);
656 tmpvalue = qBound(0, tmpvalue, 65535);
657 *dest_data = (uint16_t)tmpvalue;
661 tmpvalue = (int)(((
float)(0x03ff & (*src_word)) / 1023.0f) * 65535.0f + 0.5f);
662 tmpvalue = qBound(0, tmpvalue, 65535);
663 *dest_data = (uint16_t)tmpvalue;
669 for (
int y = 0; y < imageHeight; y++) {
670 const uint16_t *src_word =
reinterpret_cast<const uint16_t *
>(src + (y * stride));
671 uint16_t *dest_data =
reinterpret_cast<uint16_t *
>(m_current_image.scanLine(y));
672 for (
int x = 0; x < imageWidth; x++) {
675 tmpvalue = (int)(((
float)(0x03ff & (*src_word)) / 1023.0f) * 65535.0f + 0.5f);
676 tmpvalue = qBound(0, tmpvalue, 65535);
677 *dest_data = (uint16_t)tmpvalue;
681 tmpvalue = (int)(((
float)(0x03ff & (*src_word)) / 1023.0f) * 65535.0f + 0.5f);
682 tmpvalue = qBound(0, tmpvalue, 65535);
683 *dest_data = (uint16_t)tmpvalue;
687 tmpvalue = (int)(((
float)(0x03ff & (*src_word)) / 1023.0f) * 65535.0f + 0.5f);
688 tmpvalue = qBound(0, tmpvalue, 65535);
689 *dest_data = (uint16_t)tmpvalue;
700 if (hasAlphaChannel) {
701 for (
int y = 0; y < imageHeight; y++) {
702 const uint8_t *src_byte = src + (y * stride);
703 uint32_t *dest_pixel =
reinterpret_cast<uint32_t *
>(m_current_image.scanLine(y));
704 for (
int x = 0; x < imageWidth; x++) {
705 int red = *src_byte++;
706 int green = *src_byte++;
707 int blue = *src_byte++;
708 int alpha = *src_byte++;
709 *dest_pixel = qRgba(red, green, blue, alpha);
714 for (
int y = 0; y < imageHeight; y++) {
715 const uint8_t *src_byte = src + (y * stride);
716 uint32_t *dest_pixel =
reinterpret_cast<uint32_t *
>(m_current_image.scanLine(y));
717 for (
int x = 0; x < imageWidth; x++) {
718 int red = *src_byte++;
719 int green = *src_byte++;
720 int blue = *src_byte++;
721 *dest_pixel = qRgb(red, green, blue);
728 heif_image_release(img);
729 heif_image_handle_release(handle);
730 heif_context_free(ctx);
731 m_parseState = ParseHeicError;
732 qWarning() <<
"Unsupported bit depth:" << bit_depth;
737 heif_color_profile_type profileType = heif_image_handle_get_color_profile_type(handle);
738 if (profileType == heif_color_profile_type_prof || profileType == heif_color_profile_type_rICC) {
739 size_t rawProfileSize = heif_image_handle_get_raw_color_profile_size(handle);
740 if (rawProfileSize > 0 && rawProfileSize < std::numeric_limits<int>::max()) {
742 err = heif_image_handle_get_raw_color_profile(handle, ba.data());
744 qWarning() <<
"icc profile loading failed";
747 if (!m_current_image.colorSpace().isValid()) {
748 qWarning() <<
"HEIC image has Qt-unsupported or invalid ICC profile!";
752 qWarning() <<
"icc profile is empty or above limits";
755 }
else if (profileType == heif_color_profile_type_nclx) {
756 struct heif_color_profile_nclx *nclx =
nullptr;
757 err = heif_image_handle_get_nclx_color_profile(handle, &nclx);
758 if (err.code || !nclx) {
759 qWarning() <<
"nclx profile loading failed";
761 const QPointF redPoint(nclx->color_primary_red_x, nclx->color_primary_red_y);
762 const QPointF greenPoint(nclx->color_primary_green_x, nclx->color_primary_green_y);
763 const QPointF bluePoint(nclx->color_primary_blue_x, nclx->color_primary_blue_y);
764 const QPointF whitePoint(nclx->color_primary_white_x, nclx->color_primary_white_y);
767 float q_trc_gamma = 0.0f;
769 switch (nclx->transfer_characteristics) {
771 q_trc = QColorSpace::TransferFunction::Gamma;
775 q_trc = QColorSpace::TransferFunction::Gamma;
779 q_trc = QColorSpace::TransferFunction::Linear;
783 q_trc = QColorSpace::TransferFunction::SRgb;
786 qWarning(
"CICP color_primaries: %d, transfer_characteristics: %d\nThe colorspace is unsupported by this plug-in yet.",
787 nclx->color_primaries,
788 nclx->transfer_characteristics);
789 q_trc = QColorSpace::TransferFunction::SRgb;
793 if (q_trc != QColorSpace::TransferFunction::Custom) {
794 switch (nclx->color_primaries) {
797 m_current_image.setColorSpace(
QColorSpace(QColorSpace::Primaries::SRgb, q_trc, q_trc_gamma));
800 m_current_image.setColorSpace(
QColorSpace(QColorSpace::Primaries::DciP3D65, q_trc, q_trc_gamma));
803 m_current_image.setColorSpace(
QColorSpace(whitePoint, redPoint, greenPoint, bluePoint, q_trc, q_trc_gamma));
807 heif_nclx_color_profile_free(nclx);
809 if (!m_current_image.colorSpace().isValid()) {
810 qWarning() <<
"HEIC plugin created invalid QColorSpace from NCLX!";
818 heif_image_release(img);
819 heif_image_handle_release(handle);
820 heif_context_free(ctx);
821 m_parseState = ParseHeicSuccess;
825bool HEIFHandler::isHeifDecoderAvailable()
829 if (!m_plugins_queried) {
830#if LIBHEIF_HAVE_VERSION(1, 13, 0)
831 if (m_initialized_count == 0) {
836#if LIBHEIF_HAVE_VERSION(1, 13, 0)
837 m_hej2_decoder_available = heif_have_decoder_for_format(heif_compression_JPEG2000);
839 m_heif_encoder_available = heif_have_encoder_for_format(heif_compression_HEVC);
840 m_heif_decoder_available = heif_have_decoder_for_format(heif_compression_HEVC);
841 m_plugins_queried =
true;
843#if LIBHEIF_HAVE_VERSION(1, 13, 0)
844 if (m_initialized_count == 0) {
850 return m_heif_decoder_available;
853bool HEIFHandler::isHeifEncoderAvailable()
857 if (!m_plugins_queried) {
858#if LIBHEIF_HAVE_VERSION(1, 13, 0)
859 if (m_initialized_count == 0) {
864#if LIBHEIF_HAVE_VERSION(1, 13, 0)
865 m_hej2_decoder_available = heif_have_decoder_for_format(heif_compression_JPEG2000);
867 m_heif_decoder_available = heif_have_decoder_for_format(heif_compression_HEVC);
868 m_heif_encoder_available = heif_have_encoder_for_format(heif_compression_HEVC);
869 m_plugins_queried =
true;
871#if LIBHEIF_HAVE_VERSION(1, 13, 0)
872 if (m_initialized_count == 0) {
878 return m_heif_encoder_available;
881bool HEIFHandler::isHej2DecoderAvailable()
885 if (!m_plugins_queried) {
886#if LIBHEIF_HAVE_VERSION(1, 13, 0)
887 if (m_initialized_count == 0) {
892 m_heif_encoder_available = heif_have_encoder_for_format(heif_compression_HEVC);
893 m_heif_decoder_available = heif_have_decoder_for_format(heif_compression_HEVC);
894#if LIBHEIF_HAVE_VERSION(1, 13, 0)
895 m_hej2_decoder_available = heif_have_decoder_for_format(heif_compression_JPEG2000);
897 m_plugins_queried =
true;
899#if LIBHEIF_HAVE_VERSION(1, 13, 0)
900 if (m_initialized_count == 0) {
906 return m_hej2_decoder_available;
909void HEIFHandler::startHeifLib()
911#if LIBHEIF_HAVE_VERSION(1, 13, 0)
914 if (m_initialized_count == 0) {
918 m_initialized_count++;
922void HEIFHandler::finishHeifLib()
924#if LIBHEIF_HAVE_VERSION(1, 13, 0)
927 if (m_initialized_count == 0) {
931 m_initialized_count--;
932 if (m_initialized_count == 0) {
939QMutex &HEIFHandler::getHEIFHandlerMutex()
941 static QMutex heif_handler_mutex;
942 return heif_handler_mutex;
947 if (format ==
"heif" || format ==
"heic") {
949 if (HEIFHandler::isHeifDecoderAvailable()) {
950 format_cap |= CanRead;
952 if (HEIFHandler::isHeifEncoderAvailable()) {
953 format_cap |= CanWrite;
958 if (format ==
"hej2") {
960 if (HEIFHandler::isHej2DecoderAvailable()) {
961 format_cap |= CanRead;
977 if (HEIFHandler::isSupportedBMFFType(header) && HEIFHandler::isHeifDecoderAvailable()) {
981 if (HEIFHandler::isSupportedHEJ2(header) && HEIFHandler::isHej2DecoderAvailable()) {
986 if (device->
isWritable() && HEIFHandler::isHeifEncoderAvailable()) {
1000#include "moc_heif_p.cpp"
KGUIADDONS_EXPORT qreal chroma(const QColor &)
QFlags< Capability > Capabilities
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
const char * constData() const const
bool isEmpty() const const
qsizetype size() const const
QColorSpace fromIccProfile(const QByteArray &iccProfile)
QByteArray iccProfile() const const
QColorSpace colorSpace() const const
const uchar * constScanLine(int i) const const
bool hasAlphaChannel() const const
bool isNull() const const
void setDevice(QIODevice *device)
virtual void setOption(ImageOption option, const QVariant &value)
bool isOpen() const const
bool isReadable() const const
bool isWritable() const const
QByteArray peek(qint64 maxSize)
qint64 write(const QByteArray &data)
int toInt(bool *ok) const const